diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index c3df84a..375002b 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,54 @@ 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);
+
+  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);
+
+
+  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 +2477,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 +2490,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 +4238,39 @@ 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 +5799,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/gtkmain.c b/gtk/gtkmain.c
index 5a8a0ef..2d8694c 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,32 @@ gtk_main_do_event (GdkEvent *event)
 	  if (gtk_invoke_key_snoopers (grab_widget, event))
 	    break;
 	}
+      /* catch alt press to enable auto-mnemonics */
+      if (((GdkEventKey*) event)->keyval == GDK_Alt_L
+          || ((GdkEventKey*) event)->keyval == GDK_Alt_R)
+        {
+          gboolean auto_mnemonics;
+          GtkWidget *window;
+
+          g_object_get (gtk_widget_get_settings (grab_widget),
+                        "gtk-auto-mnemonics", &auto_mnemonics, NULL);
+
+          window = gtk_widget_get_toplevel (grab_widget);
+
+          if (GTK_IS_WINDOW (window) && auto_mnemonics)
+            {
+              /* never turn off mnemonics if they have been activated in a menu
+               */
+              if (GTK_IS_MENU (grab_widget))
+                gtk_window_set_mnemonics_visible (GTK_WINDOW (window), TRUE);
+              else
+                {
+                  gboolean mnemonics_visible = (event->type == GDK_KEY_PRESS);
+                  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 0bdf1de..3c2f976 100644
--- a/gtk/gtkmenu.c
+++ b/gtk/gtkmenu.c
@@ -1608,6 +1608,16 @@ gtk_menu_popup (GtkMenu		    *menu,
         gtk_menu_shell_select_first (menu_shell, TRUE);
     }
 
+  /* copy the mnemonic-visible property from the top-level of the parent menu
+   * shell */
+  if (GTK_IS_WINDOW (parent_toplevel))
+    {
+      gboolean setting;
+
+      setting = gtk_window_get_mnemonics_visible (GTK_WINDOW (parent_toplevel));
+      gtk_window_set_mnemonics_visible (GTK_WINDOW (menu->toplevel), setting);
+    }
+
   /* Once everything is set up correctly, map the toplevel window on
      the screen.
    */
diff --git a/gtk/gtkmenushell.c b/gtk/gtkmenushell.c
index 910c760..733ec8b 100644
--- a/gtk/gtkmenushell.c
+++ b/gtk/gtkmenushell.c
@@ -974,10 +974,24 @@ gtk_real_menu_shell_deactivate (GtkMenuShell *menu_shell)
 {
   if (menu_shell->active)
     {
+      gboolean auto_mnemonics;
+
       menu_shell->button = 0;
       menu_shell->active = FALSE;
       menu_shell->activate_time = 0;
 
+
+      /* set the mnemonic-visible property to false */
+      g_object_get (gtk_widget_get_settings (GTK_WIDGET (menu_shell)),
+                    "gtk-auto-mnemonics", &auto_mnemonics, NULL);
+      if (auto_mnemonics)
+        {
+          GtkWidget *window;
+          window = gtk_widget_get_toplevel (GTK_WIDGET (menu_shell));
+          if (GTK_IS_WINDOW (window))
+            gtk_window_set_mnemonics_visible (GTK_WINDOW (window), FALSE);
+        }
+
       if (menu_shell->active_menu_item)
 	{
 	  gtk_menu_item_deselect (GTK_MENU_ITEM (menu_shell->active_menu_item));
diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c
index 9c744da..b9e324c 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.14
+   */
+  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 98747b2..615f971 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;
 
+  gboolean mnemonics_visible : 1;
+  gboolean mnemonics_visible_set : 1;
+
   GdkWindowTypeHint type_hint;
 
   gdouble opacity;
@@ -591,6 +596,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 +941,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 +964,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 +1066,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 +1184,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 +4559,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 +4635,13 @@ gtk_window_map (GtkWidget *widget)
           gdk_notify_startup_complete ();
         }
     }
+
+  /* if auto-mnemnoics is enabled and mnemonics visible is not already set (as
+   * in the case of popup menus), then hide mnemonics initialy */
+  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
@@ -5286,10 +5316,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;
 }
 
@@ -8427,6 +8465,37 @@ 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);
+
+  if (priv->mnemonics_visible != setting)
+    {
+      priv->mnemonics_visible = setting;
+      g_object_notify (G_OBJECT (window), "mnemonics-visible");
+    }
+
+  priv->mnemonics_visible_set = TRUE;
+}
+
 #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 dc59dfe..1b4362f 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);
