[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