From 307c97541c4b4ecec09c08950c4132406d2d4cdb Mon Sep 17 00:00:00 2001 From: Theo Linkspfeifer Date: Sun, 12 May 2019 12:41:17 +0200 Subject: [PATCH 1/2] Fix queued context menu popup --- thunar/thunar-abstract-icon-view.c | 4 ++-- thunar/thunar-chooser-dialog.c | 2 +- thunar/thunar-details-view.c | 6 +++--- thunar/thunar-dnd.c | 2 +- thunar/thunar-gtk-extensions.c | 27 ++++++++++++++++++++------- thunar/thunar-gtk-extensions.h | 3 ++- thunar/thunar-history-action.c | 2 +- thunar/thunar-location-buttons.c | 2 +- thunar/thunar-renamer-dialog.c | 2 +- thunar/thunar-shortcuts-view.c | 4 ++-- thunar/thunar-standard-view.c | 16 ++++++++++++---- thunar/thunar-standard-view.h | 3 ++- thunar/thunar-tree-view.c | 2 +- thunar/thunar-window.c | 2 +- 14 files changed, 50 insertions(+), 27 deletions(-) diff --git a/thunar/thunar-abstract-icon-view.c b/thunar/thunar-abstract-icon-view.c index 91ee300a..fd26f831 100644 --- a/thunar/thunar-abstract-icon-view.c +++ b/thunar/thunar-abstract-icon-view.c @@ -518,7 +518,7 @@ thunar_abstract_icon_view_button_press_event (ExoIconView *view, exo_icon_view_unselect_all (view); /* open the context menu */ - thunar_standard_view_context_menu (THUNAR_STANDARD_VIEW (abstract_icon_view)); + thunar_standard_view_context_menu (THUNAR_STANDARD_VIEW (abstract_icon_view), NULL); } return TRUE; @@ -694,7 +694,7 @@ thunar_abstract_icon_view_key_press_event (ExoIconView *view, /* popup context menu if "Menu" or "F10" is pressed */ if (event->keyval == GDK_KEY_Menu || ((event->state & GDK_SHIFT_MASK) != 0 && event->keyval == GDK_KEY_F10)) { - thunar_standard_view_context_menu (THUNAR_STANDARD_VIEW (abstract_icon_view)); + thunar_standard_view_context_menu (THUNAR_STANDARD_VIEW (abstract_icon_view), NULL); return TRUE; } diff --git a/thunar/thunar-chooser-dialog.c b/thunar/thunar-chooser-dialog.c index cc5ff7d5..a5e642b6 100644 --- a/thunar/thunar-chooser-dialog.c +++ b/thunar/thunar-chooser-dialog.c @@ -567,7 +567,7 @@ thunar_chooser_dialog_context_menu (ThunarChooserDialog *dialog) gtk_widget_show (item); /* run the menu (takes over the floating of menu) */ - thunar_gtk_menu_run (GTK_MENU (menu)); + thunar_gtk_menu_run (GTK_MENU (menu), NULL); /* clean up */ g_object_unref (app_info); diff --git a/thunar/thunar-details-view.c b/thunar/thunar-details-view.c index 5dabad6e..e1a18836 100644 --- a/thunar/thunar-details-view.c +++ b/thunar/thunar-details-view.c @@ -730,7 +730,7 @@ thunar_details_view_button_press_event (GtkTreeView *tree_view, if (path == NULL) { /* open the context menu */ - thunar_standard_view_context_menu (THUNAR_STANDARD_VIEW (details_view)); + thunar_standard_view_context_menu (THUNAR_STANDARD_VIEW (details_view), NULL); } else { @@ -753,7 +753,7 @@ thunar_details_view_button_press_event (GtkTreeView *tree_view, } /* show the context menu */ - thunar_standard_view_context_menu (THUNAR_STANDARD_VIEW (details_view)); + thunar_standard_view_context_menu (THUNAR_STANDARD_VIEW (details_view), NULL); } gtk_tree_path_free (path); } @@ -817,7 +817,7 @@ thunar_details_view_key_press_event (GtkTreeView *tree_view, /* popup context menu if "Menu" or "F10" is pressed */ if (event->keyval == GDK_KEY_Menu || ((event->state & GDK_SHIFT_MASK) != 0 && event->keyval == GDK_KEY_F10)) { - thunar_standard_view_context_menu (THUNAR_STANDARD_VIEW (details_view)); + thunar_standard_view_context_menu (THUNAR_STANDARD_VIEW (details_view), NULL); return TRUE; } diff --git a/thunar/thunar-dnd.c b/thunar/thunar-dnd.c index fdb54ef4..b74d330a 100644 --- a/thunar/thunar-dnd.c +++ b/thunar/thunar-dnd.c @@ -171,7 +171,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS gtk_widget_show (item); /* run the menu (takes over the floating of menu) */ - thunar_gtk_menu_run (GTK_MENU (menu)); + thunar_gtk_menu_run (GTK_MENU (menu), NULL); /* cleanup */ g_object_unref (G_OBJECT (factory)); diff --git a/thunar/thunar-gtk-extensions.c b/thunar/thunar-gtk-extensions.c index 4852c118..31b61968 100644 --- a/thunar/thunar-gtk-extensions.c +++ b/thunar/thunar-gtk-extensions.c @@ -129,29 +129,42 @@ thunar_gtk_label_set_a11y_relation (GtkLabel *label, /** * thunar_gtk_menu_run: - * @menu : a #GtkMenu. + * @menu : a #GtkMenu. + * @event : a #GdkEvent which may be NULL if no previous event was stored. * - * A simple wrapper around gtk_menu_popup_at_pointer(), which takes care on the - * menu and returns only after the @menu was deactivated. + * A simple wrapper around gtk_menu_popup_at_pointer(), which runs the @menu in a separate + * main loop and returns only after the @menu was deactivated. * * This method automatically takes over the floating reference of @menu if any and * releases it on return. That means if you created the menu via gtk_menu_new() you'll * not need to take care of destroying the menu later. **/ void -thunar_gtk_menu_run (GtkMenu *menu) +thunar_gtk_menu_run (GtkMenu *menu, GdkEvent *event) { - GdkEvent *event; + GMainLoop *loop; + gulong signal_id; _thunar_return_if_fail (GTK_IS_MENU (menu)); /* take over the floating reference on the menu */ g_object_ref_sink (G_OBJECT (menu)); - event = gtk_get_current_event (); + /* run an internal main loop */ + loop = g_main_loop_new (NULL, FALSE); + signal_id = g_signal_connect_swapped (G_OBJECT (menu), "deactivate", G_CALLBACK (g_main_loop_quit), loop); + /* get the current event if none was passed */ + if (G_LIKELY (event == NULL)) + event = gtk_get_current_event (); gtk_menu_popup_at_pointer (menu, event); - gdk_event_free (event); gtk_menu_reposition (menu); + gdk_event_free (event); + gtk_grab_add (GTK_WIDGET (menu)); + g_main_loop_run (loop); + g_main_loop_unref (loop); + gtk_grab_remove (GTK_WIDGET (menu)); + + g_signal_handler_disconnect (G_OBJECT (menu), signal_id); /* release the menu reference */ g_object_unref (G_OBJECT (menu)); diff --git a/thunar/thunar-gtk-extensions.h b/thunar/thunar-gtk-extensions.h index a264595c..4ba2a707 100644 --- a/thunar/thunar-gtk-extensions.h +++ b/thunar/thunar-gtk-extensions.h @@ -35,7 +35,8 @@ void thunar_gtk_action_group_set_action_sensitive (GtkActionGroup void thunar_gtk_label_set_a11y_relation (GtkLabel *label, GtkWidget *widget); -void thunar_gtk_menu_run (GtkMenu *menu); +void thunar_gtk_menu_run (GtkMenu *menu, + GdkEvent *event); GtkAction *thunar_gtk_ui_manager_get_action_by_name (GtkUIManager *ui_manager, const gchar *action_name); diff --git a/thunar/thunar-history-action.c b/thunar/thunar-history-action.c index 5f2baab5..3c1c355f 100644 --- a/thunar/thunar-history-action.c +++ b/thunar/thunar-history-action.c @@ -319,7 +319,7 @@ thunar_history_action_show_menu (GtkWidget *toggle_button, gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle_button), TRUE); /* run the menu (takes over the floating of menu) */ - thunar_gtk_menu_run (GTK_MENU (menu)); + thunar_gtk_menu_run (GTK_MENU (menu), NULL); } diff --git a/thunar/thunar-location-buttons.c b/thunar/thunar-location-buttons.c index 872e4568..1c8c7b84 100644 --- a/thunar/thunar-location-buttons.c +++ b/thunar/thunar-location-buttons.c @@ -1308,7 +1308,7 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS G_GNUC_END_IGNORE_DEPRECATIONS /* run the menu (takes over the floating of menu) */ - thunar_gtk_menu_run (GTK_MENU (menu)); + thunar_gtk_menu_run (GTK_MENU (menu), NULL); /* cleanup */ g_object_unref (buttons); diff --git a/thunar/thunar-renamer-dialog.c b/thunar/thunar-renamer-dialog.c index 88ff90e8..a18a34da 100644 --- a/thunar/thunar-renamer-dialog.c +++ b/thunar/thunar-renamer-dialog.c @@ -885,7 +885,7 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS /* run the menu (takes over the floating of menu) */ menu = gtk_ui_manager_get_widget (renamer_dialog->ui_manager, "/file-context-menu"); - thunar_gtk_menu_run (GTK_MENU (menu)); + thunar_gtk_menu_run (GTK_MENU (menu), NULL); /* remove the previously merge items from the UI manager */ if (G_UNLIKELY (renamer_merge_id != 0)) diff --git a/thunar/thunar-shortcuts-view.c b/thunar/thunar-shortcuts-view.c index 5faabf94..a2d8fb4b 100644 --- a/thunar/thunar-shortcuts-view.c +++ b/thunar/thunar-shortcuts-view.c @@ -1041,7 +1041,7 @@ thunar_shortcuts_view_context_menu_visibility (ThunarShortcutsView *view, gtk_tree_path_free (path); /* run the menu (taking over the floating reference on menu) */ - thunar_gtk_menu_run (GTK_MENU (menu)); + thunar_gtk_menu_run (GTK_MENU (menu), NULL); } @@ -1317,7 +1317,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS gtk_tree_path_free (path); /* run the menu (taking over the floating reference on menu) */ - thunar_gtk_menu_run (GTK_MENU (menu)); + thunar_gtk_menu_run (GTK_MENU (menu), NULL); } diff --git a/thunar/thunar-standard-view.c b/thunar/thunar-standard-view.c index af514ddd..a4572471 100644 --- a/thunar/thunar-standard-view.c +++ b/thunar/thunar-standard-view.c @@ -346,6 +346,7 @@ struct _ThunarStandardViewPrivate GList *drag_g_file_list; guint drag_scroll_timer_id; guint drag_timer_id; + GdkEvent *drag_timer_event; gint drag_x; gint drag_y; @@ -859,6 +860,10 @@ thunar_standard_view_dispose (GObject *object) if (G_UNLIKELY (standard_view->priv->drag_timer_id != 0)) g_source_remove (standard_view->priv->drag_timer_id); + /* be sure to free any pending drag timer event */ + if (G_UNLIKELY (standard_view->priv->drag_timer_event != NULL)) + gdk_event_free (standard_view->priv->drag_timer_event); + /* reset the UI manager property */ thunar_component_set_ui_manager (THUNAR_COMPONENT (standard_view), NULL); @@ -3086,7 +3091,7 @@ thunar_standard_view_button_release_event (GtkWidget *view, g_source_remove (standard_view->priv->drag_timer_id); /* fire up the context menu */ - thunar_standard_view_context_menu (standard_view); + thunar_standard_view_context_menu (standard_view, NULL); return TRUE; } @@ -3106,6 +3111,7 @@ thunar_standard_view_motion_notify_event (GtkWidget *view, { /* cancel the drag timer, as we won't popup the menu anymore */ g_source_remove (standard_view->priv->drag_timer_id); + gdk_event_free (standard_view->priv->drag_timer_event); /* FIXME * - according to doc, the GdkWindow associated to the widget needs to enable the GDK_POINTER_MOTION_MASK mask to use this event. @@ -4053,7 +4059,7 @@ thunar_standard_view_drag_timer (gpointer user_data) /* fire up the context menu */ THUNAR_THREADS_ENTER - thunar_standard_view_context_menu (standard_view); + thunar_standard_view_context_menu (standard_view, standard_view->priv->drag_timer_event); THUNAR_THREADS_LEAVE return FALSE; @@ -4341,7 +4347,7 @@ thunar_standard_view_size_allocate (ThunarStandardView *standard_view, * using one of the context menu shortcuts. **/ void -thunar_standard_view_context_menu (ThunarStandardView *standard_view) +thunar_standard_view_context_menu (ThunarStandardView *standard_view, GdkEvent *event) { GtkWidget *menu; GList *selected_items; @@ -4359,7 +4365,7 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS /* run the menu (figuring out whether to use the file or the folder context menu) */ menu = gtk_ui_manager_get_widget (standard_view->ui_manager, (selected_items != NULL) ? "/file-context-menu" : "/folder-context-menu"); G_GNUC_END_IGNORE_DEPRECATIONS - thunar_gtk_menu_run (GTK_MENU (menu)); + thunar_gtk_menu_run (GTK_MENU (menu), event); g_list_free_full (selected_items, (GDestroyNotify) gtk_tree_path_free); @@ -4414,6 +4420,8 @@ thunar_standard_view_queue_popup (ThunarStandardView *standard_view, /* schedule the timer */ standard_view->priv->drag_timer_id = g_timeout_add_full (G_PRIORITY_LOW, MAX (225, delay), thunar_standard_view_drag_timer, standard_view, thunar_standard_view_drag_timer_destroy); + /* store current event data */ + standard_view->priv->drag_timer_event = gtk_get_current_event (); /* register the motion notify and the button release events on the real view */ g_signal_connect (G_OBJECT (view), "button-release-event", G_CALLBACK (thunar_standard_view_button_release_event), standard_view); diff --git a/thunar/thunar-standard-view.h b/thunar/thunar-standard-view.h index f8513685..b929e106 100644 --- a/thunar/thunar-standard-view.h +++ b/thunar/thunar-standard-view.h @@ -144,7 +144,8 @@ struct _ThunarStandardView GType thunar_standard_view_get_type (void) G_GNUC_CONST; -void thunar_standard_view_context_menu (ThunarStandardView *standard_view); +void thunar_standard_view_context_menu (ThunarStandardView *standard_view, + GdkEvent *event); void thunar_standard_view_queue_popup (ThunarStandardView *standard_view, GdkEventButton *event); diff --git a/thunar/thunar-tree-view.c b/thunar/thunar-tree-view.c index 9752138a..2c9c08b0 100644 --- a/thunar/thunar-tree-view.c +++ b/thunar/thunar-tree-view.c @@ -1588,7 +1588,7 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS G_GNUC_END_IGNORE_DEPRECATIONS /* run the menu (taking over the floating reference on the menu) */ - thunar_gtk_menu_run (GTK_MENU (menu)); + thunar_gtk_menu_run (GTK_MENU (menu), NULL); /* cleanup */ if (G_UNLIKELY (device != NULL)) diff --git a/thunar/thunar-window.c b/thunar/thunar-window.c index df24b900..893a1202 100644 --- a/thunar/thunar-window.c +++ b/thunar/thunar-window.c @@ -1683,7 +1683,7 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS /* run the menu (figuring out whether to use the file or the folder context menu) */ menu = gtk_ui_manager_get_widget (window->ui_manager, "/tab-context-menu"); G_GNUC_END_IGNORE_DEPRECATIONS - thunar_gtk_menu_run (GTK_MENU (menu)); + thunar_gtk_menu_run (GTK_MENU (menu), NULL); } -- 2.20.1