[gnome-shell] Fix hang when clicking on the user status menu in the overview
- From: Owen Taylor <otaylor src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-shell] Fix hang when clicking on the user status menu in the overview
- Date: Fri, 28 Aug 2009 16:34:37 +0000 (UTC)
commit 1340413740c44d1568d8ebe0413ea9ebcd009dfb
Author: Owen W. Taylor <otaylor fishsoup net>
Date: Fri Aug 28 11:27:39 2009 -0400
Fix hang when clicking on the user status menu in the overview
shell-global.[ch]: Add shell_global_display_is_grabbed() that
uses the newly added meta_display_get_grab_op() to check
for existing grabs.
shell-status-menu.[ch]: Add shell_status_menu_is_active() to
check if the menu is popped up. Check for active grabs before
popping the menu up. Use gtk_menu_popdown() rather than
gtk_widget_hide(). Remove an excess gtk_widget_show() and
some excess casts.
panel.js: Check whether the status menu is popped up after button
release, and if it's not popped up, unhighlight the button.
Reported by Nuno Donato
http://bugzilla.gnome.org/show_bug.cgi?id=593362
js/ui/panel.js | 8 ++++++++
src/shell-global.c | 24 ++++++++++++++++++++++++
src/shell-global.h | 2 ++
src/shell-status-menu.c | 38 ++++++++++++++++++++++++++++++++++----
src/shell-status-menu.h | 2 +-
5 files changed, 69 insertions(+), 5 deletions(-)
---
diff --git a/js/ui/panel.js b/js/ui/panel.js
index e015109..5c9330e 100644
--- a/js/ui/panel.js
+++ b/js/ui/panel.js
@@ -381,6 +381,14 @@ Panel.prototype = {
statusmenu.toggle(e);
return false;
});
+ // This depends on connection ordering: since we are after the Button's
+ // ::button-release-event handler, calling button.release() will properly
+ // unset the 'active' flag for this stays-pressed button
+ statusbutton.button.connect('button-release-event', function (b, e) {
+ if (!statusmenu.is_active())
+ statusbutton.release();
+ return false;
+ });
this._rightBox.append(statusbutton.button, Big.BoxPackFlags.NONE);
// We get a deactivated event when the popup disappears
this._statusmenu.connect('deactivated', function (sm) {
diff --git a/src/shell-global.c b/src/shell-global.c
index 6193e0e..f8eff40 100644
--- a/src/shell-global.c
+++ b/src/shell-global.c
@@ -512,6 +512,30 @@ shell_global_end_modal (ShellGlobal *global,
mutter_plugin_end_modal (global->plugin, timestamp);
}
+/**
+ * shell_global_display_is_grabbed
+ * @global: a #ShellGlobal
+ *
+ * Determines whether Mutter currently has a grab (keyboard or mouse or
+ * both) on the display. This could be the result of a current window
+ * management operation like a window move, or could be from
+ * shell_global_begin_modal().
+ *
+ * This function is useful to for ad-hoc checks to avoid over-grabbing
+ * the Mutter grab a grab from GTK+. Longer-term we might instead want a
+ * mechanism to make Mutter use GDK grabs instead of raw XGrabPointer().
+ *
+ * Return value: %TRUE if Mutter has a grab on the display
+ */
+gboolean
+shell_global_display_is_grabbed (ShellGlobal *global)
+{
+ MetaScreen *screen = mutter_plugin_get_screen (global->plugin);
+ MetaDisplay *display = meta_screen_get_display (screen);
+
+ return meta_display_get_grab_op (display) != META_GRAB_OP_NONE;
+}
+
/* Code to close all file descriptors before we exec; copied from gspawn.c in GLib.
*
* Authors: Padraig O'Briain, Matthias Clasen, Lennart Poettering
diff --git a/src/shell-global.h b/src/shell-global.h
index a3ad263..3cda07b 100644
--- a/src/shell-global.h
+++ b/src/shell-global.h
@@ -69,6 +69,8 @@ gboolean shell_global_begin_modal (ShellGlobal *global,
void shell_global_end_modal (ShellGlobal *global,
guint32 timestamp);
+gboolean shell_global_display_is_grabbed (ShellGlobal *global);
+
void shell_global_reexec_self (ShellGlobal *global);
void shell_global_format_time_relative_pretty (ShellGlobal *global, guint delta, char **text, guint *update_time);
diff --git a/src/shell-status-menu.c b/src/shell-status-menu.c
index a5b1ccd..4018faf 100644
--- a/src/shell-status-menu.c
+++ b/src/shell-status-menu.c
@@ -660,24 +660,54 @@ position_menu (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user
*y = (gint)(0.5 + src_y + height);
}
+/**
+ * shell_status_menu_toggle:
+ * @menu: a #ShellStatusMenu
+ *
+ * If the menu is not currently up, pops it up. Otherwise, hides it.
+ * Popping up may fail if another grab is already active; check with
+ * shell_status_menu_is_active().
+ */
void
shell_status_menu_toggle (ShellStatusMenu *status, ClutterEvent *event)
{
ShellStatusMenuPrivate *priv = status->priv;
- if (GTK_WIDGET_VISIBLE (GTK_WIDGET (priv->menu)))
+ if (GTK_WIDGET_VISIBLE (priv->menu))
{
- gtk_widget_hide (GTK_WIDGET (priv->menu));
+ gtk_menu_popdown (GTK_MENU (priv->menu));
}
else
{
- gtk_widget_show (GTK_WIDGET (priv->menu));
+ /* We don't want to overgrab a Mutter grab with the grab that GTK+
+ * uses on menus.
+ */
+ ShellGlobal *global = shell_global_get ();
+ if (shell_global_display_is_grabbed (global))
+ return;
+
gtk_menu_popup (GTK_MENU (priv->menu), NULL, NULL, position_menu,
- status, 1, event->button.time);
+ status, 1, event->button.time);
}
}
/**
+ * shell_status_menu_is_active:
+ * @menu: a #ShellStatusMenu
+ *
+ * Gets whether the menu is currently popped up
+ *
+ * Return value: %TRUE if the menu is currently popped up
+ */
+gboolean
+shell_status_menu_is_active (ShellStatusMenu *status)
+{
+ ShellStatusMenuPrivate *priv = status->priv;
+
+ return GTK_WIDGET_VISIBLE (priv->menu);
+}
+
+/**
* shell_status_menu_get_name:
* @menu: a #ShellStatusMenu
*
diff --git a/src/shell-status-menu.h b/src/shell-status-menu.h
index 9831741..9a7c296 100644
--- a/src/shell-status-menu.h
+++ b/src/shell-status-menu.h
@@ -36,7 +36,7 @@ struct _ShellStatusMenuClass
GType shell_status_menu_get_type (void);
void shell_status_menu_toggle (ShellStatusMenu *menu, ClutterEvent *event);
-
+gboolean shell_status_menu_is_active (ShellStatusMenu *menu);
ClutterText *shell_status_menu_get_name (ShellStatusMenu *menu);
ClutterTexture *shell_status_menu_get_icon (ShellStatusMenu *menu);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]