Skip to content

Commit 2eaf503

Browse files
authored
Merge pull request #451 from Rafostar/resize-me
Resize app window to match aspect ratio with middle click
2 parents 5049f62 + 28de283 commit 2eaf503

File tree

5 files changed

+206
-16
lines changed

5 files changed

+206
-16
lines changed

src/bin/clapper-app/clapper-app-application.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,7 @@ clapper_app_application_constructed (GObject *object)
700700
{ "app.preferences", { "<Control>comma", NULL, NULL }},
701701
{ "app.about", { "F1", NULL, NULL }},
702702
{ "win.toggle-fullscreen", { "F11", "f", NULL }},
703+
{ "win.auto-resize", { "<Super>r", NULL, NULL }},
703704
{ "win.show-help-overlay", { "<Control>question", NULL, NULL }},
704705
{ "window.close", { "<Control>q", "q", NULL }},
705706
};

src/bin/clapper-app/clapper-app-window.c

Lines changed: 195 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
#include "clapper-app-file-dialog.h"
2929
#include "clapper-app-utils.h"
3030

31+
#define MIN_WINDOW_WIDTH 352
32+
#define MIN_WINDOW_HEIGHT 198
33+
3134
#define DEFAULT_WINDOW_WIDTH 1024
3235
#define DEFAULT_WINDOW_HEIGHT 576
3336

@@ -40,6 +43,8 @@
4043
#define PERCENTAGE_ROUND(a) (round ((gdouble) a / 0.01) * 0.01)
4144
#define AXIS_WINS_OVER(a,b) ((a > 0 && a - 0.3 > b) || (a < 0 && a + 0.3 < b))
4245

46+
#define MIN_STEP_DELAY 12000
47+
4348
#define GST_CAT_DEFAULT clapper_app_window_debug
4449
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
4550

@@ -59,6 +64,7 @@ struct _ClapperAppWindow
5964
GSettings *settings;
6065

6166
guint seek_timeout;
67+
guint resize_tick_id;
6268

6369
gboolean key_held;
6470
gboolean scrolling;
@@ -74,6 +80,12 @@ struct _ClapperAppWindow
7480
#define parent_class clapper_app_window_parent_class
7581
G_DEFINE_TYPE (ClapperAppWindow, clapper_app_window, GTK_TYPE_APPLICATION_WINDOW)
7682

83+
typedef struct
84+
{
85+
gint dest_width, dest_height;
86+
gint64 last_tick;
87+
} ClapperAppWindowResizeData;
88+
7789
static guint16 instance_count = 0;
7890

7991
static inline GQuark
@@ -246,12 +258,16 @@ _open_subtitles_cb (ClapperGtkExtraMenuButton *button G_GNUC_UNUSED,
246258
}
247259

