[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