[Xfce4-commits] <xfce4-clipman-plugin:master> Fix popup from keyboard shortcut not always working #bug 5909
Mike Massonnet
noreply at xfce.org
Sun Nov 1 02:46:01 CET 2009
Updating branch refs/heads/master
to 5a06e78aabb5e76fb732424ca4402323f0c83a71 (commit)
from f4923bc34b4d123a973f6b5354ae93c880bf481b (commit)
commit 5a06e78aabb5e76fb732424ca4402323f0c83a71
Author: Mike Massonnet <mmassonnet at gmail.com>
Date: Sat Oct 31 17:37:04 2009 +0100
Fix popup from keyboard shortcut not always working #bug 5909
ChangeLog | 9 +++
panel-plugin/main-panel-plugin.c | 32 +++++++-----
panel-plugin/main-status-icon.c | 8 ++--
panel-plugin/plugin.c | 103 +++++++++++++++++++++++++++++++++-----
panel-plugin/plugin.h | 6 ++-
5 files changed, 125 insertions(+), 33 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index d5d17cd..00f5597 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2009-10-31 Mike Massonnet
+Fix popup from keyboard shortcut not always working #bug 5909
+
+ Factorize the popup action inside plugin.c(plugin_popup_menu) and add
+ a menu position function callback pointer within the MyPlugin
+ structure.
+ Add workaround from xfdesktop for the popup action called through a
+ keyboard shortcut.
+
2009-09-30 Mike Massonnet
=== Release 1.1.1 ===
diff --git a/panel-plugin/main-panel-plugin.c b/panel-plugin/main-panel-plugin.c
index c3941c7..6ca334a 100644
--- a/panel-plugin/main-panel-plugin.c
+++ b/panel-plugin/main-panel-plugin.c
@@ -42,7 +42,8 @@ XFCE_PANEL_PLUGIN_REGISTER_EXTERNAL (panel_plugin_register);
static gboolean panel_plugin_set_size (MyPlugin *plugin,
gint size);
-static void cb_button_toggled (GtkToggleButton *button,
+static gboolean cb_button_pressed (GtkButton *button,
+ GdkEventButton *event,
MyPlugin *plugin);
static void cb_menu_deactivate (GtkMenuShell *menu,
MyPlugin *plugin);
@@ -63,6 +64,9 @@ panel_plugin_register (XfcePanelPlugin *panel_plugin)
{
MyPlugin *plugin = plugin_register ();
+ /* Menu Position Func */
+ plugin->menu_position_func = (GtkMenuPositionFunc)my_plugin_position_menu;
+
/* Panel Plugin */
plugin->panel_plugin = panel_plugin;
#if GTK_CHECK_VERSION (2,12,0)
@@ -76,8 +80,8 @@ panel_plugin_register (XfcePanelPlugin *panel_plugin)
gtk_container_add (GTK_CONTAINER (plugin->button), plugin->image);
gtk_container_add (GTK_CONTAINER (panel_plugin), plugin->button);
xfce_panel_plugin_add_action_widget (panel_plugin, plugin->button);
- g_signal_connect (plugin->button, "toggled",
- G_CALLBACK (cb_button_toggled), plugin);
+ g_signal_connect (plugin->button, "button-press-event",
+ G_CALLBACK (cb_button_pressed), plugin);
/* Signals */
g_signal_connect_swapped (panel_plugin, "size-changed",
@@ -115,18 +119,18 @@ panel_plugin_set_size (MyPlugin *plugin,
return TRUE;
}
-static void
-cb_button_toggled (GtkToggleButton *button,
+static gboolean
+cb_button_pressed (GtkButton *button,
+ GdkEventButton *event,
MyPlugin *plugin)
{
- if (gtk_toggle_button_get_active (button))
- {
- gtk_menu_set_screen (GTK_MENU (plugin->menu), gtk_widget_get_screen (plugin->button));
- xfce_panel_plugin_register_menu (plugin->panel_plugin, GTK_MENU (plugin->menu));
- gtk_menu_popup (GTK_MENU (plugin->menu), NULL, NULL,
- (GtkMenuPositionFunc)my_plugin_position_menu, plugin,
- 0, gtk_get_current_event_time ());
- }
+ if (event->button != 1 && !(event->state & GDK_CONTROL_MASK))
+ return FALSE;
+
+ if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
+ plugin_popup_menu (plugin);
+
+ return TRUE;
}
static void
@@ -150,7 +154,7 @@ my_plugin_position_menu (GtkMenu *menu,
button = plugin->button;
orientation = xfce_panel_plugin_get_orientation (plugin->panel_plugin);
gtk_widget_size_request (GTK_WIDGET (menu), &requisition);
- gdk_window_get_origin (button->window, x, y);
+ gdk_window_get_origin (GTK_WIDGET (plugin->panel_plugin)->window, x, y);
switch (orientation)
{
diff --git a/panel-plugin/main-status-icon.c b/panel-plugin/main-status-icon.c
index d1f28e9..9a8db73 100644
--- a/panel-plugin/main-status-icon.c
+++ b/panel-plugin/main-status-icon.c
@@ -80,6 +80,9 @@ status_icon_register ()
{
MyPlugin *plugin = plugin_register ();
+ /* Menu Position Func */
+ plugin->menu_position_func = (GtkMenuPositionFunc)gtk_status_icon_position_menu;
+
/* Status Icon */
plugin->status_icon = gtk_status_icon_new_from_stock (GTK_STOCK_PASTE);
gtk_status_icon_set_tooltip (plugin->status_icon, _("Clipman"));
@@ -110,10 +113,7 @@ cb_status_icon_is_embedded (GtkStatusIcon *status_icon)
static void
cb_status_icon_activate (MyPlugin *plugin)
{
- gtk_menu_set_screen (GTK_MENU (plugin->menu), gtk_status_icon_get_screen (plugin->status_icon));
- gtk_menu_popup (GTK_MENU (plugin->menu), NULL, NULL,
- (GtkMenuPositionFunc)gtk_status_icon_position_menu, plugin->status_icon,
- 0, gtk_get_current_event_time ());
+ plugin_popup_menu (plugin);
}
static void
diff --git a/panel-plugin/plugin.c b/panel-plugin/plugin.c
index b3f7f2d..56387d2 100644
--- a/panel-plugin/plugin.c
+++ b/panel-plugin/plugin.c
@@ -38,12 +38,14 @@
#include "menu.h"
/*
- * X11 Selection for the popup command
+ * Popup command
*/
static gboolean my_plugin_set_popup_selection (MyPlugin *plugin);
static gboolean cb_popup_message_received (MyPlugin *plugin,
GdkEventClient *ev);
+static gboolean xfce_popup_grab_available (GdkWindow *win,
+ guint32 timestamp);
@@ -331,6 +333,27 @@ plugin_configure (MyPlugin *plugin)
}
}
+void
+plugin_popup_menu (MyPlugin *plugin)
+{
+#ifdef PANEL_PLUGIN
+ gtk_menu_set_screen (GTK_MENU (plugin->menu), gtk_widget_get_screen (plugin->button));
+ gtk_menu_popup (GTK_MENU (plugin->menu), NULL, NULL,
+ plugin->menu_position_func, plugin,
+ 0, gtk_get_current_event_time ());
+ if (gtk_grab_get_current () == plugin->menu)
+ {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (plugin->button), TRUE);
+ xfce_panel_plugin_register_menu (plugin->panel_plugin, GTK_MENU (plugin->menu));
+ }
+#elif STATUS_ICON
+ gtk_menu_set_screen (GTK_MENU (plugin->menu), gtk_status_icon_get_screen (plugin->status_icon));
+ gtk_menu_popup (GTK_MENU (plugin->menu), NULL, NULL,
+ plugin->menu_position_func, plugin->status_icon,
+ 0, gtk_get_current_event_time ());
+#endif
+}
+
/*
* X11 Selection for the popup command
*/
@@ -372,26 +395,80 @@ static gboolean
cb_popup_message_received (MyPlugin *plugin,
GdkEventClient *ev)
{
+ {
+ /* Copy workaround from xfdesktop to handle the awkward case where binding
+ * a keyboard shortcut to the popup command doesn't always work out... */
+#ifdef PANEL_PLUGIN
+ GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (plugin->button));
+#elif STATUS_ICON
+ GdkScreen *screen = gtk_status_icon_get_screen (plugin->status_icon);
+#endif
+ GdkWindow *root = gdk_screen_get_root_window (screen);
+ if (!xfce_popup_grab_available (root, GDK_CURRENT_TIME))
+ {
+ g_critical ("Unable to get keyboard/mouse grab.");
+ return FALSE;
+ }
+ }
+
if (G_LIKELY (ev->data_format == 8 && *(ev->data.b) != '\0'))
{
if (!g_ascii_strcasecmp (XFCE_CLIPMAN_MESSAGE, ev->data.b))
{
DBG ("Message received: %s", ev->data.b);
-
-#ifdef PANEL_PLUGIN
- xfce_panel_plugin_set_panel_hidden (plugin->panel_plugin, FALSE);
-#endif
- while (gtk_events_pending ())
- gtk_main_iteration ();
-
-#ifdef PANEL_PLUGIN
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (plugin->button), TRUE);
-#elif STATUS_ICON
- g_signal_emit_by_name (plugin->status_icon, "activate", NULL);
-#endif
+ plugin_popup_menu (plugin);
return TRUE;
}
}
+
return FALSE;
}
+/* 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.
+ */
+static gboolean
+xfce_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, waiting... (%i)", i);
+ 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/panel-plugin/plugin.h b/panel-plugin/plugin.h
index 47d4f89..2cbccd1 100644
--- a/panel-plugin/plugin.h
+++ b/panel-plugin/plugin.h
@@ -44,6 +44,8 @@ struct _MyPlugin
{
#ifdef PANEL_PLUGIN
XfcePanelPlugin *panel_plugin;
+ GtkWidget *button;
+ GtkWidget *image;
#elif STATUS_ICON
GtkStatusIcon *status_icon;
#endif
@@ -52,9 +54,8 @@ struct _MyPlugin
ClipmanActions *actions;
ClipmanCollector *collector;
ClipmanHistory *history;
- GtkWidget *button;
- GtkWidget *image;
GtkWidget *menu;
+ GtkMenuPositionFunc menu_position_func;
GtkWidget *popup_menu;
gulong popup_menu_id;
};
@@ -69,6 +70,7 @@ void plugin_save (MyPlugin *plugin);
void plugin_free (MyPlugin *plugin);
void plugin_about (MyPlugin *plugin);
void plugin_configure (MyPlugin *plugin);
+void plugin_menu_popup (MyPlugin *plugin);
#endif /* !__CLIPMAN_PLUGIN_H__ */
More information about the Xfce4-commits
mailing list