[gtk/css-focus-changes: 1/2] Add a focus-within state



commit 01cb523a0e047297d83195f9c2073b93c9e83177
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu Apr 16 01:36:13 2020 -0400

    Add a focus-within state
    
    This is used for widgets that contain the focus widget,
    reserving the focused state for the focus location itself.
    
    This aligns our focus state handling with
    https://www.w3.org/TR/selectors-4/

 gtk/gtkcssselector.c   |  1 +
 gtk/gtkcsstypes.c      |  3 ++-
 gtk/gtkenums.h         |  4 +++-
 gtk/gtkwidgetprivate.h |  2 +-
 gtk/gtkwindow.c        | 10 ++++++++++
 5 files changed, 17 insertions(+), 3 deletions(-)
---
diff --git a/gtk/gtkcssselector.c b/gtk/gtkcssselector.c
index 5752005463..c7bc7bd7d5 100644
--- a/gtk/gtkcssselector.c
+++ b/gtk/gtkcssselector.c
@@ -1283,6 +1283,7 @@ gtk_css_selector_parse_selector_pseudo_class (GtkCssParser   *parser,
         { "visited",        GTK_STATE_FLAG_VISITED, },
         { "checked",        GTK_STATE_FLAG_CHECKED, },
         { "focus-visible",  GTK_STATE_FLAG_FOCUS_VISIBLE, },
+        { "focus-within",   GTK_STATE_FLAG_FOCUS_WITHIN, },
       };
       guint i;
 
diff --git a/gtk/gtkcsstypes.c b/gtk/gtkcsstypes.c
index 928b0f9a2a..ea83226317 100644
--- a/gtk/gtkcsstypes.c
+++ b/gtk/gtkcsstypes.c
@@ -232,7 +232,8 @@ gtk_css_pseudoclass_name (GtkStateFlags state)
     "visited",
     "checked",
     "drop(active)",
-    "focus-visible"
+    "focus-visible",
+    "focus-within"
   };
   guint i;
 
diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h
index 658be5f338..a7657a84ed 100644
--- a/gtk/gtkenums.h
+++ b/gtk/gtkenums.h
@@ -736,6 +736,7 @@ typedef enum
  * @GTK_STATE_FLAG_CHECKED: Widget is checked
  * @GTK_STATE_FLAG_DROP_ACTIVE: Widget is highlighted as a drop target for DND
  * @GTK_STATE_FLAG_FOCUS_VISIBLE: Widget has the visible focus
+ * @GTK_STATE_FLAG_FOCUS_WITHIN: Widget contains the keyboard focus
  *
  * Describes a widget state. Widget states are used to match the widget
  * against CSS pseudo-classes. Note that GTK extends the regular CSS
@@ -757,7 +758,8 @@ typedef enum
   GTK_STATE_FLAG_VISITED       = 1 << 10,
   GTK_STATE_FLAG_CHECKED       = 1 << 11,
   GTK_STATE_FLAG_DROP_ACTIVE   = 1 << 12,
-  GTK_STATE_FLAG_FOCUS_VISIBLE = 1 << 13
+  GTK_STATE_FLAG_FOCUS_VISIBLE = 1 << 13,
+  GTK_STATE_FLAG_FOCUS_WITHIN  = 1 << 14
 } GtkStateFlags;
 
 /**
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index b2a4836ca0..1b104e77d9 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -45,7 +45,7 @@ typedef gboolean (*GtkSurfaceTransformChangedCallback) (GtkWidget
                                                         const graphene_matrix_t *surface_transform,
                                                         gpointer                 user_data);
 
-#define GTK_STATE_FLAGS_BITS 14
+#define GTK_STATE_FLAGS_BITS 15
 
 typedef struct _GtkWidgetSurfaceTransformData
 {
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 0451719907..eeb9a6998f 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -5612,8 +5612,14 @@ synthesize_focus_change_events (GtkWindow *window,
       gtk_widget_set_focus_child (widget, NULL);
       prev = widget;
       widget = gtk_widget_get_parent (widget);
+
+      flags = (flags & ~GTK_STATE_FLAG_FOCUSED) | GTK_STATE_FLAG_FOCUS_WITHIN;
     }
 
+  flags = GTK_STATE_FLAG_FOCUS_WITHIN;
+  if (gtk_window_get_focus_visible (GTK_WINDOW (window)))
+    flags |= GTK_STATE_FLAG_FOCUS_VISIBLE;
+
   list = NULL;
   for (widget = new_focus; widget; widget = gtk_widget_get_parent (widget))
     list = g_list_prepend (list, widget);
@@ -5652,6 +5658,10 @@ synthesize_focus_change_events (GtkWindow *window,
         }
       check_crossing_invariants (widget, &crossing);
       gtk_widget_handle_crossing (widget, &crossing, 0, 0);
+
+      if (l->next == NULL)
+        flags = (flags & ~GTK_STATE_FLAG_FOCUS_WITHIN) | GTK_STATE_FLAG_FOCUSED;
+
       gtk_widget_set_state_flags (widget, flags, FALSE);
       gtk_widget_set_focus_child (widget, focus_child);
     }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]