Skip to content

Commit

Permalink
clapper-app: Resize window to match aspect ratio with middle click
Browse files Browse the repository at this point in the history
  • Loading branch information
Rafostar committed May 23, 2024
1 parent 5049f62 commit 6863442
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 16 deletions.
180 changes: 175 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,139 @@ right_click_pressed_cb (GtkGestureClick *click, gint n_press,
}
}

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

if (now - resize_data->last_tick >= MIN_STEP_DELAY) {
gint win_width = 1, win_height = 1;

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);
resize_data->last_tick = now;

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;
}
}

return G_SOURCE_CONTINUE;
}

static void
right_click_released_cb (GtkGestureClick *click, gint n_press,
gdouble x, gdouble y, ClapperAppWindow *self)
_calculate_resize_for_width (ClapperAppWindowResizeData *resize_data,
gint width, gdouble video_aspect)
{
resize_data->dest_width = width;

while (!G_APPROX_VALUE (fmod (resize_data->dest_width, video_aspect), 0, FLT_EPSILON))
resize_data->dest_width++;

resize_data->dest_height = round ((gdouble) resize_data->dest_width / video_aspect);
}

static void
_calculate_resize_for_height (ClapperAppWindowResizeData *resize_data,
gint height, gdouble video_aspect)
{
resize_data->dest_height = height;

while (!G_APPROX_VALUE (fmod (resize_data->dest_height * video_aspect, 1.0), 0, FLT_EPSILON))
resize_data->dest_height++;

resize_data->dest_width = round ((gdouble) resize_data->dest_height * video_aspect);
}

static void
_handle_middle_click (ClapperAppWindow *self, GtkGestureClick *click)
{
ClapperPlayer *player;
ClapperStreamList *vstreams;
ClapperVideoStream *vstream;

if (self->resize_tick_id != 0
|| gtk_window_is_fullscreen (GTK_WINDOW (self)))
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, video_height;

video_width = clapper_video_stream_get_width (vstream);
video_height = clapper_video_stream_get_height (vstream);

if (G_LIKELY (video_width > 0 && video_height > 0)) {
ClapperAppWindowResizeData *resize_data;
gdouble video_aspect, win_aspect;
gint win_width = 1, win_height = 1;

resize_data = g_new0 (ClapperAppWindowResizeData, 1);
gtk_window_get_default_size (GTK_WINDOW (self), &win_width, &win_height);

video_aspect = (gdouble) video_width / video_height;
win_aspect = (gdouble) win_width / win_height;

if (win_aspect < video_aspect) {
_calculate_resize_for_width (resize_data, win_width, video_aspect);

if (resize_data->dest_height < MIN_WINDOW_HEIGHT)
_calculate_resize_for_height (resize_data, MIN_WINDOW_HEIGHT, video_aspect);
} else {
_calculate_resize_for_height (resize_data, win_height, video_aspect);

if (resize_data->dest_width < MIN_WINDOW_WIDTH) {
_calculate_resize_for_width (resize_data, MIN_WINDOW_WIDTH, video_aspect);
}
}

/* Only begin resize when not already at perfect size */
if (resize_data->dest_width != win_width
|| resize_data->dest_height != win_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);
} else {
g_free (resize_data);
}
}

gst_object_unref (vstream);
}

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 +435,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 @@ -998,6 +1160,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 @@ -1126,6 +1291,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 +1355,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
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 6863442

Please sign in to comment.