[Xfce4-commits] <xfdesktop:master> Right click issues persist (Bug 9323)

Eric Koegel noreply at xfce.org
Mon Oct 14 19:06:01 CEST 2013


Updating branch refs/heads/master
         to c102646246a09f93431c37499b40f9e49ae1b783 (commit)
       from af240b063cd0678dc1739ffa28e93f1ff530bead (commit)

commit c102646246a09f93431c37499b40f9e49ae1b783
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Tue Oct 8 14:56:35 2013 +0300

    Right click issues persist (Bug 9323)
    
    This patch uses the gtk_grab_add/remove functions to handle grabs
    prior to a menu popup. Additionally, the menu will pop up on the
    button press event if there's no conflict (i.e. right click DND).

 common/xfdesktop-common.c |   81 ----------------------------------
 common/xfdesktop-common.h |    3 --
 src/xfce-desktop.c        |  108 +++++++++++++++++----------------------------
 src/xfdesktop-icon-view.c |   59 ++++++++++++++++++++-----
 4 files changed, 90 insertions(+), 161 deletions(-)

diff --git a/common/xfdesktop-common.c b/common/xfdesktop-common.c
index b2fb406..6d5546d 100644
--- a/common/xfdesktop-common.c
+++ b/common/xfdesktop-common.c
@@ -315,84 +315,3 @@ xfce_translate_image_styles(gint input)
 
     return style;
 }
-
-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 725da4f..4dcec73 100644
--- a/common/xfdesktop-common.h
+++ b/common/xfdesktop-common.h
@@ -88,9 +88,6 @@ void xfdesktop_send_client_message(Window xid, const gchar *msg);
 
 gint xfce_translate_image_styles(gint input);
 
-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 4bd7040..3ac5297 100644
--- a/src/xfce-desktop.c
+++ b/src/xfce-desktop.c
@@ -853,6 +853,7 @@ xfce_desktop_init(XfceDesktop *desktop)
     
     gtk_window_set_type_hint(GTK_WINDOW(desktop), GDK_WINDOW_TYPE_HINT_DESKTOP);
     gtk_window_set_accept_focus(GTK_WINDOW(desktop), FALSE);
+    gtk_widget_set_can_focus(GTK_WIDGET(desktop), TRUE);
     gtk_window_set_resizable(GTK_WINDOW(desktop), FALSE);
 }
 
@@ -1112,21 +1113,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)
@@ -1135,37 +1121,32 @@ 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;
+            /* no icons on the desktop, grab the focus and pop up the menu */
+            if(!gtk_widget_has_grab(w))
+                gtk_grab_add(w);
 
-            if(desktop->priv->grab_time != 0) {
-                xfce_desktop_popup_root_menu(desktop, button,
-                                             desktop->priv->grab_time);
+                xfce_desktop_popup_root_menu(desktop, button, evt->time);
                 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;
+            /* always grab the focus and pop up the menu */
+            if(!gtk_widget_has_grab(w))
+                gtk_grab_add(w);
 
-            if(desktop->priv->grab_time != 0) {
-                xfce_desktop_popup_secondary_root_menu(desktop, button,
-                                                       desktop->priv->grab_time);
-                return TRUE;
-            }
+            xfce_desktop_popup_secondary_root_menu(desktop, button, evt->time);
+            return TRUE;
         }
     }
     
