diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt
index d995d71..e76afeb 100644
--- a/docs/reference/gtk/gtk3-sections.txt
+++ b/docs/reference/gtk/gtk3-sections.txt
@@ -5108,6 +5108,7 @@ gtk_widget_unset_state_flags
 gtk_widget_get_state_flags
 gtk_widget_has_default
 gtk_widget_has_focus
+gtk_widget_has_visible_focus
 gtk_widget_has_grab
 gtk_widget_has_rc_style
 gtk_widget_is_drawable
@@ -5290,6 +5291,8 @@ gtk_window_get_opacity
 gtk_window_set_opacity
 gtk_window_get_mnemonics_visible
 gtk_window_set_mnemonics_visible
+gtk_window_get_focus_visible
+gtk_window_set_focus_visible
 gtk_window_set_has_resize_grip
 gtk_window_get_has_resize_grip
 gtk_window_resize_grip_is_visible
diff --git a/gdk/x11/gdksettings.c b/gdk/x11/gdksettings.c
index 8edb7dc..e48538f 100644
--- a/gdk/x11/gdksettings.c
+++ b/gdk/x11/gdksettings.c
@@ -80,7 +80,8 @@ static const char gdk_settings_names[] =
   "Net/EnableInputFeedbackSounds\0" "gtk-enable-input-feedback-sounds\0"
   "Net/EnableEventSounds\0"   "gtk-enable-event-sounds\0"
   "Gtk/CursorBlinkTimeout\0"  "gtk-cursor-blink-timeout\0"
-  "Gtk/AutoMnemonics\0"       "gtk-auto-mnemonics\0";
+  "Gtk/AutoMnemonics\0"       "gtk-auto-mnemonics\0"
+  "Gtk/AutoFocus\0"           "gtk-auto-focus\0";
 
 
 static const struct
@@ -133,5 +134,6 @@ static const struct
   { 1573, 1603 },
   { 1636, 1658 },
   { 1682, 1705 },
-  { 1730, 1748 }
+  { 1730, 1748 },
+  { 1767, 1781 }
 };
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
index 33fb915..044ae08 100644
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@ -3540,6 +3540,7 @@ gtk_widget_has_focus
 gtk_widget_has_grab
 gtk_widget_has_rc_style
 gtk_widget_has_screen
+gtk_widget_has_visible_focus
 gtk_widget_help_type_get_type G_GNUC_CONST
 gtk_widget_hide
 gtk_widget_hide_on_delete
@@ -3704,6 +3705,7 @@ gtk_window_get_deletable
 gtk_window_get_destroy_with_parent
 gtk_window_get_focus
 gtk_window_get_focus_on_map
+gtk_window_get_focus_visible
 gtk_window_get_gravity
 gtk_window_get_group
 gtk_window_get_has_resize_grip
@@ -3770,6 +3772,7 @@ gtk_window_set_deletable
 gtk_window_set_destroy_with_parent
 gtk_window_set_focus
 gtk_window_set_focus_on_map
+gtk_window_set_focus_visible
 gtk_window_set_geometry_hints
 gtk_window_set_gravity
 gtk_window_set_has_resize_grip
