[gtk/focus-ring-experiment] window: Tweak visible focus behavior
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/focus-ring-experiment] window: Tweak visible focus behavior
- Date: Thu, 23 Apr 2020 13:34:12 +0000 (UTC)
commit b0f2cd02ad39f3078c26c0dcf187bb5709167f3a
Author: Matthias Clasen <mclasen redhat com>
Date: Tue Apr 21 18:14:40 2020 -0400
window: Tweak visible focus behavior
Only turn on visible focus when a key event actually leads
to a change in focus location (ie, 'keynav').
Make the visible focus disappear after 5 seconds of no
keyboard interaction, to avoid permanent focus ring
distraction.
As an extra bonus, make it so that we make the focus
visible while the Alt key is pressed. This gives us
a 'find my focus!' shortcut, and goes well with the
prexisting use of Alt for finding mnemonics.
Discussed in: #2644
gtk/gtkwindow.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 81 insertions(+), 5 deletions(-)
---
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 9d87e68d35..194d0ef0c4 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -191,12 +191,15 @@ typedef struct
guint mnemonics_display_timeout_id;
+ guint focus_visible_timeout;
+
gint scale;
gint title_height;
GtkWidget *title_box;
GtkWidget *titlebar;
GtkWidget *popup_menu;
+ GtkWidget *key_press_focus;
GdkMonitor *initial_fullscreen_monitor;
guint edge_constraints;
@@ -4068,6 +4071,12 @@ gtk_window_finalize (GObject *object)
priv->mnemonics_display_timeout_id = 0;
}
+ if (priv->focus_visible_timeout)
+ {
+ g_source_remove (priv->focus_visible_timeout);
+ priv->focus_visible_timeout = 0;
+ }
+
g_clear_object (&priv->constraint_solver);
g_clear_object (&priv->renderer);
g_clear_object (&priv->resize_cursor);
@@ -5362,6 +5371,36 @@ update_mnemonics_visible (GtkWindow *window,
}
}
+static void
+update_focus_visible (GtkWindow *window,
+ guint keyval,
+ GdkModifierType state,
+ gboolean visible)
+{
+ GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
+ if (visible)
+ {
+ if (priv->focus_visible)
+ priv->key_press_focus = NULL;
+ else
+ priv->key_press_focus = priv->focus_widget;
+
+ if ((keyval == GDK_KEY_Alt_L || keyval == GDK_KEY_Alt_R) &&
+ ((state & (gtk_accelerator_get_default_mod_mask ()) & ~(GDK_ALT_MASK)) == 0))
+ gtk_window_set_focus_visible (window, TRUE);
+ }
+ else
+ {
+ if (priv->key_press_focus == priv->focus_widget)
+ gtk_window_set_focus_visible (window, FALSE);
+ else
+ gtk_window_set_focus_visible (window, TRUE);
+
+ priv->key_press_focus = NULL;
+ }
+}
+
static gboolean
gtk_window_key_pressed (GtkWidget *widget,
guint keyval,
@@ -5371,8 +5410,7 @@ gtk_window_key_pressed (GtkWidget *widget,
{
GtkWindow *window = GTK_WINDOW (widget);
- gtk_window_set_focus_visible (window, TRUE);
-
+ update_focus_visible (window, keyval, state, TRUE);
update_mnemonics_visible (window, keyval, state, TRUE);
return FALSE;
@@ -5387,6 +5425,7 @@ gtk_window_key_released (GtkWidget *widget,
{
GtkWindow *window = GTK_WINDOW (widget);
+ update_focus_visible (window, keyval, state, FALSE);
update_mnemonics_visible (window, keyval, state, FALSE);
return FALSE;
@@ -7406,6 +7445,19 @@ gtk_window_get_focus_visible (GtkWindow *window)
return priv->focus_visible;
}
+static gboolean
+unset_focus_visible (gpointer data)
+{
+ GtkWindow *window = data;
+ GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
+ priv->focus_visible_timeout = 0;
+
+ gtk_window_set_focus_visible (window, FALSE);
+
+ return G_SOURCE_REMOVE;
+}
+
/**
* gtk_window_set_focus_visible:
* @window: a #GtkWindow
@@ -7417,15 +7469,39 @@ void
gtk_window_set_focus_visible (GtkWindow *window,
gboolean setting)
{
+ gboolean changed;
+
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
g_return_if_fail (GTK_IS_WINDOW (window));
- setting = setting != FALSE;
+ changed = priv->focus_visible != setting;
- if (priv->focus_visible != setting)
+ priv->focus_visible = setting;
+
+ if (priv->focus_visible_timeout)
+ {
+ g_source_remove (priv->focus_visible_timeout);
+ priv->focus_visible_timeout = 0;
+ }
+
+ if (priv->focus_visible)
+ priv->focus_visible_timeout = g_timeout_add_seconds (5, unset_focus_visible, window);
+
+ if (changed)
{
- priv->focus_visible = setting;
+ if (priv->focus_widget)
+ {
+ GtkWidget *widget;
+
+ for (widget = priv->focus_widget; widget; widget = gtk_widget_get_parent (widget))
+ {
+ if (priv->focus_visible)
+ gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_FOCUS_VISIBLE, FALSE);
+ else
+ gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_FOCUS_VISIBLE);
+ }
+ }
g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_FOCUS_VISIBLE]);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]