Skip to content

Commit

Permalink
Merge pull request #451 from Rafostar/resize-me
Browse files Browse the repository at this point in the history
Resize app window to match aspect ratio with middle click
  • Loading branch information
Rafostar committed May 26, 2024
2 parents 5049f62 + 28de283 commit 2eaf503
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 16 deletions.
1 change: 1 addition & 0 deletions src/bin/clapper-app/clapper-app-application.c
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,7 @@ clapper_app_application_constructed (GObject *object)
{ "app.preferences", { "<Control>comma", NULL, NULL }},
{ "app.about", { "F1", NULL, NULL }},
{ "win.toggle-fullscreen", { "F11", "f", NULL }},
{ "win.auto-resize", { "<Super>r", NULL, NULL }},
{ "win.show-help-overlay", { "<Control>question", NULL, NULL }},
{ "window.close", { "<Control>q", "q", NULL }},
};
Expand Down
200 changes: 195 additions & 5 deletions src/bin/clapper-app/clapper-app-window.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
#include "clapper-app-file-dialog.h"
#include "clapper-app-utils.h"

#define MIN_WINDOW_WIDTH 352
#define MIN_WINDOW_HEIGHT 198

#define DEFAULT_WINDOW_WIDTH 1024
#define DEFAULT_WINDOW_HEIGHT 576

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

#define MIN_STEP_DELAY 12000

#define GST_CAT_DEFAULT clapper_app_window_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);

Expand All @@ -59,6 +64,7 @@ struct _ClapperAppWindow
GSettings *settings;

guint seek_timeout;
guint resize_tick_id;

gboolean key_held;
gboolean scrolling;
Expand All @@ -74,6 +80,12 @@ struct _ClapperAppWindow
#define parent_class clapper_app_window_parent_class
G_DEFINE_TYPE (ClapperAppWindow, clapper_app_window, GTK_TYPE_APPLICATION_WINDOW)

typedef struct
{
gint dest_width, dest_height;
gint64 last_tick;
} ClapperAppWindowResizeData;

static guint16 instance_count = 0;

static inline GQuark
Expand Down Expand Up @@ -246,12 +258,16 @@ _open_subtitles_cb (ClapperGtkExtraMenuButton *button G_GNUC_UNUSED,
}