diff --git a/gtk/gtkbutton.c b/gtk/gtkbutton.c
index ba121b5..8839420 100644
--- a/gtk/gtkbutton.c
+++ b/gtk/gtkbutton.c
@@ -1472,7 +1472,6 @@ gtk_button_size_allocate (GtkWidget     *widget,
   GtkButtonPrivate *priv = button->priv;
   GtkAllocation child_allocation;
   GtkStyleContext *context;
-  GtkStateFlags state;
   GtkWidget *child;
   GtkBorder default_border;
   GtkBorder inner_border;
@@ -1481,7 +1480,6 @@ gtk_button_size_allocate (GtkWidget     *widget,
   gint focus_pad;
 
   context = gtk_widget_get_style_context (widget);
-  state = gtk_widget_get_state_flags (widget);
 
   gtk_button_get_props (button, &default_border, NULL, &inner_border, &padding, NULL);
   gtk_style_context_get_style (context,
@@ -1569,6 +1567,7 @@ _gtk_button_paint (GtkButton          *button,
   gint focus_pad;
   GtkAllocation allocation;
   GtkStyleContext *context;
+  gboolean draw_focus;
 
   widget = GTK_WIDGET (button);
   context = gtk_widget_get_style_context (widget);
@@ -1604,8 +1603,10 @@ _gtk_button_paint (GtkButton          *button,
       width -= default_outside_border.left + default_outside_border.right;
       height -= default_outside_border.top + default_outside_border.bottom;
     }
-   
-  if (!interior_focus && gtk_widget_has_focus (widget))
+
+  draw_focus = gtk_widget_has_visible_focus (widget);
+
+  if (!interior_focus && draw_focus)
     {
       x += focus_width + focus_pad;
       y += focus_width + focus_pad;
@@ -1622,7 +1623,7 @@ _gtk_button_paint (GtkButton          *button,
 			x, y, width, height);
     }
 
-  if (gtk_widget_has_focus (widget))
+  if (draw_focus)
     {
       gint child_displacement_x;
       gint child_displacement_y;
@@ -1660,8 +1661,7 @@ _gtk_button_paint (GtkButton          *button,
           y += child_displacement_y;
         }
 
-      gtk_render_focus (context, cr,
-			x, y, width, height);
+      gtk_render_focus (context, cr, x, y, width, height);
 
       gtk_border_free (border);
     }
@@ -1924,7 +1924,6 @@ gtk_button_get_size (GtkWidget      *widget,
 {
   GtkButton *button = GTK_BUTTON (widget);
   GtkStyleContext *context;
-  GtkStateFlags state;
   GtkWidget *child;
   GtkBorder default_border;
   GtkBorder inner_border;
@@ -1934,7 +1933,6 @@ gtk_button_get_size (GtkWidget      *widget,
   gint minimum, natural;
 
   context = gtk_widget_get_style_context (widget);
-  state = gtk_widget_get_state_flags (widget);
 
   gtk_button_get_props (button, &default_border, NULL, &inner_border, &padding, NULL);
   gtk_style_context_get_style (context,
diff --git a/gtk/gtkcalendar.c b/gtk/gtkcalendar.c
index 404dfe9..4aa84d2 100644
--- a/gtk/gtkcalendar.c
+++ b/gtk/gtkcalendar.c
@@ -2707,8 +2707,8 @@ calendar_paint_day (GtkCalendar *calendar,
       pango_cairo_show_layout (cr, layout);
     }
 
-  if (gtk_widget_has_focus (widget)
-      && priv->focus_row == row && priv->focus_col == col)
+  if (gtk_widget_has_visible_focus (widget) &&
+      priv->focus_row == row && priv->focus_col == col)
     gtk_render_focus (context, cr,
                       day_rect.x, day_rect.y,
                       day_rect.width, day_rect.height);
diff --git a/gtk/gtkcellarea.c b/gtk/gtkcellarea.c
index 0af3c53..e35074f 100644
--- a/gtk/gtkcellarea.c
+++ b/gtk/gtkcellarea.c
@@ -1204,6 +1204,9 @@ gtk_cell_area_real_render (GtkCellArea          *area,
   if (gtk_cell_area_get_edited_cell (area))
     render_data.paint_focus = FALSE;
 
+  if (!gtk_widget_has_visible_focus (widget))
+    render_data.paint_focus = FALSE;
+
   /* If no cell can activate but the caller wants focus painted,
    * then we paint focus around all cells */
   if ((flags & GTK_CELL_RENDERER_FOCUSED) != 0 && paint_focus &&
diff --git a/gtk/gtkcheckbutton.c b/gtk/gtkcheckbutton.c
index 9ceb6b1..a16093d 100644
--- a/gtk/gtkcheckbutton.c
+++ b/gtk/gtkcheckbutton.c
@@ -170,26 +170,27 @@ gtk_check_button_paint (GtkWidget    *widget,
 			cairo_t      *cr)
 {
   GtkCheckButton *check_button = GTK_CHECK_BUTTON (widget);
-  gint border_width;
-  gint interior_focus;
-  gint focus_width;
-  gint focus_pad;
-      
-  gtk_widget_style_get (widget,
-                        "interior-focus", &interior_focus,
-                        "focus-line-width", &focus_width,
-                        "focus-padding", &focus_pad,
-                        NULL);
 
   gtk_check_button_draw_indicator (check_button, cr);
 
-  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
-  if (gtk_widget_has_focus (widget))
+  if (gtk_widget_has_visible_focus (widget))
     {
       GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
       GtkStyleContext *context;
       GtkStateFlags state;
       GtkAllocation allocation;
+      gint border_width;
+      gint interior_focus;
+      gint focus_width;
+      gint focus_pad;
+
+      border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+
+      gtk_widget_style_get (widget,
+                            "interior-focus", &interior_focus,
+                            "focus-line-width", &focus_width,
+                            "focus-padding", &focus_pad,
+                            NULL);
 
       gtk_widget_get_allocation (widget, &allocation);
       context = gtk_widget_get_style_context (widget);
diff --git a/gtk/gtkcolorsel.c b/gtk/gtkcolorsel.c
index febb1a9..c896004 100644
--- a/gtk/gtkcolorsel.c
+++ b/gtk/gtkcolorsel.c
@@ -1127,7 +1127,7 @@ palette_draw (GtkWidget *drawing_area,
   gdk_cairo_set_source_rgba (cr, &color);
   cairo_paint (cr);
 
-  if (gtk_widget_has_focus (drawing_area))
+  if (gtk_widget_has_visible_focus (drawing_area))
     {
       set_focus_line_attributes (drawing_area, cr, &focus_width);
 
diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c
index b95fd8b..55a0b75 100644
--- a/gtk/gtkentry.c
+++ b/gtk/gtkentry.c
@@ -3444,7 +3444,7 @@ gtk_entry_draw_frame (GtkWidget       *widget,
 
   gtk_entry_draw_progress (widget, context, cr);
 
-  if (gtk_widget_has_focus (widget) && !priv->interior_focus)
+  if (gtk_widget_has_visible_focus (widget) && !priv->interior_focus)
     {
       x -= priv->focus_width;
       y -= priv->focus_width;
diff --git a/gtk/gtkexpander.c b/gtk/gtkexpander.c
index 2bfc6c8..7efeedd 100644
--- a/gtk/gtkexpander.c
+++ b/gtk/gtkexpander.c
@@ -1013,7 +1013,7 @@ gtk_expander_draw (GtkWidget *widget,
 
   gtk_expander_paint (expander, cr);
 
-  if (gtk_widget_has_focus (widget))
+  if (gtk_widget_has_visible_focus (widget))
     gtk_expander_paint_focus (expander, cr);
 
   GTK_WIDGET_CLASS (gtk_expander_parent_class)->draw (widget, cr);
diff --git a/gtk/gtkhsv.c b/gtk/gtkhsv.c
index 913f6df..227ed48 100644
--- a/gtk/gtkhsv.c
+++ b/gtk/gtkhsv.c
@@ -860,13 +860,6 @@ paint_ring (GtkHSV  *hsv,
   cairo_surface_t *source;
   cairo_t *source_cr;
   gint stride;
-  gint focus_width;
-  gint focus_pad;
-
-  gtk_widget_style_get (widget,
-                        "focus-line-width", &focus_width,
-                        "focus-padding", &focus_pad,
-                        NULL);
 
   width = gtk_widget_get_allocated_width (widget);
   height = gtk_widget_get_allocated_height (widget);
@@ -991,8 +984,9 @@ get_color (gdouble h,
 
 /* Paints the HSV triangle */
 static void
-paint_triangle (GtkHSV      *hsv,
-                cairo_t     *cr)
+paint_triangle (GtkHSV   *hsv,
+                cairo_t  *cr,
+                gboolean  draw_focus)
 {
   GtkHSVPrivate *priv = hsv->priv;
   GtkWidget *widget = GTK_WIDGET (hsv);
@@ -1180,8 +1174,7 @@ paint_triangle (GtkHSV      *hsv,
   
   /* Draw focus outline */
 
-  if (gtk_widget_has_focus (widget) &&
-      !priv->focus_on_ring)
+  if (draw_focus && !priv->focus_on_ring)
     {
       gint focus_width;
       gint focus_pad;
@@ -1203,16 +1196,20 @@ paint_triangle (GtkHSV      *hsv,
 
 /* Paints the contents of the HSV color selector */
 static gboolean
-gtk_hsv_draw (GtkWidget      *widget,
-              cairo_t        *cr)
+gtk_hsv_draw (GtkWidget *widget,
+              cairo_t   *cr)
 {
   GtkHSV *hsv = GTK_HSV (widget);
   GtkHSVPrivate *priv = hsv->priv;
+  gboolean draw_focus;
+
+  draw_focus = gtk_widget_has_visible_focus (widget);
 
   paint_ring (hsv, cr);
-  paint_triangle (hsv, cr);
+  paint_triangle (hsv, cr, draw_focus);
+
 
-  if (gtk_widget_has_focus (widget) && priv->focus_on_ring)
+  if (draw_focus && priv->focus_on_ring)
     {
       GtkStyleContext *context;
       GtkStateFlags state;
diff --git a/gtk/gtkiconview.c b/gtk/gtkiconview.c
index b395f43..495af33 100644
--- a/gtk/gtkiconview.c
+++ b/gtk/gtkiconview.c
@@ -1588,7 +1588,7 @@ gtk_icon_view_draw (GtkWidget *widget,
   cairo_save (cr);
 
   gtk_cairo_transform_to_window (cr, widget, icon_view->priv->bin_window);
-      
+
   cairo_set_line_width (cr, 1.);
 
   gtk_icon_view_get_drag_dest_item (icon_view, &path, &dest_pos);
@@ -1601,7 +1601,7 @@ gtk_icon_view_draw (GtkWidget *widget,
   else
     dest_index = -1;
 
-  for (icons = icon_view->priv->items; icons; icons = icons->next) 
+  for (icons = icon_view->priv->items; icons; icons = icons->next)
     {
       GtkIconViewItem *item = icons->data;
       GdkRectangle paint_area;
@@ -1620,8 +1620,8 @@ gtk_icon_view_draw (GtkWidget *widget,
         {
           gtk_icon_view_paint_item (icon_view, cr, item,
                                     ((GdkRectangle *)item)->x, ((GdkRectangle *)item)->y,
-                                    icon_view->priv->draw_focus); 
-     
+                                    icon_view->priv->draw_focus);
+
           if (dest_index == item->index)
             dest_item = item;
         }
@@ -1676,7 +1676,7 @@ gtk_icon_view_draw (GtkWidget *widget,
                         rect.x, rect.y,
                         rect.width, rect.height);
     }
-  
+
   if (icon_view->priv->doing_rubberband)
     gtk_icon_view_paint_rubberband (icon_view, cr);
 
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index 9b9752b..24c7349 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -4227,7 +4227,6 @@ gtk_label_draw (GtkWidget *widget,
           focus_link = gtk_label_get_focus_link (label);
           active_link = info->active_link;
 
-
           if (active_link)
             {
               GdkRGBA *bg_color;
@@ -4274,7 +4273,7 @@ gtk_label_draw (GtkWidget *widget,
               cairo_restore (cr);
             }
 
-          if (focus_link && gtk_widget_has_focus (widget))
+          if (focus_link && gtk_widget_has_visible_focus (widget))
             {
               range[0] = focus_link->start;
               range[1] = focus_link->end;
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index 950c499..f454781 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -1841,6 +1841,14 @@ gtk_main_do_event (GdkEvent *event)
             break;
         }
 
+      /* make focus visible in a window that receives a key event */
+      {
+        GtkWidget *window;
+        window = gtk_widget_get_toplevel (grab_widget);
+        if (GTK_IS_WINDOW (window))
+          gtk_window_set_focus_visible (GTK_WINDOW (window), TRUE);
+      }
+
       /* Catch alt press to enable auto-mnemonics;
        * menus are handled elsewhere
        * FIXME: this does not work with mnemonic modifiers other than Alt
@@ -1862,7 +1870,6 @@ gtk_main_do_event (GdkEvent *event)
               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);
             }
diff --git a/gtk/gtknotebook.c b/gtk/gtknotebook.c
index b6ebff4..3e3d702 100644
--- a/gtk/gtknotebook.c
+++ b/gtk/gtknotebook.c
@@ -5176,7 +5176,7 @@ gtk_notebook_draw_tab (GtkNotebook     *notebook,
                        page->allocation.height,
                        get_tab_gap_pos (notebook));
 
-  if (gtk_widget_has_focus (widget) &&
+  if (gtk_widget_has_visible_focus (widget) &&
       priv->cur_page == page)
     {
       gint focus_width, focus_pad;
diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c
index 94239e7..944c96f 100644
--- a/gtk/gtkrange.c
+++ b/gtk/gtkrange.c
@@ -2191,7 +2191,7 @@ gtk_range_draw (GtkWidget *widget,
 
       gtk_style_context_restore (context);
 
-      if (sensitive && gtk_widget_has_focus (widget))
+      if (sensitive && gtk_widget_has_visible_focus (widget))
         {
           gtk_style_context_save (context);
           gtk_style_context_set_state (context,
diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c
index fe5383d..c86637e 100644
--- a/gtk/gtksettings.c
+++ b/gtk/gtksettings.c
@@ -179,6 +179,7 @@ enum {
   PROP_TOOLBAR_STYLE,
   PROP_TOOLBAR_ICON_SIZE,
   PROP_AUTO_MNEMONICS,
+  PROP_AUTO_FOCUS,
   PROP_APPLICATION_PREFER_DARK_THEME,
   PROP_BUTTON_IMAGES,
   PROP_ENTRY_SELECT_ON_FOCUS,
@@ -1115,6 +1116,23 @@ gtk_settings_class_init (GtkSettingsClass *class)
   g_assert (result == PROP_AUTO_MNEMONICS);
 
   /**
+   * GtkSettings:gtk-auto-focus:
+   *
+   * Whether 'focus rectangles' should be hidden until the user
+   * starts to use the keyboard.
+   *
+   * Since: 3.2
+   */
+  result = settings_install_property_parser (class,
+                                             g_param_spec_boolean ("gtk-auto-focus",
+                                                                   P_("Auto Focus"),
+                                                                   P_("Whether 'focus rectangles' should be hidden until the user starts to use the keyboard."),
+                                                                   FALSE,
+                                                                   GTK_PARAM_READWRITE),
+                                             NULL);
+  g_assert (result == PROP_AUTO_FOCUS);
+
+  /**
    * GtkSettings:gtk-application-prefer-dark-theme:
    *
    * Whether the application prefers to use a dark theme. If a GTK+ theme
diff --git a/gtk/gtkswitch.c b/gtk/gtkswitch.c
index 9b831c7..64a95de 100644
--- a/gtk/gtkswitch.c
+++ b/gtk/gtkswitch.c
@@ -573,7 +573,7 @@ gtk_switch_draw (GtkWidget *widget,
   width = gtk_widget_get_allocated_width (widget);
   height = gtk_widget_get_allocated_height (widget);
 
-  if (gtk_widget_has_focus (widget))
+  if (gtk_widget_has_visible_focus (widget))
     gtk_render_focus (context, cr, x, y, width, height);
 
   x += focus_width + focus_pad;
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index b859e0b..99ef2a5 100644
--- a/gtk/gtktextview.c
+++ b/gtk/gtktextview.c
@@ -4919,7 +4919,7 @@ gtk_text_view_draw_focus (GtkWidget *widget,
 			"interior-focus", &interior_focus,
 			NULL);
   
-  if (gtk_widget_has_focus (widget) && !interior_focus)
+  if (gtk_widget_has_visible_focus (widget) && !interior_focus)
     {
       GtkStyleContext *context;
 
diff --git a/gtk/gtktrayicon-x11.c b/gtk/gtktrayicon-x11.c
index 3dd5129..9c35daf 100644
--- a/gtk/gtktrayicon-x11.c
+++ b/gtk/gtktrayicon-x11.c
@@ -387,7 +387,7 @@ gtk_tray_icon_draw (GtkWidget *widget,
     retval = GTK_WIDGET_CLASS (gtk_tray_icon_parent_class)->draw (widget, cr);
 
   focus_child = gtk_container_get_focus_child (GTK_CONTAINER (widget));
-  if (focus_child && gtk_widget_has_focus (focus_child))
+  if (focus_child && gtk_widget_has_visible_focus (focus_child))
     {
       GtkStyleContext *context;
       GtkStateFlags state;
diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c
index 7c2901d..f0e49bd 100644
--- a/gtk/gtktreeview.c
+++ b/gtk/gtktreeview.c
@@ -4538,7 +4538,7 @@ draw_empty_focus (GtkTreeView *tree_view, cairo_t *cr)
   GtkWidget *widget = GTK_WIDGET (tree_view);
   gint w, h;
 
-  if (!gtk_widget_has_focus (widget))
+  if (!gtk_widget_has_visible_focus (widget))
     return;
 
   w = gdk_window_get_width (tree_view->priv->bin_window) - 2;
@@ -4984,7 +4984,7 @@ gtk_tree_view_bin_draw (GtkWidget      *widget,
 	  if (node == cursor && has_can_focus_cell
               && ((column == tree_view->priv->focus_column
                    && tree_view->priv->draw_keyfocus &&
-                   gtk_widget_has_focus (widget))
+                   gtk_widget_has_visible_focus (widget))
                   || (column == tree_view->priv->edited_column)))
             draw_focus = TRUE;
           else
@@ -5214,7 +5214,7 @@ gtk_tree_view_bin_draw (GtkWidget      *widget,
       /* draw the big row-spanning focus rectangle, if needed */
       if (!has_can_focus_cell && node == cursor &&
           tree_view->priv->draw_keyfocus &&
-	  gtk_widget_has_focus (widget))
+	  gtk_widget_has_visible_focus (widget))
         {
 	  gint tmp_y, tmp_height;
 	  GtkStateFlags focus_rect_state = 0;
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index db2b824..710e29b 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -6657,6 +6657,48 @@ gtk_widget_has_focus (GtkWidget *widget)
 }
 
 /**
+ * gtk_widget_has_visible_focus:
+ * @widget: a #GtkWidget
+ *
+ * Determines if the widget should show a visible indication that
+ * it has the global input focus. This is a convenience function for
+ * use in ::draw handlers that takes into account whether focus
+ * indication should currently be shown in the toplevel window of
+ * @widget. See gtk_window_get_focus_visible() for more information
+ * about focus indication.
+ *
+ * To find out if the widget has the global input focus, use
+ * gtk_widget_has_focus().
+ *
+ * Return value: %TRUE if the widget should display a 'focus rectangle'
+ *
+ * Since: 3.2
+ */
+gboolean
+gtk_widget_has_visible_focus (GtkWidget *widget)
+{
+  gboolean draw_focus;
+
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  if (widget->priv->has_focus)
+    {
+      GtkWidget *toplevel;
+
+      toplevel = gtk_widget_get_toplevel (widget);
+
+      if (GTK_IS_WINDOW (toplevel))
+        draw_focus = gtk_window_get_focus_visible (GTK_WINDOW (toplevel));
+      else
+        draw_focus = TRUE;
+    }
+  else
+    draw_focus = FALSE;
+
+  return draw_focus;
+}
+
+/**
  * gtk_widget_is_focus:
  * @widget: a #GtkWidget
  *
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index 078de3e..f413e3b 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -560,6 +560,7 @@ void       gtk_widget_set_can_focus       (GtkWidget           *widget,
 gboolean   gtk_widget_get_can_focus       (GtkWidget           *widget);
 gboolean   gtk_widget_has_focus           (GtkWidget           *widget);
 gboolean   gtk_widget_is_focus            (GtkWidget           *widget);
+gboolean   gtk_widget_has_visible_focus   (GtkWidget           *widget);
 void       gtk_widget_grab_focus          (GtkWidget           *widget);
 
 void       gtk_widget_set_can_default     (GtkWidget           *widget,
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 2af5409..2b2a78d 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -156,6 +156,7 @@ struct _GtkWindowPrivate
   guint    maximize_initially        : 1;
   guint    mnemonics_visible         : 1;
   guint    mnemonics_visible_set     : 1;
+  guint    focus_visible             : 1;
   guint    modal                     : 1;
   guint    opacity_set               : 1;
   guint    position                  : 3;
@@ -224,11 +225,12 @@ enum {
   /* Readonly properties */
   PROP_IS_ACTIVE,
   PROP_HAS_TOPLEVEL_FOCUS,
-  
+
   /* Writeonly properties */
   PROP_STARTUP_ID,
-  
+
   PROP_MNEMONICS_VISIBLE,
+  PROP_FOCUS_VISIBLE,
 
   LAST_ARG
 };
@@ -701,6 +703,18 @@ gtk_window_class_init (GtkWindowClass *klass)
                                                         P_("Icon for this window"),
                                                         GDK_TYPE_PIXBUF,
                                                         GTK_PARAM_READWRITE));
+
+  /**
+   * GtkWindow:mnemonics-visible:
+   *
+   * Whether mnemonics are currently visible in this window.
+   *
+   * This property is maintained by GTK+ based on the
+   * #GtkSettings:gtk-auto-mnemonics setting and user input,
+   * and should not be set by applications.
+   *
+   * Since: 2.20
+   */
   g_object_class_install_property (gobject_class,
                                    PROP_MNEMONICS_VISIBLE,
                                    g_param_spec_boolean ("mnemonics-visible",
@@ -708,6 +722,25 @@ gtk_window_class_init (GtkWindowClass *klass)
                                                          P_("Whether mnemonics are currently visible in this window"),
                                                          TRUE,
                                                          GTK_PARAM_READWRITE));
+
+  /**
+   * GtkWindow:focus-visible:
+   *
+   * Whether 'focus rectangles' are currently visible in this window.
+   *
+   * This property is maintained by GTK+ based on the
+   * #GtkSettings:gtk-auto-focus setting and user input
+   * and should not be set by applications.
+   *
+   * Since: 2.20
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_FOCUS_VISIBLE,
+                                   g_param_spec_boolean ("focus-visible",
+                                                         P_("Focus Visible"),
+                                                         P_("Whether focus rectangles are currently visible in this window"),
+                                                         TRUE,
+                                                         GTK_PARAM_READWRITE));
   
   /**
    * GtkWindow:icon-name:
@@ -1109,6 +1142,7 @@ gtk_window_init (GtkWindow *window)
   priv->initial_timestamp = GDK_CURRENT_TIME;
   priv->has_resize_grip = TRUE;
   priv->mnemonics_visible = TRUE;
+  priv->focus_visible = TRUE;
 
   g_object_ref_sink (window);
   priv->has_user_ref_count = TRUE;
@@ -1228,6 +1262,9 @@ gtk_window_set_property (GObject      *object,
     case PROP_MNEMONICS_VISIBLE:
       gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
       break;
+    case PROP_FOCUS_VISIBLE:
+      gtk_window_set_focus_visible (window, g_value_get_boolean (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1346,6 +1383,9 @@ gtk_window_get_property (GObject      *object,
     case PROP_MNEMONICS_VISIBLE:
       g_value_set_boolean (value, priv->mnemonics_visible);
       break;
+    case PROP_FOCUS_VISIBLE:
+      g_value_set_boolean (value, priv->focus_visible);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -4672,6 +4712,7 @@ gtk_window_map (GtkWidget *widget)
   GdkWindow *toplevel;
   GdkWindow *gdk_window;
   gboolean auto_mnemonics;
+  gboolean auto_focus;
 
   gdk_window = gtk_widget_get_window (widget);
 
@@ -4760,10 +4801,20 @@ gtk_window_map (GtkWidget *widget)
   /* 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);
+  g_object_get (gtk_widget_get_settings (widget),
+                "gtk-auto-mnemonics", &auto_mnemonics,
+                "gtk-auto-focus", &auto_focus,
+                NULL);
   if (auto_mnemonics && !priv->mnemonics_visible_set)
     gtk_window_set_mnemonics_visible (window, FALSE);
+
+  /* inherit from transient parent, so that a dialog that is
+   * opened via keynav shows focus initially
+   */
+  if (priv->transient_parent)
+    gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent));
+  else
+    gtk_window_set_focus_visible (window, !auto_focus);
 }
 
 static gboolean
@@ -5980,7 +6031,7 @@ gtk_window_focus_in_event (GtkWidget     *widget,
       if (auto_mnemonics)
         maybe_set_mnemonics_visible (window);
     }
-      
+
   return FALSE;
 }
 
@@ -9483,6 +9534,55 @@ gtk_window_set_mnemonics_visible (GtkWindow *window,
   priv->mnemonics_visible_set = TRUE;
 }
 
+/**
+ * gtk_window_get_focus_visible:
+ * @window: a #GtkWindow
+ *
+ * Gets the value of the #GtkWindow:focus-visible property.
+ *
+ * Returns: %TRUE if 'focus rectangles' are supposed to be visible
+ *     in this window.
+ *
+ * Since: 3.2
+ */
+gboolean
+gtk_window_get_focus_visible (GtkWindow *window)
+{
+  g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+
+  return window->priv->focus_visible;
+}
+
+/**
+ * gtk_window_set_focus_visible:
+ * @window: a #GtkWindow
+ * @setting: the new value
+ *
+ * Sets the #GtkWindow:focus-visible property.
+ *
+ * Since: 3.2
+ */
+void
+gtk_window_set_focus_visible (GtkWindow *window,
+                              gboolean   setting)
+{
+  GtkWindowPrivate *priv;
+
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  priv = window->priv;
+
+  setting = setting != FALSE;
+
+  if (priv->focus_visible != setting)
+    {
+      priv->focus_visible = setting;
+      //g_object_notify (G_OBJECT (window), "focus-visible");
+    }
+
+  //priv->focus_visible_set = TRUE;
+}
+
 void
 _gtk_window_get_wmclass (GtkWindow  *window,
                          gchar     **wmclass_name,
diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h
index 3820070..ec9197a 100644
--- a/gtk/gtkwindow.h
+++ b/gtk/gtkwindow.h
@@ -162,6 +162,9 @@ 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_focus_visible        (GtkWindow           *window,
+                                                gboolean             setting);
+gboolean   gtk_window_get_focus_visible        (GtkWindow           *window);
 
 void       gtk_window_set_resizable            (GtkWindow           *window,
                                                 gboolean             resizable);