248260
static void
249-
right_click_pressed_cb (GtkGestureClick *click, gint n_press,
261+
click_pressed_cb (GtkGestureClick *click, gint n_press,
250262
gdouble x, gdouble y, ClapperAppWindow *self)
251263
{
252264
GdkCursor *cursor;
253265
const gchar *cursor_name = NULL;
254266

267+
if (gtk_gesture_single_get_current_button (
268+
GTK_GESTURE_SINGLE (click)) != GDK_BUTTON_SECONDARY)
269+
return;
270+
255271
GST_LOG_OBJECT (self, "Right click pressed");
256272

257273
if ((cursor = gtk_widget_get_cursor (self->video)))
@@ -266,9 +282,152 @@ right_click_pressed_cb (GtkGestureClick *click, gint n_press,
266282
}
267283
}
268284

285+
static gboolean
286+
_resize_tick (GtkWidget *widget, GdkFrameClock *frame_clock,
287+
ClapperAppWindowResizeData *resize_data)
288+
{
289+
gint64 now = gdk_frame_clock_get_frame_time (frame_clock);
290+
291+
if (now - resize_data->last_tick >= MIN_STEP_DELAY) {
292+
ClapperAppWindow *self = CLAPPER_APP_WINDOW_CAST (widget);
293+
gint win_width, win_height;
294+
295+
GST_LOG_OBJECT (self, "Resize step, last: %" G_GINT64_FORMAT
296+
", now: %" G_GINT64_FORMAT, resize_data->last_tick, now);
297+
298+
gtk_window_get_default_size (GTK_WINDOW (self), &win_width, &win_height);
299+
300+
if (win_width != resize_data->dest_width) {
301+
gint width_diff = ABS (win_width - resize_data->dest_width);
302+
gint step_size = (width_diff > 180) ? 120 : MAX (width_diff / 4, 1);
303+
304+
win_width += (win_width > resize_data->dest_width) ? -step_size : step_size;
305+
}
306+
if (win_height != resize_data->dest_height) {
307+
gint height_diff = ABS (win_height - resize_data->dest_height);
308+
gint step_size = (height_diff > 180) ? 120 : MAX (height_diff / 4, 1);
309+
310+
win_height += (win_height > resize_data->dest_height) ? -step_size : step_size;
311+
}
312+
313+
gtk_window_set_default_size (GTK_WINDOW (self), win_width, win_height);
314+
315+
if (win_width == resize_data->dest_width
316+
&& win_height == resize_data->dest_height) {
317+
GST_DEBUG_OBJECT (self, "Window resize finish");
318+
self->resize_tick_id = 0;
319+
320+
return G_SOURCE_REMOVE;
321+
}
322+
323+
resize_data->last_tick = now;
324+
}
325+
326+
return G_SOURCE_CONTINUE;
327+
}
328+
269329
static void
270-
right_click_released_cb (GtkGestureClick *click, gint n_press,
271-
gdouble x, gdouble y, ClapperAppWindow *self)
330+
_calculate_win_resize (gint win_w, gint win_h,
331+
gint vid_w, gint vid_h, gint *dest_w, gint *dest_h)
332+
{
333+
gdouble win_aspect = (gdouble) win_w / win_h;
334+
gdouble vid_aspect = (gdouble) vid_w / vid_h;
335+
336+
if (win_aspect < vid_aspect) {
337+
while (!G_APPROX_VALUE (fmod (win_w, vid_aspect), 0, FLT_EPSILON))
338+
win_w++;
339+
340+
win_h = round ((gdouble) win_w / vid_aspect);
341+
342+
if (win_h < MIN_WINDOW_HEIGHT) {
343+
_calculate_win_resize (G_MAXINT, MIN_WINDOW_HEIGHT, vid_w, vid_h, dest_w, dest_h);
344+
return;
345+
}
346+
} else {
347+
while (!G_APPROX_VALUE (fmod (win_h * vid_aspect, 1.0), 0, FLT_EPSILON))
348+
win_h++;
349+
350+
win_w = round ((gdouble) win_h * vid_aspect);
351+
352+
if (win_w < MIN_WINDOW_WIDTH) {
353+
_calculate_win_resize (MIN_WINDOW_WIDTH, G_MAXINT, vid_w, vid_h, dest_w, dest_h);
354+
return;
355+
}
356+
}
357+
358+
*dest_w = win_w;
359+
*dest_h = win_h;
360+
}
361+
362+
static void
363+
_resize_window (ClapperAppWindow *self)
364+
{
365+
ClapperPlayer *player;
366+
ClapperStreamList *vstreams;
367+
ClapperVideoStream *vstream;
368+
GdkToplevelState toplevel_state, disallowed;
369+
370+
if (self->resize_tick_id != 0)
371+
return;
372+
373+
toplevel_state = gdk_toplevel_get_state (GDK_TOPLEVEL (
374+
gtk_native_get_surface (GTK_NATIVE (self))));
375+
disallowed = (GDK_TOPLEVEL_STATE_MINIMIZED
376+
| GDK_TOPLEVEL_STATE_MAXIMIZED
377+
| GDK_TOPLEVEL_STATE_FULLSCREEN
378+
| GDK_TOPLEVEL_STATE_TILED);
379+
380+
if ((toplevel_state & disallowed) > 0) {
381+
GST_DEBUG_OBJECT (self, "Cannot resize window in disallowed state");
382+
return;
383+
}
384+
385+
player = clapper_app_window_get_player (self);
386+
vstreams = clapper_player_get_video_streams (player);
387+
vstream = CLAPPER_VIDEO_STREAM_CAST (
388+
clapper_stream_list_get_current_stream (vstreams));
389+
390+
if (vstream) {
391+
gint video_width = clapper_video_stream_get_width (vstream);
392+
gint video_height = clapper_video_stream_get_height (vstream);
393+
394+
if (G_LIKELY (video_width > 0 && video_height > 0)) {
395+
gint win_width, win_height, dest_width, dest_height;
396+
397+
gtk_window_get_default_size (GTK_WINDOW (self), &win_width, &win_height);
398+
399+
_calculate_win_resize (win_width, win_height,
400+
video_width, video_height, &dest_width, &dest_height);
401+
402+
/* Only begin resize when not already at perfect size */
403+
if (dest_width != win_width || dest_height != win_height) {
404+
ClapperAppWindowResizeData *resize_data;
405+
406+
resize_data = g_new0 (ClapperAppWindowResizeData, 1);
407+
resize_data->dest_width = dest_width;
408+
resize_data->dest_height = dest_height;
409+
410+
GST_DEBUG_OBJECT (self, "Window resize start, dest: %ix%i",
411+
resize_data->dest_width, resize_data->dest_height);
412+
413+
self->resize_tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (self),
414+
(GtkTickCallback) _resize_tick, resize_data, g_free);
415+
}
416+
}
417+
418+
gst_object_unref (vstream);
419+
}
420+
}
421+
422+
static void
423+
_handle_middle_click (ClapperAppWindow *self, GtkGestureClick *click)
424+
{
425+
_resize_window (self);
426+
gtk_gesture_set_state (GTK_GESTURE (click), GTK_EVENT_SEQUENCE_CLAIMED);
427+
}
428+
429+
static void
430+
_handle_right_click (ClapperAppWindow *self, GtkGestureClick *click)
272431
{
273432
GdkSurface *surface;
274433
GdkEventSequence *sequence;
@@ -289,6 +448,22 @@ right_click_released_cb (GtkGestureClick *click, gint n_press,
289448
gtk_gesture_set_state (GTK_GESTURE (click), GTK_EVENT_SEQUENCE_CLAIMED);
290449
}
291450

451+
static void
452+
click_released_cb (GtkGestureClick *click, gint n_press,
453+
gdouble x, gdouble y, ClapperAppWindow *self)
454+
{
455+
switch (gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (click))) {
456+
case GDK_BUTTON_MIDDLE:
457+
_handle_middle_click (self, click);
458+
break;
459+
case GDK_BUTTON_SECONDARY:
460+
_handle_right_click (self, click);
461+
break;
462+
default:
463+
break;
464+
}
465+
}
466+
292467
static void
293468
drag_begin_cb (GtkGestureDrag *drag,
294469
gdouble start_x, gdouble start_y, ClapperAppWindow *self)
@@ -888,6 +1063,12 @@ toggle_fullscreen (GSimpleAction *action, GVariant *param, gpointer user_data)
8881063
video_toggle_fullscreen_cb (CLAPPER_GTK_VIDEO_CAST (self->video), self);
8891064
}
8901065

