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/
This commit is contained in:
Matthias Clasen
2020-04-16 01:36:13 -04:00
parent e83d87c20a
commit 54b99d281b
5 changed files with 18 additions and 4 deletions

View File

@@ -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;

View File

@@ -232,7 +232,8 @@ gtk_css_pseudoclass_name (GtkStateFlags state)
"visited",
"checked",
"drop(active)",
"focus-visible"
"focus-visible",
"focus-within"
};
guint i;

View File

@@ -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;
/**

View File

@@ -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
{

View File

@@ -5568,7 +5568,7 @@ synthesize_focus_change_events (GtkWindow *window,
else
ancestor = NULL;
flags = GTK_STATE_FLAG_FOCUSED;
flags = GTK_STATE_FLAG_FOCUSED | GTK_STATE_FLAG_FOCUS_WITHIN;
if (gtk_window_get_focus_visible (GTK_WINDOW (window)))
flags |= GTK_STATE_FLAG_FOCUS_VISIBLE;
@@ -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;
}
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_FOCUSED;
gtk_widget_set_state_flags (widget, flags, FALSE);
gtk_widget_set_focus_child (widget, focus_child);
}