summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2010-03-14 16:11:48 -0400
committerMatthias Clasen <mclasen@redhat.com>2010-03-14 16:11:48 -0400
commita085bb1f0bcbd20723d181a5d7fa89f9ae56f92a (patch)
tree217709fb7515cbca479b3e92cdc3c8ca3827b45b
parentf3f44d665027459cd66ac957d26fa241cf189284 (diff)
downloadgtk+-a085bb1f0bcbd20723d181a5d7fa89f9ae56f92a.tar.gz
Improve the behaviour of automatic mnemonics
With this change, key events continue to go to an open menu even when the pointer is moved over a non-selectable menuitem. The mnemonics are shown and hidden accordingly.
-rw-r--r--gtk/gtkmenu.c7
-rw-r--r--gtk/gtkmenushell.c50
2 files changed, 46 insertions, 11 deletions
diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c
index 62039fe531..b5b9820faa 100644
--- a/gtk/gtkmenu.c
+++ b/gtk/gtkmenu.c
@@ -3262,7 +3262,10 @@ gtk_menu_motion_notify (GtkWidget *widget,
*/
if (!_gtk_menu_item_is_selectable (menu_item))
{
- gtk_menu_shell_deselect (menu_shell);
+ /* We really want to deselect, but this gives the menushell code
+ * a chance to do some bookkeeping about the menuitem.
+ */
+ gtk_menu_shell_select_item (menu_shell, menu_item);
return FALSE;
}
@@ -3916,7 +3919,7 @@ gtk_menu_leave_notify (GtkWidget *widget,
return TRUE;
menu_item = GTK_MENU_ITEM (event_widget);
-
+
/* Here we check to see if we're leaving an active menu item with a submenu,
* in which case we enter submenu navigation mode.
*/
diff --git a/gtk/gtkmenushell.c b/gtk/gtkmenushell.c
index bc8ea19bb9..710f835be8 100644
--- a/gtk/gtkmenushell.c
+++ b/gtk/gtkmenushell.c
@@ -137,6 +137,10 @@ struct _GtkMenuShellPrivate
guint take_focus : 1;
guint activated_submenu : 1;
+ /* This flag is a crutch to keep mnemonics in the same menu
+ * if the user moves the mouse over an unselectable menuitem.
+ */
+ guint in_unselectable_item : 1;
};
static void gtk_menu_shell_set_property (GObject *object,
@@ -805,6 +809,7 @@ _gtk_menu_shell_update_mnemonics (GtkMenuShell *menu_shell)
found = FALSE;
while (target)
{
+ GtkMenuShellPrivate *priv = GTK_MENU_SHELL_GET_PRIVATE (target);
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (target));
/* The idea with keyboard mode is that once you start using
@@ -824,7 +829,7 @@ _gtk_menu_shell_update_mnemonics (GtkMenuShell *menu_shell)
* dismissing menus.
*/
mnemonics_visible = target->keyboard_mode &&
- ((target->active_menu_item && !found) ||
+ (((target->active_menu_item || priv->in_unselectable_item) && !found) ||
(target == menu_shell &&
!target->parent_menu_shell &&
gtk_widget_has_grab (GTK_WIDGET (target))));
@@ -841,7 +846,7 @@ _gtk_menu_shell_update_mnemonics (GtkMenuShell *menu_shell)
else
gtk_window_set_mnemonics_visible (GTK_WINDOW (toplevel), mnemonics_visible);
- if (target->active_menu_item)
+ if (target->active_menu_item || priv->in_unselectable_item)
found = TRUE;
target = GTK_MENU_SHELL (target->parent_menu_shell);
@@ -853,11 +858,12 @@ gtk_menu_shell_key_press (GtkWidget *widget,
GdkEventKey *event)
{
GtkMenuShell *menu_shell = GTK_MENU_SHELL (widget);
+ GtkMenuShellPrivate *priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
gboolean enable_mnemonics;
menu_shell->keyboard_mode = TRUE;
- if (!menu_shell->active_menu_item && menu_shell->parent_menu_shell)
+ if (!(menu_shell->active_menu_item || priv->in_unselectable_item) && menu_shell->parent_menu_shell)
return gtk_widget_event (menu_shell->parent_menu_shell, (GdkEvent *)event);
if (gtk_bindings_activate_event (GTK_OBJECT (widget), event))
@@ -890,10 +896,19 @@ gtk_menu_shell_enter_notify (GtkWidget *widget,
menu_item = gtk_get_event_widget ((GdkEvent*) event);
- if (!menu_item ||
- (GTK_IS_MENU_ITEM (menu_item) &&
- !_gtk_menu_item_is_selectable (menu_item)))
- return TRUE;
+ if (!menu_item)
+ return TRUE;
+
+ if (GTK_IS_MENU_ITEM (menu_item) &&
+ !_gtk_menu_item_is_selectable (menu_item))
+ {
+ GtkMenuShellPrivate *priv;
+
+ priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
+ priv->in_unselectable_item = TRUE;
+
+ return TRUE;
+ }
if (menu_item->parent == widget &&
GTK_IS_MENU_ITEM (menu_item))
@@ -966,7 +981,14 @@ gtk_menu_shell_leave_notify (GtkWidget *widget,
menu_item = GTK_MENU_ITEM (event_widget);
if (!_gtk_menu_item_is_selectable (event_widget))
- return TRUE;
+ {
+ GtkMenuShellPrivate *priv;
+
+ priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
+ priv->in_unselectable_item = TRUE;
+
+ return TRUE;
+ }
if ((menu_shell->active_menu_item == event_widget) &&
(menu_item->submenu == NULL))
@@ -1149,7 +1171,14 @@ gtk_menu_shell_real_select_item (GtkMenuShell *menu_shell,
gtk_menu_shell_deselect (menu_shell);
if (!_gtk_menu_item_is_selectable (menu_item))
- return;
+ {
+ GtkMenuShellPrivate *priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
+
+ priv->in_unselectable_item = TRUE;
+ _gtk_menu_shell_update_mnemonics (menu_shell);
+
+ return;
+ }
menu_shell->active_menu_item = menu_item;
if (pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT)
@@ -1396,10 +1425,13 @@ static void
gtk_real_menu_shell_move_current (GtkMenuShell *menu_shell,
GtkMenuDirectionType direction)
{
+ GtkMenuShellPrivate *priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
GtkMenuShell *parent_menu_shell = NULL;
gboolean had_selection;
gboolean touchscreen_mode;
+ priv->in_unselectable_item = FALSE;
+
had_selection = menu_shell->active_menu_item != NULL;
g_object_get (gtk_widget_get_settings (GTK_WIDGET (menu_shell)),