@@ -1176,17 +1157,23 @@ static gboolean
 xfce_desktop_button_release_event(GtkWidget *w,
                                   GdkEventButton *evt)
 {
-    xfce_desktop_release_grab(w);
+    TRACE("entering");
 
-    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;
@@ -1589,11 +1576,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
@@ -1601,24 +1591,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
@@ -1626,24 +1608,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..817db45 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
@@ -789,10 +790,25 @@ xfdesktop_icon_view_button_press(GtkWidget *widget,
 {
     XfdesktopIconView *icon_view = XFDESKTOP_ICON_VIEW(user_data);
     XfdesktopIcon *icon;
-    
+
+    TRACE("entering");
+
     if(evt->type == GDK_BUTTON_PRESS) {
         GList *icon_l;
-        
+
+        /* Let xfce-desktop handle button 2 */
+        if(evt->button == 2) {
+            /* If we had the grab release it so the desktop gets the event */
+            if(gtk_widget_has_grab(widget))
+                gtk_grab_remove(widget);
+
+            return FALSE;
+        }
+
+        /* Grab the focus, release on button release */
+        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)) {
@@ -848,6 +864,7 @@ xfdesktop_icon_view_button_press(GtkWidget *widget,
             
             return TRUE;
         } else {
+            /* Button press wasn't over any icons */
             /* unselect previously selected icons if we didn't click one */
             if(icon_view->priv->sel_mode != GTK_SELECTION_MULTIPLE
                || !(evt->state & GDK_CONTROL_MASK))
@@ -864,6 +881,13 @@ xfdesktop_icon_view_button_press(GtkWidget *widget,
                 icon_view->priv->press_start_x = evt->x;
                 icon_view->priv->press_start_y = evt->y;
             }
+
+            /* Since we're not over any icons this won't be the start of a
+             * drag so we can pop up menu */
+            if(evt->button == 3 || (evt->button == 1 && (evt->state & GDK_SHIFT_MASK))) {
+                xfce_desktop_popup_root_menu(XFCE_DESKTOP(widget), evt->button, evt->time);
+                return TRUE;
+            }
         }
     } else if(evt->type == GDK_2BUTTON_PRESS) {
         /* be sure to cancel any pending drags that might have snuck through.
@@ -904,7 +928,9 @@ xfdesktop_icon_view_button_release(GtkWidget *widget,
                                    gpointer user_data)
 {
     XfdesktopIconView *icon_view = XFDESKTOP_ICON_VIEW(user_data);
-    
+    XfdesktopIcon *icon;
+    GList *icon_l = NULL;
+
     TRACE("entering btn=%d", evt->button);
 
     /* single-click */
@@ -914,10 +940,11 @@ xfdesktop_icon_view_button_release(GtkWidget *widget,
        && !(evt->state & GDK_CONTROL_MASK)
        && !icon_view->priv->definitely_dragging
        && !icon_view->priv->definitely_rubber_banding) {
-        XfdesktopIcon *icon;
-        GList *icon_l = g_list_find_custom(icon_view->priv->icons, evt,
-                                           (GCompareFunc)xfdesktop_check_icon_clicked);
+        /* Find out if we clicked on an icon */
+        icon_l = g_list_find_custom(icon_view->priv->icons, evt,
+                                    (GCompareFunc)xfdesktop_check_icon_clicked);
         if(icon_l && (icon = icon_l->data)) {
+            /* We did, activate it */
             icon_view->priv->cursor = icon;
             g_signal_emit(G_OBJECT(icon_view), __signals[SIG_ICON_ACTIVATED],
                           0, NULL);
@@ -930,7 +957,18 @@ xfdesktop_icon_view_button_release(GtkWidget *widget,
        icon_view->priv->definitely_dragging == FALSE &&
        icon_view->priv->definitely_rubber_banding == FALSE)
     {
-        xfce_desktop_popup_root_menu(XFCE_DESKTOP(widget), evt->button, evt->time);
+        /* If we're in single click mode we may already have the icon, don't
+         * find it again. */
+        if(icon_l == NULL) {
+            icon_l = g_list_find_custom(icon_view->priv->icons, evt,
+                                        (GCompareFunc)xfdesktop_check_icon_clicked);
+        }
+
+        /* If we clicked an icon then we didn't pop up the menu during the
+         * button press in order to support right click DND, pop up the menu
+         * now */
+        if(icon_l && (icon = icon_l->data))
+            xfce_desktop_popup_root_menu(XFCE_DESKTOP(widget), evt->button, evt->time);
     }
 
     if(evt->button == 1 || evt->button == 3) {
@@ -938,15 +976,17 @@ xfdesktop_icon_view_button_release(GtkWidget *widget,
         icon_view->priv->definitely_dragging = FALSE;
         icon_view->priv->maybe_begin_drag = FALSE;
         if(icon_view->priv->definitely_rubber_banding) {
+            /* Remove the rubber band selection box */
             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 +1154,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));
 


More information about the Xfce4-commits mailing list