forked from AuroraMiddleware/gtk
wip: Add more information to crossing events
Add fields for direct descendents to GtkCrossingData, and populate them when emitting focus change events. Also add accessors for these fields to GtkEventControllerKey, and verify that they are set properly in the focus test. Not done yet: Do the same for pointer crossing events.
This commit is contained in:
parent
7bb6abb1d4
commit
89c3a7ab24
@ -48,10 +48,15 @@ typedef struct _GtkCrossingData GtkCrossingData;
|
||||
* @direction: whether this is a focus-in or focus-out event
|
||||
* @mode: the crossing mode
|
||||
* @old_target: the old target
|
||||
* @old_descendent: the direct child of the receiving widget that
|
||||
* is an ancestor of @old_target, or %NULL if @old_target is not
|
||||
* a descendent of the receiving widget
|
||||
* @new_target: the new target
|
||||
* @new_descendent: the direct child of the receiving widget that
|
||||
* is an ancestor of @new_target, or %NULL if @new_target is not
|
||||
* a descendent of the receiving widget
|
||||
*
|
||||
* The struct that is passed to gtk_event_controller_handle_crossing()
|
||||
* and is also passed to #GtkEventControllerKey::focus-change.
|
||||
* The struct that is passed to gtk_event_controller_handle_crossing().
|
||||
*
|
||||
* The @old_target and @new_target fields are set to the old or new
|
||||
* focus or hover location.
|
||||
@ -61,7 +66,9 @@ struct _GtkCrossingData {
|
||||
GtkCrossingDirection direction;
|
||||
GdkCrossingMode mode;
|
||||
GtkWidget *old_target;
|
||||
GtkWidget *old_descendent;
|
||||
GtkWidget *new_target;
|
||||
GtkWidget *new_descendent;
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
|
@ -548,6 +548,24 @@ gtk_event_controller_key_get_focus_target (GtkEventControllerKey *controller)
|
||||
return controller->current_crossing->new_target;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gtk_event_controller_key_get_old_focus_child (GtkEventControllerKey *controller)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER_KEY (controller), NULL);
|
||||
g_return_val_if_fail (controller->current_crossing != NULL, NULL);
|
||||
|
||||
return controller->current_crossing->old_descendent;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gtk_event_controller_key_get_new_focus_child (GtkEventControllerKey *controller)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER_KEY (controller), NULL);
|
||||
g_return_val_if_fail (controller->current_crossing != NULL, NULL);
|
||||
|
||||
return controller->current_crossing->new_descendent;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_event_controller_key_contains_focus:
|
||||
* @self: a #GtkEventControllerKey
|
||||
|
@ -62,6 +62,10 @@ GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_event_controller_key_get_focus_origin (GtkEventControllerKey *controller);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_event_controller_key_get_focus_target (GtkEventControllerKey *controller);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_event_controller_key_get_old_focus_child (GtkEventControllerKey *controller);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_event_controller_key_get_new_focus_child (GtkEventControllerKey *controller);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_event_controller_key_contains_focus (GtkEventControllerKey *self);
|
||||
|
@ -6346,15 +6346,49 @@ gtk_window_move_focus (GtkWidget *widget,
|
||||
gtk_window_set_focus (GTK_WINDOW (widget), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
check_crossing_invariants (GtkWidget *widget,
|
||||
GtkCrossingData *crossing)
|
||||
{
|
||||
if (crossing->old_target == NULL)
|
||||
g_assert (crossing->old_descendent == NULL);
|
||||
else if (crossing->old_descendent == NULL)
|
||||
g_assert (crossing->old_target == widget || !gtk_widget_is_ancestor (crossing->old_target, widget));
|
||||
else
|
||||
{
|
||||
g_assert (gtk_widget_get_parent (crossing->old_descendent) == widget);
|
||||
g_assert (gtk_widget_is_ancestor (crossing->old_descendent, widget));
|
||||
g_assert (crossing->old_target == crossing->old_descendent || gtk_widget_is_ancestor (crossing->old_target, crossing->old_descendent));
|
||||
}
|
||||
if (crossing->new_target == NULL)
|
||||
g_assert (crossing->new_descendent == NULL);
|
||||
else if (crossing->new_descendent == NULL)
|
||||
g_assert (crossing->new_target == widget || !gtk_widget_is_ancestor (crossing->new_target, widget));
|
||||
else
|
||||
{
|
||||
g_assert (gtk_widget_get_parent (crossing->new_descendent) == widget);
|
||||
g_assert (gtk_widget_is_ancestor (crossing->new_descendent, widget));
|
||||
g_assert (crossing->new_target == crossing->new_descendent || gtk_widget_is_ancestor (crossing->new_target, crossing->new_descendent));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
synthesize_focus_change_events (GtkWindow *window,
|
||||
GtkWidget *old_focus,
|
||||
GtkWidget *new_focus)
|
||||
{
|
||||
GtkCrossingData crossing;
|
||||
GtkWidget *ancestor;
|
||||
GtkWidget *widget, *focus_child;
|
||||
GList *list, *l;
|
||||
GtkStateFlags flags;
|
||||
GtkWidget *prev;
|
||||
gboolean seen_ancestor;
|
||||
|
||||
if (old_focus && new_focus)
|
||||
ancestor = gtk_widget_common_ancestor (old_focus, new_focus);
|
||||
else
|
||||
ancestor = NULL;
|
||||
|
||||
flags = GTK_STATE_FLAG_FOCUSED;
|
||||
if (gtk_window_get_focus_visible (GTK_WINDOW (window)))
|
||||
@ -6363,29 +6397,52 @@ synthesize_focus_change_events (GtkWindow *window,
|
||||
crossing.type = GTK_CROSSING_FOCUS;
|
||||
crossing.mode = GDK_CROSSING_NORMAL;
|
||||
crossing.old_target = old_focus;
|
||||
crossing.old_descendent = NULL;
|
||||
crossing.new_target = new_focus;
|
||||
crossing.new_descendent = NULL;
|
||||
|
||||
crossing.direction = GTK_CROSSING_OUT;
|
||||
|
||||
prev = NULL;
|
||||
seen_ancestor = FALSE;
|
||||
widget = old_focus;
|
||||
while (widget)
|
||||
{
|
||||
crossing.old_descendent = prev;
|
||||
if (seen_ancestor)
|
||||
{
|
||||
crossing.new_descendent = new_focus ? prev : NULL;
|
||||
}
|
||||
else if (widget == ancestor)
|
||||
{
|
||||
GtkWidget *w;
|
||||
|
||||
crossing.new_descendent = NULL;
|
||||
for (w = new_focus; w != ancestor; w = gtk_widget_get_parent (w))
|
||||
crossing.new_descendent = w;
|
||||
|
||||
seen_ancestor = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
crossing.new_descendent = NULL;
|
||||
}
|
||||
|
||||
check_crossing_invariants (widget, &crossing);
|
||||
gtk_widget_handle_crossing (widget, &crossing, 0, 0);
|
||||
gtk_widget_unset_state_flags (widget, flags);
|
||||
gtk_widget_set_focus_child (widget, NULL);
|
||||
prev = widget;
|
||||
widget = gtk_widget_get_parent (widget);
|
||||
}
|
||||
|
||||
list = NULL;
|
||||
widget = new_focus;
|
||||
while (widget)
|
||||
{
|
||||
list = g_list_prepend (list, widget);
|
||||
widget = gtk_widget_get_parent (widget);
|
||||
}
|
||||
for (widget = new_focus; widget; widget = gtk_widget_get_parent (widget))
|
||||
list = g_list_prepend (list, widget);
|
||||
|
||||
crossing.direction = GTK_CROSSING_IN;
|
||||
|
||||
seen_ancestor = FALSE;
|
||||
for (l = list; l; l = l->next)
|
||||
{
|
||||
widget = l->data;
|
||||
@ -6393,6 +6450,29 @@ synthesize_focus_change_events (GtkWindow *window,
|
||||
focus_child = l->next->data;
|
||||
else
|
||||
focus_child = NULL;
|
||||
|
||||
crossing.new_descendent = focus_child;
|
||||
if (seen_ancestor)
|
||||
{
|
||||
crossing.old_descendent = NULL;
|
||||
}
|
||||
else if (widget == ancestor)
|
||||
{
|
||||
GtkWidget *w;
|
||||
|
||||
crossing.old_descendent = NULL;
|
||||
for (w = old_focus; w != ancestor; w = gtk_widget_get_parent (w))
|
||||
{
|
||||
crossing.old_descendent = w;
|
||||
}
|
||||
|
||||
seen_ancestor = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
crossing.old_descendent = old_focus ? focus_child : NULL;
|
||||
}
|
||||
check_crossing_invariants (widget, &crossing);
|
||||
gtk_widget_handle_crossing (widget, &crossing, 0, 0);
|
||||
gtk_widget_set_state_flags (widget, flags, FALSE);
|
||||
gtk_widget_set_focus_child (widget, focus_child);
|
||||
|
Loading…
Reference in New Issue
Block a user