1066+
static void
1067+
auto_resize (GSimpleAction *action, GVariant *param, gpointer user_data)
1068+
{
1069+
_resize_window (CLAPPER_APP_WINDOW_CAST (user_data));
1070+
}
1071+
8911072
static void
8921073
show_help_overlay (GSimpleAction *action, GVariant *param, gpointer user_data)
8931074
{
@@ -998,6 +1179,9 @@ clapper_app_window_init (ClapperAppWindow *self)
9981179
GtkWidget *dummy_titlebar;
9991180
gint distance = 0;
10001181

1182+
gtk_widget_set_size_request (GTK_WIDGET (self),
1183+
MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT);
1184+
10011185
extra_opts = g_new0 (ClapperAppWindowExtraOptions, 1);
10021186
GST_TRACE ("Created window extra options: %p", extra_opts);
10031187

@@ -1039,6 +1223,7 @@ clapper_app_window_constructed (GObject *object)
10391223

10401224
static const GActionEntry win_entries[] = {
10411225
{ "toggle-fullscreen", toggle_fullscreen, NULL, NULL, NULL },
1226+
{ "auto-resize", auto_resize, NULL, NULL, NULL },
10421227
{ "show-help-overlay", show_help_overlay, NULL, NULL, NULL },
10431228
};
10441229

@@ -1126,6 +1311,11 @@ clapper_app_window_dispose (GObject *object)
11261311
{
11271312
ClapperAppWindow *self = CLAPPER_APP_WINDOW_CAST (object);
11281313

1314+
if (self->resize_tick_id != 0) {
1315+
gtk_widget_remove_tick_callback (GTK_WIDGET (self), self->resize_tick_id);
1316+
self->resize_tick_id = 0;
1317+
}
1318+
11291319
g_clear_handle_id (&self->seek_timeout, g_source_remove);
11301320

11311321
gtk_widget_dispose_template (GTK_WIDGET (object), CLAPPER_APP_TYPE_WINDOW);
@@ -1185,8 +1375,8 @@ clapper_app_window_class_init (ClapperAppWindowClass *klass)
11851375
gtk_widget_class_bind_template_callback (widget_class, key_pressed_cb);
11861376
gtk_widget_class_bind_template_callback (widget_class, key_released_cb);
11871377

1188-
gtk_widget_class_bind_template_callback (widget_class, right_click_pressed_cb);
1189-
gtk_widget_class_bind_template_callback (widget_class, right_click_released_cb);
1378+
gtk_widget_class_bind_template_callback (widget_class, click_pressed_cb);
1379+
gtk_widget_class_bind_template_callback (widget_class, click_released_cb);
11901380
gtk_widget_class_bind_template_callback (widget_class, drag_begin_cb);
11911381
gtk_widget_class_bind_template_callback (widget_class, drag_update_cb);
11921382

src/bin/clapper-app/css/styles.css

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
window.app {
2-
min-width: 352px;
3-
min-height: 198px;
4-
}
5-
61
window .initialstate {
72
padding-left: 6px;
83
padding-right: 6px;

src/bin/clapper-app/ui/clapper-app-help-overlay.ui

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@
3333
<property name="accelerator">F11 f</property>
3434
</object>
3535
</child>
36+
<child>
37+
<object class="GtkShortcutsShortcut">
38+
<property name="title" translatable="yes">Auto window resize</property>
39+
<property name="subtitle" translatable="yes">Middle click</property>
40+
<property name="accelerator">&lt;Super&gt;r</property>
41+
</object>
42+
</child>
3643
<child>
3744
<object class="GtkShortcutsShortcut">
3845
<property name="title" translatable="yes">Quit</property>

src/bin/clapper-app/ui/clapper-app-window.ui

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@
4747
</child>
4848
<child>
4949
<object class="GtkGestureClick">
50-
<property name="button">3</property>
51-
<signal name="pressed" handler="right_click_pressed_cb"/>
52-
<signal name="released" handler="right_click_released_cb"/>
50+
<property name="button">0</property>
51+
<signal name="pressed" handler="click_pressed_cb"/>
52+
<signal name="released" handler="click_released_cb"/>
5353
</object>
5454
</child>
5555
<child>
@@ -68,8 +68,5 @@
6868
<signal name="drop" handler="drop_cb"/>
6969
</object>
7070
</child>
71-
<style>
72-
<class name="app"/>
73-
</style>
7471
</template>
7572
</interface>

0 commit comments

Comments
 (0)