summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2009-12-20 03:04:52 -0500
committerMatthias Clasen <mclasen@redhat.com>2009-12-20 03:11:05 -0500
commitc59f76fda2560273d7ee3255db9b697a7077ac38 (patch)
tree49c8796ebfd5eea5a25edf4d52cd6190722e87b9
parentaf268d5b072b062fbc0325fe31e441e38700a21c (diff)
downloadgdk-pixbuf-c59f76fda2560273d7ee3255db9b697a7077ac38.tar.gz
Only show the mnemonic underline when pressing Alt
...and show them in menus when navigating the menu with the keyboard. This is similar to what other platforms do, and reduces visual clutter. There is a setting to control this. Most of the work on this patch was done by Thomas Wood. See bug 588554.
-rw-r--r--gtk/gtklabel.c108
-rw-r--r--gtk/gtklabel.h5
-rw-r--r--gtk/gtkmain.c23
-rw-r--r--gtk/gtkmenu.c12
-rw-r--r--gtk/gtkmenubar.c1
-rw-r--r--gtk/gtkmenuitem.c3
-rw-r--r--gtk/gtkmenushell.c86
-rw-r--r--gtk/gtkmenushell.h6
-rw-r--r--gtk/gtksettings.c20
-rw-r--r--gtk/gtkwindow.c94
-rw-r--r--gtk/gtkwindow.h3
11 files changed, 353 insertions, 8 deletions
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index 73fa93a35..475d84278 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -58,6 +58,8 @@ typedef struct
gint wrap_width;
gint width_chars;
gint max_width_chars;
+
+ gboolean mnemonics_visible;
} GtkLabelPrivate;
/* Notes about the handling of links:
@@ -264,6 +266,9 @@ static void gtk_label_buildable_custom_finished (GtkBuildable *builda
gpointer user_data);
+static void connect_mnemonics_visible_notify (GtkLabel *label);
+
+
/* For selectable labels: */
static void gtk_label_move_cursor (GtkLabel *label,
GtkMovementStep step,
@@ -1037,6 +1042,8 @@ gtk_label_init (GtkLabel *label)
label->mnemonic_widget = NULL;
label->mnemonic_window = NULL;
+ priv->mnemonics_visible = TRUE;
+
gtk_label_set_text (label, "");
}
@@ -1486,7 +1493,9 @@ gtk_label_setup_mnemonic (GtkLabel *label,
}
if (label->mnemonic_keyval == GDK_VoidSymbol)
- goto done;
+ goto done;
+
+ connect_mnemonics_visible_notify (GTK_LABEL (widget));
toplevel = gtk_widget_get_toplevel (widget);
if (GTK_WIDGET_TOPLEVEL (toplevel))
@@ -1565,6 +1574,65 @@ label_shortcut_setting_changed (GtkSettings *settings)
}
static void
+mnemonics_visible_apply (GtkWidget *widget,
+ gboolean mnemonics_visible)
+{
+ GtkLabel *label;
+ GtkLabelPrivate *priv;
+
+ label = GTK_LABEL (widget);
+
+ if (!label->use_underline)
+ return;
+
+ priv = GTK_LABEL_GET_PRIVATE (label);
+
+ mnemonics_visible = mnemonics_visible != FALSE;
+
+ if (priv->mnemonics_visible != mnemonics_visible)
+ {
+ priv->mnemonics_visible = mnemonics_visible;
+
+ gtk_label_recalculate (label);
+ }
+}
+
+static void
+label_mnemonics_visible_traverse_container (GtkWidget *widget,
+ gpointer data)
+{
+ gboolean mnemonics_visible = GPOINTER_TO_INT (data);
+
+ _gtk_label_mnemonics_visible_apply_recursively (widget, mnemonics_visible);
+}
+
+void
+_gtk_label_mnemonics_visible_apply_recursively (GtkWidget *widget,
+ gboolean mnemonics_visible)
+{
+ if (GTK_IS_LABEL (widget))
+ mnemonics_visible_apply (widget, mnemonics_visible);
+ else if (GTK_IS_CONTAINER (widget))
+ gtk_container_forall (GTK_CONTAINER (widget),
+ label_mnemonics_visible_traverse_container,
+ GINT_TO_POINTER (mnemonics_visible));
+}
+
+static void
+label_mnemonics_visible_changed (GtkWindow *window,
+ GParamSpec *pspec,
+ gpointer data)
+{
+ gboolean mnemonics_visible;
+
+ g_object_get (window, "mnemonics-visible", &mnemonics_visible, NULL);
+
+ gtk_container_forall (GTK_CONTAINER (window),
+ label_mnemonics_visible_traverse_container,
+ GINT_TO_POINTER (mnemonics_visible));
+}
+
+static void
gtk_label_screen_changed (GtkWidget *widget,
GdkScreen *old_screen)
{
@@ -2420,6 +2488,7 @@ static void
gtk_label_set_pattern_internal (GtkLabel *label,
const gchar *pattern)
{
+ GtkLabelPrivate *priv = GTK_LABEL_GET_PRIVATE (label);
PangoAttrList *attrs;
gboolean enable_mnemonics;
@@ -2432,7 +2501,8 @@ gtk_label_set_pattern_internal (GtkLabel *label,
"gtk-enable-mnemonics", &enable_mnemonics,
NULL);
- if (enable_mnemonics && pattern)
+ if (enable_mnemonics && priv->mnemonics_visible && pattern &&
+ GTK_WIDGET_IS_SENSITIVE (label))
attrs = gtk_label_pattern_to_attrs (label, pattern);
else
attrs = NULL;
@@ -4179,6 +4249,38 @@ gtk_label_button_release (GtkWidget *widget,
}
static void
+connect_mnemonics_visible_notify (GtkLabel *label)
+{
+ GtkLabelPrivate *priv = GTK_LABEL_GET_PRIVATE (label);
+ GtkWidget *toplevel;
+ gboolean connected;
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (label));
+
+ if (!GTK_IS_WINDOW (toplevel))
+ return;
+
+ /* always set up this widgets initial value */
+ priv->mnemonics_visible =
+ gtk_window_get_mnemonics_visible (GTK_WINDOW (toplevel));
+
+ connected =
+ GPOINTER_TO_INT (g_object_get_data (G_OBJECT (toplevel),
+ "gtk-label-mnemonics-visible-connected"));
+
+ if (!connected)
+ {
+ g_signal_connect (toplevel,
+ "notify::mnemonics-visible",
+ G_CALLBACK (label_mnemonics_visible_changed),
+ label);
+ g_object_set_data (G_OBJECT (toplevel),
+ "gtk-label-mnemonics-visible-connected",
+ GINT_TO_POINTER (1));
+ }
+}
+
+static void
drag_begin_cb (GtkWidget *widget,
GdkDragContext *context,
gpointer data)
@@ -5707,7 +5809,7 @@ gtk_label_activate_current_link (GtkLabel *label)
if (window &&
window->default_widget != widget &&
!(widget == window->focus_widget &&
- (!window->default_widget || !GTK_WIDGET_SENSITIVE (window->default_widget))))
+ (!window->default_widget || !GTK_WIDGET_IS_SENSITIVE (window->default_widget))))
gtk_window_activate_default (window);
}
}
diff --git a/gtk/gtklabel.h b/gtk/gtklabel.h
index d44b142fa..88a9db7dd 100644
--- a/gtk/gtklabel.h
+++ b/gtk/gtklabel.h
@@ -197,6 +197,11 @@ guint gtk_label_parse_uline (GtkLabel *label,
#endif /* GTK_DISABLE_DEPRECATED */
+/* private */
+
+void _gtk_label_mnemonics_visible_apply_recursively (GtkWidget *widget,
+ gboolean mnemonics_visible);
+
G_END_DECLS
#endif /* __GTK_LABEL_H__ */
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index 581403b54..af03f3578 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -63,6 +63,8 @@
#include "gtktooltip.h"
#include "gtkdebug.h"
#include "gtkalias.h"
+#include "gtkmenu.h"
+#include "gdk/gdkkeysyms.h"
#include "gdk/gdkprivate.h" /* for GDK_WINDOW_DESTROYED */
@@ -1613,6 +1615,27 @@ gtk_main_do_event (GdkEvent *event)
if (gtk_invoke_key_snoopers (grab_widget, event))
break;
}
+ /* catch alt press to enable auto-mnemonics */
+ if (event->key.keyval == GDK_Alt_L || event->key.keyval == GDK_Alt_R)
+ {
+ gboolean auto_mnemonics;
+
+ g_object_get (gtk_widget_get_settings (grab_widget),
+ "gtk-auto-mnemonics", &auto_mnemonics, NULL);
+
+ if (auto_mnemonics)
+ {
+ gboolean mnemonics_visible;
+ GtkWidget *window;
+
+ mnemonics_visible = (event->type == GDK_KEY_PRESS);
+
+ window = gtk_widget_get_toplevel (grab_widget);
+
+ if (GTK_IS_WINDOW (window))
+ gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
+ }
+ }
/* else fall through */
case GDK_MOTION_NOTIFY:
case GDK_BUTTON_RELEASE:
diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c
index e8813c9f0..241ef413e 100644
--- a/gtk/gtkmenu.c
+++ b/gtk/gtkmenu.c
@@ -1616,6 +1616,18 @@ gtk_menu_popup (GtkMenu *menu,
if (xgrab_shell == widget)
popup_grab_on_window (widget->window, activate_time, grab_keyboard); /* Should always succeed */
gtk_grab_add (GTK_WIDGET (menu));
+
+ if (parent_menu_shell)
+ {
+ gboolean keyboard_mode;
+
+ keyboard_mode = _gtk_menu_shell_get_keyboard_mode (GTK_MENU_SHELL (parent_menu_shell));
+ _gtk_menu_shell_set_keyboard_mode (menu_shell, keyboard_mode);
+ }
+ else if (menu_shell->button == 0) /* a keynav-activated context menu */
+ _gtk_menu_shell_set_keyboard_mode (menu_shell, TRUE);
+
+ _gtk_menu_shell_update_mnemonics (menu_shell);
}
void
diff --git a/gtk/gtkmenubar.c b/gtk/gtkmenubar.c
index a54e456d1..3d2bbb513 100644
--- a/gtk/gtkmenubar.c
+++ b/gtk/gtkmenubar.c
@@ -625,6 +625,7 @@ window_key_press_handler (GtkWidget *widget,
{
GtkMenuShell *menu_shell = GTK_MENU_SHELL (menubars->data);
+ _gtk_menu_shell_set_keyboard_mode (menu_shell, TRUE);
_gtk_menu_shell_activate (menu_shell);
gtk_menu_shell_select_first (menu_shell, FALSE);
diff --git a/gtk/gtkmenuitem.c b/gtk/gtkmenuitem.c
index 13db059bd..1f3e1a969 100644
--- a/gtk/gtkmenuitem.c
+++ b/gtk/gtkmenuitem.c
@@ -1374,6 +1374,9 @@ static gboolean
gtk_menu_item_mnemonic_activate (GtkWidget *widget,
gboolean group_cycling)
{
+ if (GTK_IS_MENU_SHELL (widget->parent))
+ _gtk_menu_shell_set_keyboard_mode (GTK_MENU_SHELL (widget->parent), TRUE);
+
if (group_cycling &&
widget->parent &&
GTK_IS_MENU_SHELL (widget->parent) &&
diff --git a/gtk/gtkmenushell.c b/gtk/gtkmenushell.c
index 910c760d5..4f7d82c8e 100644
--- a/gtk/gtkmenushell.c
+++ b/gtk/gtkmenushell.c
@@ -30,6 +30,7 @@
#include "gdk/gdkkeysyms.h"
#include "gtkbindings.h"
#include "gtkkeyhash.h"
+#include "gtklabel.h"
#include "gtkmain.h"
#include "gtkmarshalers.h"
#include "gtkmenu.h"
@@ -773,6 +774,76 @@ gtk_menu_shell_button_release (GtkWidget *widget,
return TRUE;
}
+void
+_gtk_menu_shell_set_keyboard_mode (GtkMenuShell *menu_shell,
+ gboolean keyboard_mode)
+{
+ menu_shell->keyboard_mode = keyboard_mode;
+}
+
+gboolean
+_gtk_menu_shell_get_keyboard_mode (GtkMenuShell *menu_shell)
+{
+ return menu_shell->keyboard_mode;
+}
+
+void
+_gtk_menu_shell_update_mnemonics (GtkMenuShell *menu_shell)
+{
+ GtkMenuShell *target;
+ gboolean auto_mnemonics;
+ gboolean found;
+ gboolean mnemonics_visible;
+
+ g_object_get (gtk_widget_get_settings (GTK_WIDGET (menu_shell)),
+ "gtk-auto-mnemonics", &auto_mnemonics, NULL);
+
+ if (!auto_mnemonics)
+ return;
+
+ target = menu_shell;
+ found = FALSE;
+ while (target)
+ {
+ /* The idea with keyboard mode is that once you start using
+ * the keyboard to navigate the menus, we show mnemonics
+ * until the menu navigation is over. To that end, we spread
+ * the keyboard mode upwards in the menu hierarchy here.
+ * Also see gtk_menu_popup, where we inherit it downwards.
+ */
+ if (menu_shell->keyboard_mode)
+ target->keyboard_mode = TRUE;
+
+ /* While navigating menus, the first parent menu with an active
+ * item is the one where mnemonics are effective, as can be seen
+ * in gtk_menu_shell_key_press below.
+ * We also show mnemonics in context menus. The grab condition is
+ * necessary to ensure we remove underlines from menu bars when
+ * dismissing menus.
+ */
+ mnemonics_visible = target->keyboard_mode &&
+ ((target->active_menu_item && !found) ||
+ (target == menu_shell &&
+ !target->parent_menu_shell &&
+ gtk_widget_has_grab (target)));
+
+ /* While menus are up, only show underlines inside the menubar,
+ * not in the entire window.
+ */
+ if (GTK_IS_MENU_BAR (target))
+ _gtk_label_mnemonics_visible_apply_recursively (GTK_WIDGET (target),
+ mnemonics_visible);
+ else
+ gtk_window_set_mnemonics_visible (GTK_WINDOW (gtk_widget_get_toplevel (target)),
+ mnemonics_visible);
+
+ if (target->active_menu_item)
+ found = TRUE;
+
+ target = GTK_MENU_SHELL (target->parent_menu_shell);
+ }
+}
+
static gint
gtk_menu_shell_key_press (GtkWidget *widget,
GdkEventKey *event)
@@ -780,9 +851,11 @@ gtk_menu_shell_key_press (GtkWidget *widget,
GtkMenuShell *menu_shell = GTK_MENU_SHELL (widget);
gboolean enable_mnemonics;
+ menu_shell->keyboard_mode = TRUE;
+
if (!menu_shell->active_menu_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))
return TRUE;
@@ -992,11 +1065,15 @@ gtk_real_menu_shell_deactivate (GtkMenuShell *menu_shell)
if (menu_shell->have_xgrab)
{
GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (menu_shell));
-
+
menu_shell->have_xgrab = FALSE;
gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
}
+
+ menu_shell->keyboard_mode = FALSE;
+
+ _gtk_menu_shell_update_mnemonics (menu_shell);
}
}
@@ -1079,6 +1156,8 @@ gtk_menu_shell_real_select_item (GtkMenuShell *menu_shell,
GTK_MENU_SHELL_GET_CLASS (menu_shell)->submenu_placement);
gtk_menu_item_select (GTK_MENU_ITEM (menu_shell->active_menu_item));
+ _gtk_menu_shell_update_mnemonics (menu_shell);
+
/* This allows the bizarre radio buttons-with-submenus-display-history
* behavior
*/
@@ -1095,6 +1174,7 @@ gtk_menu_shell_deselect (GtkMenuShell *menu_shell)
{
gtk_menu_item_deselect (GTK_MENU_ITEM (menu_shell->active_menu_item));
menu_shell->active_menu_item = NULL;
+ _gtk_menu_shell_update_mnemonics (menu_shell);
}
}
@@ -1340,6 +1420,7 @@ gtk_real_menu_shell_move_current (GtkMenuShell *menu_shell,
* menu.
*/
_gtk_menu_item_popdown_submenu (menu_shell->active_menu_item);
+ _gtk_menu_shell_update_mnemonics (menu_shell);
}
else if (parent_menu_shell)
{
@@ -1347,6 +1428,7 @@ gtk_real_menu_shell_move_current (GtkMenuShell *menu_shell,
{
/* close menu when returning from submenu. */
_gtk_menu_item_popdown_submenu (GTK_MENU (menu_shell)->parent_menu_item);
+ _gtk_menu_shell_update_mnemonics (parent_menu_shell);
break;
}
diff --git a/gtk/gtkmenushell.h b/gtk/gtkmenushell.h
index e8281bcbb..614d3975f 100644
--- a/gtk/gtkmenushell.h
+++ b/gtk/gtkmenushell.h
@@ -65,6 +65,7 @@ struct _GtkMenuShell
guint GSEAL (ignore_leave) : 1; /* unused */
guint GSEAL (menu_flag) : 1; /* unused */
guint GSEAL (ignore_enter) : 1;
+ guint GSEAL (keyboard_mode) : 1;
};
struct _GtkMenuShellClass
@@ -130,6 +131,11 @@ gboolean gtk_menu_shell_get_take_focus (GtkMenuShell *menu_shell);
void gtk_menu_shell_set_take_focus (GtkMenuShell *menu_shell,
gboolean take_focus);
+void _gtk_menu_shell_update_mnemonics (GtkMenuShell *menu_shell);
+void _gtk_menu_shell_set_keyboard_mode (GtkMenuShell *menu_shell,
+ gboolean keyboard_mode);
+gboolean _gtk_menu_shell_get_keyboard_mode (GtkMenuShell *menu_shell);
+
G_END_DECLS
#endif /* __GTK_MENU_SHELL_H__ */
diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c
index 9e28fb922..a7ca546a0 100644
--- a/gtk/gtksettings.c
+++ b/gtk/gtksettings.c
@@ -124,7 +124,8 @@ enum {
PROP_ENABLE_EVENT_SOUNDS,
PROP_ENABLE_TOOLTIPS,
PROP_TOOLBAR_STYLE,
- PROP_TOOLBAR_ICON_SIZE
+ PROP_TOOLBAR_ICON_SIZE,
+ PROP_AUTO_MNEMONICS
};
@@ -999,6 +1000,23 @@ gtk_settings_class_init (GtkSettingsClass *class)
GTK_PARAM_READWRITE),
gtk_rc_property_parse_enum);
g_assert (result == PROP_TOOLBAR_ICON_SIZE);
+
+ /**
+ * GtkSettings:gtk-auto-mnemonics:
+ *
+ * Whether mnemonics should be automatically shown and hidden when the user
+ * presses the mnemonic activator.
+ *
+ * Since: 2.20
+ */
+ result = settings_install_property_parser (class,
+ g_param_spec_boolean ("gtk-auto-mnemonics",
+ P_("Auto Mnemonics"),
+ P_("Whether mnemonics should be automatically shown and hidden when the user presses the mnemonic activator."),
+ FALSE,
+ GTK_PARAM_READWRITE),
+ NULL);
+ g_assert (result == PROP_AUTO_MNEMONICS);
}
static void
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index f01820d1f..f5ec59ff4 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -101,6 +101,8 @@ enum {
/* Writeonly properties */
PROP_STARTUP_ID,
+ PROP_MNEMONICS_VISIBLE,
+
LAST_ARG
};
@@ -185,6 +187,9 @@ struct _GtkWindowPrivate
guint opacity_set : 1;
guint builder_visible : 1;
+ guint mnemonics_visible : 1;
+ guint mnemonics_visible_set : 1;
+
GdkWindowTypeHint type_hint;
gdouble opacity;
@@ -230,6 +235,8 @@ static gint gtk_window_client_event (GtkWidget *widget,
static void gtk_window_check_resize (GtkContainer *container);
static gint gtk_window_focus (GtkWidget *widget,
GtkDirectionType direction);
+static void gtk_window_grab_notify (GtkWidget *widget,
+ gboolean was_grabbed);
static void gtk_window_real_set_focus (GtkWindow *window,
GtkWidget *focus);
@@ -456,9 +463,9 @@ gtk_window_class_init (GtkWindowClass *klass)
widget_class->focus_out_event = gtk_window_focus_out_event;
widget_class->client_event = gtk_window_client_event;
widget_class->focus = gtk_window_focus;
-
widget_class->expose_event = gtk_window_expose;
-
+ widget_class->grab_notify = gtk_window_grab_notify;
+
container_class->check_resize = gtk_window_check_resize;
klass->set_focus = gtk_window_real_set_focus;
@@ -591,6 +598,13 @@ gtk_window_class_init (GtkWindowClass *klass)
P_("Icon for this window"),
GDK_TYPE_PIXBUF,
GTK_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_MNEMONICS_VISIBLE,
+ g_param_spec_boolean ("mnemonics-visible",
+ P_("Mnemonics Visible"),
+ P_("Whether mnemonics are currently visible in this window"),
+ TRUE,
+ GTK_PARAM_READWRITE));
/**
* GtkWindow:icon-name:
@@ -929,6 +943,7 @@ gtk_window_init (GtkWindow *window)
priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
priv->opacity = 1.0;
priv->startup_id = NULL;
+ priv->mnemonics_visible = TRUE;
colormap = _gtk_widget_peek_colormap ();
if (colormap)
@@ -951,9 +966,12 @@ gtk_window_set_property (GObject *object,
GParamSpec *pspec)
{
GtkWindow *window;
+ GtkWindowPrivate *priv;
window = GTK_WINDOW (object);
+ priv = GTK_WINDOW_GET_PRIVATE (window);
+
switch (prop_id)
{
case PROP_TYPE:
@@ -1050,6 +1068,9 @@ gtk_window_set_property (GObject *object,
case PROP_OPACITY:
gtk_window_set_opacity (window, g_value_get_double (value));
break;
+ case PROP_MNEMONICS_VISIBLE:
+ gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1165,6 +1186,9 @@ gtk_window_get_property (GObject *object,
case PROP_OPACITY:
g_value_set_double (value, gtk_window_get_opacity (window));
break;
+ case PROP_MNEMONICS_VISIBLE:
+ g_value_set_boolean (value, priv->mnemonics_visible);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -4537,6 +4561,7 @@ gtk_window_map (GtkWidget *widget)
GtkWindow *window = GTK_WINDOW (widget);
GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
GdkWindow *toplevel;
+ gboolean auto_mnemonics;
GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
@@ -4612,6 +4637,14 @@ gtk_window_map (GtkWidget *widget)
gdk_notify_startup_complete ();
}
}
+
+ /* if auto-mnemonics is enabled and mnemonics visible is not already set
+ * (as in the case of popup menus), then hide mnemonics initially
+ */
+ g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
+ &auto_mnemonics, NULL);
+ if (auto_mnemonics && !priv->mnemonics_visible_set)
+ gtk_window_set_mnemonics_visible (window, FALSE);
}
static gboolean
@@ -5288,10 +5321,18 @@ gtk_window_focus_out_event (GtkWidget *widget,
GdkEventFocus *event)
{
GtkWindow *window = GTK_WINDOW (widget);
+ gboolean auto_mnemonics;
_gtk_window_set_has_toplevel_focus (window, FALSE);
_gtk_window_set_is_active (window, FALSE);
+ /* set the mnemonic-visible property to false */
+ g_object_get (gtk_widget_get_settings (widget),
+ "gtk-auto-mnemonics", &auto_mnemonics, NULL);
+ if (auto_mnemonics)
+ gtk_window_set_mnemonics_visible (window, FALSE);
+
+
return FALSE;
}
@@ -8432,6 +8473,55 @@ gtk_window_get_window_type (GtkWindow *window)
return window->type;
}
+gboolean
+gtk_window_get_mnemonics_visible (GtkWindow *window)
+{
+ GtkWindowPrivate *priv;
+
+ g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+
+ priv = GTK_WINDOW_GET_PRIVATE (window);
+
+ return priv->mnemonics_visible;
+}
+
+void
+gtk_window_set_mnemonics_visible (GtkWindow *window,
+ gboolean setting)
+{
+ GtkWindowPrivate *priv;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ priv = GTK_WINDOW_GET_PRIVATE (window);
+
+ setting = setting != FALSE;
+
+ if (priv->mnemonics_visible != setting)
+ {
+ priv->mnemonics_visible = setting;
+ g_object_notify (G_OBJECT (window), "mnemonics-visible");
+ }
+
+ priv->mnemonics_visible_set = TRUE;
+}
+
+static void
+gtk_window_grab_notify (GtkWidget *widget,
+ gboolean was_grabbed)
+{
+ gboolean auto_mnemonics;
+
+ if (was_grabbed)
+ return;
+
+ g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
+ &auto_mnemonics, NULL);
+
+ if (auto_mnemonics)
+ gtk_window_set_mnemonics_visible (GTK_WINDOW (widget), FALSE);
+}
+
#if defined (G_OS_WIN32) && !defined (_WIN64)
#undef gtk_window_set_icon_from_file
diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h
index dc59dfe08..1b4362fea 100644
--- a/gtk/gtkwindow.h
+++ b/gtk/gtkwindow.h
@@ -230,6 +230,9 @@ gboolean gtk_window_get_focus_on_map (GtkWindow *window);
void gtk_window_set_destroy_with_parent (GtkWindow *window,
gboolean setting);
gboolean gtk_window_get_destroy_with_parent (GtkWindow *window);
+void gtk_window_set_mnemonics_visible (GtkWindow *window,
+ gboolean setting);
+gboolean gtk_window_get_mnemonics_visible (GtkWindow *window);
void gtk_window_set_resizable (GtkWindow *window,
gboolean resizable);