static void
right_click_pressed_cb (GtkGestureClick *click, gint n_press,
click_pressed_cb (GtkGestureClick *click, gint n_press,
gdouble x, gdouble y, ClapperAppWindow *self)
{
GdkCursor *cursor;
const gchar *cursor_name = NULL;

if (gtk_gesture_single_get_current_button (
GTK_GESTURE_SINGLE (click)) != GDK_BUTTON_SECONDARY)
return;

GST_LOG_OBJECT (self, "Right click pressed");

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

static gboolean
_resize_tick (GtkWidget *widget, GdkFrameClock *frame_clock,
ClapperAppWindowResizeData *resize_data)
{
gint64 now = gdk_frame_clock_get_frame_time (frame_clock);

if (now - resize_data->last_tick >= MIN_STEP_DELAY) {
ClapperAppWindow *self = CLAPPER_APP_WINDOW_CAST (widget);
gint win_width, win_height;

GST_LOG_OBJECT (self, "Resize step, last: %" G_GINT64_FORMAT
", now: %" G_GINT64_FORMAT, resize_data->last_tick, now);

gtk_window_get_default_size (GTK_WINDOW (self), &win_width, &win_height);

if (win_width != resize_data->dest_width) {
gint width_diff = ABS (win_width - resize_data->dest_width);
gint step_size = (width_diff > 180) ? 120 : MAX (width_diff / 4, 1);

win_width += (win_width > resize_data->dest_width) ? -step_size : step_size;
}
if (win_height != resize_data->dest_height) {
gint height_diff = ABS (win_height - resize_data->dest_height);
gint step_size = (height_diff > 180) ? 120 : MAX (height_diff / 4, 1);

win_height += (win_height > resize_data->dest_height) ? -step_size : step_size;
}

gtk_window_set_default_size (GTK_WINDOW (self), win_width, win_height);

if (win_width == resize_data->dest_width
&& win_height == resize_data->dest_height) {
GST_DEBUG_OBJECT (self, "Window resize finish");
self->resize_tick_id = 0;

return G_SOURCE_REMOVE;
}

resize_data->last_tick = now;
}

return G_SOURCE_CONTINUE;
}

static void
right_click_released_cb (GtkGestureClick *click, gint n_press,
gdouble x, gdouble y, ClapperAppWindow *self)
_calculate_win_resize (gint win_w, gint win_h,
gint vid_w, gint vid_h, gint *dest_w, gint *dest_h)
{
gdouble win_aspect = (gdouble) win_w / win_h;
gdouble vid_aspect = (gdouble) vid_w / vid_h;

if (win_aspect < vid_aspect) {
while (!G_APPROX_VALUE (fmod (win_w, vid_aspect), 0, FLT_EPSILON))
win_w++;

win_h = round ((gdouble) win_w / vid_aspect);

if (win_h < MIN_WINDOW_HEIGHT) {
_calculate_win_resize (G_MAXINT, MIN_WINDOW_HEIGHT, vid_w, vid_h, dest_w, dest_h);
return;
}
} else {
while (!G_APPROX_VALUE (fmod (win_h * vid_aspect, 1.0), 0, FLT_EPSILON))
win_h++;

win_w = round ((gdouble) win_h * vid_aspect);

if (win_w < MIN_WINDOW_WIDTH) {
_calculate_win_resize (MIN_WINDOW_WIDTH, G_MAXINT, vid_w, vid_h, dest_w, dest_h);
return;
}
}

*dest_w = win_w;
*dest_h = win_h;
}

static void
_resize_window (ClapperAppWindow *self)
{
ClapperPlayer *player;
ClapperStreamList *vstreams;
ClapperVideoStream *vstream;
GdkToplevelState toplevel_state, disallowed;

if (self->resize_tick_id != 0)
return;

toplevel_state = gdk_toplevel_get_state (GDK_TOPLEVEL (
gtk_native_get_surface (GTK_NATIVE (self))));
disallowed = (GDK_TOPLEVEL_STATE_MINIMIZED
| GDK_TOPLEVEL_STATE_MAXIMIZED
| GDK_TOPLEVEL_STATE_FULLSCREEN
| GDK_TOPLEVEL_STATE_TILED);

if ((toplevel_state & disallowed) > 0) {
GST_DEBUG_OBJECT (self, "Cannot resize window in disallowed state");
return;
}

player = clapper_app_window_get_player (self);
vstreams = clapper_player_get_video_streams (player);
vstream = CLAPPER_VIDEO_STREAM_CAST (
clapper_stream_list_get_current_stream (vstreams));

if (vstream) {
gint video_width = clapper_video_stream_get_width (vstream);
gint video_height = clapper_video_stream_get_height (vstream);

if (G_LIKELY (video_width > 0 && video_height > 0)) {
gint win_width, win_height, dest_width, dest_height;

gtk_window_get_default_size (GTK_WINDOW (self), &win_width, &win_height);

_calculate_win_resize (win_width, win_height,
video_width, video_height, &dest_width, &dest_height);

/* Only begin resize when not already at perfect size */
if (dest_width != win_width || dest_height != win_height) {
ClapperAppWindowResizeData *resize_data;

resize_data = g_new0 (ClapperAppWindowResizeData, 1);
resize_data->dest_width = dest_width;
resize_data->dest_height = dest_height;

GST_DEBUG_OBJECT (self, "Window resize start, dest: %ix%i",
resize_data->dest_width, resize_data->dest_height);

self->resize_tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (self),
(GtkTickCallback) _resize_tick, resize_data, g_free);
}
}

gst_object_unref (vstream);
}
}

static void
_handle_middle_click (ClapperAppWindow *self, GtkGestureClick *click)
{
_resize_window (self);
gtk_gesture_set_state (GTK_GESTURE (click), GTK_EVENT_SEQUENCE_CLAIMED);
}

static void
_handle_right_click (ClapperAppWindow *self, GtkGestureClick *click)
{
GdkSurface *surface;
GdkEventSequence *sequence;
Expand All @@ -289,6 +448,22 @@ right_click_released_cb (GtkGestureClick *click, gint n_press,
gtk_gesture_set_state (GTK_GESTURE (click), GTK_EVENT_SEQUENCE_CLAIMED);
}

static void
click_released_cb (GtkGestureClick *click, gint n_press,
gdouble x, gdouble y, ClapperAppWindow *self)
{
switch (gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (click))) {
case GDK_BUTTON_MIDDLE:
_handle_middle_click (self, click);
break;
case GDK_BUTTON_SECONDARY:
_handle_right_click (self, click);
break;
default:
break;
}
}

static void
drag_begin_cb (GtkGestureDrag *drag,
gdouble start_x, gdouble start_y, ClapperAppWindow *self)
Expand Down Expand Up @@ -888,6 +1063,12 @@ toggle_fullscreen (GSimpleAction *action, GVariant *param, gpointer user_data)
video_toggle_fullscreen_cb (CLAPPER_GTK_VIDEO_CAST (self->video), self);
}

