diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt index e1a8a84847..3677068d94 100644 --- a/docs/reference/gtk/gtk3-sections.txt +++ b/docs/reference/gtk/gtk3-sections.txt @@ -5111,6 +5111,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 @@ -5293,6 +5294,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 8edb7dc8f4..7a876f03c2 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/VisibleFocus\0" "gtk-visible-focus\0"; static const struct @@ -133,5 +134,6 @@ static const struct { 1573, 1603 }, { 1636, 1658 }, { 1682, 1705 }, - { 1730, 1748 } + { 1730, 1748 }, + { 1767, 1784 } }; diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index 4325f2f12f..06878dd823 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -3725,6 +3725,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 @@ -3791,6 +3792,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 6b967846fb..aa3fe63b18 100644 --- a/gtk/gtkbutton.c +++ b/gtk/gtkbutton.c @@ -1570,6 +1570,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); @@ -1605,8 +1606,11 @@ _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; @@ -1623,7 +1627,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; @@ -1658,8 +1662,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_style_context_restore (context); diff --git a/gtk/gtkcalendar.c b/gtk/gtkcalendar.c index c8eac51368..cff79bf564 100644 --- a/gtk/gtkcalendar.c +++ b/gtk/gtkcalendar.c @@ -2710,8 +2710,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 099c4e58b6..7ef6cc9364 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 3b8b950b82..7982e7fe53 100644 --- a/gtk/gtkcheckbutton.c +++ b/gtk/gtkcheckbutton.c @@ -172,26 +172,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 a098799cf2..c83279a335 100644 --- a/gtk/gtkcolorsel.c +++ b/gtk/gtkcolorsel.c @@ -1131,7 +1131,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 f5b42d33c5..89d8f6f629 100644 --- a/gtk/gtkentry.c +++ b/gtk/gtkentry.c @@ -3438,7 +3438,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 ef926ebf7a..4485454222 100644 --- a/gtk/gtkexpander.c +++ b/gtk/gtkexpander.c @@ -1016,7 +1016,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 ea133aaa58..6266b4f17d 100644 --- a/gtk/gtkhsv.c +++ b/gtk/gtkhsv.c @@ -862,13 +862,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); @@ -993,8 +986,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); @@ -1182,8 +1176,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; @@ -1205,16 +1198,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 456e4efdf3..fe8ccb326f 100644 --- a/gtk/gtkiconview.c +++ b/gtk/gtkiconview.c @@ -1589,7 +1589,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); @@ -1602,7 +1602,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; @@ -1621,8 +1621,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; } @@ -1677,7 +1677,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 0b7ee88332..6a6f72cf0a 100644 --- a/gtk/gtklabel.c +++ b/gtk/gtklabel.c @@ -4209,7 +4209,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; @@ -4253,7 +4252,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 f26a9f53cd..a0ca89dfb5 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1845,6 +1845,17 @@ gtk_main_do_event (GdkEvent *event) break; } + /* make focus visible in a window that receives a key event */ + { + GtkWidget *window; + GtkPolicyType visible_focus; + + window = gtk_widget_get_toplevel (grab_widget); + g_object_get (gtk_widget_get_settings (grab_widget), "gtk-visible-focus", &visible_focus, NULL); + if (GTK_IS_WINDOW (window) && visible_focus != GTK_POLICY_NEVER) + 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 @@ -1866,7 +1877,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 8cf23c40c3..cd19175631 100644 --- a/gtk/gtknotebook.c +++ b/gtk/gtknotebook.c @@ -5255,7 +5255,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 2e4331610d..96e54c6668 100644 --- a/gtk/gtkrange.c +++ b/gtk/gtkrange.c @@ -2194,7 +2194,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 ba24502fc7..ab5c5aa960 100644 --- a/gtk/gtksettings.c +++ b/gtk/gtksettings.c @@ -178,6 +178,7 @@ enum { PROP_TOOLBAR_STYLE, PROP_TOOLBAR_ICON_SIZE, PROP_AUTO_MNEMONICS, + PROP_VISIBLE_FOCUS, PROP_APPLICATION_PREFER_DARK_THEME, PROP_BUTTON_IMAGES, PROP_ENTRY_SELECT_ON_FOCUS, @@ -1113,6 +1114,24 @@ gtk_settings_class_init (GtkSettingsClass *class) NULL); g_assert (result == PROP_AUTO_MNEMONICS); + /** + * GtkSettings:gtk-visible-focus: + * + * Whether 'focus rectangles' should be always visible, never visible, + * or hidden until the user starts to use the keyboard. + * + * Since: 3.2 + */ + result = settings_install_property_parser (class, + g_param_spec_enum ("gtk-visible-focus", + P_("Visible Focus"), + P_("Whether 'focus rectangles' should be hidden until the user starts to use the keyboard."), + GTK_TYPE_POLICY_TYPE, + GTK_POLICY_ALWAYS, + GTK_PARAM_READWRITE), + NULL); + g_assert (result == PROP_VISIBLE_FOCUS); + /** * GtkSettings:gtk-application-prefer-dark-theme: * diff --git a/gtk/gtkswitch.c b/gtk/gtkswitch.c index 8d9c38aeb7..8604079cf0 100644 --- a/gtk/gtkswitch.c +++ b/gtk/gtkswitch.c @@ -570,7 +570,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 b722c51d98..4ddc279e16 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -4906,7 +4906,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 3dd5129d29..9c35dafd70 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 494d4ad522..36d1bb258c 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -4519,7 +4519,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; @@ -4965,7 +4965,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 @@ -5202,7 +5202,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 a84f31c881..95422621b8 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -6681,6 +6681,48 @@ gtk_widget_has_focus (GtkWidget *widget) return widget->priv->has_focus; } +/** + * 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 4694ffa1af..ead01ed4d1 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 3eb31054e7..e281d6e081 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -157,6 +157,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; @@ -225,11 +226,12 @@ enum { /* Readonly properties */ PROP_IS_ACTIVE, PROP_HAS_TOPLEVEL_FOCUS, - + /* Writeonly properties */ PROP_STARTUP_ID, - + PROP_MNEMONICS_VISIBLE, + PROP_FOCUS_VISIBLE, LAST_ARG }; @@ -702,6 +704,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", @@ -709,6 +723,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-visible-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: @@ -1112,6 +1145,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; @@ -1231,6 +1265,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; @@ -1349,6 +1386,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; @@ -4675,6 +4715,7 @@ gtk_window_map (GtkWidget *widget) GdkWindow *toplevel; GdkWindow *gdk_window; gboolean auto_mnemonics; + GtkPolicyType visible_focus; gdk_window = gtk_widget_get_window (widget); @@ -4747,7 +4788,7 @@ gtk_window_map (GtkWidget *widget) if (priv->startup_id != NULL) { /* Make sure we have a "real" id */ - if (!startup_id_is_fake (priv->startup_id)) + if (!startup_id_is_fake (priv->startup_id)) gdk_notify_startup_complete_with_id (priv->startup_id); g_free (priv->startup_id); @@ -4763,10 +4804,21 @@ 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-visible-focus", &visible_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, visible_focus == GTK_POLICY_ALWAYS); } static gboolean @@ -5983,7 +6035,7 @@ gtk_window_focus_in_event (GtkWidget *widget, if (auto_mnemonics) maybe_set_mnemonics_visible (window); } - + return FALSE; } @@ -9486,6 +9538,53 @@ 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"); + } +} + void _gtk_window_get_wmclass (GtkWindow *window, gchar **wmclass_name, diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h index 2752d8daed..d44eedaf7d 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);