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
This commit is contained in:
parent
3adec65e20
commit
1340413740
@ -381,6 +381,14 @@ Panel.prototype = {
|
|||||||
statusmenu.toggle(e);
|
statusmenu.toggle(e);
|
||||||
return false;
|
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);
|
this._rightBox.append(statusbutton.button, Big.BoxPackFlags.NONE);
|
||||||
// We get a deactivated event when the popup disappears
|
// We get a deactivated event when the popup disappears
|
||||||
this._statusmenu.connect('deactivated', function (sm) {
|
this._statusmenu.connect('deactivated', function (sm) {
|
||||||
|
@ -512,6 +512,30 @@ shell_global_end_modal (ShellGlobal *global,
|
|||||||
mutter_plugin_end_modal (global->plugin, timestamp);
|
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.
|
/* Code to close all file descriptors before we exec; copied from gspawn.c in GLib.
|
||||||
*
|
*
|
||||||
* Authors: Padraig O'Briain, Matthias Clasen, Lennart Poettering
|
* Authors: Padraig O'Briain, Matthias Clasen, Lennart Poettering
|
||||||
|
@ -69,6 +69,8 @@ gboolean shell_global_begin_modal (ShellGlobal *global,
|
|||||||
void shell_global_end_modal (ShellGlobal *global,
|
void shell_global_end_modal (ShellGlobal *global,
|
||||||
guint32 timestamp);
|
guint32 timestamp);
|
||||||
|
|
||||||
|
gboolean shell_global_display_is_grabbed (ShellGlobal *global);
|
||||||
|
|
||||||
void shell_global_reexec_self (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);
|
void shell_global_format_time_relative_pretty (ShellGlobal *global, guint delta, char **text, guint *update_time);
|
||||||
|
@ -660,23 +660,53 @@ position_menu (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user
|
|||||||
*y = (gint)(0.5 + src_y + height);
|
*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
|
void
|
||||||
shell_status_menu_toggle (ShellStatusMenu *status, ClutterEvent *event)
|
shell_status_menu_toggle (ShellStatusMenu *status, ClutterEvent *event)
|
||||||
{
|
{
|
||||||
ShellStatusMenuPrivate *priv = status->priv;
|
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
|
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,
|
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:
|
* shell_status_menu_get_name:
|
||||||
* @menu: a #ShellStatusMenu
|
* @menu: a #ShellStatusMenu
|
||||||
|
@ -36,7 +36,7 @@ struct _ShellStatusMenuClass
|
|||||||
GType shell_status_menu_get_type (void);
|
GType shell_status_menu_get_type (void);
|
||||||
|
|
||||||
void shell_status_menu_toggle (ShellStatusMenu *menu, ClutterEvent *event);
|
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);
|
ClutterText *shell_status_menu_get_name (ShellStatusMenu *menu);
|
||||||
ClutterTexture *shell_status_menu_get_icon (ShellStatusMenu *menu);
|
ClutterTexture *shell_status_menu_get_icon (ShellStatusMenu *menu);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user