static void
auto_resize (GSimpleAction *action, GVariant *param, gpointer user_data)
{
_resize_window (CLAPPER_APP_WINDOW_CAST (user_data));
}

static void
show_help_overlay (GSimpleAction *action, GVariant *param, gpointer user_data)
{
Expand Down Expand Up @@ -998,6 +1179,9 @@ clapper_app_window_init (ClapperAppWindow *self)
GtkWidget *dummy_titlebar;
gint distance = 0;

gtk_widget_set_size_request (GTK_WIDGET (self),
MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT);

extra_opts = g_new0 (ClapperAppWindowExtraOptions, 1);
GST_TRACE ("Created window extra options: %p", extra_opts);

Expand Down Expand Up @@ -1039,6 +1223,7 @@ clapper_app_window_constructed (GObject *object)

static const GActionEntry win_entries[] = {
{ "toggle-fullscreen", toggle_fullscreen, NULL, NULL, NULL },
{ "auto-resize", auto_resize, NULL, NULL, NULL },
{ "show-help-overlay", show_help_overlay, NULL, NULL, NULL },
};

Expand Down Expand Up @@ -1126,6 +1311,11 @@ clapper_app_window_dispose (GObject *object)
{
ClapperAppWindow *self = CLAPPER_APP_WINDOW_CAST (object);

if (self->resize_tick_id != 0) {
gtk_widget_remove_tick_callback (GTK_WIDGET (self), self->resize_tick_id);
self->resize_tick_id = 0;
}

g_clear_handle_id (&self->seek_timeout, g_source_remove);

gtk_widget_dispose_template (GTK_WIDGET (object), CLAPPER_APP_TYPE_WINDOW);
Expand Down Expand Up @@ -1185,8 +1375,8 @@ clapper_app_window_class_init (ClapperAppWindowClass *klass)
gtk_widget_class_bind_template_callback (widget_class, key_pressed_cb);
gtk_widget_class_bind_template_callback (widget_class, key_released_cb);

gtk_widget_class_bind_template_callback (widget_class, right_click_pressed_cb);
gtk_widget_class_bind_template_callback (widget_class, right_click_released_cb);
gtk_widget_class_bind_template_callback (widget_class, click_pressed_cb);
gtk_widget_class_bind_template_callback (widget_class, click_released_cb);
gtk_widget_class_bind_template_callback (widget_class, drag_begin_cb);
gtk_widget_class_bind_template_callback (widget_class, drag_update_cb);

Expand Down
5 changes: 0 additions & 5 deletions src/bin/clapper-app/css/styles.css
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
window.app {
min-width: 352px;
min-height: 198px;
}

window .initialstate {
padding-left: 6px;
padding-right: 6px;
Expand Down
7 changes: 7 additions & 0 deletions src/bin/clapper-app/ui/clapper-app-help-overlay.ui
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@
<property name="accelerator">F11 f</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes">Auto window resize</property>
<property name="subtitle" translatable="yes">Middle click</property>
<property name="accelerator">&lt;Super&gt;r</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes">Quit</property>
Expand Down
9 changes: 3 additions & 6 deletions src/bin/clapper-app/ui/clapper-app-window.ui
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@
</child>
<child>
<object class="GtkGestureClick">
<property name="button">3</property>
<signal name="pressed" handler="right_click_pressed_cb"/>
<signal name="released" handler="right_click_released_cb"/>
<property name="button">0</property>
<signal name="pressed" handler="click_pressed_cb"/>
<signal name="released" handler="click_released_cb"/>
</object>
</child>
<child>
Expand All @@ -68,8 +68,5 @@
<signal name="drop" handler="drop_cb"/>
</object>
</child>
<style>
<class name="app"/>
</style>
</template>
</interface>

0 comments on commit 2eaf503

Please sign in to comment.