From 92f1bdcf45dbb87ad9a537879bd5c5eae59964e7 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 2 Mar 2019 00:54:56 -0500 Subject: Redo focus handling GtkWindow has a focus_widget that points to the current input focus. GtkWidget has a focus_child that points to the child that contains the input focus. Following the focus_child chain from the toplevel always leads to the focus_widget. We never unset focus_child, we only set it. We bubble focus change events. --- gtk/gtkwidget.c | 109 ++------------------------------------------ gtk/gtkwindow.c | 139 ++++++++++++++------------------------------------------ 2 files changed, 38 insertions(+), 210 deletions(-) diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index cb37b01ff2..fb085f2f80 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -5340,88 +5340,16 @@ gtk_widget_grab_focus (GtkWidget *widget) if (!gtk_widget_is_sensitive (widget)) return; - g_object_ref (widget); GTK_WIDGET_GET_CLASS (widget)->grab_focus (widget); - g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_HAS_FOCUS]); - g_object_unref (widget); -} - -static void -reset_focus_recurse (GtkWidget *widget, - gpointer data) -{ - gtk_widget_set_focus_child (widget, NULL); - - gtk_widget_forall (widget, - reset_focus_recurse, - NULL); } static void gtk_widget_real_grab_focus (GtkWidget *focus_widget) { GtkWidget *toplevel; - GtkWidget *widget; - - /* clear the current focus setting, break if the current widget - * is the focus widget's parent, since containers above that will - * be set by the next loop. - */ - toplevel = _gtk_widget_get_toplevel (focus_widget); - if (_gtk_widget_is_toplevel (toplevel) && GTK_IS_WINDOW (toplevel)) - { - widget = gtk_window_get_focus (GTK_WINDOW (toplevel)); - - if (widget == focus_widget) - { - /* We call _gtk_window_internal_set_focus() here so that the - * toplevel window can request the focus if necessary. - * This is needed when the toplevel is a GtkPlug - */ - if (!gtk_widget_has_focus (widget)) - _gtk_window_internal_set_focus (GTK_WINDOW (toplevel), focus_widget); - - return; - } - - if (widget) - { - GtkWidget *common_ancestor = gtk_widget_common_ancestor (widget, focus_widget); - if (widget != common_ancestor) - { - while (widget->priv->parent) - { - widget = widget->priv->parent; - gtk_widget_set_focus_child (widget, NULL); - if (widget == common_ancestor) - break; - } - } - } - } - else if (toplevel != focus_widget) - { - /* gtk_widget_grab_focus() operates on a tree without window... - * actually, this is very questionable behavior. - */ - - gtk_widget_forall (toplevel, - reset_focus_recurse, - NULL); - } - - /* now propagate the new focus up the widget tree and finally - * set it on the window - */ - widget = focus_widget; - while (widget->priv->parent) - { - gtk_widget_set_focus_child (widget->priv->parent, widget); - widget = widget->priv->parent; - } - if (GTK_IS_WINDOW (widget)) - _gtk_window_internal_set_focus (GTK_WINDOW (widget), focus_widget); + toplevel = gtk_widget_get_toplevel (focus_widget); + gtk_window_set_focus (GTK_WINDOW (toplevel), focus_widget); } static gboolean @@ -5560,10 +5488,7 @@ gtk_widget_real_move_focus (GtkWidget *widget, GtkWidget *toplevel = _gtk_widget_get_toplevel (widget); if (widget != toplevel && GTK_IS_WINDOW (toplevel)) - { - g_signal_emit (toplevel, widget_signals[MOVE_FOCUS], 0, - direction); - } + g_signal_emit (toplevel, widget_signals[MOVE_FOCUS], 0, direction); } static gboolean @@ -11733,22 +11658,17 @@ gtk_widget_send_focus_change (GtkWidget *widget, GdkEvent *event) { GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); - gboolean res; g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); g_return_val_if_fail (event != NULL && event->any.type == GDK_FOCUS_CHANGE, FALSE); - g_object_ref (widget); - priv->has_focus = event->focus_change.in; - res = gtk_widget_event (widget, event); + gtk_propagate_event (widget, event); g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_HAS_FOCUS]); - g_object_unref (widget); - - return res; + return TRUE; } /** @@ -13470,26 +13390,7 @@ gtk_widget_set_focus_child (GtkWidget *widget, g_return_if_fail (gtk_widget_get_parent (child) == widget); } - if (priv->focus_child) - gtk_widget_unset_state_flags (priv->focus_child, - GTK_STATE_FLAG_FOCUSED|GTK_STATE_FLAG_FOCUS_VISIBLE); - - if (child) - { - GtkWidget *toplevel; - GtkStateFlags flags = GTK_STATE_FLAG_FOCUSED; - - toplevel = _gtk_widget_get_toplevel (widget); - if (!GTK_IS_WINDOW (toplevel) || gtk_window_get_focus_visible (GTK_WINDOW (toplevel))) - flags |= GTK_STATE_FLAG_FOCUS_VISIBLE; - - gtk_widget_set_state_flags (child, flags, FALSE); - } - g_set_object (&priv->focus_child, child); - - if (GTK_IS_CONTAINER (widget)) - gtk_container_set_focus_child (GTK_CONTAINER (widget), child); } /** diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 600e96e515..10e80d195d 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -2787,52 +2787,9 @@ void gtk_window_set_focus (GtkWindow *window, GtkWidget *focus) { - GtkWindowPrivate *priv = gtk_window_get_instance_private (window); - GtkWidget *parent; - - g_return_if_fail (GTK_IS_WINDOW (window)); - - if (focus) - { - g_return_if_fail (GTK_IS_WIDGET (focus)); - g_return_if_fail (gtk_widget_get_can_focus (focus)); - - if (!gtk_widget_get_visible (GTK_WIDGET (window))) - priv->initial_focus = focus; - else - gtk_widget_grab_focus (focus); - } - else - { - /* Clear the existing focus chain, so that when we focus into - * the window again, we start at the beginnning. - */ - GtkWidget *widget = priv->focus_widget; - if (widget) - { - while ((parent = _gtk_widget_get_parent (widget))) - { - widget = parent; - gtk_widget_set_focus_child (widget, NULL); - } - } - - _gtk_window_internal_set_focus (window, NULL); - } -} - -void -_gtk_window_internal_set_focus (GtkWindow *window, - GtkWidget *focus) -{ - GtkWindowPrivate *priv = gtk_window_get_instance_private (window); - g_return_if_fail (GTK_IS_WINDOW (window)); - priv->initial_focus = NULL; - if ((priv->focus_widget != focus) || - (focus && !gtk_widget_has_focus (focus))) - g_signal_emit (window, window_signals[SET_FOCUS], 0, focus); + g_signal_emit (window, window_signals[SET_FOCUS], 0, focus); } /** @@ -7326,79 +7283,49 @@ gtk_window_move_focus (GtkWidget *widget, } static void -gtk_window_real_set_focus (GtkWindow *window, - GtkWidget *focus) +unset_focus_widget (GtkWindow *window) { GtkWindowPrivate *priv = gtk_window_get_instance_private (window); - GtkWidget *old_focus = priv->focus_widget; + GtkWidget *f; - if (old_focus) - { - g_object_ref (old_focus); - g_object_freeze_notify (G_OBJECT (old_focus)); - } - if (focus) - { - g_object_ref (focus); - g_object_freeze_notify (G_OBJECT (focus)); - } + for (f = priv->focus_widget; f; f = gtk_widget_get_parent (f)) + gtk_widget_unset_state_flags (f, GTK_STATE_FLAG_FOCUSED|GTK_STATE_FLAG_FOCUS_VISIBLE); if (priv->focus_widget) - { - if (gtk_widget_get_receives_default (priv->focus_widget) && - (priv->focus_widget != priv->default_widget)) - { - _gtk_widget_set_has_default (priv->focus_widget, FALSE); - - if (priv->default_widget) - _gtk_widget_set_has_default (priv->default_widget, TRUE); - } + do_focus_change (priv->focus_widget, FALSE); + g_set_object (&priv->focus_widget, NULL); +} - priv->focus_widget = NULL; +static void +set_focus_widget (GtkWindow *window, + GtkWidget *focus) +{ + GtkWindowPrivate *priv = gtk_window_get_instance_private (window); + GtkWidget *f; + GtkStateFlags flags = GTK_STATE_FLAG_FOCUSED; - if (priv->is_active) - do_focus_change (old_focus, FALSE); + if (gtk_window_get_focus_visible (window)) + flags |= GTK_STATE_FLAG_FOCUS_VISIBLE; - g_object_notify (G_OBJECT (old_focus), "is-focus"); - } - - /* The above notifications may have set a new focus widget, - * if so, we don't want to override it. - */ - if (focus && !priv->focus_widget) + for (f = focus; f; f = gtk_widget_get_parent (f)) { - priv->focus_widget = focus; - - if (gtk_widget_get_receives_default (priv->focus_widget) && - (priv->focus_widget != priv->default_widget)) - { - if (gtk_widget_get_can_default (priv->focus_widget)) - _gtk_widget_set_has_default (priv->focus_widget, TRUE); - - if (priv->default_widget) - _gtk_widget_set_has_default (priv->default_widget, FALSE); - } - - if (priv->is_active) - do_focus_change (priv->focus_widget, TRUE); - - /* It's possible for do_focus_change() above to have callbacks - * that clear priv->focus_widget here. - */ - if (priv->focus_widget) - g_object_notify (G_OBJECT (priv->focus_widget), "is-focus"); + GtkWidget *parent = gtk_widget_get_parent (f); + gtk_widget_set_state_flags (f, flags, FALSE); + if (parent) + gtk_widget_set_focus_child (parent, f); } - if (old_focus) - { - g_object_thaw_notify (G_OBJECT (old_focus)); - g_object_unref (old_focus); - } - if (focus) - { - g_object_thaw_notify (G_OBJECT (focus)); - g_object_unref (focus); - } + g_set_object (&priv->focus_widget, focus); + if (priv->focus_widget) + do_focus_change (priv->focus_widget, TRUE); +} + +static void +gtk_window_real_set_focus (GtkWindow *window, + GtkWidget *focus) +{ + unset_focus_widget (window); + set_focus_widget (window, focus); } static void -- cgit v1.2.1 From ab5d3e756b21646ec57f4978fdc2312cf1a845e6 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 2 Mar 2019 08:45:13 -0500 Subject: root: Add focus Add a getter and a setter for the focus widget. The default implementations do nothing. --- gtk/gtkroot.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++ gtk/gtkroot.h | 6 +++++ gtk/gtkrootprivate.h | 8 ++++++ 3 files changed, 83 insertions(+) diff --git a/gtk/gtkroot.c b/gtk/gtkroot.c index ad93f8791a..249d7405b1 100644 --- a/gtk/gtkroot.c +++ b/gtk/gtkroot.c @@ -21,6 +21,8 @@ #include "gtkrootprivate.h" #include "gdk/gdk-private.h" +#include "gtkprivate.h" +#include "gtkintl.h" /** * SECTION:gtkroot @@ -65,6 +67,13 @@ gtk_root_default_init (GtkRootInterface *iface) iface->get_display = gtk_root_default_get_display; iface->get_renderer = gtk_root_default_get_renderer; iface->get_surface_transform = gtk_root_default_get_surface_transform; + + g_object_interface_install_property (iface, + g_param_spec_object ("focus-widget", + P_("Focus widget"), + P_("The focus widget"), + GTK_TYPE_WIDGET, + GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY)); } GdkDisplay * @@ -124,3 +133,63 @@ gtk_root_get_for_surface (GdkSurface *surface) return NULL; } + +/** + * gtk_root_set_focus: + * @self: a #GtkRoot + * @focus: (allow-none): widget to be the new focus widget, or %NULL + * to unset the focus widget + * + * If @focus is not the current focus widget, and is focusable, sets + * it as the focus widget for the root. If @focus is %NULL, unsets + * the focus widget for the root. + * + * To set the focus to a particular widget in the root, it is usually + * more convenient to use gtk_widget_grab_focus() instead of this function. + */ +void +gtk_root_set_focus (GtkRoot *self, + GtkWidget *focus) +{ + g_return_if_fail (GTK_IS_ROOT (self)); + g_return_if_fail (focus == NULL || GTK_IS_WIDGET (focus)); + + g_object_set (self, "focus-widget", focus, NULL); +} + +/** + * gtk_root_get_focus: + * @self: a #GtkRoot + * + * Retrieves the current focused widget within the root. + * + * Note that this is the widget that would have the focus + * if the root is active; if the root is not focused then + * `gtk_widget_has_focus (widget)` will be %FALSE for the + * widget. + * + * Returns: (nullable) (transfer none): the currently focused widget, + * or %NULL if there is none. + */ +GtkWidget * +gtk_root_get_focus (GtkRoot *self) +{ + GtkWidget *focus; + + g_return_val_if_fail (GTK_IS_ROOT (self), NULL); + + g_object_get (self, "focus-widget", &focus, NULL); + + if (focus) + g_object_unref (focus); + + return focus; +} + +guint +gtk_root_install_properties (GObjectClass *object_class, + guint first_prop) +{ + g_object_class_override_property (object_class, first_prop + GTK_ROOT_PROP_FOCUS_WIDGET, "focus-widget"); + return GTK_ROOT_NUM_PROPERTIES; +} diff --git a/gtk/gtkroot.h b/gtk/gtkroot.h index 45e777ba68..4c7ae89e37 100644 --- a/gtk/gtkroot.h +++ b/gtk/gtkroot.h @@ -56,6 +56,12 @@ struct _GtkRootInterface GDK_AVAILABLE_IN_ALL GtkWidget * gtk_root_get_for_surface (GdkSurface *surface); +GDK_AVAILABLE_IN_ALL +void gtk_root_set_focus (GtkRoot *self, + GtkWidget *focus); +GDK_AVAILABLE_IN_ALL +GtkWidget * gtk_root_get_focus (GtkRoot *self); + G_END_DECLS #endif /* __GTK_ROOT_H__ */ diff --git a/gtk/gtkrootprivate.h b/gtk/gtkrootprivate.h index 07ddc380e5..357bc6441f 100644 --- a/gtk/gtkrootprivate.h +++ b/gtk/gtkrootprivate.h @@ -11,6 +11,14 @@ GskRenderer * gtk_root_get_renderer (GtkRoot void gtk_root_get_surface_transform (GtkRoot *self, int *x, int *y); +enum { + GTK_ROOT_PROP_FOCUS_WIDGET, + GTK_ROOT_NUM_PROPERTIES +} GtkRootProperties; + +guint gtk_root_install_properties (GObjectClass *object_class, + guint first_prop); + G_END_DECLS #endif /* __GTK_ROOT_PRIVATE_H__ */ -- cgit v1.2.1 From bd44831987381a6e790c6703ab68b443e89cb727 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 2 Mar 2019 08:46:21 -0500 Subject: window: Implement the root focus api This just uses the existing get/set_focus functions. We keep them public for now. --- gtk/gtkwindow.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 10e80d195d..3af2dea877 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -1118,6 +1118,7 @@ gtk_window_class_init (GtkWindowClass *klass) GTK_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (gobject_class, LAST_ARG, window_props); + gtk_root_install_properties (gobject_class, LAST_ARG); /** * GtkWindow:set-focus: @@ -2095,6 +2096,9 @@ gtk_window_set_property (GObject *object, case PROP_FOCUS_VISIBLE: gtk_window_set_focus_visible (window, g_value_get_boolean (value)); break; + case LAST_ARG + GTK_ROOT_PROP_FOCUS_WIDGET: + gtk_window_set_focus (window, g_value_get_object (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2210,6 +2214,9 @@ gtk_window_get_property (GObject *object, case PROP_IS_MAXIMIZED: g_value_set_boolean (value, gtk_window_is_maximized (window)); break; + case LAST_ARG + GTK_ROOT_PROP_FOCUS_WIDGET: + g_value_set_object (value, gtk_window_get_focus (window)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -7326,6 +7333,8 @@ gtk_window_real_set_focus (GtkWindow *window, { unset_focus_widget (window); set_focus_widget (window, focus); + + g_object_notify (G_OBJECT (window), "focus-widget"); } static void -- cgit v1.2.1 From 2bf1561b48ee02f340515e6a3e08bc08d89b5f18 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 2 Mar 2019 08:49:00 -0500 Subject: Port widgets to the root focus API --- gtk/gtkcoloreditor.c | 3 ++- gtk/gtkfilechooserwidget.c | 13 +++++++------ gtk/gtklabel.c | 2 +- gtk/gtkmain.c | 4 ++-- gtk/gtknotebook.c | 8 +++++++- gtk/gtkpaned.c | 12 +++--------- gtk/gtkplacesview.c | 2 +- gtk/gtkstack.c | 34 ++++++++++++++++------------------ gtk/gtktext.c | 2 +- gtk/gtktreeviewcolumn.c | 7 ++----- gtk/gtkwidget.c | 25 +++++++------------------ gtk/gtkwidgetfocus.c | 10 +++------- gtk/inspector/misc-info.c | 4 ++-- tests/testtoolbar.c | 2 +- 14 files changed, 55 insertions(+), 73 deletions(-) diff --git a/gtk/gtkcoloreditor.c b/gtk/gtkcoloreditor.c index 34f5991ca2..8670027631 100644 --- a/gtk/gtkcoloreditor.c +++ b/gtk/gtkcoloreditor.c @@ -36,6 +36,7 @@ #include "gtkspinbutton.h" #include "gtkstylecontext.h" #include "gtkeventcontrollerkey.h" +#include "gtkroot.h" #include @@ -224,7 +225,7 @@ popup_edit (GtkWidget *widget, { dismiss_current_popup (editor); toplevel = gtk_widget_get_toplevel (GTK_WIDGET (editor)); - g_set_object (&editor->priv->popdown_focus, gtk_window_get_focus (GTK_WINDOW (toplevel))); + g_set_object (&editor->priv->popdown_focus, gtk_root_get_focus (GTK_ROOT (toplevel))); editor->priv->current_popup = popup; editor->priv->popup_position = position; gtk_widget_show (popup); diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c index 4d9ab00e05..7c7b32d119 100644 --- a/gtk/gtkfilechooserwidget.c +++ b/gtk/gtkfilechooserwidget.c @@ -82,6 +82,7 @@ #include "gtkdebug.h" #include "gtkfilechoosererrorstackprivate.h" #include "gtkentryprivate.h" +#include "gtkroot.h" #include @@ -1361,7 +1362,7 @@ key_press_cb (GtkEventController *controller, GtkWidget *default_widget, *focus_widget; default_widget = gtk_window_get_default_widget (window); - focus_widget = gtk_window_get_focus (window); + focus_widget = gtk_root_get_focus (GTK_ROOT (window)); if (widget != default_widget && !(widget == focus_widget && (!default_widget || !gtk_widget_get_sensitive (default_widget)))) @@ -2709,7 +2710,7 @@ location_mode_set (GtkFileChooserWidget *impl, switch_to_file_list = FALSE; if (toplevel) { - current_focus = gtk_window_get_focus (toplevel); + current_focus = gtk_root_get_focus (GTK_ROOT (toplevel)); if (!current_focus || current_focus == priv->location_entry) switch_to_file_list = TRUE; } @@ -3566,7 +3567,7 @@ toplevel_set_focus_cb (GtkWindow *window, { GtkFileChooserWidgetPrivate *priv = impl->priv; - priv->toplevel_last_focus_widget = gtk_window_get_focus (window); + priv->toplevel_last_focus_widget = gtk_root_get_focus (GTK_ROOT (window)); } /* We monitor the focus widget on our toplevel to be able to know which widget @@ -3586,7 +3587,7 @@ gtk_file_chooser_widget_root (GtkWidget *widget) g_assert (priv->toplevel_set_focus_id == 0); priv->toplevel_set_focus_id = g_signal_connect (toplevel, "set-focus", G_CALLBACK (toplevel_set_focus_cb), impl); - priv->toplevel_last_focus_widget = gtk_window_get_focus (GTK_WINDOW (toplevel)); + priv->toplevel_last_focus_widget = gtk_root_get_focus (GTK_ROOT (toplevel)); } static void @@ -5806,7 +5807,7 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser) toplevel = get_toplevel (GTK_WIDGET (impl)); if (toplevel) - current_focus = gtk_window_get_focus (toplevel); + current_focus = gtk_root_get_focus (GTK_ROOT (toplevel)); else current_focus = NULL; @@ -6655,7 +6656,7 @@ gtk_file_chooser_widget_should_respond (GtkFileChooserEmbed *chooser_embed) retval = FALSE; - current_focus = gtk_window_get_focus (GTK_WINDOW (toplevel)); + current_focus = gtk_root_get_focus (GTK_ROOT (toplevel)); if (current_focus == priv->browse_files_tree_view) { diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c index 86442d16a1..e3be68e02e 100644 --- a/gtk/gtklabel.c +++ b/gtk/gtklabel.c @@ -6222,7 +6222,7 @@ gtk_label_activate_current_link (GtkLabel *label) if (window) { default_widget = gtk_window_get_default_widget (window); - focus_widget = gtk_window_get_focus (window); + focus_widget = gtk_root_get_focus (GTK_ROOT (window)); if (default_widget != widget && !(widget == focus_widget && (!default_widget || !gtk_widget_is_sensitive (default_widget)))) diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 8aa278e9eb..be19d7389c 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1761,7 +1761,7 @@ gtk_main_do_event (GdkEvent *event) if (is_pointing_event (event)) target_widget = handle_pointing_event (event); - else if (GTK_IS_WINDOW (target_widget) && + else if (GTK_IS_ROOT (target_widget) && (event->any.type == GDK_KEY_PRESS || event->any.type == GDK_KEY_RELEASE)) { @@ -1771,7 +1771,7 @@ gtk_main_do_event (GdkEvent *event) gtk_window_activate_key (GTK_WINDOW (target_widget), (GdkEventKey *) event)) goto cleanup; - focus_widget = gtk_window_get_focus (GTK_WINDOW (target_widget)); + focus_widget = gtk_root_get_focus (GTK_ROOT (target_widget)); if (focus_widget) target_widget = focus_widget; } diff --git a/gtk/gtknotebook.c b/gtk/gtknotebook.c index d11ee42584..a23f9c41b7 100644 --- a/gtk/gtknotebook.c +++ b/gtk/gtknotebook.c @@ -5426,7 +5426,13 @@ gtk_notebook_real_switch_page (GtkNotebook *notebook, child_has_focus = priv->child_has_focus; if (priv->cur_page) - gtk_widget_unset_state_flags (priv->cur_page->tab_widget, GTK_STATE_FLAG_CHECKED); + { + GtkRoot *root = gtk_widget_get_root (GTK_WIDGET (notebook)); + GtkWidget *focus = gtk_root_get_focus (root); + if (focus) + child_has_focus = gtk_widget_is_ancestor (focus, priv->cur_page->child); + gtk_widget_unset_state_flags (priv->cur_page->tab_widget, GTK_STATE_FLAG_CHECKED); + } priv->cur_page = page; gtk_widget_set_state_flags (page->tab_widget, GTK_STATE_FLAG_CHECKED, FALSE); diff --git a/gtk/gtkpaned.c b/gtk/gtkpaned.c index 9fc18c9667..c09b3d9142 100644 --- a/gtk/gtkpaned.c +++ b/gtk/gtkpaned.c @@ -2256,10 +2256,8 @@ gtk_paned_restore_focus (GtkPaned *paned) if (!gtk_widget_child_focus (GTK_WIDGET (paned), GTK_DIR_TAB_FORWARD)) { - GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (paned)); - - if (GTK_IS_WINDOW (toplevel)) - gtk_window_set_focus (GTK_WINDOW (toplevel), NULL); + GtkRoot *root = gtk_widget_get_root (GTK_WIDGET (paned)); + gtk_root_set_focus (root, NULL); } } @@ -2364,7 +2362,6 @@ gtk_paned_cycle_handle_focus (GtkPaned *paned, { GtkPaned *focus; GtkPaned *first; - GtkWidget *toplevel; GtkWidget *focus_child; gtk_paned_find_neighbours (paned, &next, &prev); @@ -2410,10 +2407,7 @@ gtk_paned_cycle_handle_focus (GtkPaned *paned, first = next; } - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (paned)); - - if (GTK_IS_WINDOW (toplevel)) - gtk_paned_set_saved_focus (focus, gtk_window_get_focus (GTK_WINDOW (toplevel))); + gtk_paned_set_saved_focus (focus, gtk_root_get_focus (gtk_widget_get_root (GTK_WIDGET (paned)))); gtk_paned_set_first_paned (focus, first); priv->original_position = gtk_paned_get_position (focus); diff --git a/gtk/gtkplacesview.c b/gtk/gtkplacesview.c index bb03ef9d01..dabb486046 100644 --- a/gtk/gtkplacesview.c +++ b/gtk/gtkplacesview.c @@ -1766,7 +1766,7 @@ on_key_press_event (GtkEventController *controller, if (!toplevel) return FALSE; - focus_widget = gtk_window_get_focus (toplevel); + focus_widget = gtk_root_get_focus (GTK_ROOT (toplevel)); if (!GTK_IS_PLACES_VIEW_ROW (focus_widget)) return FALSE; diff --git a/gtk/gtkstack.c b/gtk/gtkstack.c index f9a7723448..d7222f9e5e 100644 --- a/gtk/gtkstack.c +++ b/gtk/gtkstack.c @@ -1123,7 +1123,6 @@ set_visible_child (GtkStack *stack, GtkStackPage *info; GtkWidget *widget = GTK_WIDGET (stack); GList *l; - GtkWidget *toplevel; GtkWidget *focus; gboolean contains_focus = FALSE; guint old_pos = GTK_INVALID_LIST_POSITION; @@ -1165,24 +1164,23 @@ set_visible_child (GtkStack *stack, } } - toplevel = gtk_widget_get_toplevel (widget); - if (GTK_IS_WINDOW (toplevel)) + if (gtk_widget_get_root (widget)) + focus = gtk_root_get_focus (gtk_widget_get_root (widget)); + else + focus = NULL; + if (focus && + priv->visible_child && + priv->visible_child->widget && + gtk_widget_is_ancestor (focus, priv->visible_child->widget)) { - focus = gtk_window_get_focus (GTK_WINDOW (toplevel)); - if (focus && - priv->visible_child && - priv->visible_child->widget && - gtk_widget_is_ancestor (focus, priv->visible_child->widget)) - { - contains_focus = TRUE; - - if (priv->visible_child->last_focus) - g_object_remove_weak_pointer (G_OBJECT (priv->visible_child->last_focus), - (gpointer *)&priv->visible_child->last_focus); - priv->visible_child->last_focus = focus; - g_object_add_weak_pointer (G_OBJECT (priv->visible_child->last_focus), - (gpointer *)&priv->visible_child->last_focus); - } + contains_focus = TRUE; + + if (priv->visible_child->last_focus) + g_object_remove_weak_pointer (G_OBJECT (priv->visible_child->last_focus), + (gpointer *)&priv->visible_child->last_focus); + priv->visible_child->last_focus = focus; + g_object_add_weak_pointer (G_OBJECT (priv->visible_child->last_focus), + (gpointer *)&priv->visible_child->last_focus); } if (priv->last_visible_child) diff --git a/gtk/gtktext.c b/gtk/gtktext.c index 99a5afba37..7a4d6cc2b9 100644 --- a/gtk/gtktext.c +++ b/gtk/gtktext.c @@ -3810,7 +3810,7 @@ gtk_text_real_activate (GtkText *self) if (window) { default_widget = gtk_window_get_default_widget (window); - focus_widget = gtk_window_get_focus (window); + focus_widget = gtk_root_get_focus (GTK_ROOT (window)); if (widget != default_widget && !(widget == focus_widget && (!default_widget || !gtk_widget_get_sensitive (default_widget)))) gtk_window_activate_default (window); diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c index 5817a5f2f8..8c113ad3c4 100644 --- a/gtk/gtktreeviewcolumn.c +++ b/gtk/gtktreeviewcolumn.c @@ -1016,11 +1016,8 @@ gtk_tree_view_column_update_button (GtkTreeViewColumn *tree_column) gtk_widget_set_can_focus (priv->button, FALSE); if (gtk_widget_has_focus (priv->button)) { - GtkWidget *toplevel = gtk_widget_get_toplevel (priv->tree_view); - if (gtk_widget_is_toplevel (toplevel)) - { - gtk_window_set_focus (GTK_WINDOW (toplevel), NULL); - } + GtkRoot *root = gtk_widget_get_root (priv->tree_view); + gtk_root_set_focus (root, NULL); } } /* Queue a resize on the assumption that we always want to catch all changes diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index fb085f2f80..ff817a8abb 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -5346,10 +5346,8 @@ gtk_widget_grab_focus (GtkWidget *widget) static void gtk_widget_real_grab_focus (GtkWidget *focus_widget) { - GtkWidget *toplevel; - - toplevel = gtk_widget_get_toplevel (focus_widget); - gtk_window_set_focus (GTK_WINDOW (toplevel), focus_widget); + GtkWidgetPrivate *priv = gtk_widget_get_instance_private (focus_widget); + gtk_root_set_focus (priv->root, focus_widget); } static gboolean @@ -5634,16 +5632,14 @@ gtk_widget_has_visible_focus (GtkWidget *widget) gboolean gtk_widget_is_focus (GtkWidget *widget) { - GtkWidget *toplevel; + GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); - toplevel = _gtk_widget_get_toplevel (widget); + if (priv->root) + return widget == gtk_root_get_focus (priv->root); - if (GTK_IS_WINDOW (toplevel)) - return widget == gtk_window_get_focus (GTK_WINDOW (toplevel)); - else - return FALSE; + return FALSE; } /** @@ -8849,14 +8845,7 @@ gtk_widget_propagate_state (GtkWidget *widget, priv->state_flags |= GTK_STATE_FLAG_INSENSITIVE; if (gtk_widget_is_focus (widget) && !gtk_widget_is_sensitive (widget)) - { - GtkWidget *window; - - window = _gtk_widget_get_toplevel (widget); - - if (window && _gtk_widget_is_toplevel (window)) - gtk_window_set_focus (GTK_WINDOW (window), NULL); - } + gtk_root_set_focus (priv->root, NULL); new_flags = priv->state_flags; diff --git a/gtk/gtkwidgetfocus.c b/gtk/gtkwidgetfocus.c index af68bd7a56..b1abae3894 100644 --- a/gtk/gtkwidgetfocus.c +++ b/gtk/gtkwidgetfocus.c @@ -155,15 +155,11 @@ static gboolean old_focus_coords (GtkWidget *widget, graphene_rect_t *old_focus_bounds) { - GtkWidget *toplevel = _gtk_widget_get_toplevel (widget); GtkWidget *old_focus; - if (GTK_IS_WINDOW (toplevel)) - { - old_focus = gtk_window_get_focus (GTK_WINDOW (toplevel)); - if (old_focus) - return gtk_widget_compute_bounds (old_focus, widget, old_focus_bounds); - } + old_focus = gtk_root_get_focus (gtk_widget_get_root (widget)); + if (old_focus) + return gtk_widget_compute_bounds (old_focus, widget, old_focus_bounds); return FALSE; } diff --git a/gtk/inspector/misc-info.c b/gtk/inspector/misc-info.c index 9c3b3ec05f..f352894daf 100644 --- a/gtk/inspector/misc-info.c +++ b/gtk/inspector/misc-info.c @@ -222,7 +222,7 @@ update_focus_widget (GtkInspectorMiscInfo *sl) { GtkWidget *widget; - widget = gtk_window_get_focus (GTK_WINDOW (sl->priv->object)); + widget = gtk_root_get_focus (GTK_ROOT (sl->priv->object)); if (widget) { gchar *tmp; @@ -249,7 +249,7 @@ show_focus_widget (GtkWidget *button, GtkInspectorMiscInfo *sl) { GtkWidget *widget; - widget = gtk_window_get_focus (GTK_WINDOW (sl->priv->object)); + widget = gtk_root_get_focus (GTK_ROOT (sl->priv->object)); if (widget) show_object (sl, G_OBJECT (widget), "properties"); } diff --git a/tests/testtoolbar.c b/tests/testtoolbar.c index 57c7ceb1b3..12160c8115 100644 --- a/tests/testtoolbar.c +++ b/tests/testtoolbar.c @@ -344,7 +344,7 @@ popup_context_menu (GtkToolbar *toolbar, gint x, gint y, gint button_number) GtkWidget *widget; window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (toolbar))); - widget = gtk_window_get_focus (window); + widget = gtk_root_get_focus (GTK_ROOT (window)); if (!widget) widget = GTK_WIDGET (toolbar); -- cgit v1.2.1 From 029ec38e63c41d13c20e763cfe3dae867f76ec13 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 2 Mar 2019 11:40:09 -0500 Subject: Move a check to gtk_window_set_focus gtk_widget_grab_focus is just a wrapper for gtk_window_set_focus. We should do all the enforcement there. --- gtk/gtkwidget.c | 3 --- gtk/gtkwindow.c | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index ff817a8abb..fe9a15f5bd 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -5337,9 +5337,6 @@ gtk_widget_grab_focus (GtkWidget *widget) { g_return_if_fail (GTK_IS_WIDGET (widget)); - if (!gtk_widget_is_sensitive (widget)) - return; - GTK_WIDGET_GET_CLASS (widget)->grab_focus (widget); } diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 3af2dea877..97a886009c 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -7331,6 +7331,9 @@ static void gtk_window_real_set_focus (GtkWindow *window, GtkWidget *focus) { + if (focus && !gtk_widget_is_sensitive (focus)) + return; + unset_focus_widget (window); set_focus_widget (window, focus); -- cgit v1.2.1 From 2738926dcba44c053e36ad1b454f9d55c7d28bc9 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 2 Mar 2019 12:52:56 -0500 Subject: Simplify the move_focus api No need to pass the array in from the outside. --- gtk/gtkwidget.c | 13 ++----------- gtk/gtkwidgetfocus.c | 21 ++++++++++++--------- gtk/gtkwidgetprivate.h | 3 +-- 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index fe9a15f5bd..6563563c9c 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -5459,17 +5459,8 @@ gtk_widget_real_focus (GtkWidget *widget, } else { - GPtrArray *focus_order = g_ptr_array_new (); - gboolean ret = FALSE; - - /* Try focusing any of the child widgets, depending on the given @direction */ - - gtk_widget_focus_sort (widget, direction, focus_order); - ret = gtk_widget_focus_move (widget, direction, focus_order); - - g_ptr_array_unref (focus_order); - - if (ret) + /* Try focusing any of the child widgets, depending on the given direction */ + if (gtk_widget_focus_move (widget, direction)) return TRUE; } diff --git a/gtk/gtkwidgetfocus.c b/gtk/gtkwidgetfocus.c index b1abae3894..c29adfdbe0 100644 --- a/gtk/gtkwidgetfocus.c +++ b/gtk/gtkwidgetfocus.c @@ -450,13 +450,17 @@ gtk_widget_focus_sort (GtkWidget *widget, gboolean gtk_widget_focus_move (GtkWidget *widget, - GtkDirectionType direction, - GPtrArray *focus_order) + GtkDirectionType direction) { + GPtrArray *focus_order; GtkWidget *focus_child = gtk_widget_get_focus_child (widget); int i; + gboolean ret = FALSE; + + focus_order = g_ptr_array_new (); + gtk_widget_focus_sort (widget, direction, focus_order); - for (i = 0; i < focus_order->len; i ++) + for (i = 0; i < focus_order->len && !ret; i++) { GtkWidget *child = g_ptr_array_index (focus_order, i); @@ -465,18 +469,17 @@ gtk_widget_focus_move (GtkWidget *widget, if (focus_child == child) { focus_child = NULL; - - if (gtk_widget_child_focus (child, direction)) - return TRUE; + ret = gtk_widget_child_focus (child, direction); } } else if (_gtk_widget_is_drawable (child) && gtk_widget_is_ancestor (child, widget)) { - if (gtk_widget_child_focus (child, direction)) - return TRUE; + ret = gtk_widget_child_focus (child, direction); } } - return FALSE; + g_ptr_array_unref (focus_order); + + return ret; } diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index ae8595e4dd..314d793090 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -317,8 +317,7 @@ void gtk_widget_focus_sort (GtkWidget *wi GtkDirectionType direction, GPtrArray *focus_order); gboolean gtk_widget_focus_move (GtkWidget *widget, - GtkDirectionType direction, - GPtrArray *focus_order); + GtkDirectionType direction); void gtk_widget_get_surface_allocation (GtkWidget *widget, GtkAllocation *allocation); -- cgit v1.2.1 From 8c1d852a848612fc0c63ab2b488fef6ce443325c Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 2 Mar 2019 13:22:43 -0500 Subject: widget: Drop the ::focus signal The focus vfunc is an implementation detail of GTK focus handling, and having external signal handlers interfere with it is not a good idea. --- gtk/gtkwidget.c | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 6563563c9c..2d76855c42 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -484,7 +484,6 @@ enum { GRAB_NOTIFY, CHILD_NOTIFY, MNEMONIC_ACTIVATE, - FOCUS, MOVE_FOCUS, KEYNAV_FAILED, DRAG_BEGIN, @@ -1670,23 +1669,6 @@ gtk_widget_class_init (GtkWidgetClass *klass) G_TYPE_BOOLEAN, 1, G_TYPE_BOOLEAN); - /** - * GtkWidget::focus: - * @widget: the object which received the signal. - * @direction: - * - * Returns: %TRUE to stop other handlers from being invoked for the event. %FALSE to propagate the event further. - */ - widget_signals[FOCUS] = - g_signal_new (I_("focus"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GtkWidgetClass, focus), - _gtk_boolean_handled_accumulator, NULL, - _gtk_marshal_BOOLEAN__ENUM, - G_TYPE_BOOLEAN, 1, - GTK_TYPE_DIRECTION_TYPE); - /** * GtkWidget::move-focus: * @widget: the object which received the signal. @@ -7489,8 +7471,6 @@ gboolean gtk_widget_child_focus (GtkWidget *widget, GtkDirectionType direction) { - gboolean return_val; - g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); if (!_gtk_widget_get_visible (widget) || @@ -7502,12 +7482,7 @@ gtk_widget_child_focus (GtkWidget *widget, * focus */ - g_signal_emit (widget, - widget_signals[FOCUS], - 0, - direction, &return_val); - - return return_val; + return GTK_WIDGET_GET_CLASS (widget)->focus (widget, direction); } /** -- cgit v1.2.1 From 94b0e99be5d860b13cc23fd7f7dd64ce7c3cb496 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 2 Mar 2019 20:32:11 -0500 Subject: Exclude non-drawable widgets from focus This was showing up as confusion between palette and editor in the color chooser. --- gtk/gtkwidgetfocus.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gtk/gtkwidgetfocus.c b/gtk/gtkwidgetfocus.c index c29adfdbe0..26f7f8ae24 100644 --- a/gtk/gtkwidgetfocus.c +++ b/gtk/gtkwidgetfocus.c @@ -422,7 +422,9 @@ gtk_widget_focus_sort (GtkWidget *widget, child != NULL; child = _gtk_widget_get_next_sibling (child)) { - if (_gtk_widget_get_realized (child)) + if (_gtk_widget_get_realized (child) && + _gtk_widget_is_drawable (child) && + gtk_widget_get_sensitive (child)) g_ptr_array_add (focus_order, child); } } -- cgit v1.2.1 From 15300f839e8078b7c18dd6acabf4da7e53553651 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 6 Mar 2019 22:26:27 -0500 Subject: widget: Add a private setter for has-focus --- gtk/gtkwidget.c | 13 +++++++++++++ gtk/gtkwidgetprivate.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 2d76855c42..c5eb6d63cb 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -11623,6 +11623,19 @@ gtk_widget_send_focus_change (GtkWidget *widget, return TRUE; } +void +gtk_widget_set_has_focus (GtkWidget *widget, + gboolean has_focus) +{ + GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); + + if (priv->has_focus == has_focus) + return; + + priv->has_focus = has_focus; + g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_HAS_FOCUS]); +} + /** * gtk_widget_in_destruction: * @widget: a #GtkWidget diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index 314d793090..ca30e9b0f3 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -318,6 +318,8 @@ void gtk_widget_focus_sort (GtkWidget *wi GPtrArray *focus_order); gboolean gtk_widget_focus_move (GtkWidget *widget, GtkDirectionType direction); +void gtk_widget_set_has_focus (GtkWidget *widget, + gboolean has_focus); void gtk_widget_get_surface_allocation (GtkWidget *widget, GtkAllocation *allocation); -- cgit v1.2.1 From 7819a5aab9282996fc23b5db470624b0a20f1388 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 2 Mar 2019 21:03:38 -0500 Subject: Drop gtk_widget_send_focus_change Replace this with gtk_widget_set_has_focus + gtk_widget_event. --- gtk/gtktreeview.c | 3 ++- gtk/gtkwidget.c | 50 -------------------------------------------------- gtk/gtkwidget.h | 3 --- gtk/gtkwidgetprivate.h | 1 + gtk/gtkwindow.c | 5 +++-- 5 files changed, 6 insertions(+), 56 deletions(-) diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index 1a4ed0488a..29da6f8876 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -10151,7 +10151,8 @@ send_focus_change (GtkWidget *widget, fevent->focus_change.in = in; gdk_event_set_device (fevent, device); - gtk_widget_send_focus_change (widget, fevent); + gtk_widget_set_has_focus (widget, in); + gtk_widget_event (widget, fevent); g_object_unref (fevent); } diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index c5eb6d63cb..f9dafac747 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -11573,56 +11573,6 @@ gtk_widget_get_overflow (GtkWidget *widget) return priv->overflow; } -/** - * gtk_widget_send_focus_change: - * @widget: a #GtkWidget - * @event: a #GdkEvent of type GDK_FOCUS_CHANGE - * - * Sends the focus change @event to @widget - * - * This function is not meant to be used by applications. The only time it - * should be used is when it is necessary for a #GtkWidget to assign focus - * to a widget that is semantically owned by the first widget even though - * it’s not a direct child - for instance, a search entry in a floating - * window similar to the quick search in #GtkTreeView. - * - * An example of its usage is: - * - * |[ - * GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE); - * - * fevent->focus_change.type = GDK_FOCUS_CHANGE; - * fevent->focus_change.in = TRUE; - * fevent->focus_change.surface = _gtk_widget_get_surface (widget); - * if (fevent->focus_change.surface != NULL) - * g_object_ref (fevent->focus_change.surface); - * - * gtk_widget_send_focus_change (widget, fevent); - * - * g_object_unref (event); - * ]| - * - * Returns: the return value from the event signal emission: %TRUE - * if the event was handled, and %FALSE otherwise - */ -gboolean -gtk_widget_send_focus_change (GtkWidget *widget, - GdkEvent *event) -{ - GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); - - g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); - g_return_val_if_fail (event != NULL && event->any.type == GDK_FOCUS_CHANGE, FALSE); - - priv->has_focus = event->focus_change.in; - - gtk_propagate_event (widget, event); - - g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_HAS_FOCUS]); - - return TRUE; -} - void gtk_widget_set_has_focus (GtkWidget *widget, gboolean has_focus) diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h index f3012b07a4..d9dbfaf885 100644 --- a/gtk/gtkwidget.h +++ b/gtk/gtkwidget.h @@ -451,9 +451,6 @@ gboolean gtk_widget_mnemonic_activate (GtkWidget *widget, GDK_AVAILABLE_IN_ALL gboolean gtk_widget_event (GtkWidget *widget, const GdkEvent *event); -GDK_AVAILABLE_IN_ALL -gboolean gtk_widget_send_focus_change (GtkWidget *widget, - GdkEvent *event); GDK_AVAILABLE_IN_ALL gboolean gtk_widget_activate (GtkWidget *widget); diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index ca30e9b0f3..231748d655 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -336,6 +336,7 @@ gboolean gtk_widget_run_controllers (GtkWidget const GdkEvent *event, GtkPropagationPhase phase); + /* inline getters */ static inline GtkWidget * diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 97a886009c..d2fd050ffc 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -7036,7 +7036,7 @@ gtk_window_real_activate_focus (GtkWindow *window) static void do_focus_change (GtkWidget *widget, - gboolean in) + gboolean in) { GdkSeat *seat; GList *devices, *d; @@ -7065,7 +7065,8 @@ do_focus_change (GtkWidget *widget, fevent->focus_change.in = in; gdk_event_set_device (fevent, dev); - gtk_widget_send_focus_change (widget, fevent); + gtk_widget_set_has_focus (widget, in); + gtk_widget_event (widget, fevent); g_object_unref (fevent); } -- cgit v1.2.1 From d279c666a9ea72e6bedc4eff1bfe2af9952b83d1 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 3 Mar 2019 07:55:14 -0500 Subject: inspector: Stop using ::set-focus The focus-widget is just a regular property now that shows up on the property page. No need to special-case it on the misc page anymore. --- gtk/inspector/misc-info.c | 50 ---------------------------------------------- gtk/inspector/misc-info.ui | 37 ---------------------------------- 2 files changed, 87 deletions(-) diff --git a/gtk/inspector/misc-info.c b/gtk/inspector/misc-info.c index f352894daf..1d9d053d7d 100644 --- a/gtk/inspector/misc-info.c +++ b/gtk/inspector/misc-info.c @@ -46,9 +46,6 @@ struct _GtkInspectorMiscInfoPrivate { GtkWidget *default_widget_row; GtkWidget *default_widget; GtkWidget *default_widget_button; - GtkWidget *focus_widget_row; - GtkWidget *focus_widget; - GtkWidget *focus_widget_button; GtkWidget *mnemonic_label_row; GtkWidget *mnemonic_label; GtkWidget *request_mode_row; @@ -217,43 +214,6 @@ show_default_widget (GtkWidget *button, GtkInspectorMiscInfo *sl) show_object (sl, G_OBJECT (widget), "properties"); } -static void -update_focus_widget (GtkInspectorMiscInfo *sl) -{ - GtkWidget *widget; - - widget = gtk_root_get_focus (GTK_ROOT (sl->priv->object)); - if (widget) - { - gchar *tmp; - tmp = g_strdup_printf ("%p", widget); - gtk_label_set_label (GTK_LABEL (sl->priv->focus_widget), tmp); - g_free (tmp); - gtk_widget_set_sensitive (sl->priv->focus_widget_button, TRUE); - } - else - { - gtk_label_set_label (GTK_LABEL (sl->priv->focus_widget), "NULL"); - gtk_widget_set_sensitive (sl->priv->focus_widget_button, FALSE); - } -} - -static void -set_focus_cb (GtkWindow *window, GtkWidget *focus, GtkInspectorMiscInfo *sl) -{ - update_focus_widget (sl); -} - -static void -show_focus_widget (GtkWidget *button, GtkInspectorMiscInfo *sl) -{ - GtkWidget *widget; - - widget = gtk_root_get_focus (GTK_ROOT (sl->priv->object)); - if (widget) - show_object (sl, G_OBJECT (widget), "properties"); -} - static void show_mnemonic_label (GtkWidget *button, GtkInspectorMiscInfo *sl) { @@ -358,7 +318,6 @@ update_info (gpointer data) if (GTK_IS_WINDOW (sl->priv->object)) { update_default_widget (sl); - update_focus_widget (sl); } if (GDK_IS_FRAME_CLOCK (sl->priv->object)) @@ -408,7 +367,6 @@ gtk_inspector_misc_info_set_object (GtkInspectorMiscInfo *sl, if (sl->priv->object) { g_signal_handlers_disconnect_by_func (sl->priv->object, state_flags_changed, sl); - g_signal_handlers_disconnect_by_func (sl->priv->object, set_focus_cb, sl); g_signal_handlers_disconnect_by_func (sl->priv->object, allocation_changed, sl); disconnect_each_other (sl->priv->object, G_OBJECT (sl)); disconnect_each_other (sl, sl->priv->object); @@ -475,14 +433,10 @@ gtk_inspector_misc_info_set_object (GtkInspectorMiscInfo *sl, if (GTK_IS_WINDOW (object)) { gtk_widget_show (sl->priv->default_widget_row); - gtk_widget_show (sl->priv->focus_widget_row); - - g_signal_connect_object (object, "set-focus", G_CALLBACK (set_focus_cb), sl, G_CONNECT_AFTER); } else { gtk_widget_hide (sl->priv->default_widget_row); - gtk_widget_hide (sl->priv->focus_widget_row); } if (GDK_IS_FRAME_CLOCK (object)) @@ -595,9 +549,6 @@ gtk_inspector_misc_info_class_init (GtkInspectorMiscInfoClass *klass) gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, default_widget_row); gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, default_widget); gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, default_widget_button); - gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, focus_widget_row); - gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, focus_widget); - gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, focus_widget_button); gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, mnemonic_label_row); gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, mnemonic_label); gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, request_mode_row); @@ -631,7 +582,6 @@ gtk_inspector_misc_info_class_init (GtkInspectorMiscInfoClass *klass) gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, child_visible); gtk_widget_class_bind_template_callback (widget_class, show_default_widget); - gtk_widget_class_bind_template_callback (widget_class, show_focus_widget); gtk_widget_class_bind_template_callback (widget_class, show_frame_clock); } diff --git a/gtk/inspector/misc-info.ui b/gtk/inspector/misc-info.ui index 0ee5082e24..cbb3ef65b4 100644 --- a/gtk/inspector/misc-info.ui +++ b/gtk/inspector/misc-info.ui @@ -157,42 +157,6 @@ - - - 0 - - - 10 - 40 - - - Focus Widget - start - baseline - 0.0 - 1 - - - - - 1 - end - baseline - end - - - - - end - baseline - Properties - - - - - - - 0 @@ -616,7 +580,6 @@ - -- cgit v1.2.1 From f13e6179e8638f840fa6df8d2583600e551850fb Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 3 Mar 2019 08:06:53 -0500 Subject: filechooser: Stop using ::set-focus We can achieve the same with the focus-widget property. --- gtk/gtkfilechooserwidget.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c index 7c7b32d119..3227a84e1f 100644 --- a/gtk/gtkfilechooserwidget.c +++ b/gtk/gtkfilechooserwidget.c @@ -341,6 +341,7 @@ struct _GtkFileChooserWidgetPrivate { GSource *focus_entry_idle; gulong toplevel_set_focus_id; + GtkWidget *toplevel_current_focus_widget; GtkWidget *toplevel_last_focus_widget; gint sort_column; @@ -3561,13 +3562,14 @@ gtk_file_chooser_widget_dispose (GObject *object) * widget on our toplevel. See gtk_file_chooser_widget_hierarchy_changed() */ static void -toplevel_set_focus_cb (GtkWindow *window, - GtkWidget *focus, +toplevel_set_focus_cb (GtkWindow *window, + GParamSpec *pspec, GtkFileChooserWidget *impl) { GtkFileChooserWidgetPrivate *priv = impl->priv; - priv->toplevel_last_focus_widget = gtk_root_get_focus (GTK_ROOT (window)); + priv->toplevel_last_focus_widget = priv->toplevel_current_focus_widget; + priv->toplevel_current_focus_widget = gtk_root_get_focus (GTK_ROOT (window)); } /* We monitor the focus widget on our toplevel to be able to know which widget @@ -3585,9 +3587,10 @@ gtk_file_chooser_widget_root (GtkWidget *widget) toplevel = gtk_widget_get_toplevel (widget); g_assert (priv->toplevel_set_focus_id == 0); - priv->toplevel_set_focus_id = g_signal_connect (toplevel, "set-focus", + priv->toplevel_set_focus_id = g_signal_connect (toplevel, "notify::focus-widget", G_CALLBACK (toplevel_set_focus_cb), impl); - priv->toplevel_last_focus_widget = gtk_root_get_focus (GTK_ROOT (toplevel)); + priv->toplevel_last_focus_widget = NULL; + priv->toplevel_current_focus_widget = gtk_root_get_focus (GTK_ROOT (toplevel)); } static void @@ -3603,6 +3606,7 @@ gtk_file_chooser_widget_unroot (GtkWidget *widget) g_signal_handler_disconnect (toplevel, priv->toplevel_set_focus_id); priv->toplevel_set_focus_id = 0; priv->toplevel_last_focus_widget = NULL; + priv->toplevel_current_focus_widget = NULL; } GTK_WIDGET_CLASS (gtk_file_chooser_widget_parent_class)->unroot (widget); -- cgit v1.2.1 From 31d9ecb5c30f8170af275901ccea8bf6f42ea17b Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 3 Mar 2019 08:10:14 -0500 Subject: popover: Stop using ::set-focus This will change completely when GtkPopover becomes a root. For now, stop using ::set-focus and just use the focus-widget property. --- gtk/gtkpopover.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gtk/gtkpopover.c b/gtk/gtkpopover.c index cfd697a234..c77ddc3f25 100644 --- a/gtk/gtkpopover.c +++ b/gtk/gtkpopover.c @@ -614,10 +614,11 @@ window_active_changed (GtkWindow *window, static void window_set_focus (GtkWindow *window, - GtkWidget *widget, + GParamSpec *pspec, GtkPopover *popover) { GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover); + GtkWidget *widget = gtk_root_get_focus (GTK_ROOT (window)); if (!priv->modal || !widget || !gtk_widget_is_drawable (GTK_WIDGET (popover))) return; @@ -673,7 +674,7 @@ gtk_popover_apply_modality (GtkPopover *popover, g_signal_connect (priv->window, "notify::is-active", G_CALLBACK (window_active_changed), popover); - g_signal_connect (priv->window, "set-focus", + g_signal_connect (priv->window, "notify::focus-widget", G_CALLBACK (window_set_focus), popover); } else -- cgit v1.2.1 From f68855341e9bb928f9190e2459866bc532a03a60 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 16 Mar 2019 01:28:23 -0400 Subject: window: Remove ::set-focus The focus-widget is now a property, so we don't need this signal anymore. --- gtk/gtkwindow.c | 63 ++++++++++++++++----------------------------------------- gtk/gtkwindow.h | 4 ---- 2 files changed, 17 insertions(+), 50 deletions(-) diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index d2fd050ffc..a26990f38b 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -440,8 +440,6 @@ static gint gtk_window_focus (GtkWidget *widget, GtkDirectionType direction); static void gtk_window_move_focus (GtkWidget *widget, GtkDirectionType dir); -static void gtk_window_real_set_focus (GtkWindow *window, - GtkWidget *focus); static void gtk_window_real_activate_default (GtkWindow *window); static void gtk_window_real_activate_focus (GtkWindow *window); @@ -816,8 +814,6 @@ gtk_window_class_init (GtkWindowClass *klass) container_class->remove = gtk_window_remove; container_class->forall = gtk_window_forall; - klass->set_focus = gtk_window_real_set_focus; - klass->activate_default = gtk_window_real_activate_default; klass->activate_focus = gtk_window_real_activate_focus; klass->keys_changed = gtk_window_keys_changed; @@ -1120,24 +1116,6 @@ gtk_window_class_init (GtkWindowClass *klass) g_object_class_install_properties (gobject_class, LAST_ARG, window_props); gtk_root_install_properties (gobject_class, LAST_ARG); - /** - * GtkWindow:set-focus: - * @window: the window which received the signal - * @widget: (nullable): the newly focused widget (or %NULL for no focus) - * - * This signal is emitted whenever the currently focused widget in - * this window changes. - */ - window_signals[SET_FOCUS] = - g_signal_new (I_("set-focus"), - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GtkWindowClass, set_focus), - NULL, NULL, - NULL, - G_TYPE_NONE, 1, - GTK_TYPE_WIDGET); - /** * GtkWindow::activate-focus: * @window: the window which received the signal @@ -2778,27 +2756,6 @@ gtk_window_get_role (GtkWindow *window) return priv->wm_role; } -/** - * gtk_window_set_focus: - * @window: a #GtkWindow - * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset - * any focus widget for the toplevel window. - * - * If @focus is not the current focus widget, and is focusable, sets - * it as the focus widget for the window. If @focus is %NULL, unsets - * the focus widget for this window. To set the focus to a particular - * widget in the toplevel, it is usually more convenient to use - * gtk_widget_grab_focus() instead of this function. - **/ -void -gtk_window_set_focus (GtkWindow *window, - GtkWidget *focus) -{ - g_return_if_fail (GTK_IS_WINDOW (window)); - - g_signal_emit (window, window_signals[SET_FOCUS], 0, focus); -} - /** * gtk_window_set_default: * @window: a #GtkWindow @@ -7328,10 +7285,24 @@ set_focus_widget (GtkWindow *window, do_focus_change (priv->focus_widget, TRUE); } -static void -gtk_window_real_set_focus (GtkWindow *window, - GtkWidget *focus) +/** + * gtk_window_set_focus: + * @window: a #GtkWindow + * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset + * any focus widget for the toplevel window. + * + * If @focus is not the current focus widget, and is focusable, sets + * it as the focus widget for the window. If @focus is %NULL, unsets + * the focus widget for this window. To set the focus to a particular + * widget in the toplevel, it is usually more convenient to use + * gtk_widget_grab_focus() instead of this function. + **/ +void +gtk_window_set_focus (GtkWindow *window, + GtkWidget *focus) { + g_return_if_fail (GTK_IS_WINDOW (window)); + if (focus && !gtk_widget_is_sensitive (focus)) return; diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h index fb30ab99b8..2b7a0078f5 100644 --- a/gtk/gtkwindow.h +++ b/gtk/gtkwindow.h @@ -57,7 +57,6 @@ struct _GtkWindow /** * GtkWindowClass: * @parent_class: The parent class. - * @set_focus: Sets child as the focus widget for the window. * @activate_focus: Activates the current focused widget within the window. * @activate_default: Activates the default widget for the window. * @keys_changed: Signal gets emitted when the set of accelerators or @@ -72,9 +71,6 @@ struct _GtkWindowClass /*< public >*/ - void (* set_focus) (GtkWindow *window, - GtkWidget *focus); - /* G_SIGNAL_ACTION signals for keybindings */ void (* activate_focus) (GtkWindow *window); -- cgit v1.2.1 From 7ca24f12d73a2b31bc890fbad6e12485cdc427f8 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 3 Mar 2019 12:31:12 -0500 Subject: window: Remove initial-focus builder support With focus-widget now a property, this is no longer needed. --- gtk/gtkwindow.c | 85 --------------------------------------------------------- tests/dialog.ui | 1 - 2 files changed, 86 deletions(-) diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index a26990f38b..bf6eeeb6da 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -122,16 +122,12 @@ * elements representing the #GtkAccelGroup objects you want to add to * your window (synonymous with gtk_window_add_accel_group(). * - * It also supports the element, whose name property names - * the widget to receive the focus when the window is mapped. - * * An example of a UI definition fragment with accel groups: * |[ * * * * - * * * * ... @@ -2350,55 +2346,6 @@ static const GMarkupParser window_parser = window_start_element }; -typedef struct { - GObject *object; - GtkBuilder *builder; - gchar *name; - gint line; - gint col; -} NameSubParserData; - -static void -focus_start_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **names, - const gchar **values, - gpointer user_data, - GError **error) -{ - NameSubParserData *data = (NameSubParserData*)user_data; - - if (strcmp (element_name, "initial-focus") == 0) - { - const gchar *name; - - if (!_gtk_builder_check_parent (data->builder, context, "object", error)) - return; - - if (!g_markup_collect_attributes (element_name, names, values, error, - G_MARKUP_COLLECT_STRING, "name", &name, - G_MARKUP_COLLECT_INVALID)) - { - _gtk_builder_prefix_error (data->builder, context, error); - return; - } - - data->name = g_strdup (name); - g_markup_parse_context_get_position (context, &data->line, &data->col); - } - else - { - _gtk_builder_error_unhandled_tag (data->builder, context, - "GtkWindow", element_name, - error); - } -} - -static const GMarkupParser focus_parser = -{ - focus_start_element -}; - static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable, GtkBuilder *builder, @@ -2426,21 +2373,6 @@ gtk_window_buildable_custom_tag_start (GtkBuildable *buildable, return TRUE; } - if (strcmp (tagname, "initial-focus") == 0) - { - NameSubParserData *data; - - data = g_slice_new0 (NameSubParserData); - data->name = NULL; - data->object = G_OBJECT (buildable); - data->builder = builder; - - *parser = focus_parser; - *parser_data = data; - - return TRUE; - } - return FALSE; } @@ -2463,23 +2395,6 @@ gtk_window_buildable_custom_finished (GtkBuildable *buildable, g_slice_free (GSListSubParserData, data); } - - if (strcmp (tagname, "initial-focus") == 0) - { - NameSubParserData *data = (NameSubParserData*)user_data; - - if (data->name) - { - GObject *object; - - object = _gtk_builder_lookup_object (builder, data->name, data->line, data->col); - if (object) - gtk_window_set_focus (GTK_WINDOW (buildable), GTK_WIDGET (object)); - g_free (data->name); - } - - g_slice_free (NameSubParserData, data); - } } static GdkDisplay * diff --git a/tests/dialog.ui b/tests/dialog.ui index 93aa2015bc..baa032ec48 100644 --- a/tests/dialog.ui +++ b/tests/dialog.ui @@ -239,6 +239,5 @@ cancel_button confirm_button - -- cgit v1.2.1 From a3abf0693d687e9b6325de6e7015f119ca846b94 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 4 Mar 2019 20:15:39 -0500 Subject: Clarify grab_focus docs --- gtk/gtkwidget.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index f9dafac747..ca206fc6a4 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -5303,16 +5303,11 @@ _gtk_widget_grab_notify (GtkWidget *widget, * gtk_widget_grab_focus: * @widget: a #GtkWidget * - * Causes @widget to have the keyboard focus for the #GtkWindow it's - * inside. @widget must be a focusable widget, such as a #GtkEntry; - * something like #GtkFrame won’t work. + * Causes @widget (or one of its descendents) to have the keyboard focus + * for the #GtkWindow it's inside. * - * More precisely, it must have the %GTK_CAN_FOCUS flag set. Use - * gtk_widget_set_can_focus() to modify that flag. - * - * The widget also needs to be realized and mapped. This is indicated by the - * related signals. Grabbing the focus immediately after creating the widget - * will likely fail and cause critical warnings. + * @widget must be focusable, or have a ::grab_focus implementation that + * transfers the focus to a descendant of @widget that is focusable. **/ void gtk_widget_grab_focus (GtkWidget *widget) @@ -5487,9 +5482,15 @@ gtk_widget_real_keynav_failed (GtkWidget *widget, * @widget: a #GtkWidget * @can_focus: whether or not @widget can own the input focus. * - * Specifies whether @widget can own the input focus. See - * gtk_widget_grab_focus() for actually setting the input focus on a - * widget. + * Specifies whether @widget can own the input focus. + * + * Note that having @can_focus be %TRUE is only one of the + * necessary conditions for being focusable. A widget must + * also be sensitive and not have a ancestor that is marked + * as not child-focusable in order to receive input focus. + * + * See gtk_widget_grab_focus() for actually setting the input + * focus on a widget. **/ void gtk_widget_set_can_focus (GtkWidget *widget, -- cgit v1.2.1 From 8d5f1ae6620dcf0d81d05c480fc4da194249d06b Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 6 Mar 2019 16:55:27 -0500 Subject: gdk: Add crossing mode and detail to focus events We want focus events more similar to crossing events. --- gdk/gdkevents.c | 10 ++++++++++ gdk/gdkeventsprivate.h | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c index 3b0944d3cc..55b744d4f3 100644 --- a/gdk/gdkevents.c +++ b/gdk/gdkevents.c @@ -1980,6 +1980,11 @@ gdk_event_get_crossing_mode (const GdkEvent *event, *mode = event->crossing.mode; return TRUE; } + else if (event->any.type == GDK_FOCUS_CHANGE) + { + *mode = event->focus_change.mode; + return TRUE; + } return FALSE; } @@ -2006,6 +2011,11 @@ gdk_event_get_crossing_detail (const GdkEvent *event, *detail = event->crossing.detail; return TRUE; } + else if (event->any.type == GDK_FOCUS_CHANGE) + { + *detail = event->focus_change.detail; + return TRUE; + } return FALSE; } diff --git a/gdk/gdkeventsprivate.h b/gdk/gdkeventsprivate.h index b81faba589..1c6756e60a 100644 --- a/gdk/gdkeventsprivate.h +++ b/gdk/gdkeventsprivate.h @@ -312,6 +312,8 @@ struct _GdkEventCrossing * @send_event: %TRUE if the event was sent explicitly. * @in: %TRUE if the surface has gained the keyboard focus, %FALSE if * it has lost the focus. + * @mode: the crossing mode + * @detail: the kind of crossing that happened * * Describes a change of keyboard focus. */ @@ -319,6 +321,8 @@ struct _GdkEventFocus { GdkEventAny any; gint16 in; + GdkCrossingMode mode; + GdkNotifyType detail; }; /* -- cgit v1.2.1 From c73972f7df8bfc630ffca58f9f21502dab3f8fb7 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 8 Mar 2019 11:27:16 -0500 Subject: gdk: Rename gdk_event_set_user_data Lets call it what it is, the target. All of this is private api anyway. Update all callers. --- gdk/gdk-private.h | 2 -- gdk/gdkevents.c | 16 ++++++++-------- gdk/gdkeventsprivate.h | 7 ++++--- gtk/gtkmain.c | 6 +++--- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/gdk/gdk-private.h b/gdk/gdk-private.h index 9344ac2e49..b5551b750c 100644 --- a/gdk/gdk-private.h +++ b/gdk/gdk-private.h @@ -20,8 +20,6 @@ void gdk_surface_thaw_toplevel_updates (GdkSurface *surface); gboolean gdk_surface_supports_edge_constraints (GdkSurface *surface); -GObject * gdk_event_get_user_data (const GdkEvent *event); - guint32 gdk_display_get_last_seen_time (GdkDisplay *display); void gdk_display_set_double_click_time (GdkDisplay *display, diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c index 55b744d4f3..bacc1eb777 100644 --- a/gdk/gdkevents.c +++ b/gdk/gdkevents.c @@ -564,8 +564,8 @@ gdk_event_copy (const GdkEvent *event) g_object_ref (new_event->any.device); if (new_event->any.source_device) g_object_ref (new_event->any.source_device); - if (new_event->any.user_data) - g_object_ref (new_event->any.user_data); + if (new_event->any.target) + g_object_ref (new_event->any.target); switch ((guint) event->any.type) { @@ -675,7 +675,7 @@ gdk_event_finalize (GObject *object) g_clear_object (&event->any.device); g_clear_object (&event->any.source_device); - g_clear_object (&event->any.user_data); + g_clear_object (&event->any.target); G_OBJECT_CLASS (gdk_event_parent_class)->finalize (object); } @@ -1904,16 +1904,16 @@ gdk_event_get_scancode (GdkEvent *event) } void -gdk_event_set_user_data (GdkEvent *event, - GObject *user_data) +gdk_event_set_target (GdkEvent *event, + GObject *target) { - g_set_object (&event->any.user_data, user_data); + g_set_object (&event->any.target, target); } GObject * -gdk_event_get_user_data (const GdkEvent *event) +gdk_event_get_target (const GdkEvent *event) { - return event->any.user_data; + return event->any.target; } /** diff --git a/gdk/gdkeventsprivate.h b/gdk/gdkeventsprivate.h index 1c6756e60a..f3ccd3d9f7 100644 --- a/gdk/gdkeventsprivate.h +++ b/gdk/gdkeventsprivate.h @@ -61,7 +61,7 @@ struct _GdkEventAny GdkDevice *device; GdkDevice *source_device; GdkDisplay *display; - GObject *user_data; + GObject *target; }; /* @@ -636,8 +636,9 @@ union _GdkEvent GdkEventPadGroupMode pad_group_mode; }; -void gdk_event_set_user_data (GdkEvent *event, - GObject *user_data); +void gdk_event_set_target (GdkEvent *event, + GObject *user_data); +GObject * gdk_event_get_target (const GdkEvent *event); #endif /* __GDK_EVENTS_PRIVATE_H__ */ diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index be19d7389c..9cc8c22e7d 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1416,7 +1416,7 @@ synth_crossing (GtkWidget *widget, gdouble x, y; event = gdk_event_new (enter ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY); - gdk_event_set_user_data (event, G_OBJECT (widget)); + gdk_event_set_target (event, G_OBJECT (widget)); gdk_event_set_device (event, gdk_event_get_device (source)); gdk_event_set_source_device (event, gdk_event_get_source_device (source)); @@ -1779,7 +1779,7 @@ gtk_main_do_event (GdkEvent *event) if (!target_widget) goto cleanup; - gdk_event_set_user_data (event, G_OBJECT (target_widget)); + gdk_event_set_target (event, G_OBJECT (target_widget)); window_group = gtk_main_get_window_group (target_widget); device = gdk_event_get_device (event); @@ -2398,7 +2398,7 @@ gtk_get_event_widget (const GdkEvent *event) GtkWidget * gtk_get_event_target (const GdkEvent *event) { - return GTK_WIDGET (gdk_event_get_user_data (event)); + return GTK_WIDGET (gdk_event_get_target (event)); } /** -- cgit v1.2.1 From 06f790d6630d2265841571ded13f78b6d465c3e2 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 8 Mar 2019 11:12:30 -0500 Subject: gdk: Add a related_target field to some events Crossing and focus change events are emitted between two widgets, and want to associate both with the events. --- gdk/gdkevents.c | 35 +++++++++++++++++++++++++++++++++++ gdk/gdkeventsprivate.h | 5 +++++ 2 files changed, 40 insertions(+) diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c index bacc1eb777..d9e9af6eef 100644 --- a/gdk/gdkevents.c +++ b/gdk/gdkevents.c @@ -573,6 +573,13 @@ gdk_event_copy (const GdkEvent *event) case GDK_LEAVE_NOTIFY: if (event->crossing.child_surface != NULL) g_object_ref (event->crossing.child_surface); + if (event->crossing.related_target) + g_object_ref (event->crossing.related_target); + break; + + case GDK_FOCUS_CHANGE: + if (event->focus_change.related_target) + g_object_ref (event->focus_change.related_target); break; case GDK_DRAG_ENTER: @@ -634,6 +641,11 @@ gdk_event_finalize (GObject *object) case GDK_ENTER_NOTIFY: case GDK_LEAVE_NOTIFY: g_clear_object (&event->crossing.child_surface); + g_clear_object (&event->crossing.related_target); + break; + + case GDK_FOCUS_CHANGE: + g_clear_object (&event->focus_change.related_target); break; case GDK_DRAG_ENTER: @@ -1916,6 +1928,29 @@ gdk_event_get_target (const GdkEvent *event) return event->any.target; } +void +gdk_event_set_related_target (GdkEvent *event, + GObject *target) +{ + if (event->any.type == GDK_ENTER_NOTIFY || + event->any.type == GDK_LEAVE_NOTIFY) + g_set_object (&event->crossing.related_target, target); + else if (event->any.type == GDK_FOCUS_CHANGE) + g_set_object (&event->focus_change.related_target, target); +} + +GObject * +gdk_event_get_related_target (const GdkEvent *event) +{ + if (event->any.type == GDK_ENTER_NOTIFY || + event->any.type == GDK_LEAVE_NOTIFY) + return event->crossing.related_target; + else if (event->any.type == GDK_FOCUS_CHANGE) + return event->focus_change.related_target; + + return NULL; +} + /** * gdk_event_is_sent: * @event: a #GdkEvent diff --git a/gdk/gdkeventsprivate.h b/gdk/gdkeventsprivate.h index f3ccd3d9f7..2db43d9a82 100644 --- a/gdk/gdkeventsprivate.h +++ b/gdk/gdkeventsprivate.h @@ -303,6 +303,7 @@ struct _GdkEventCrossing GdkNotifyType detail; gboolean focus; guint state; + GObject *related_target; }; /* @@ -323,6 +324,7 @@ struct _GdkEventFocus gint16 in; GdkCrossingMode mode; GdkNotifyType detail; + GObject *related_target; }; /* @@ -639,6 +641,9 @@ union _GdkEvent void gdk_event_set_target (GdkEvent *event, GObject *user_data); GObject * gdk_event_get_target (const GdkEvent *event); +void gdk_event_set_related_target (GdkEvent *event, + GObject *user_data); +GObject * gdk_event_get_related_target (const GdkEvent *event); #endif /* __GDK_EVENTS_PRIVATE_H__ */ -- cgit v1.2.1 From cdcd2bb073e55a50eacad04497fbbb6eacac378a Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 6 Mar 2019 22:25:31 -0500 Subject: Share crossing and focus change event code Make a single function that can emit both enter/leave and focus change events. --- gtk/gtkmain.c | 106 +++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 67 insertions(+), 39 deletions(-) diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 9cc8c22e7d..70a7c43313 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1407,61 +1407,65 @@ static void synth_crossing (GtkWidget *widget, GtkWidget *toplevel, gboolean enter, - GtkWidget *other_widget, + GtkWidget *target, + GtkWidget *related_target, GdkEvent *source, GdkNotifyType notify_type, GdkCrossingMode crossing_mode) { GdkEvent *event; - gdouble x, y; + GtkStateFlags flags; + + if (gdk_event_get_event_type (source) == GDK_FOCUS_CHANGE) + { + event = gdk_event_new (GDK_FOCUS_CHANGE); + event->focus_change.in = enter; + event->focus_change.mode = crossing_mode; + event->focus_change.detail = notify_type; + + flags = GTK_STATE_FLAG_FOCUSED; + if (!GTK_IS_WINDOW (toplevel) || gtk_window_get_focus_visible (GTK_WINDOW (toplevel))) + flags |= GTK_STATE_FLAG_FOCUS_VISIBLE; + } + else + { + gdouble x, y; + event = gdk_event_new (enter ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY); + if (related_target) + event->crossing.child_surface = g_object_ref (gtk_widget_get_surface (related_target)); + gdk_event_get_coords (source, &x, &y); + event->crossing.x = x; + event->crossing.y = y; + event->crossing.mode = crossing_mode; + event->crossing.detail = notify_type; + + flags = GTK_STATE_FLAG_PRELIGHT; + } - event = gdk_event_new (enter ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY); - gdk_event_set_target (event, G_OBJECT (widget)); + gdk_event_set_target (event, G_OBJECT (target)); + gdk_event_set_related_target (event, G_OBJECT (related_target)); gdk_event_set_device (event, gdk_event_get_device (source)); gdk_event_set_source_device (event, gdk_event_get_source_device (source)); event->any.surface = g_object_ref (gtk_widget_get_surface (toplevel)); - if (other_widget) - event->crossing.child_surface = g_object_ref (gtk_widget_get_surface (other_widget)); if (enter) - gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_PRELIGHT, FALSE); + gtk_widget_set_state_flags (widget, flags, FALSE); else - gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_PRELIGHT); - - gdk_event_get_coords (source, &x, &y); - event->crossing.x = x; - event->crossing.y = y; - event->crossing.mode = crossing_mode; - event->crossing.detail = notify_type; + gtk_widget_unset_state_flags (widget, flags); + if (gdk_event_get_event_type (source) == GDK_FOCUS_CHANGE) + { + if (notify_type == GDK_NOTIFY_ANCESTOR || + notify_type == GDK_NOTIFY_INFERIOR || + notify_type == GDK_NOTIFY_NONLINEAR) + gtk_widget_set_has_focus (widget, enter); + } + gtk_widget_event (widget, event); g_object_unref (event); } -static GtkWidget * -update_pointer_focus_state (GtkWindow *toplevel, - GdkEvent *event, - GtkWidget *new_target) -{ - GtkWidget *old_target = NULL; - GdkEventSequence *sequence; - GdkDevice *device; - gdouble x, y; - - device = gdk_event_get_device (event); - sequence = gdk_event_get_event_sequence (event); - old_target = gtk_window_lookup_pointer_focus_widget (toplevel, device, sequence); - if (old_target == new_target) - return old_target; - - gdk_event_get_coords (event, &x, &y); - gtk_window_update_pointer_focus (toplevel, device, sequence, - new_target, x, y); - - return old_target; -} - static void gtk_synthesize_crossing_events (GtkWindow *toplevel, GtkWidget *old_target, @@ -1498,7 +1502,7 @@ gtk_synthesize_crossing_events (GtkWindow *toplevel, leave_type : get_virtual_notify_type (leave_type); synth_crossing (widget, GTK_WIDGET (toplevel), FALSE, - new_target, event, notify_type, mode); + old_target, new_target, event, notify_type, mode); widget = gtk_widget_get_parent (widget); } } @@ -1523,11 +1527,35 @@ gtk_synthesize_crossing_events (GtkWindow *toplevel, enter_type : get_virtual_notify_type (enter_type); synth_crossing (widget, GTK_WIDGET (toplevel), TRUE, - old_target, event, notify_type, mode); + new_target, old_target, event, notify_type, mode); } } } + +static GtkWidget * +update_pointer_focus_state (GtkWindow *toplevel, + GdkEvent *event, + GtkWidget *new_target) +{ + GtkWidget *old_target = NULL; + GdkEventSequence *sequence; + GdkDevice *device; + gdouble x, y; + + device = gdk_event_get_device (event); + sequence = gdk_event_get_event_sequence (event); + old_target = gtk_window_lookup_pointer_focus_widget (toplevel, device, sequence); + if (old_target == new_target) + return old_target; + + gdk_event_get_coords (event, &x, &y); + gtk_window_update_pointer_focus (toplevel, device, sequence, + new_target, x, y); + + return old_target; +} + static gboolean is_pointing_event (GdkEvent *event) { -- cgit v1.2.1 From adb547a1478738828c09595f848b6105328df5bc Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 6 Mar 2019 23:39:53 -0500 Subject: Export gtk_synthesize_crossing_events internally We want to use this for focus changes, now that it can emit focus change events. --- gtk/gtkmain.c | 2 +- gtk/gtkwidgetprivate.h | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 70a7c43313..043d02e221 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1466,7 +1466,7 @@ synth_crossing (GtkWidget *widget, g_object_unref (event); } -static void +void gtk_synthesize_crossing_events (GtkWindow *toplevel, GtkWidget *old_target, GtkWidget *new_target, diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index 231748d655..d995faa87a 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -242,6 +242,12 @@ GdkSurface * _gtk_widget_get_device_surface (GtkWidget *widget, GdkDevice *device); GList * _gtk_widget_list_devices (GtkWidget *widget); +void gtk_synthesize_crossing_events (GtkWindow *toplevel, + GtkWidget *from, + GtkWidget *to, + GdkEvent *event, + GdkCrossingMode mode); + void _gtk_widget_synthesize_crossing (GtkWidget *from, GtkWidget *to, GdkDevice *device, -- cgit v1.2.1 From 4238a04c7be9717ae8efc1debd709b10a82f9268 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 6 Mar 2019 23:40:29 -0500 Subject: window: Use gtk_synthesize_crossing_events Emit focus change events in the same way as crossing events. Also change the code to only emit focus change events for the master keyboard - we only maintain a single focus location, so sending multiple focus change events for different devices seems confusing. --- gtk/gtkwindow.c | 119 ++++++++++++++++++++++++-------------------------------- 1 file changed, 51 insertions(+), 68 deletions(-) diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index bf6eeeb6da..85a965c169 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -6911,40 +6911,28 @@ do_focus_change (GtkWidget *widget, gboolean in) { GdkSeat *seat; - GList *devices, *d; - - g_object_ref (widget); + GdkDevice *device; + GdkEvent *event; seat = gdk_display_get_default_seat (gtk_widget_get_display (widget)); - devices = gdk_seat_get_slaves (seat, GDK_SEAT_CAPABILITY_KEYBOARD); - devices = g_list_prepend (devices, gdk_seat_get_keyboard (seat)); - - for (d = devices; d; d = d->next) - { - GdkDevice *dev = d->data; - GdkEvent *fevent; - GdkSurface *surface; - - surface = _gtk_widget_get_surface (widget); + device = gdk_seat_get_keyboard (seat); - fevent = gdk_event_new (GDK_FOCUS_CHANGE); - gdk_event_set_display (fevent, gtk_widget_get_display (widget)); + event = gdk_event_new (GDK_FOCUS_CHANGE); + gdk_event_set_display (event, gtk_widget_get_display (widget)); + gdk_event_set_device (event, device); - fevent->any.type = GDK_FOCUS_CHANGE; - fevent->any.surface = surface; - if (surface) - g_object_ref (surface); - fevent->focus_change.in = in; - gdk_event_set_device (fevent, dev); + event->any.type = GDK_FOCUS_CHANGE; + event->any.surface = _gtk_widget_get_surface (widget); + if (event->any.surface) + g_object_ref (event->any.surface); + event->focus_change.in = in; + event->focus_change.mode = GDK_CROSSING_STATE_CHANGED; + event->focus_change.detail = GDK_NOTIFY_ANCESTOR; - gtk_widget_set_has_focus (widget, in); - gtk_widget_event (widget, fevent); + gtk_widget_set_has_focus (widget, in); + gtk_widget_event (widget, event); - g_object_unref (fevent); - } - - g_list_free (devices); - g_object_unref (widget); + g_object_unref (event); } static gboolean @@ -7162,44 +7150,6 @@ gtk_window_move_focus (GtkWidget *widget, gtk_window_set_focus (GTK_WINDOW (widget), NULL); } -static void -unset_focus_widget (GtkWindow *window) -{ - GtkWindowPrivate *priv = gtk_window_get_instance_private (window); - GtkWidget *f; - - for (f = priv->focus_widget; f; f = gtk_widget_get_parent (f)) - gtk_widget_unset_state_flags (f, GTK_STATE_FLAG_FOCUSED|GTK_STATE_FLAG_FOCUS_VISIBLE); - - if (priv->focus_widget) - do_focus_change (priv->focus_widget, FALSE); - g_set_object (&priv->focus_widget, NULL); -} - -static void -set_focus_widget (GtkWindow *window, - GtkWidget *focus) -{ - GtkWindowPrivate *priv = gtk_window_get_instance_private (window); - GtkWidget *f; - GtkStateFlags flags = GTK_STATE_FLAG_FOCUSED; - - if (gtk_window_get_focus_visible (window)) - flags |= GTK_STATE_FLAG_FOCUS_VISIBLE; - - for (f = focus; f; f = gtk_widget_get_parent (f)) - { - GtkWidget *parent = gtk_widget_get_parent (f); - gtk_widget_set_state_flags (f, flags, FALSE); - if (parent) - gtk_widget_set_focus_child (parent, f); - } - - g_set_object (&priv->focus_widget, focus); - if (priv->focus_widget) - do_focus_change (priv->focus_widget, TRUE); -} - /** * gtk_window_set_focus: * @window: a #GtkWindow @@ -7216,13 +7166,46 @@ void gtk_window_set_focus (GtkWindow *window, GtkWidget *focus) { + GtkWindowPrivate *priv = gtk_window_get_instance_private (window); + GtkWidget *old_focus = NULL; + GtkWidget *f; + GdkSeat *seat; + GdkDevice *device; + GdkEvent *event; + g_return_if_fail (GTK_IS_WINDOW (window)); if (focus && !gtk_widget_is_sensitive (focus)) return; - unset_focus_widget (window); - set_focus_widget (window, focus); + if (priv->focus_widget) + old_focus = g_object_ref (priv->focus_widget); + g_set_object (&priv->focus_widget, NULL); + + seat = gdk_display_get_default_seat (gtk_widget_get_display (GTK_WIDGET (window))); + device = gdk_seat_get_keyboard (seat); + + event = gdk_event_new (GDK_FOCUS_CHANGE); + gdk_event_set_display (event, gtk_widget_get_display (GTK_WIDGET (window))); + gdk_event_set_device (event, device); + event->any.surface = _gtk_widget_get_surface (GTK_WIDGET (window)); + if (event->any.surface) + g_object_ref (event->any.surface); + + gtk_synthesize_crossing_events (window, old_focus, focus, event, GDK_CROSSING_NORMAL); + + g_object_unref (event); + + g_set_object (&priv->focus_widget, focus); + + g_clear_object (&old_focus); + + for (f = focus; f; f = gtk_widget_get_parent (f)) + { + GtkWidget *parent = gtk_widget_get_parent (f); + if (parent) + gtk_widget_set_focus_child (parent, f); + } g_object_notify (G_OBJECT (window), "focus-widget"); } -- cgit v1.2.1 From 7d354b5084b75ffb38d1e35e76d2fd4cefae92f6 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 8 Mar 2019 09:08:05 -0500 Subject: Some fixes to crossing event generation In the inferior and ancestor cases, we were missing the initial/final event. --- gtk/gtkmain.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 043d02e221..e3c8b930cc 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1447,7 +1447,9 @@ synth_crossing (GtkWidget *widget, gdk_event_set_device (event, gdk_event_get_device (source)); gdk_event_set_source_device (event, gdk_event_get_source_device (source)); - event->any.surface = g_object_ref (gtk_widget_get_surface (toplevel)); + event->any.surface = gtk_widget_get_surface (toplevel); + if (event->any.surface) + g_object_ref (event->any.surface); if (enter) gtk_widget_set_state_flags (widget, flags, FALSE); @@ -1496,13 +1498,16 @@ gtk_synthesize_crossing_events (GtkWindow *toplevel, { widget = old_target; - while (widget != ancestor) + while (widget) { notify_type = (widget == old_target) ? leave_type : get_virtual_notify_type (leave_type); - synth_crossing (widget, GTK_WIDGET (toplevel), FALSE, - old_target, new_target, event, notify_type, mode); + if (widget != ancestor || widget == old_target) + synth_crossing (widget, GTK_WIDGET (toplevel), FALSE, + old_target, new_target, event, notify_type, mode); + if (widget == ancestor) + break; widget = gtk_widget_get_parent (widget); } } @@ -1513,9 +1518,11 @@ gtk_synthesize_crossing_events (GtkWindow *toplevel, widget = new_target; - while (widget != ancestor) + while (widget) { widgets = g_slist_prepend (widgets, widget); + if (widget == ancestor) + break; widget = gtk_widget_get_parent (widget); } @@ -1526,8 +1533,9 @@ gtk_synthesize_crossing_events (GtkWindow *toplevel, notify_type = (widget == new_target) ? enter_type : get_virtual_notify_type (enter_type); - synth_crossing (widget, GTK_WIDGET (toplevel), TRUE, - new_target, old_target, event, notify_type, mode); + if (widget != ancestor || widget == new_target) + synth_crossing (widget, GTK_WIDGET (toplevel), TRUE, + new_target, old_target, event, notify_type, mode); } } } -- cgit v1.2.1 From 888b92674f492c9932c18cabb76217b2b97dd4bb Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 8 Mar 2019 13:52:46 -0500 Subject: Move maintaining the focus chain Put this code in the same place where we generate the crossing events. --- gtk/gtkmain.c | 15 +++++++++++++++ gtk/gtkwindow.c | 8 -------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index e3c8b930cc..92873dee1e 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1458,6 +1458,21 @@ synth_crossing (GtkWidget *widget, if (gdk_event_get_event_type (source) == GDK_FOCUS_CHANGE) { + /* maintain focus chain */ + if (enter || notify_type == GDK_NOTIFY_INFERIOR) + { + GtkWidget *parent = gtk_widget_get_parent (widget); + if (parent) + gtk_widget_set_focus_child (parent, widget); + } + else if (!enter && notify_type != GDK_NOTIFY_INFERIOR) + { + GtkWidget *parent = gtk_widget_get_parent (widget); + if (parent) + gtk_widget_set_focus_child (parent, NULL); + } + + /* maintain widget state */ if (notify_type == GDK_NOTIFY_ANCESTOR || notify_type == GDK_NOTIFY_INFERIOR || notify_type == GDK_NOTIFY_NONLINEAR) diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 85a965c169..976777717d 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -7168,7 +7168,6 @@ gtk_window_set_focus (GtkWindow *window, { GtkWindowPrivate *priv = gtk_window_get_instance_private (window); GtkWidget *old_focus = NULL; - GtkWidget *f; GdkSeat *seat; GdkDevice *device; GdkEvent *event; @@ -7200,13 +7199,6 @@ gtk_window_set_focus (GtkWindow *window, g_clear_object (&old_focus); - for (f = focus; f; f = gtk_widget_get_parent (f)) - { - GtkWidget *parent = gtk_widget_get_parent (f); - if (parent) - gtk_widget_set_focus_child (parent, f); - } - g_object_notify (G_OBJECT (window), "focus-widget"); } -- cgit v1.2.1 From 921eccb4592f8cbd9b06eb14be74dbcbd065bff7 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 7 Mar 2019 00:14:26 -0500 Subject: Pass mode and detail to focus-in/out signals This information is useful when maintaining a 'last focus' field. Update all users. --- gtk/gtkcalendar.c | 4 ++++ gtk/gtkeventcontrollerkey.c | 32 +++++++++++++++++++++++--------- gtk/gtkspinbutton.c | 2 ++ gtk/gtktreeview.c | 4 ++++ gtk/gtktreeviewcolumn.c | 2 ++ 5 files changed, 35 insertions(+), 9 deletions(-) diff --git a/gtk/gtkcalendar.c b/gtk/gtkcalendar.c index 6b941ced3e..32df686852 100644 --- a/gtk/gtkcalendar.c +++ b/gtk/gtkcalendar.c @@ -295,6 +295,8 @@ static gboolean gtk_calendar_key_controller_key_pressed (GtkEventControllerKey * GdkModifierType state, GtkWidget *widget); static void gtk_calendar_key_controller_focus (GtkEventControllerKey *controller, + GdkCrossingMode mode, + GdkNotifyType detail, GtkWidget *widget); static void gtk_calendar_grab_notify (GtkWidget *widget, gboolean was_grabbed); @@ -2854,6 +2856,8 @@ gtk_calendar_key_controller_key_pressed (GtkEventControllerKey *controller, static void gtk_calendar_key_controller_focus (GtkEventControllerKey *key, + GdkCrossingMode mode, + GdkNotifyType detail, GtkWidget *widget) { GtkCalendar *calendar = GTK_CALENDAR (widget); diff --git a/gtk/gtkeventcontrollerkey.c b/gtk/gtkeventcontrollerkey.c index f1b28d999b..2c5a69f7a7 100644 --- a/gtk/gtkeventcontrollerkey.c +++ b/gtk/gtkeventcontrollerkey.c @@ -93,11 +93,16 @@ gtk_event_controller_key_handle_event (GtkEventController *controller, if (event_type == GDK_FOCUS_CHANGE) { gboolean focus_in; + GdkCrossingMode mode; + GdkNotifyType detail; + + gdk_event_get_crossing_mode (event, &mode); + gdk_event_get_crossing_detail (event, &detail); if (gdk_event_get_focus_in (event, &focus_in) && focus_in) - g_signal_emit (controller, signals[FOCUS_IN], 0); + g_signal_emit (controller, signals[FOCUS_IN], 0, mode, detail); else - g_signal_emit (controller, signals[FOCUS_OUT], 0); + g_signal_emit (controller, signals[FOCUS_OUT], 0, mode, detail); return FALSE; } @@ -233,12 +238,14 @@ gtk_event_controller_key_class_init (GtkEventControllerKeyClass *klass) GTK_TYPE_EVENT_CONTROLLER_KEY, G_SIGNAL_RUN_LAST, 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, G_TYPE_NONE, 0); /** * GtkEventControllerKey::focus-in: * @controller: the object which received the signal. + * @mode: crossing mode indicating what caused this change + * @detail: detail indication where the focus is coming from * * This signal is emitted whenever the #GtkEventController:widget controlled * by the @controller is given the keyboard focus. @@ -248,12 +255,17 @@ gtk_event_controller_key_class_init (GtkEventControllerKeyClass *klass) GTK_TYPE_EVENT_CONTROLLER_KEY, G_SIGNAL_RUN_LAST, 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + NULL, + G_TYPE_NONE, + 2, + GDK_TYPE_CROSSING_MODE, + GDK_TYPE_NOTIFY_TYPE); /** * GtkEventControllerKey::focus-out: * @controller: the object which received the signal. + * @mode: crossing mode indicating what caused this change + * @detail: detail indication where the focus is going * * This signal is emitted whenever the #GtkEventController:widget controlled * by the @controller loses the keyboard focus. @@ -263,8 +275,11 @@ gtk_event_controller_key_class_init (GtkEventControllerKeyClass *klass) GTK_TYPE_EVENT_CONTROLLER_KEY, G_SIGNAL_RUN_LAST, 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + NULL, + G_TYPE_NONE, + 2, + GDK_TYPE_CROSSING_MODE, + GDK_TYPE_NOTIFY_TYPE); } static void @@ -283,8 +298,7 @@ gtk_event_controller_key_init (GtkEventControllerKey *controller) GtkEventController * gtk_event_controller_key_new (void) { - return g_object_new (GTK_TYPE_EVENT_CONTROLLER_KEY, - NULL); + return g_object_new (GTK_TYPE_EVENT_CONTROLLER_KEY, NULL); } /** diff --git a/gtk/gtkspinbutton.c b/gtk/gtkspinbutton.c index 8e16faa837..b273b2e30d 100644 --- a/gtk/gtkspinbutton.c +++ b/gtk/gtkspinbutton.c @@ -824,6 +824,8 @@ key_controller_key_released (GtkEventControllerKey *key, static void key_controller_focus_out (GtkEventControllerKey *key, + GdkCrossingMode mode, + GdkNotifyType detail, GtkSpinButton *spin_button) { GtkSpinButtonPrivate *priv = gtk_spin_button_get_instance_private (spin_button); diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index 29da6f8876..6a45c7893d 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -614,6 +614,8 @@ static void gtk_tree_view_key_controller_key_released (GtkEventControllerKey GdkModifierType state, GtkTreeView *tree_view); static void gtk_tree_view_key_controller_focus_out (GtkEventControllerKey *key, + GdkCrossingMode mode, + GdkNotifyType detail, GtkTreeView *tree_view); static gint gtk_tree_view_focus (GtkWidget *widget, @@ -5475,6 +5477,8 @@ gtk_tree_view_motion_controller_leave (GtkEventControllerMotion *controller, static void gtk_tree_view_key_controller_focus_out (GtkEventControllerKey *key, + GdkCrossingMode mode, + GdkNotifyType detail, GtkTreeView *tree_view) { gtk_widget_queue_draw (GTK_WIDGET (tree_view)); diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c index 8c113ad3c4..78e22c5ef2 100644 --- a/gtk/gtktreeviewcolumn.c +++ b/gtk/gtktreeviewcolumn.c @@ -814,6 +814,8 @@ gtk_tree_view_column_cell_layout_get_area (GtkCellLayout *cell_layout) static void focus_in (GtkEventControllerKey *controller, + GdkCrossingMode mode, + GdkNotifyType detail, GtkTreeViewColumn *column) { _gtk_tree_view_set_focus_column (GTK_TREE_VIEW (column->priv->tree_view), column); -- cgit v1.2.1 From 2f1194c0c108274ee3ea2ecc7bd7921de317ab4b Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 8 Mar 2019 09:20:06 -0500 Subject: key controller: Fix a copy/paste error Prefix the finalize function properly. --- gtk/gtkeventcontrollerkey.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gtk/gtkeventcontrollerkey.c b/gtk/gtkeventcontrollerkey.c index 2c5a69f7a7..9f32cc9023 100644 --- a/gtk/gtkeventcontrollerkey.c +++ b/gtk/gtkeventcontrollerkey.c @@ -69,7 +69,7 @@ G_DEFINE_TYPE (GtkEventControllerKey, gtk_event_controller_key, GTK_TYPE_EVENT_CONTROLLER) static void -gtk_event_controller_finalize (GObject *object) +gtk_event_controller_key_finalize (GObject *object) { GtkEventControllerKey *key = GTK_EVENT_CONTROLLER_KEY (object); @@ -169,7 +169,7 @@ gtk_event_controller_key_class_init (GtkEventControllerKeyClass *klass) GtkEventControllerClass *controller_class = GTK_EVENT_CONTROLLER_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->finalize = gtk_event_controller_finalize; + object_class->finalize = gtk_event_controller_key_finalize; controller_class->handle_event = gtk_event_controller_key_handle_event; /** -- cgit v1.2.1 From 4f5a8207bca2c1b968c27ffd25cb76c770b7cf75 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 8 Mar 2019 09:55:27 -0500 Subject: key controller: Add focus properties Add boolean properties, is-focus and contains-focus, that track whether the focus is in the widget itself or in one of its descendants. --- gtk/gtkeventcontrollerkey.c | 131 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 126 insertions(+), 5 deletions(-) diff --git a/gtk/gtkeventcontrollerkey.c b/gtk/gtkeventcontrollerkey.c index 9f32cc9023..390ec4e2f4 100644 --- a/gtk/gtkeventcontrollerkey.c +++ b/gtk/gtkeventcontrollerkey.c @@ -46,6 +46,9 @@ struct _GtkEventControllerKey GHashTable *pressed_keys; const GdkEvent *current_event; + + guint is_focus : 1; + guint contains_focus : 1; }; struct _GtkEventControllerKeyClass @@ -65,6 +68,14 @@ enum { static guint signals[N_SIGNALS] = { 0 }; +enum { + PROP_IS_FOCUS = 1, + PROP_CONTAINS_FOCUS, + NUM_PROPERTIES +}; + +static GParamSpec *props[NUM_PROPERTIES] = { NULL, }; + G_DEFINE_TYPE (GtkEventControllerKey, gtk_event_controller_key, GTK_TYPE_EVENT_CONTROLLER) @@ -79,6 +90,50 @@ gtk_event_controller_key_finalize (GObject *object) G_OBJECT_CLASS (gtk_event_controller_key_parent_class)->finalize (object); } +static void +update_focus (GtkEventControllerKey *key, + gboolean focus_in, + GdkNotifyType detail) +{ + gboolean is_focus; + gboolean contains_focus; + + switch (detail) + { + case GDK_NOTIFY_VIRTUAL: + case GDK_NOTIFY_NONLINEAR_VIRTUAL: + is_focus = FALSE; + contains_focus = focus_in; + break; + case GDK_NOTIFY_ANCESTOR: + case GDK_NOTIFY_NONLINEAR: + is_focus = focus_in; + contains_focus = FALSE; + break; + case GDK_NOTIFY_INFERIOR: + is_focus = focus_in; + contains_focus = !focus_in; + break; + case GDK_NOTIFY_UNKNOWN: + default: + g_warning ("Unknown focus change detail"); + return; + } + + g_object_freeze_notify (G_OBJECT (key)); + if (key->is_focus != is_focus) + { + key->is_focus = is_focus; + g_object_notify (G_OBJECT (key), "is-focus"); + } + if (key->contains_focus != contains_focus) + { + key->contains_focus = contains_focus; + g_object_notify (G_OBJECT (key), "contains-focus"); + } + g_object_thaw_notify (G_OBJECT (key)); +} + static gboolean gtk_event_controller_key_handle_event (GtkEventController *controller, const GdkEvent *event) @@ -96,10 +151,13 @@ gtk_event_controller_key_handle_event (GtkEventController *controller, GdkCrossingMode mode; GdkNotifyType detail; + gdk_event_get_focus_in (event, &focus_in); gdk_event_get_crossing_mode (event, &mode); gdk_event_get_crossing_detail (event, &detail); - if (gdk_event_get_focus_in (event, &focus_in) && focus_in) + update_focus (key, focus_in, detail); + + if (focus_in) g_signal_emit (controller, signals[FOCUS_IN], 0, mode, detail); else g_signal_emit (controller, signals[FOCUS_OUT], 0, mode, detail); @@ -163,6 +221,29 @@ gtk_event_controller_key_handle_event (GtkEventController *controller, return handled; } +static void +gtk_event_controller_key_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkEventControllerKey *controller = GTK_EVENT_CONTROLLER_KEY (object); + + switch (prop_id) + { + case PROP_IS_FOCUS: + g_value_set_boolean (value, controller->is_focus); + break; + + case PROP_CONTAINS_FOCUS: + g_value_set_boolean (value, controller->contains_focus); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + static void gtk_event_controller_key_class_init (GtkEventControllerKeyClass *klass) { @@ -170,8 +251,46 @@ gtk_event_controller_key_class_init (GtkEventControllerKeyClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gtk_event_controller_key_finalize; + object_class->get_property = gtk_event_controller_key_get_property; controller_class->handle_event = gtk_event_controller_key_handle_event; + /** + * GtkEventControllerKey:is-focus: + * + * Whether focus is in the controllers widget itself, + * as opposed to in a descendent widget. See + * #GtkEventControllerKey:contains-focus. + * + * When handling focus events, this property is updated + * before #GtkEventControllerKey::focus-in or + * #GtkEventControllerKey::focus-out are emitted. + */ + props[PROP_IS_FOCUS] = + g_param_spec_boolean ("is-focus", + P_("Is Focus"), + P_("Whether the focus is in the controllers widget"), + FALSE, + G_PARAM_READABLE); + + /** + * GtkEventControllerKey:contains-focus: + * + * Whether focus is in a descendant of the controllers widget. + * See #GtkEventControllerKey:is-focus. + * + * When handling focus events, this property is updated + * before #GtkEventControllerKey::focus-in or + * #GtkEventControllerKey::focus-out are emitted. + */ + props[PROP_CONTAINS_FOCUS] = + g_param_spec_boolean ("contains-focus", + P_("Contains Focus"), + P_("Whether the focus is in a descendant of the controllers widget"), + FALSE, + G_PARAM_READABLE); + + g_object_class_install_properties (object_class, NUM_PROPERTIES, props); + /** * GtkEventControllerKey::key-pressed: * @controller: the object which received the signal. @@ -247,8 +366,9 @@ gtk_event_controller_key_class_init (GtkEventControllerKeyClass *klass) * @mode: crossing mode indicating what caused this change * @detail: detail indication where the focus is coming from * - * This signal is emitted whenever the #GtkEventController:widget controlled - * by the @controller is given the keyboard focus. + * This signal is emitted whenever the widget controlled + * by the @controller or one of its descendants) is given + * the keyboard focus. */ signals[FOCUS_IN] = g_signal_new (I_("focus-in"), @@ -267,8 +387,9 @@ gtk_event_controller_key_class_init (GtkEventControllerKeyClass *klass) * @mode: crossing mode indicating what caused this change * @detail: detail indication where the focus is going * - * This signal is emitted whenever the #GtkEventController:widget controlled - * by the @controller loses the keyboard focus. + * This signal is emitted whenever the widget controlled + * by the @controller (or one of its descendants) loses + * the keyboard focus. */ signals[FOCUS_OUT] = g_signal_new (I_("focus-out"), -- cgit v1.2.1 From f3ed3e99c396a82b792dc30f7329ff806d559f3b Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 8 Mar 2019 10:16:27 -0500 Subject: key controller: Add getters for focus event targets This information can be needed in signal handlers, so make it available. --- gtk/gtkeventcontrollerkey.c | 66 +++++++++++++++++++++++++++++++++++++++++++++ gtk/gtkeventcontrollerkey.h | 5 ++++ 2 files changed, 71 insertions(+) diff --git a/gtk/gtkeventcontrollerkey.c b/gtk/gtkeventcontrollerkey.c index 390ec4e2f4..b57e9df19e 100644 --- a/gtk/gtkeventcontrollerkey.c +++ b/gtk/gtkeventcontrollerkey.c @@ -36,6 +36,7 @@ #include "gtkeventcontrollerkey.h" #include "gtkbindings.h" #include "gtkenums.h" +#include "gtkmain.h" #include @@ -157,11 +158,15 @@ gtk_event_controller_key_handle_event (GtkEventController *controller, update_focus (key, focus_in, detail); + key->current_event = event; + if (focus_in) g_signal_emit (controller, signals[FOCUS_IN], 0, mode, detail); else g_signal_emit (controller, signals[FOCUS_OUT], 0, mode, detail); + key->current_event = NULL; + return FALSE; } @@ -512,3 +517,64 @@ gtk_event_controller_key_get_group (GtkEventControllerKey *controller) return group; } + +/** + * gtk_event_controller_key_get_focus_origin: + * @controller: a #GtkEventControllerKey + * + * Returns the widget that was holding focus before. + * + * This function can only be used in handlers for the + * #GtkEventControllerKey::focus-in and + * #GtkEventControllerKey::focus-out signals. + * + * Returns: (transfer none): the previous focus + */ +GtkWidget * +gtk_event_controller_key_get_focus_origin (GtkEventControllerKey *controller) +{ + gboolean focus_in; + GtkWidget *origin; + + g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER_KEY (controller), NULL); + g_return_val_if_fail (controller->current_event != NULL, NULL); + g_return_val_if_fail (gdk_event_get_event_type (controller->current_event) == GDK_FOCUS_CHANGE, NULL); + + gdk_event_get_focus_in (controller->current_event, &focus_in); + + if (focus_in) + origin = (GtkWidget *)gdk_event_get_related_target (controller->current_event); + else + origin = (GtkWidget *)gdk_event_get_target (controller->current_event); + + return origin; +} + +/** + * gtk_event_controller_key_get_focus_target: + * @controller: a #GtkEventControllerKey + * + * Returns the widget that will be holding focus afterwards. + * + * This function can only be used in handlers for the + * #GtkEventControllerKey::focus-in and + * #GtkEventControllerKey::focus-out signals. + * + * Returns: (transfer none): the next focus + */ +GtkWidget * +gtk_event_controller_key_get_focus_target (GtkEventControllerKey *controller) +{ + gboolean focus_in; + + g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER_KEY (controller), NULL); + g_return_val_if_fail (controller->current_event != NULL, NULL); + g_return_val_if_fail (gdk_event_get_event_type (controller->current_event) == GDK_FOCUS_CHANGE, NULL); + + gdk_event_get_focus_in (controller->current_event, &focus_in); + + if (focus_in) + return (GtkWidget *)gdk_event_get_target (controller->current_event); + else + return (GtkWidget *)gdk_event_get_related_target (controller->current_event); +} diff --git a/gtk/gtkeventcontrollerkey.h b/gtk/gtkeventcontrollerkey.h index c8a579773a..b036bde7ec 100644 --- a/gtk/gtkeventcontrollerkey.h +++ b/gtk/gtkeventcontrollerkey.h @@ -58,6 +58,11 @@ gboolean gtk_event_controller_key_forward (GtkEventControllerK GDK_AVAILABLE_IN_ALL guint gtk_event_controller_key_get_group (GtkEventControllerKey *controller); +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); + G_END_DECLS #endif /* __GTK_EVENT_CONTROLLER_KEY_H__ */ -- cgit v1.2.1 From 4f06b669c5ab281984e0bc20aca1ecdee7f34341 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 8 Mar 2019 10:19:12 -0500 Subject: key controller: Improve the docs Mention the limitations of the key forwarding api. --- gtk/gtkeventcontrollerkey.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gtk/gtkeventcontrollerkey.c b/gtk/gtkeventcontrollerkey.c index b57e9df19e..2909095979 100644 --- a/gtk/gtkeventcontrollerkey.c +++ b/gtk/gtkeventcontrollerkey.c @@ -470,6 +470,13 @@ gtk_event_controller_key_get_im_context (GtkEventControllerKey *controller) * * Forwards the current event of this @controller to a @widget. * + * This function can only be used in handlers for the + * #GtkEventControllerKey::key-pressed, + * #GtkEventControllerKey::key-released + * or + * #GtkEventControllerKey::modifiers + * signals. + * * Returns: whether the @widget handled the event **/ gboolean -- cgit v1.2.1 From 93905a85134e6cbbb71ac512feac686ce07c1cda Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 8 Mar 2019 10:21:02 -0500 Subject: key controller: Enforce limitations of key forwarding We now set current_event for focus-change as well, so make sure to check the event type. --- gtk/gtkeventcontrollerkey.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gtk/gtkeventcontrollerkey.c b/gtk/gtkeventcontrollerkey.c index 2909095979..f7f3fe1017 100644 --- a/gtk/gtkeventcontrollerkey.c +++ b/gtk/gtkeventcontrollerkey.c @@ -486,6 +486,8 @@ gtk_event_controller_key_forward (GtkEventControllerKey *controller, g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER_KEY (controller), FALSE); g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); g_return_val_if_fail (controller->current_event != NULL, FALSE); + g_return_val_if_fail (gdk_event_get_event_type (controller->current_event) == GDK_KEY_PRESS || + gdk_event_get_event_type (controller->current_event) == GDK_KEY_RELEASE, FALSE); if (!gtk_widget_get_realized (widget)) gtk_widget_realize (widget); -- cgit v1.2.1 From 181a4bce2503c6e4f1f6c3f0111e785c2094f2b5 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 8 Mar 2019 11:44:43 -0500 Subject: Add key controller API to the docs A bunch of API was missing here. --- docs/reference/gtk/gtk4-sections.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt index 9d3e68f683..e0b068bcdc 100644 --- a/docs/reference/gtk/gtk4-sections.txt +++ b/docs/reference/gtk/gtk4-sections.txt @@ -6702,6 +6702,12 @@ gtk_event_controller_motion_get_type GtkEventControllerKey GtkEventControllerKey gtk_event_controller_key_new +gtk_event_controller_key_set_im_context +gtk_event_controller_key_get_im_context +gtk_event_controller_key_forward +gtk_event_controller_key_get_group +gtk_event_controller_key_get_focus_origin +gtk_event_controller_key_get_focus_target GTK_TYPE_EVENT_CONTROLLER_KEY -- cgit v1.2.1 From 492a38c2297a325e6ceac4e148309afe4aba2f88 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 8 Mar 2019 13:46:17 -0500 Subject: Make gtk_widget_get_focus_child public It doesn't really make sense to have only the setter, but not the getter public. --- gtk/gtkwidget.h | 3 +++ gtk/gtkwidgetprivate.h | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h index d9dbfaf885..97848c698e 100644 --- a/gtk/gtkwidget.h +++ b/gtk/gtkwidget.h @@ -1059,6 +1059,9 @@ void gtk_widget_insert_before (GtkWidget *widget, GDK_AVAILABLE_IN_ALL void gtk_widget_set_focus_child (GtkWidget *widget, GtkWidget *child); +GDK_AVAILABLE_IN_ALL +GtkWidget * gtk_widget_get_focus_child (GtkWidget *widget); + GDK_AVAILABLE_IN_ALL void gtk_widget_snapshot_child (GtkWidget *widget, GtkWidget *child, diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index d995faa87a..49d7fcad8b 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -317,8 +317,6 @@ void gtk_widget_forall (GtkWidget GtkCallback callback, gpointer user_data); -GtkWidget *gtk_widget_get_focus_child (GtkWidget *widget); - void gtk_widget_focus_sort (GtkWidget *widget, GtkDirectionType direction, GPtrArray *focus_order); -- cgit v1.2.1 From 6ddb61119a8f185d6268d4927fbb53100e2305db Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 16 Mar 2019 03:06:29 -0400 Subject: Use root in gdk_synthesize_crossing_events --- gtk/gtkmain.c | 8 ++++---- gtk/gtkwidgetprivate.h | 2 +- gtk/gtkwindow.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 92873dee1e..b435c489a3 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1484,7 +1484,7 @@ synth_crossing (GtkWidget *widget, } void -gtk_synthesize_crossing_events (GtkWindow *toplevel, +gtk_synthesize_crossing_events (GtkRoot *toplevel, GtkWidget *old_target, GtkWidget *new_target, GdkEvent *event, @@ -1655,7 +1655,7 @@ handle_pointing_event (GdkEvent *event) old_target = update_pointer_focus_state (toplevel, event, NULL); if (event->any.type == GDK_LEAVE_NOTIFY) - gtk_synthesize_crossing_events (toplevel, old_target, NULL, + gtk_synthesize_crossing_events (GTK_ROOT (toplevel), old_target, NULL, event, event->crossing.mode); break; case GDK_ENTER_NOTIFY: @@ -1680,7 +1680,7 @@ handle_pointing_event (GdkEvent *event) if (!gtk_window_lookup_pointer_focus_implicit_grab (toplevel, device, sequence)) { - gtk_synthesize_crossing_events (toplevel, old_target, target, + gtk_synthesize_crossing_events (GTK_ROOT (toplevel), old_target, target, event, GDK_CROSSING_NORMAL); } @@ -1710,7 +1710,7 @@ handle_pointing_event (GdkEvent *event) new_target = gtk_widget_pick (GTK_WIDGET (toplevel), x, y); if (new_target == NULL) new_target = GTK_WIDGET (toplevel); - gtk_synthesize_crossing_events (toplevel, target, new_target, event, + gtk_synthesize_crossing_events (GTK_ROOT (toplevel), target, new_target, event, GDK_CROSSING_UNGRAB); gtk_window_maybe_update_cursor (toplevel, NULL, device); } diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index 49d7fcad8b..9ede6b8b79 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -242,7 +242,7 @@ GdkSurface * _gtk_widget_get_device_surface (GtkWidget *widget, GdkDevice *device); GList * _gtk_widget_list_devices (GtkWidget *widget); -void gtk_synthesize_crossing_events (GtkWindow *toplevel, +void gtk_synthesize_crossing_events (GtkRoot *toplevel, GtkWidget *from, GtkWidget *to, GdkEvent *event, diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 976777717d..bc2a53cff2 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -7191,7 +7191,7 @@ gtk_window_set_focus (GtkWindow *window, if (event->any.surface) g_object_ref (event->any.surface); - gtk_synthesize_crossing_events (window, old_focus, focus, event, GDK_CROSSING_NORMAL); + gtk_synthesize_crossing_events (GTK_ROOT (window), old_focus, focus, event, GDK_CROSSING_NORMAL); g_object_unref (event); -- cgit v1.2.1 From 8619b109cc116836204d76f1ad72fbe11d5703f2 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 7 Mar 2019 23:25:50 -0500 Subject: Update the focus test Check that we get the expected sequences of focus change events for the nonlinear, inferior and ancestor cases. It would be nice to do the same checks for crossing events, but we have no gtk_window_set_hover(). --- testsuite/gtk/focus.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 154 insertions(+), 9 deletions(-) diff --git a/testsuite/gtk/focus.c b/testsuite/gtk/focus.c index 0605c8eb53..a6ffeccbad 100644 --- a/testsuite/gtk/focus.c +++ b/testsuite/gtk/focus.c @@ -1,41 +1,186 @@ #include +const char * +widget_name (GtkWidget *widget) +{ + if (gtk_widget_get_name (widget)) + return gtk_widget_get_name (widget); + else if (GTK_IS_LABEL (widget)) + return gtk_label_get_label (GTK_LABEL (widget)); + else if (GTK_IS_EDITABLE (widget)) + return gtk_editable_get_text (GTK_EDITABLE (widget)); + else + return G_OBJECT_TYPE_NAME (widget); +} + +static char * +mode_to_string (GdkCrossingMode mode) +{ + return g_enum_to_string (GDK_TYPE_CROSSING_MODE, mode); +} + +static char * +detail_to_string (GdkNotifyType detail) +{ + return g_enum_to_string (GDK_TYPE_NOTIFY_TYPE, detail); +} + +static void +focus_in (GtkEventController *controller, + GdkCrossingMode mode, + GdkNotifyType detail, + GString *s) +{ + GtkWidget *widget = gtk_event_controller_get_widget (controller); + g_string_append_printf (s, "%s: focus-in %s %s\n", + widget_name (widget), + mode_to_string (mode), + detail_to_string (detail)); +} + +static void +focus_out (GtkEventController *controller, + GdkCrossingMode mode, + GdkNotifyType detail, + GString *s) +{ + GtkWidget *widget = gtk_event_controller_get_widget (controller); + g_string_append_printf (s, "%s: focus-out %s %s\n", + widget_name (widget), + mode_to_string (mode), + detail_to_string (detail)); +} + +static void +add_controller (GtkWidget *widget, GString *s) +{ + GtkEventController *controller; + + controller = gtk_event_controller_key_new (); + g_signal_connect (controller, "focus-in", G_CALLBACK (focus_in), s); + g_signal_connect (controller, "focus-out", G_CALLBACK (focus_out), s); + gtk_widget_add_controller (widget, controller); +} + static void test_window_focus (void) { GtkWidget *window; GtkWidget *box; + GtkWidget *box1; + GtkWidget *box2; + GtkWidget *label1; + GtkWidget *label2; GtkWidget *entry1; GtkWidget *entry2; + GString *s = g_string_new (""); + + /* + * The tree look like this, with [] indicating + * focus locations: + * + * window + * | + * +----[box]-----+ + * | | | + * label1 box1 box2------+ + * | | | + * [entry1] label2 [entry2] + */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_widget_set_name (window, "window"); + add_controller (window, s); box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_can_focus (box, TRUE); + gtk_widget_set_name (box, "box"); + add_controller (box, s); gtk_container_add (GTK_CONTAINER (window), box); - gtk_container_add (GTK_CONTAINER (box), gtk_label_new ("label1")); + label1 = gtk_label_new ("label1"); + gtk_widget_set_name (label1, "label1"); + add_controller (label1, s); + gtk_container_add (GTK_CONTAINER (box), label1); + box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_name (box1, "box1"); + add_controller (box1, s); + gtk_container_add (GTK_CONTAINER (box), box1); entry1 = gtk_text_new (); - gtk_container_add (GTK_CONTAINER (box), entry1); - gtk_container_add (GTK_CONTAINER (box), gtk_label_new ("label2")); + gtk_widget_set_name (entry1, "entry1"); + add_controller (entry1, s); + gtk_container_add (GTK_CONTAINER (box1), entry1); + box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_name (box2, "box2"); + add_controller (box2, s); + gtk_container_add (GTK_CONTAINER (box), box2); + label2 = gtk_label_new ("label2"); + gtk_widget_set_name (label2, "label2"); + add_controller (label2, s); + gtk_container_add (GTK_CONTAINER (box2), label2); entry2 = gtk_text_new (); - gtk_container_add (GTK_CONTAINER (box), entry2); + gtk_widget_set_name (entry2, "entry2"); + add_controller (entry2, s); + gtk_container_add (GTK_CONTAINER (box2), entry2); g_assert_null (gtk_window_get_focus (GTK_WINDOW (window))); - gtk_window_set_focus (GTK_WINDOW (window), entry1); + gtk_widget_show (window); - g_assert (gtk_window_get_focus (GTK_WINDOW (window)) == entry1); + /* show puts the initial focus on box */ + g_assert (gtk_window_get_focus (GTK_WINDOW (window)) == box); - gtk_widget_show (window); + if (g_test_verbose ()) + g_print ("-> box\n%s\n", s->str); + + g_assert_cmpstr (s->str, ==, +"window: focus-in GDK_CROSSING_NORMAL GDK_NOTIFY_VIRTUAL\n" +"box: focus-in GDK_CROSSING_NORMAL GDK_NOTIFY_ANCESTOR\n"); + g_string_truncate (s, 0); + + gtk_widget_grab_focus (entry1); + + if (g_test_verbose ()) + g_print ("box -> entry1\n%s\n", s->str); + + g_assert_cmpstr (s->str, ==, +"box: focus-out GDK_CROSSING_NORMAL GDK_NOTIFY_INFERIOR\n" +"box1: focus-in GDK_CROSSING_NORMAL GDK_NOTIFY_VIRTUAL\n" +"entry1: focus-in GDK_CROSSING_NORMAL GDK_NOTIFY_ANCESTOR\n"); + + g_string_truncate (s, 0); g_assert (gtk_window_get_focus (GTK_WINDOW (window)) == entry1); gtk_widget_grab_focus (entry2); - g_assert (gtk_window_get_focus (GTK_WINDOW (window)) == entry2); + if (g_test_verbose ()) + g_print ("entry1 -> entry2\n%s\n", s->str); - gtk_widget_hide (window); + g_assert_cmpstr (s->str, ==, +"entry1: focus-out GDK_CROSSING_NORMAL GDK_NOTIFY_NONLINEAR\n" +"box1: focus-out GDK_CROSSING_NORMAL GDK_NOTIFY_NONLINEAR_VIRTUAL\n" +"box2: focus-in GDK_CROSSING_NORMAL GDK_NOTIFY_NONLINEAR_VIRTUAL\n" +"entry2: focus-in GDK_CROSSING_NORMAL GDK_NOTIFY_NONLINEAR\n"); + + g_string_truncate (s, 0); g_assert (gtk_window_get_focus (GTK_WINDOW (window)) == entry2); + gtk_widget_grab_focus (box); + + if (g_test_verbose ()) + g_print ("entry2 -> box\n%s", s->str); + + g_assert_cmpstr (s->str, ==, +"entry2: focus-out GDK_CROSSING_NORMAL GDK_NOTIFY_ANCESTOR\n" +"box2: focus-out GDK_CROSSING_NORMAL GDK_NOTIFY_VIRTUAL\n" +"box: focus-in GDK_CROSSING_NORMAL GDK_NOTIFY_INFERIOR\n"); + + g_string_truncate (s, 0); + + gtk_widget_hide (window); + + g_assert (gtk_window_get_focus (GTK_WINDOW (window)) == box); + gtk_window_set_focus (GTK_WINDOW (window), entry1); g_assert (gtk_window_get_focus (GTK_WINDOW (window)) == entry1); -- cgit v1.2.1 From ad3773b2e12a839fef2ac01f572f6490d1ca5f64 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 16 Mar 2019 21:49:24 -0400 Subject: a11y tests: Update expected results The changes here are all related to initial focus. --- testsuite/a11y/about.txt | 4 ++-- testsuite/a11y/accessible-name.txt | 4 ++-- testsuite/a11y/actionbar.txt | 4 ++-- testsuite/a11y/assistant.txt | 2 +- testsuite/a11y/buttons.txt | 4 ++-- testsuite/a11y/calendar.txt | 4 ++-- testsuite/a11y/colorchooser.txt | 4 ++-- testsuite/a11y/combos.txt | 2 +- testsuite/a11y/entries.txt | 2 +- testsuite/a11y/expander.txt | 4 ++-- testsuite/a11y/headerbar.txt | 4 ++-- testsuite/a11y/hello-world.txt | 4 ++-- testsuite/a11y/iconview.txt | 4 ++-- testsuite/a11y/label-static.txt | 4 ++-- testsuite/a11y/label.txt | 4 ++-- testsuite/a11y/link.txt | 4 ++-- testsuite/a11y/listbox.txt | 4 ++-- testsuite/a11y/lockbutton.txt | 4 ++-- testsuite/a11y/menubutton.txt | 4 ++-- testsuite/a11y/menubutton2.txt | 4 ++-- testsuite/a11y/menubutton3.txt | 4 ++-- testsuite/a11y/menus.txt | 8 ++++++++ testsuite/a11y/mnemonic.txt | 2 +- testsuite/a11y/notebook.txt | 4 ++-- testsuite/a11y/pickers.txt | 2 +- testsuite/a11y/placeholder-text.txt | 8 ++++---- testsuite/a11y/range.txt | 4 ++-- testsuite/a11y/scale-drawvalue.txt | 4 ++-- testsuite/a11y/stack.txt | 4 ++-- testsuite/a11y/text.txt | 4 ++-- testsuite/a11y/tooltips.txt | 4 ++-- testsuite/a11y/tree.txt | 10 +++++----- 32 files changed, 70 insertions(+), 62 deletions(-) diff --git a/testsuite/a11y/about.txt b/testsuite/a11y/about.txt index 165234e97a..5add6017ca 100644 --- a/testsuite/a11y/about.txt +++ b/testsuite/a11y/about.txt @@ -2,7 +2,7 @@ window1 "dialog" index: 0 name: About FancyPants - state: enabled sensitive showing visible + state: active enabled sensitive showing visible toolkit: gtk window-type: dialog @@ -374,7 +374,7 @@ See the GNU General Public License, version 3 or later for details. parent: stack_switcher index: 0 name: About - state: checked enabled focusable sensitive showing visible + state: checked enabled focusable focused sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/accessible-name.txt b/testsuite/a11y/accessible-name.txt index 1c5be98fb8..f2274db1e5 100644 --- a/testsuite/a11y/accessible-name.txt +++ b/testsuite/a11y/accessible-name.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -12,7 +12,7 @@ window1 parent: window1 index: 0 name: Accessible name - state: enabled focusable sensitive showing visible + state: enabled focusable focused sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/actionbar.txt b/testsuite/a11y/actionbar.txt index c5323a4f29..abd273cb1c 100644 --- a/testsuite/a11y/actionbar.txt +++ b/testsuite/a11y/actionbar.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -21,7 +21,7 @@ window1 parent: unnamed-GtkContainerAccessible-0 index: 0 name: Start 1 - state: enabled focusable sensitive showing visible + state: enabled focusable focused sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/assistant.txt b/testsuite/a11y/assistant.txt index 6de0d4f1c3..022637ed4a 100644 --- a/testsuite/a11y/assistant.txt +++ b/testsuite/a11y/assistant.txt @@ -13,7 +13,7 @@ window1 parent: content index: 0 name: Page 1 - state: enabled focusable sensitive showing visible + state: enabled focusable focused sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/buttons.txt b/testsuite/a11y/buttons.txt index 0a43e143c6..30d0a3ff12 100644 --- a/testsuite/a11y/buttons.txt +++ b/testsuite/a11y/buttons.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -21,7 +21,7 @@ window1 parent: grid1 index: 0 name: Hello World! - state: checked enabled focusable sensitive showing visible + state: checked enabled focusable focused sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/calendar.txt b/testsuite/a11y/calendar.txt index 768d6c479d..f9e6a18c3b 100644 --- a/testsuite/a11y/calendar.txt +++ b/testsuite/a11y/calendar.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -11,7 +11,7 @@ window1 "calendar" parent: window1 index: 0 - state: enabled focusable sensitive showing visible + state: enabled focusable focused sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/colorchooser.txt b/testsuite/a11y/colorchooser.txt index d1dc6adce6..b509b61519 100644 --- a/testsuite/a11y/colorchooser.txt +++ b/testsuite/a11y/colorchooser.txt @@ -2,7 +2,7 @@ window1 "dialog" index: 0 name: Select a Color - state: enabled sensitive showing visible + state: active enabled sensitive showing visible toolkit: gtk window-type: dialog @@ -58,7 +58,7 @@ window1 parent: unnamed-GtkContainerAccessible-1 index: 0 name: Light Scarlet Red - state: enabled focusable sensitive showing visible + state: enabled focusable focused sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/combos.txt b/testsuite/a11y/combos.txt index 490ecd390b..3d635149dc 100644 --- a/testsuite/a11y/combos.txt +++ b/testsuite/a11y/combos.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal diff --git a/testsuite/a11y/entries.txt b/testsuite/a11y/entries.txt index 3fc7c7ee99..342b557ec8 100644 --- a/testsuite/a11y/entries.txt +++ b/testsuite/a11y/entries.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal diff --git a/testsuite/a11y/expander.txt b/testsuite/a11y/expander.txt index 6a66719dde..5f6ac1ed38 100644 --- a/testsuite/a11y/expander.txt +++ b/testsuite/a11y/expander.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -12,7 +12,7 @@ window1 parent: window1 index: 0 name: Reveal this - state: enabled expandable focusable sensitive showing visible + state: enabled expandable focusable focused sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/headerbar.txt b/testsuite/a11y/headerbar.txt index 1905c05131..6a933d0110 100644 --- a/testsuite/a11y/headerbar.txt +++ b/testsuite/a11y/headerbar.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -21,7 +21,7 @@ window1 parent: headerbar1 index: 0 name: Yes - state: enabled focusable sensitive showing visible + state: enabled focusable focused sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/hello-world.txt b/testsuite/a11y/hello-world.txt index 76119e2099..a3816eda2e 100644 --- a/testsuite/a11y/hello-world.txt +++ b/testsuite/a11y/hello-world.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -12,7 +12,7 @@ window1 parent: window1 index: 0 name: Hello World! - state: enabled focusable sensitive showing visible + state: enabled focusable focused sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/iconview.txt b/testsuite/a11y/iconview.txt index eebac50f42..760937982f 100644 --- a/testsuite/a11y/iconview.txt +++ b/testsuite/a11y/iconview.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -11,7 +11,7 @@ window1 "layered pane" parent: window1 index: 0 - state: enabled focusable sensitive showing visible + state: enabled focusable focused sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/label-static.txt b/testsuite/a11y/label-static.txt index eff7a8e47c..885522437c 100644 --- a/testsuite/a11y/label-static.txt +++ b/testsuite/a11y/label-static.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -12,7 +12,7 @@ window1 parent: window1 index: 0 name: Go to the GTK+ website or >google it - state: enabled focusable multi-line sensitive showing visible has-tooltip + state: enabled focusable focused multi-line sensitive showing visible has-tooltip toolkit: gtk layer: widget diff --git a/testsuite/a11y/label.txt b/testsuite/a11y/label.txt index cf01c56f2f..2875ee2d14 100644 --- a/testsuite/a11y/label.txt +++ b/testsuite/a11y/label.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -12,7 +12,7 @@ window1 parent: window1 index: 0 name: Go to the GTK+ website or >google it - state: enabled focusable multi-line sensitive showing visible has-tooltip + state: enabled focusable focused multi-line sensitive showing visible has-tooltip toolkit: gtk layer: widget diff --git a/testsuite/a11y/link.txt b/testsuite/a11y/link.txt index dcd795b596..4d8ff1ad7e 100644 --- a/testsuite/a11y/link.txt +++ b/testsuite/a11y/link.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -12,7 +12,7 @@ window1 parent: window1 index: 0 name: Hello World! - state: enabled focusable sensitive showing visible visited has-tooltip + state: enabled focusable focused sensitive showing visible visited has-tooltip toolkit: gtk layer: widget diff --git a/testsuite/a11y/listbox.txt b/testsuite/a11y/listbox.txt index 366d3341e6..46c5abce48 100644 --- a/testsuite/a11y/listbox.txt +++ b/testsuite/a11y/listbox.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -30,7 +30,7 @@ window1 "list item" parent: listbox1 index: 0 - state: enabled focusable sensitive showing visible + state: enabled focusable focused sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/lockbutton.txt b/testsuite/a11y/lockbutton.txt index fef97f64a6..b8968cd386 100644 --- a/testsuite/a11y/lockbutton.txt +++ b/testsuite/a11y/lockbutton.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -14,7 +14,7 @@ window1 name: Lock description: Dialog is unlocked. Click to prevent further changes - state: enabled focusable sensitive showing visible has-tooltip + state: enabled focusable focused sensitive showing visible has-tooltip toolkit: gtk layer: widget diff --git a/testsuite/a11y/menubutton.txt b/testsuite/a11y/menubutton.txt index d9893ab868..ecfe438f70 100644 --- a/testsuite/a11y/menubutton.txt +++ b/testsuite/a11y/menubutton.txt @@ -1,7 +1,7 @@ window1 "frame" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -20,7 +20,7 @@ window1 parent: window1 index: 0 name: Menu - state: enabled focusable sensitive showing visible + state: enabled focusable focused sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/menubutton2.txt b/testsuite/a11y/menubutton2.txt index e5d8cbb537..5dafe5000c 100644 --- a/testsuite/a11y/menubutton2.txt +++ b/testsuite/a11y/menubutton2.txt @@ -1,7 +1,7 @@ window1 "frame" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -89,7 +89,7 @@ window1 parent: window1 index: 0 name: Menu - state: enabled focusable sensitive showing visible + state: enabled focusable focused sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/menubutton3.txt b/testsuite/a11y/menubutton3.txt index e5d8cbb537..5dafe5000c 100644 --- a/testsuite/a11y/menubutton3.txt +++ b/testsuite/a11y/menubutton3.txt @@ -1,7 +1,7 @@ window1 "frame" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -89,7 +89,7 @@ window1 parent: window1 index: 0 name: Menu - state: enabled focusable sensitive showing visible + state: enabled focusable focused sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/menus.txt b/testsuite/a11y/menus.txt index 44ca3ddab9..ab89b99250 100644 --- a/testsuite/a11y/menus.txt +++ b/testsuite/a11y/menus.txt @@ -7,6 +7,14 @@ window1 layer: window alpha: 1 + unnamed-GtkContainerAccessible-0 + "panel" + parent: window1 + state: enabled sensitive showing visible + toolkit: gtk + + layer: widget + alpha: 1 menubar1 "menu bar" parent: window1 diff --git a/testsuite/a11y/mnemonic.txt b/testsuite/a11y/mnemonic.txt index 362afca174..cd95e32062 100644 --- a/testsuite/a11y/mnemonic.txt +++ b/testsuite/a11y/mnemonic.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal diff --git a/testsuite/a11y/notebook.txt b/testsuite/a11y/notebook.txt index 7cdd28ec0c..d2e50bf062 100644 --- a/testsuite/a11y/notebook.txt +++ b/testsuite/a11y/notebook.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -11,7 +11,7 @@ window1 "page tab list" parent: window1 index: 0 - state: enabled focusable sensitive showing visible + state: enabled focusable focused sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/pickers.txt b/testsuite/a11y/pickers.txt index 7f457e374a..f6971e5bf2 100644 --- a/testsuite/a11y/pickers.txt +++ b/testsuite/a11y/pickers.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal diff --git a/testsuite/a11y/placeholder-text.txt b/testsuite/a11y/placeholder-text.txt index 8079c61f03..b8d9cd2f3e 100644 --- a/testsuite/a11y/placeholder-text.txt +++ b/testsuite/a11y/placeholder-text.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -20,7 +20,7 @@ window1 "text" parent: box1 index: 0 - state: editable enabled focusable sensitive showing single-line visible + state: editable enabled sensitive showing single-line visible toolkit: gtk placeholder-text: Subject or Addresses contain @@ -62,7 +62,7 @@ window1 "text" parent: box1 index: 1 - state: editable enabled focusable sensitive showing single-line visible + state: editable enabled sensitive showing single-line visible toolkit: gtk placeholder-text: Message contains @@ -104,7 +104,7 @@ window1 "text" parent: box1 index: 2 - state: editable enabled focusable sensitive showing single-line visible + state: editable enabled sensitive showing single-line visible toolkit: gtk placeholder-text: Body contains diff --git a/testsuite/a11y/range.txt b/testsuite/a11y/range.txt index be18a34fd2..e044e08dc8 100644 --- a/testsuite/a11y/range.txt +++ b/testsuite/a11y/range.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -21,7 +21,7 @@ window1 parent: grid1 index: 0 description: 45.5 - state: enabled focusable horizontal sensitive showing visible + state: enabled focusable focused horizontal sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/scale-drawvalue.txt b/testsuite/a11y/scale-drawvalue.txt index 327b819ffa..c0f9915470 100644 --- a/testsuite/a11y/scale-drawvalue.txt +++ b/testsuite/a11y/scale-drawvalue.txt @@ -1,7 +1,7 @@ window1 "frame" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -20,7 +20,7 @@ window1 parent: window1 index: 0 description: -42.0 - state: enabled focusable horizontal sensitive showing visible + state: enabled focusable focused horizontal sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/stack.txt b/testsuite/a11y/stack.txt index bb07325586..5d41385ccd 100644 --- a/testsuite/a11y/stack.txt +++ b/testsuite/a11y/stack.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -30,7 +30,7 @@ window1 parent: stackswitcher1 index: 0 name: Page 1 - state: checked enabled focusable sensitive showing visible + state: checked enabled focusable focused sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/text.txt b/testsuite/a11y/text.txt index f69dfca29c..f873df4a99 100644 --- a/testsuite/a11y/text.txt +++ b/testsuite/a11y/text.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -11,7 +11,7 @@ window1 "text" parent: window1 index: 0 - state: editable enabled focusable multi-line sensitive showing visible + state: editable enabled focusable focused multi-line sensitive showing visible toolkit: gtk layer: widget diff --git a/testsuite/a11y/tooltips.txt b/testsuite/a11y/tooltips.txt index e2a0f3ed99..d351486336 100644 --- a/testsuite/a11y/tooltips.txt +++ b/testsuite/a11y/tooltips.txt @@ -1,7 +1,7 @@ window1 "frame" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -29,7 +29,7 @@ window1 parent: box1 index: 0 description: Tooltip1 - state: enabled focusable sensitive showing visible has-tooltip + state: enabled focusable focused sensitive showing visible has-tooltip toolkit: gtk layer: widget diff --git a/testsuite/a11y/tree.txt b/testsuite/a11y/tree.txt index c26c1a9c84..1ed8066958 100644 --- a/testsuite/a11y/tree.txt +++ b/testsuite/a11y/tree.txt @@ -1,7 +1,7 @@ window1 "window" index: 0 - state: enabled resizable sensitive showing visible + state: active enabled resizable sensitive showing visible toolkit: gtk window-type: normal @@ -11,7 +11,7 @@ window1 "table" parent: window1 index: 0 - state: enabled focusable sensitive showing visible manages-descendants + state: enabled focusable focused sensitive showing visible manages-descendants toolkit: gtk layer: widget @@ -48,7 +48,7 @@ window1 "table cell" parent: tv index: 1 - state: enabled focusable selectable selected sensitive showing transient visible + state: active enabled focusable focused selectable selected sensitive showing transient visible layer: widget alpha: 1 @@ -69,7 +69,7 @@ window1 parent: tv index: 0 name: One - state: enabled focusable selectable selected sensitive showing single-line transient visible + state: active enabled focusable focused selectable selected sensitive showing single-line transient visible layer: widget alpha: 1 @@ -118,7 +118,7 @@ window1 parent: tv index: 1 name: 234 - state: enabled focusable selectable selected sensitive showing single-line transient visible + state: active enabled focusable focused selectable selected sensitive showing single-line transient visible layer: widget alpha: 1 -- cgit v1.2.1 From 1ce5327058071f4c29261898037e546e1956e90a Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 16 Mar 2019 22:16:10 -0400 Subject: xim: Stop using GtkWidget::event It does not exist anymore. I'm removing this code now because our CI tests are using xim and fail due to this. Eventually, this code should be ported to use a popover. --- gtk/gtkimcontextxim.c | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/gtk/gtkimcontextxim.c b/gtk/gtkimcontextxim.c index 98f6e530a6..c203f502df 100644 --- a/gtk/gtkimcontextxim.c +++ b/gtk/gtkimcontextxim.c @@ -1580,40 +1580,6 @@ on_status_toplevel_notify_display (GtkWindow *toplevel, gtk_widget_get_display (GTK_WIDGET (toplevel))); } -/* Called when the toplevel window is moved; updates the position of - * the status window to follow it. - */ -static gboolean -on_status_toplevel_configure (GtkWidget *toplevel, - GdkEvent *event, - StatusWindow *status_window) -{ - if (gdk_event_get_event_type (event) == GDK_CONFIGURE) - { - GdkRectangle rect; - GtkRequisition requisition; - gint y; - gint height; - - if (status_window->window) - { - height = DisplayHeight(GDK_SURFACE_XDISPLAY (gtk_widget_get_surface (toplevel)), 0); - - gdk_surface_get_frame_extents (gtk_widget_get_surface (toplevel), &rect); - gtk_widget_get_preferred_size ( (status_window->window), &requisition, NULL); - - if (rect.y + rect.height + requisition.height < height) - y = rect.y + rect.height; - else - y = height - requisition.height; - - gtk_window_move (GTK_WINDOW (status_window->window), rect.x, y); - } - } - - return GDK_EVENT_PROPAGATE; -} - /* Frees a status window and removes its link from the status_windows list */ static void @@ -1630,9 +1596,6 @@ status_window_free (StatusWindow *status_window) g_signal_handlers_disconnect_by_func (status_window->toplevel, G_CALLBACK (on_status_toplevel_notify_display), status_window); - g_signal_handlers_disconnect_by_func (status_window->toplevel, - G_CALLBACK (on_status_toplevel_configure), - status_window); if (status_window->window) gtk_widget_destroy (status_window->window); @@ -1661,9 +1624,6 @@ status_window_get (GtkWidget *toplevel) g_signal_connect (toplevel, "destroy", G_CALLBACK (on_status_toplevel_destroy), status_window); - g_signal_connect (toplevel, "event", - G_CALLBACK (on_status_toplevel_configure), - status_window); g_signal_connect (toplevel, "notify::display", G_CALLBACK (on_status_toplevel_notify_display), status_window); @@ -1695,8 +1655,6 @@ status_window_make_window (StatusWindow *status_window) gtk_window_set_display (GTK_WINDOW (status_window->window), gtk_widget_get_display (status_window->toplevel)); - - on_status_toplevel_configure (status_window->toplevel, NULL, status_window); } /* Updates the text in the status window, hiding or -- cgit v1.2.1