From a96852c41e5917876a72dd19eb346677c728f96c Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Sun, 20 Feb 2022 13:07:28 +0100 Subject: [PATCH 1/3] backend: Simplify cursor setting Keep track of the state, and update the cursor from a single location. --- src/backend/bacon-video-widget.c | 69 ++++++++++++++++---------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/src/backend/bacon-video-widget.c b/src/backend/bacon-video-widget.c index bd3d16bc8..1a0ba3520 100644 --- a/src/backend/bacon-video-widget.c +++ b/src/backend/bacon-video-widget.c @@ -200,14 +200,16 @@ struct _BaconVideoWidget gboolean got_redirect; - GdkCursor *cursor; + GdkCursor *blank_cursor; + GdkCursor *hand_cursor; + gboolean cursor_shown; + gboolean hovering_menu; /* Visual effects */ GstElement *audio_capsfilter; GstElement *audio_pitchcontrol; /* Other stuff */ - gboolean cursor_shown; gboolean uses_audio_fakesink; gdouble volume; gboolean is_menu; @@ -400,13 +402,35 @@ bvw_show_error_if_video_decoder_is_missing (BaconVideoWidget * bvw) } } +static void +update_cursor (BaconVideoWidget *bvw) +{ + GdkWindow *window; + + window = gtk_widget_get_window (GTK_WIDGET (bvw)); + + if (bvw->hovering_menu) + gdk_window_set_cursor (window, bvw->hand_cursor); + else if (bvw->cursor_shown) + gdk_window_set_cursor (window, NULL); + else + gdk_window_set_cursor (window, bvw->blank_cursor); +} + static void bacon_video_widget_realize (GtkWidget * widget) { BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (widget); + GdkWindow *window; + GdkDisplay *display; GTK_WIDGET_CLASS (parent_class)->realize (widget); + window = gtk_widget_get_window (widget); + display = gdk_window_get_display (window); + bvw->hand_cursor = gdk_cursor_new_for_display (display, GDK_HAND2); + bvw->blank_cursor = gdk_cursor_new_for_display (display, GDK_BLANK_CURSOR); + bvw->missing_plugins_cancellable = g_cancellable_new (); g_object_set_data_full (G_OBJECT (bvw), "missing-plugins-cancellable", bvw->missing_plugins_cancellable, g_object_unref); @@ -420,6 +444,9 @@ bacon_video_widget_unrealize (GtkWidget *widget) GTK_WIDGET_CLASS (parent_class)->unrealize (widget); + g_clear_object (&bvw->blank_cursor); + g_clear_object (&bvw->hand_cursor); + g_cancellable_cancel (bvw->missing_plugins_cancellable); bvw->missing_plugins_cancellable = NULL; g_object_set_data (G_OBJECT (bvw), "missing-plugins-cancellable", NULL); @@ -1182,20 +1209,10 @@ bvw_handle_element_message (BaconVideoWidget *bvw, GstMessage *msg) switch (nav_msg_type) { case GST_NAVIGATION_MESSAGE_MOUSE_OVER: { gint active; - GdkWindow *window; - GdkDisplay *display; if (!gst_navigation_message_parse_mouse_over (msg, &active)) break; - window = gtk_widget_get_window (GTK_WIDGET (bvw)); - if (active) { - if (bvw->cursor == NULL) { - display = gdk_window_get_display (window); - bvw->cursor = gdk_cursor_new_for_display (display, GDK_HAND2); - } - } else { - g_clear_object (&bvw->cursor); - } - gdk_window_set_cursor (window, bvw->cursor); + bvw->hovering_menu = active; + update_cursor (bvw); goto done; } case GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED: { @@ -2456,8 +2473,6 @@ bacon_video_widget_finalize (GObject * object) bvw->eos_id = 0; } - g_clear_object (&bvw->cursor); - if (bvw->mount_cancellable) g_cancellable_cancel (bvw->mount_cancellable); g_clear_object (&bvw->mount_cancellable); @@ -4331,28 +4346,12 @@ void bacon_video_widget_set_show_cursor (BaconVideoWidget * bvw, gboolean show_cursor) { - GdkWindow *window; - g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw)); - - bvw->cursor_shown = show_cursor; - window = gtk_widget_get_window (GTK_WIDGET (bvw)); - - if (!window) + if (bvw->cursor_shown == show_cursor) return; - - if (show_cursor == FALSE) { - GdkCursor *cursor; - GdkDisplay *display; - - display = gdk_window_get_display (window); - cursor = gdk_cursor_new_for_display (display, GDK_BLANK_CURSOR); - gdk_window_set_cursor (window, cursor); - g_object_unref (cursor); - } else { - gdk_window_set_cursor (window, bvw->cursor); - } + bvw->cursor_shown = show_cursor; + update_cursor (bvw); } /** -- GitLab From 954e251ad8dc2b9c7eb0ae4f8e3eb6518aee430f Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Sun, 20 Feb 2022 13:18:02 +0100 Subject: [PATCH 2/3] backend: Always show cursor when toplevel is unfocused Closes: #129 --- src/backend/bacon-video-widget.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/backend/bacon-video-widget.c b/src/backend/bacon-video-widget.c index 1a0ba3520..00a5de80e 100644 --- a/src/backend/bacon-video-widget.c +++ b/src/backend/bacon-video-widget.c @@ -166,6 +166,8 @@ struct _BaconVideoWidget GtkWidget *broken_video; GtkWidget *video_widget; + GtkWindow *parent_toplevel; + GError *init_error; char *user_agent; @@ -409,6 +411,11 @@ update_cursor (BaconVideoWidget *bvw) window = gtk_widget_get_window (GTK_WIDGET (bvw)); + if (!gtk_window_is_active (bvw->parent_toplevel)) { + gdk_window_set_cursor (window, NULL); + return; + } + if (bvw->hovering_menu) gdk_window_set_cursor (window, bvw->hand_cursor); else if (bvw->cursor_shown) @@ -431,6 +438,10 @@ bacon_video_widget_realize (GtkWidget * widget) bvw->hand_cursor = gdk_cursor_new_for_display (display, GDK_HAND2); bvw->blank_cursor = gdk_cursor_new_for_display (display, GDK_BLANK_CURSOR); + bvw->parent_toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (bvw))); + g_signal_connect_swapped (G_OBJECT (bvw->parent_toplevel), "notify::is-active", + G_CALLBACK (update_cursor), bvw); + bvw->missing_plugins_cancellable = g_cancellable_new (); g_object_set_data_full (G_OBJECT (bvw), "missing-plugins-cancellable", bvw->missing_plugins_cancellable, g_object_unref); @@ -444,6 +455,10 @@ bacon_video_widget_unrealize (GtkWidget *widget) GTK_WIDGET_CLASS (parent_class)->unrealize (widget); + if (bvw->parent_toplevel != NULL) { + g_signal_handlers_disconnect_by_func (bvw->parent_toplevel, update_cursor, bvw); + bvw->parent_toplevel = NULL; + } g_clear_object (&bvw->blank_cursor); g_clear_object (&bvw->hand_cursor); -- GitLab From f8c275ead72f4492e214ce3c8a82c1926fc6ffb5 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Sun, 20 Feb 2022 13:19:02 +0100 Subject: [PATCH 3/3] backend: Simplify code that uses the toplevel window We're already keeping track of it for the cursor, might as well use it in the rest of the code. --- src/backend/bacon-video-widget.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/backend/bacon-video-widget.c b/src/backend/bacon-video-widget.c index 00a5de80e..296aae16f 100644 --- a/src/backend/bacon-video-widget.c +++ b/src/backend/bacon-video-widget.c @@ -1163,7 +1163,6 @@ bvw_handle_element_message (BaconVideoWidget *bvw, GstMessage *msg) const GValue *val; GFile *file; GMountOperation *mount_op; - GtkWidget *toplevel; GstState target_state; const char *uri; @@ -1178,10 +1177,6 @@ bvw_handle_element_message (BaconVideoWidget *bvw, GstMessage *msg) GST_DEBUG ("Trying to mount location '%s'", GST_STR_NULL (uri)); - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (bvw)); - if (toplevel == GTK_WIDGET (bvw) || !GTK_IS_WINDOW (toplevel)) - toplevel = NULL; - val = gst_structure_get_value (structure, "file"); if (val == NULL) goto done; @@ -1195,7 +1190,7 @@ bvw_handle_element_message (BaconVideoWidget *bvw, GstMessage *msg) bacon_video_widget_stop (bvw); bvw->target_state = target_state; - mount_op = gtk_mount_operation_new (toplevel ? GTK_WINDOW (toplevel) : NULL); + mount_op = gtk_mount_operation_new (bvw->parent_toplevel); bvw->mount_in_progress = TRUE; bvw->mount_cancellable = g_cancellable_new (); g_file_mount_enclosing_volume (file, G_MOUNT_MOUNT_NONE, @@ -1424,7 +1419,6 @@ done: static gboolean bvw_check_missing_auth (BaconVideoWidget * bvw, GstMessage * err_msg) { - GtkWidget *toplevel; GMountOperationClass *klass; int code; @@ -1455,8 +1449,7 @@ bvw_check_missing_auth (BaconVideoWidget * bvw, GstMessage * err_msg) GST_DEBUG ("Trying to get auth for location '%s'", GST_STR_NULL (bvw->mrl)); if (bvw->auth_dialog == NULL) { - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (bvw)); - bvw->auth_dialog = gtk_mount_operation_new (GTK_WINDOW (toplevel)); + bvw->auth_dialog = gtk_mount_operation_new (bvw->parent_toplevel); g_signal_connect (G_OBJECT (bvw->auth_dialog), "reply", G_CALLBACK (bvw_auth_reply_cb), bvw); } -- GitLab