[Xfce4-commits] <xfdesktop:master> Hold the cursor grab when presenting the menu (Bug 9323)

Eric Koegel noreply at xfce.org
Fri Aug 30 08:12:01 CEST 2013


Updating branch refs/heads/master
         to af35570486899140425227767e27385fb5b3fa70 (commit)
       from 2c960680d0261af538fa722b4d79d769a5956741 (commit)

commit af35570486899140425227767e27385fb5b3fa70
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Fri Aug 30 09:08:00 2013 +0300

    Hold the cursor grab when presenting the menu (Bug 9323)
    
    Rewrite how key press and release events are handled so that the
    right-click menu appears more consistently.

 common/xfdesktop-common.c |   30 ++++++++++
 common/xfdesktop-common.h |    2 +
 src/main.c                |    6 +-
 src/xfce-desktop.c        |  140 ++++++++++++++++++++++++++++++++++-----------
 src/xfdesktop-icon-view.c |    4 +-
 5 files changed, 141 insertions(+), 41 deletions(-)

diff --git a/common/xfdesktop-common.c b/common/xfdesktop-common.c
index 755e273..f36d9fa 100644
--- a/common/xfdesktop-common.c
+++ b/common/xfdesktop-common.c
@@ -301,6 +301,36 @@ 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.
diff --git a/common/xfdesktop-common.h b/common/xfdesktop-common.h
index b34d7b5..d95ec59 100644
--- a/common/xfdesktop-common.h
+++ b/common/xfdesktop-common.h
@@ -28,6 +28,7 @@
 
 #include <glib.h>
 #include <gdk/gdk.h>
+#include <gtk/gtk.h>
 
 #include <X11/Xlib.h>
 
@@ -84,6 +85,7 @@ 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
diff --git a/src/main.c b/src/main.c
index f8b7063..cdf5612 100644
--- a/src/main.c
+++ b/src/main.c
@@ -182,12 +182,10 @@ client_message_received(GtkWidget *w, GdkEventClient *evt, gpointer user_data)
             g_idle_add((GSourceFunc)reload_idle_cb, user_data);
             return TRUE;
         } else if(!strcmp(MENU_MESSAGE, evt->data.b)) {
-            xfce_desktop_popup_root_menu(XFCE_DESKTOP(w), 0,
-                                         GDK_CURRENT_TIME);
+            xfce_desktop_popup_root_menu(XFCE_DESKTOP(w), 0, 0);
             return TRUE;
         } else if(!strcmp(WINDOWLIST_MESSAGE, evt->data.b)) {
-            xfce_desktop_popup_secondary_root_menu(XFCE_DESKTOP(w), 0,
-                                                   GDK_CURRENT_TIME);
+            xfce_desktop_popup_secondary_root_menu(XFCE_DESKTOP(w), 0, 0);
             return TRUE;
 #ifdef ENABLE_FILE_ICONS
         } else if(!strcmp(ARRANGE_MESSAGE, evt->data.b)) {
diff --git a/src/xfce-desktop.c b/src/xfce-desktop.c
index 149a833..70a326d 100644
--- a/src/xfce-desktop.c
+++ b/src/xfce-desktop.c
@@ -106,7 +106,9 @@ struct _XfceDesktopPriv
     gint single_workspace_num;
 
     SessionLogoutFunc session_logout_func;
-    
+
+    guint32 grab_time;
+
 #ifdef ENABLE_DESKTOP_ICONS
     XfceDesktopIconStyle icons_style;
     gboolean icons_font_size_set;
@@ -152,6 +154,8 @@ static void xfce_desktop_realize(GtkWidget *widget);
 static void xfce_desktop_unrealize(GtkWidget *widget);
 static gboolean xfce_desktop_button_press_event(GtkWidget *widget,
                                                 GdkEventButton *evt);
+static gboolean xfce_desktop_button_release_event(GtkWidget *widget,
+                                                  GdkEventButton *evt);
 static gboolean xfce_desktop_popup_menu(GtkWidget *widget);
 
 static gboolean xfce_desktop_expose(GtkWidget *w,
@@ -723,6 +727,7 @@ xfce_desktop_class_init(XfceDesktopClass *klass)
     widget_class->realize = xfce_desktop_realize;
     widget_class->unrealize = xfce_desktop_unrealize;
     widget_class->button_press_event = xfce_desktop_button_press_event;
+    widget_class->button_release_event = xfce_desktop_button_release_event;
     widget_class->expose_event = xfce_desktop_expose;
     widget_class->delete_event = xfce_desktop_delete_event;
     widget_class->popup_menu = xfce_desktop_popup_menu;
@@ -1093,29 +1098,60 @@ 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)
 {
     guint button = evt->button;
     guint state = evt->state;
+    XfceDesktop *desktop = XFCE_DESKTOP(w);
+
     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
-            if(XFCE_DESKTOP(w)->priv->icons_style != XFCE_DESKTOP_ICON_STYLE_NONE)
+            if(desktop->priv->icons_style != XFCE_DESKTOP_ICON_STYLE_NONE)
                 return FALSE;
 #endif
-            xfce_desktop_popup_root_menu(XFCE_DESKTOP(w),
-                                         button,
-                                         evt->time);
+            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);
+                return TRUE;
+            }
         } else if(button == 2 || (button == 1 && (state & GDK_SHIFT_MASK)
                                   && (state & GDK_CONTROL_MASK)))
         {
-            xfce_desktop_popup_secondary_root_menu(XFCE_DESKTOP(w),
-                                                   button, evt->time);
-            return TRUE;
+            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);
+                return TRUE;
+            }
         }
     }
     
