From 33feb181da5a7cbe067a48d8583d841c6017c55b Mon Sep 17 00:00:00 2001 From: Eric Koegel Date: Tue, 8 Oct 2013 07:56:33 +0300 Subject: [PATCH] Right click issues persist (Bug 9323) This patch changes the desktop menu popups to button release instead of button press which should fix issues where unintended items were selected and executed. Additonally we switch to using gtk_grab_add. --- common/xfdesktop-common.c | 81 ----------------------------- common/xfdesktop-common.h | 3 -- src/xfce-desktop.c | 130 ++++++++++++++++++++++------------------------ src/xfdesktop-icon-view.c | 12 +++-- 4 files changed, 71 insertions(+), 155 deletions(-) diff --git a/common/xfdesktop-common.c b/common/xfdesktop-common.c index 65f0214..d0f4c65 100644 --- a/common/xfdesktop-common.c +++ b/common/xfdesktop-common.c @@ -300,84 +300,3 @@ xfdesktop_send_client_message(Window xid, const gchar *msg) gtk_widget_destroy(win); } - -guint -xfce_grab_cursor(GtkWidget *w, - GdkEventButton *evt) -{ - GdkCursor *cursor; - GdkGrabStatus status; - GdkDisplay *display; - - TRACE("entering"); - - /* create a cursor */ - display = gdk_screen_get_display(gtk_widget_get_screen(w)); - cursor = gdk_cursor_new_for_display(display, GDK_FLEUR); - - /* grab the pointer for the desktop */ - status = gdk_pointer_grab(evt->window, FALSE, - GDK_BUTTON_MOTION_MASK - | GDK_BUTTON_RELEASE_MASK, - NULL, cursor, evt->time); - - gdk_cursor_unref(cursor); - - if(status != GDK_GRAB_SUCCESS) { - g_warning("mouse grab failed."); - return 0; - } - - return evt->time; -} - -/* Code taken from xfwm4/src/menu.c:grab_available(). This should fix the case - * where binding 'xfdesktop -menu' to a keyboard shortcut sometimes works and - * sometimes doesn't. Credit for this one goes to Olivier. - */ -gboolean -xfdesktop_popup_grab_available (GdkWindow *win, guint32 timestamp) -{ - GdkEventMask mask = - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | - GDK_POINTER_MOTION_MASK; - GdkGrabStatus g1; - GdkGrabStatus g2; - gboolean grab_failed = FALSE; - gint i = 0; - - TRACE ("entering grab_available"); - - g1 = gdk_pointer_grab (win, TRUE, mask, NULL, NULL, timestamp); - g2 = gdk_keyboard_grab (win, TRUE, timestamp); - - while ((i++ < 2500) && (grab_failed = ((g1 != GDK_GRAB_SUCCESS) - || (g2 != GDK_GRAB_SUCCESS)))) - { - TRACE ("grab not available yet, mouse reason: %d, keyboard reason: %d, waiting... (%i)", g1, g2, i); - if(g1 == GDK_GRAB_INVALID_TIME || g2 == GDK_GRAB_INVALID_TIME) - break; - - g_usleep (100); - if (g1 != GDK_GRAB_SUCCESS) - { - g1 = gdk_pointer_grab (win, TRUE, mask, NULL, NULL, timestamp); - } - if (g2 != GDK_GRAB_SUCCESS) - { - g2 = gdk_keyboard_grab (win, TRUE, timestamp); - } - } - - if (g1 == GDK_GRAB_SUCCESS) - { - gdk_pointer_ungrab (timestamp); - } - if (g2 == GDK_GRAB_SUCCESS) - { - gdk_keyboard_ungrab (timestamp); - } - - return (!grab_failed); -} diff --git a/common/xfdesktop-common.h b/common/xfdesktop-common.h index 1d6db85..e462c77 100644 --- a/common/xfdesktop-common.h +++ b/common/xfdesktop-common.h @@ -86,9 +86,6 @@ gchar *xfdesktop_get_file_mimetype(const gchar *file); gboolean xfdesktop_check_is_running(Window *xid); void xfdesktop_send_client_message(Window xid, const gchar *msg); -guint xfce_grab_cursor(GtkWidget *w, GdkEventButton *evt); -gboolean xfdesktop_popup_grab_available(GdkWindow *win, guint32 timestamp); - G_END_DECLS #endif diff --git a/src/xfce-desktop.c b/src/xfce-desktop.c index aeebd57..9d0c409 100644 --- a/src/xfce-desktop.c +++ b/src/xfce-desktop.c @@ -848,7 +848,8 @@ xfce_desktop_init(XfceDesktop *desktop) XfceDesktopPriv); gtk_window_set_type_hint(GTK_WINDOW(desktop), GDK_WINDOW_TYPE_HINT_DESKTOP); - gtk_window_set_accept_focus(GTK_WINDOW(desktop), FALSE); + gtk_window_set_accept_focus(GTK_WINDOW(desktop), TRUE); + gtk_widget_set_can_focus(GTK_WIDGET(desktop), TRUE); gtk_window_set_resizable(GTK_WINDOW(desktop), FALSE); } @@ -1111,21 +1112,6 @@ xfce_desktop_unrealize(GtkWidget *widget) gtk_widget_set_realized(widget, FALSE); } -static void -xfce_desktop_release_grab(GtkWidget *w) -{ - XfceDesktop *desktop = XFCE_DESKTOP(w); - GdkDisplay *display; - - g_return_if_fail(XFCE_IS_DESKTOP(w)); - - if(desktop->priv->grab_time != 0) { - display = gdk_screen_get_display(desktop->priv->gscreen); - gdk_display_pointer_ungrab(display, desktop->priv->grab_time); - desktop->priv->grab_time = 0; - } -} - static gboolean xfce_desktop_button_press_event(GtkWidget *w, GdkEventButton *evt) @@ -1134,35 +1120,29 @@ xfce_desktop_button_press_event(GtkWidget *w, guint state = evt->state; XfceDesktop *desktop = XFCE_DESKTOP(w); + TRACE("entering"); + g_return_val_if_fail(XFCE_IS_DESKTOP(w), FALSE); if(evt->type == GDK_BUTTON_PRESS) { if(button == 3 || (button == 1 && (state & GDK_SHIFT_MASK))) { #ifdef ENABLE_DESKTOP_ICONS + /* Let the icon view handle these menu pop ups */ if(desktop->priv->icons_style != XFCE_DESKTOP_ICON_STYLE_NONE) return FALSE; #endif - if(desktop->priv->grab_time == 0) - desktop->priv->grab_time = xfce_grab_cursor(w, evt); - else - return FALSE; - - if(desktop->priv->grab_time != 0) { - xfce_desktop_popup_root_menu(desktop, button, - desktop->priv->grab_time); + /* no icons on the desktop, grab the focus */ + if(!gtk_widget_has_grab(w)) { + gtk_grab_add(w); return TRUE; } + } else if(button == 2 || (button == 1 && (state & GDK_SHIFT_MASK) && (state & GDK_CONTROL_MASK))) { - if(desktop->priv->grab_time == 0) - desktop->priv->grab_time = xfce_grab_cursor(w, evt); - else - return FALSE; - - if(desktop->priv->grab_time != 0) { - xfce_desktop_popup_secondary_root_menu(desktop, button, - desktop->priv->grab_time); + /* always grab the focus */ + if(!gtk_widget_has_grab(w)) { + gtk_grab_add(w); return TRUE; } } @@ -1175,17 +1155,46 @@ static gboolean xfce_desktop_button_release_event(GtkWidget *w, GdkEventButton *evt) { - xfce_desktop_release_grab(w); + guint button = evt->button; + guint state = evt->state; + XfceDesktop *desktop = XFCE_DESKTOP(w); - return TRUE; + TRACE("entering"); + + if(button == 3 || (button == 1 && (state & GDK_SHIFT_MASK))) + { +#ifdef ENABLE_DESKTOP_ICONS + /* Let the icon view handle these menu pop ups */ + if(desktop->priv->icons_style != XFCE_DESKTOP_ICON_STYLE_NONE) + return FALSE; +#endif + + xfce_desktop_popup_root_menu(desktop, button, evt->time); + gtk_grab_remove(w); + return TRUE; + } else if(button == 2 || (button == 1 && (state & GDK_SHIFT_MASK) + && (state & GDK_CONTROL_MASK))) + { + xfce_desktop_popup_secondary_root_menu(desktop, button, evt->time); + gtk_grab_remove(w); + return TRUE; + } + + gtk_grab_remove(w); + + return FALSE; } +/* This function gets called when the user presses the menu key on the keyboard. + * Or Shift+F10 or whatever key binding the user has chosen. */ static gboolean xfce_desktop_popup_menu(GtkWidget *w) { GdkEventButton *evt; guint button, etime; - + + TRACE("entering"); + evt = (GdkEventButton *)gtk_get_current_event(); if(evt && GDK_BUTTON_PRESS == evt->type) { button = evt->button; @@ -1586,11 +1595,14 @@ xfce_desktop_do_menu_popup(XfceDesktop *desktop, gtk_menu_attach_to_widget(GTK_MENU(menu), GTK_WIDGET(desktop), NULL); + /* Per gtk_menu_popup's documentation "for conflict-resolve initiation of + * concurrent requests for mouse/keyboard grab requests." */ + if(activate_time == 0) + activate_time = gtk_get_current_event_time(); + /* bug #3652: for some reason passing the correct button here breaks * on some systems but not others. always pass 0 for now. */ gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, activate_time); - - xfce_desktop_release_grab(GTK_WIDGET(desktop)); } void @@ -1598,24 +1610,16 @@ xfce_desktop_popup_root_menu(XfceDesktop *desktop, guint button, guint activate_time) { - GdkScreen *screen; - - if(gtk_widget_has_screen(GTK_WIDGET(desktop))) - screen = gtk_widget_get_screen(GTK_WIDGET(desktop)); - else - screen = gdk_display_get_default_screen(gdk_display_get_default()); - - if(activate_time == 0) { - activate_time = GDK_CURRENT_TIME; - if(!xfdesktop_popup_grab_available(gdk_screen_get_root_window(screen), - activate_time)) { - g_critical("keyboard or mouse grab failed."); - return; - } - } + /* If it's launched by xfdesktop --menu we won't have an event time. + * Just grab the focus so the menu can pop up */ + if(activate_time == 0) + gtk_grab_add(GTK_WIDGET(desktop)); xfce_desktop_do_menu_popup(desktop, button, activate_time, signals[SIG_POPULATE_ROOT_MENU]); + + if(activate_time == 0) + gtk_grab_remove(GTK_WIDGET(desktop)); } void @@ -1623,24 +1627,16 @@ xfce_desktop_popup_secondary_root_menu(XfceDesktop *desktop, guint button, guint activate_time) { - GdkScreen *screen; - - if(gtk_widget_has_screen(GTK_WIDGET(desktop))) - screen = gtk_widget_get_screen(GTK_WIDGET(desktop)); - else - screen = gdk_display_get_default_screen(gdk_display_get_default()); - - if(activate_time == 0) { - activate_time = GDK_CURRENT_TIME; - if(!xfdesktop_popup_grab_available(gdk_screen_get_root_window(screen), - activate_time)) { - g_critical("keyboard or mouse grab failed."); - return; - } - } + /* If it's launched by xfdesktop --windowlist we won't have an event time. + * Just grab the focus so the menu can pop up */ + if(activate_time == 0) + gtk_grab_add(GTK_WIDGET(desktop)); xfce_desktop_do_menu_popup(desktop, button, activate_time, signals[SIG_POPULATE_SECONDARY_ROOT_MENU]); + + if(activate_time == 0) + gtk_grab_remove(GTK_WIDGET(desktop)); } void xfce_desktop_refresh(XfceDesktop *desktop) diff --git a/src/xfdesktop-icon-view.c b/src/xfdesktop-icon-view.c index 2290884..388aca7 100644 --- a/src/xfdesktop-icon-view.c +++ b/src/xfdesktop-icon-view.c @@ -686,6 +686,7 @@ xfdesktop_icon_view_init(XfdesktopIconView *icon_view) G_CALLBACK(xfdesktop_icon_view_show_tooltip), NULL); gtk_widget_set_has_window(GTK_WIDGET(icon_view), FALSE); + gtk_widget_set_can_focus(GTK_WIDGET(icon_view), TRUE); } static void @@ -792,7 +793,10 @@ xfdesktop_icon_view_button_press(GtkWidget *widget, if(evt->type == GDK_BUTTON_PRESS) { GList *icon_l; - + + if(!gtk_widget_has_grab(widget)) + gtk_grab_add(widget); + icon_l = g_list_find_custom(icon_view->priv->icons, evt, (GCompareFunc)xfdesktop_check_icon_clicked); if(icon_l && (icon = icon_l->data)) { @@ -939,14 +943,15 @@ xfdesktop_icon_view_button_release(GtkWidget *widget, icon_view->priv->maybe_begin_drag = FALSE; if(icon_view->priv->definitely_rubber_banding) { icon_view->priv->definitely_rubber_banding = FALSE; - gtk_grab_remove(widget); gtk_widget_queue_draw_area(widget, icon_view->priv->band_rect.x, icon_view->priv->band_rect.y, icon_view->priv->band_rect.width, icon_view->priv->band_rect.height); } } - + + gtk_grab_remove(widget); + return FALSE; } @@ -1114,7 +1119,6 @@ xfdesktop_icon_view_motion_notify(GtkWidget *widget, old_rect.x = icon_view->priv->press_start_x; old_rect.y = icon_view->priv->press_start_y; old_rect.width = old_rect.height = 1; - gtk_grab_add(widget); } else memcpy(&old_rect, new_rect, sizeof(old_rect)); -- 1.8.3.2