@@ -1123,6 +1159,15 @@ xfce_desktop_button_press_event(GtkWidget *w,
 }
 
 static gboolean
+xfce_desktop_button_release_event(GtkWidget *w,
+                                  GdkEventButton *evt)
+{
+    xfce_desktop_release_grab(w);
+
+    return TRUE;
+}
+
+static gboolean
 xfce_desktop_popup_menu(GtkWidget *w)
 {
     GdkEventButton *evt;
@@ -1510,34 +1555,30 @@ xfce_desktop_do_menu_popup(XfceDesktop *desktop,
     else
         screen = gdk_display_get_default_screen(gdk_display_get_default());
 
-    if(xfdesktop_popup_grab_available(gdk_screen_get_root_window(screen),
-                                      activate_time))
-    {
-        menu = gtk_menu_new();
-        gtk_menu_set_screen(GTK_MENU(menu), screen);
-        g_signal_connect_swapped(G_OBJECT(menu), "deactivate",
-                                 G_CALLBACK(g_idle_add),
-                                 (gpointer)xfce_desktop_menu_destroy_idled);
-
-        g_signal_emit(G_OBJECT(desktop), populate_signal, 0, menu);
-
-        /* if nobody populated the menu, don't do anything */
-        menu_children = gtk_container_get_children(GTK_CONTAINER(menu));
-        if(!menu_children) {
-            gtk_widget_destroy(menu);
-            return;
-        }
+    menu = gtk_menu_new();
+    gtk_menu_set_screen(GTK_MENU(menu), screen);
+    g_signal_connect_swapped(G_OBJECT(menu), "deactivate",
+                             G_CALLBACK(g_idle_add),
+                             (gpointer)xfce_desktop_menu_destroy_idled);
 
-        g_list_free(menu_children);
+    g_signal_emit(G_OBJECT(desktop), populate_signal, 0, menu);
 
-        gtk_menu_attach_to_widget(GTK_MENU(menu), GTK_WIDGET(desktop), NULL);
+    /* if nobody populated the menu, don't do anything */
+    menu_children = gtk_container_get_children(GTK_CONTAINER(menu));
+    if(!menu_children) {
+        gtk_widget_destroy(menu);
+        return;
+    }
+
+    g_list_free(menu_children);
+
+    gtk_menu_attach_to_widget(GTK_MENU(menu), GTK_WIDGET(desktop), NULL);
 
-        /* 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);
-    } else
-        g_critical("Unable to get keyboard/mouse grab. Unable to pop up menu");
+    /* 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
@@ -1545,6 +1586,22 @@ 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;
+        }
+    }
+
     xfce_desktop_do_menu_popup(desktop, button, activate_time,
                                signals[SIG_POPULATE_ROOT_MENU]);
 }
@@ -1554,10 +1611,25 @@ 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;
+        }
+    }
+
     xfce_desktop_do_menu_popup(desktop, button, activate_time,
                                signals[SIG_POPULATE_SECONDARY_ROOT_MENU]);
 }
-
 void
 xfce_desktop_refresh(XfceDesktop *desktop)
 {
diff --git a/src/xfdesktop-icon-view.c b/src/xfdesktop-icon-view.c
index 6a8f223..0691570 100644
--- a/src/xfdesktop-icon-view.c
+++ b/src/xfdesktop-icon-view.c
@@ -922,9 +922,7 @@ 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);
+        xfce_desktop_popup_root_menu(XFCE_DESKTOP(widget), evt->button, evt->time);
     }
 
     if(evt->button == 1 || evt->button == 3) {


More information about the Xfce4-commits mailing list