diff options
author | Matthias Clasen <mclasen@redhat.com> | 2020-10-21 11:43:58 +0000 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2020-10-21 11:43:58 +0000 |
commit | 8880e3bd2e060874aba303595303624116c883e0 (patch) | |
tree | 95fda5bc4862e91b3418bf20c844212fba4eba8a | |
parent | 0b5b908a741d9795dbd38f05f2657f1043e6b29e (diff) | |
parent | cbb6828657d84485af8806845f53e943f0873ddb (diff) | |
download | gtk+-8880e3bd2e060874aba303595303624116c883e0.tar.gz |
Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master
See merge request GNOME/gtk!2729
-rw-r--r-- | docs/reference/gtk/migrating-3to4.md | 25 | ||||
-rw-r--r-- | gtk/a11y/gtkatspicontext.c | 24 | ||||
-rw-r--r-- | gtk/gtkatcontext.c | 2 | ||||
-rw-r--r-- | gtk/gtkcolumnview.c | 7 | ||||
-rw-r--r-- | gtk/gtkflowbox.c | 5 | ||||
-rw-r--r-- | gtk/gtkgridview.c | 5 | ||||
-rw-r--r-- | gtk/gtklinkbutton.c | 2 | ||||
-rw-r--r-- | gtk/gtklistbox.c | 5 | ||||
-rw-r--r-- | gtk/gtklistview.c | 5 | ||||
-rw-r--r-- | gtk/gtktext.c | 6 | ||||
-rw-r--r-- | gtk/gtkwidget.c | 14 | ||||
-rw-r--r-- | gtk/inspector/a11y.c | 30 | ||||
-rw-r--r-- | gtk/inspector/a11y.ui | 24 | ||||
-rw-r--r-- | testsuite/a11y/button.c | 19 |
14 files changed, 157 insertions, 16 deletions
diff --git a/docs/reference/gtk/migrating-3to4.md b/docs/reference/gtk/migrating-3to4.md index 6ce96a8878..44f7d785b9 100644 --- a/docs/reference/gtk/migrating-3to4.md +++ b/docs/reference/gtk/migrating-3to4.md @@ -239,6 +239,31 @@ you get to the point that you actually build your application against GTK 4. Making it possible to prepare for these in GTK 3 would have been either impossible or impractical. +### Larger changes + +Some of the larger themes of GTK 4 development are hard to cover in the form +of checklist items, so we mention them separately up-front. + +#### Subclassing + +Compared to previous versions, GTK 4 emphasizes composition and delegation +over subclassing. As a consequence, many widgets can no longer be subclassed. +In most cases, you should look deriving your widget directly from GtkWidget +and use complex widgets as child widgets instead of deriving from them. + +#### Life-cycle handling + +Widgets in GTK 4 are treated like any other objects - their parent widget +holds a reference on them, and GTK holds a reference on toplevel windows. +gtk_window_destroy() will drop the reference on the toplevel window, and +cause the whole widget hierarchy to be finalized unless there are other +references that keep widgets alive. + +The #GtkWidget::destroy signal is emitted when a widget is disposed, and +therefore can no longer be used to break reference cycles. A typical sign +of a reference cycle involving a toplevel window is when closing the window +does not make the application quit. + ### Stop using GdkScreen The GdkScreen object has been removed in GTK 4. Most of its APIs already diff --git a/gtk/a11y/gtkatspicontext.c b/gtk/a11y/gtkatspicontext.c index a72a6ad40e..b030d1cfd7 100644 --- a/gtk/a11y/gtkatspicontext.c +++ b/gtk/a11y/gtkatspicontext.c @@ -729,14 +729,24 @@ emit_text_selection_changed (GtkAtSpiContext *self, const char *kind, int cursor_position) { - g_dbus_connection_emit_signal (self->connection, - NULL, - self->context_path, - "org.a11y.atspi.Event.Object", - "TextChanged", - g_variant_new ("(siiva{sv})", - kind, cursor_position, 0, g_variant_new_string (""), NULL), + if (strcmp (kind, "text-caret-moved") == 0) + g_dbus_connection_emit_signal (self->connection, + NULL, + self->context_path, + "org.a11y.atspi.Event.Object", + "TextCaretMoved", + g_variant_new ("(siiva{sv})", + "", cursor_position, 0, g_variant_new_string (""), NULL), NULL); + else + g_dbus_connection_emit_signal (self->connection, + NULL, + self->context_path, + "org.a11y.atspi.Event.Object", + "TextSelectionChanged", + g_variant_new ("(siiva{sv})", + "", 0, 0, g_variant_new_string (""), NULL), + NULL); } static void diff --git a/gtk/gtkatcontext.c b/gtk/gtkatcontext.c index 8a62e2821d..dd771bc10c 100644 --- a/gtk/gtkatcontext.c +++ b/gtk/gtkatcontext.c @@ -760,7 +760,7 @@ gtk_at_context_get_name_accumulate (GtkATContext *self, GList *list = gtk_reference_list_accessible_value_get (value); - for (GList *l = list; l != NULL; l = l->data) + for (GList *l = list; l != NULL; l = l->next) { GtkAccessible *rel = GTK_ACCESSIBLE (l->data); GtkATContext *rel_context = gtk_accessible_get_at_context (rel); diff --git a/gtk/gtkcolumnview.c b/gtk/gtkcolumnview.c index bc0b1b8be5..d6c8c58b73 100644 --- a/gtk/gtkcolumnview.c +++ b/gtk/gtkcolumnview.c @@ -105,6 +105,13 @@ * The main columnview node may also carry style classes to select * the style of [list presentation](ListContainers.html#list-styles): * .rich-list, .navigation-sidebar or .data-table. + * + * # Accessibility + * + * GtkColumnView uses the #GTK_ACCESSIBLE_ROLE_TREE_GRID role, header title + * widgets are using the #GTK_ACCESSIBLE_ROLE_COLUMN_HEADER role. The row widgets + * are using the #GTK_ACCESSIBLE_ROLE_ROW role, and individual cells are using + * the #GTK_ACCESSIBLE_ROLE_GRID_CELL role */ /* We create a subclass of GtkListView for the sole purpose of overriding diff --git a/gtk/gtkflowbox.c b/gtk/gtkflowbox.c index 79106c74c6..0ec12db7e4 100644 --- a/gtk/gtkflowbox.c +++ b/gtk/gtkflowbox.c @@ -69,6 +69,11 @@ * GtkFlowBox uses a single CSS node with name flowbox. GtkFlowBoxChild * uses a single CSS node with name flowboxchild. * For rubberband selection, a subnode with name rubberband is used. + * + * # Accessibility + * + * GtkFlowBox uses the #GTK_ACCESSIBLE_ROLE_GRID role, and GtkFlowBoxChild + * uses the #GTK_ACCESSIBLE_ROLE_GRID_CELL role. */ #include <config.h> diff --git a/gtk/gtkgridview.c b/gtk/gtkgridview.c index 8c24afc9e1..1f3b4c37ef 100644 --- a/gtk/gtkgridview.c +++ b/gtk/gtkgridview.c @@ -77,6 +77,11 @@ * GtkGridView uses a single CSS node with name gridview. Each child * uses a single CSS node with name child. For rubberband selection, * a subnode with name rubberband is used. + * + * # Accessibility + * + * GtkGridView uses the #GTK_ACCESSIBLE_ROLE_GRID role, and the items + * use the #GTK_ACCESSIBLE_ROLE_GRID_CELL role. */ typedef struct _Cell Cell; diff --git a/gtk/gtklinkbutton.c b/gtk/gtklinkbutton.c index 7cd2476a2c..53a01cc207 100644 --- a/gtk/gtklinkbutton.c +++ b/gtk/gtklinkbutton.c @@ -50,7 +50,7 @@ * * # Accessibility * - * GtkLinkButton uses the #GTK_ACCESSIBKE_ROLE_BUTTON role. + * GtkLinkButton uses the #GTK_ACCESSIBLE_ROLE_BUTTON role. */ #include "config.h" diff --git a/gtk/gtklistbox.c b/gtk/gtklistbox.c index b6612f34c7..f08e3bf559 100644 --- a/gtk/gtklistbox.c +++ b/gtk/gtklistbox.c @@ -85,6 +85,11 @@ * The main list node may also carry style classes to select * the style of [list presentation](ListContainers.html#list-styles): * .rich-list, .navigation-sidebar or .data-table. + * + * # Accessibility + * + * GtkListBox uses the #GTK_ACCESSIBLE_ROLE_LIST role and GtkListBoxRow uses + * the #GTK_ACCESSIBLE_ROLE_LIST_ITEM role. */ typedef struct _GtkListBoxClass GtkListBoxClass; diff --git a/gtk/gtklistview.c b/gtk/gtklistview.c index ad8f8ea16c..6d1eb3413b 100644 --- a/gtk/gtklistview.c +++ b/gtk/gtklistview.c @@ -135,6 +135,11 @@ * The main listview node may also carry style classes to select * the style of [list presentation](ListContainers.html#list-styles): * .rich-list, .navigation-sidebar or .data-table. + * + * # Accessibility + * + * GtkListView uses the #GTK_ACCESSIBLE_ROLE_LIST role, and the list + * items use the #GTK_ACCESSIBLE_ROLE_LIST_ITEM role. */ typedef struct _ListRow ListRow; diff --git a/gtk/gtktext.c b/gtk/gtktext.c index 59f68d04f7..7f3d064a94 100644 --- a/gtk/gtktext.c +++ b/gtk/gtktext.c @@ -122,6 +122,12 @@ * CSS nodes with name cursor-handle. They get the .top or .bottom style class * depending on where they are shown in relation to the selection. If there is * just a single handle for the text cursor, it gets the style class .insertion-cursor. + * + * # Accessibility + * + * GtkText uses the #GTK_ACCESSIBLE_ROLE_NONE role, which causes it to be skipped + * for accessibility. This is because GtkText is expected to be used as a delegate + * for a #GtkEditable implementation that will be represented to accessibility. */ #define NAT_ENTRY_WIDTH 150 diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 0ebe20f7e8..49a16937cb 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -8973,6 +8973,7 @@ gtk_widget_add_mnemonic_label (GtkWidget *widget, GtkWidget *label) { GSList *old_list, *new_list; + GList *list; g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (GTK_IS_WIDGET (label)); @@ -8983,8 +8984,9 @@ gtk_widget_add_mnemonic_label (GtkWidget *widget, g_object_set_qdata_full (G_OBJECT (widget), quark_mnemonic_labels, new_list, (GDestroyNotify) g_slist_free); + list = gtk_widget_list_mnemonic_labels (widget); gtk_accessible_update_relation (GTK_ACCESSIBLE (widget), - GTK_ACCESSIBLE_RELATION_LABELLED_BY, new_list, + GTK_ACCESSIBLE_RELATION_LABELLED_BY, list, -1); } @@ -9017,15 +9019,17 @@ gtk_widget_remove_mnemonic_label (GtkWidget *widget, if (new_list != NULL && new_list->data != NULL) { + GList *list; + + list = gtk_widget_list_mnemonic_labels (widget); gtk_accessible_update_relation (GTK_ACCESSIBLE (widget), - GTK_ACCESSIBLE_RELATION_LABELLED_BY, new_list, + GTK_ACCESSIBLE_RELATION_LABELLED_BY, list, -1); } else { - gtk_accessible_update_relation (GTK_ACCESSIBLE (widget), - GTK_ACCESSIBLE_RELATION_LABELLED_BY, NULL, - -1); + gtk_accessible_reset_relation (GTK_ACCESSIBLE (widget), + GTK_ACCESSIBLE_RELATION_LABELLED_BY); } } diff --git a/gtk/inspector/a11y.c b/gtk/inspector/a11y.c index f4c93b3d65..b6cd169e29 100644 --- a/gtk/inspector/a11y.c +++ b/gtk/inspector/a11y.c @@ -34,6 +34,9 @@ #include "gtknoselection.h" #include "gtkfilterlistmodel.h" #include "gtkboolfilter.h" +#ifdef G_OS_UNIX +#include "a11y/gtkatspicontextprivate.h" +#endif typedef enum { STATE, @@ -198,6 +201,7 @@ struct _GtkInspectorA11y GtkWidget *box; GtkWidget *role; + GtkWidget *path; GtkWidget *attributes; }; @@ -223,6 +227,21 @@ update_role (GtkInspectorA11y *sl) g_type_class_unref (eclass); } +static void +update_path (GtkInspectorA11y *sl) +{ + const char *path = "—"; +#ifdef G_OS_UNIX + GtkATContext *context; + + context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (sl->object)); + if (GTK_IS_AT_SPI_CONTEXT (context)) + path = gtk_at_spi_context_get_context_path (GTK_AT_SPI_CONTEXT (context)); +#endif + + gtk_label_set_label (GTK_LABEL (sl->path), path); +} + extern GType gtk_string_pair_get_type (void); static void @@ -244,6 +263,8 @@ update_attributes (GtkInspectorA11y *sl) gboolean has_value; context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (sl->object)); + if (!context) + return; store = g_list_store_new (G_TYPE_OBJECT); @@ -380,6 +401,7 @@ static void refresh_all (GtkInspectorA11y *sl) { update_role (sl); + update_path (sl); update_attributes (sl); } @@ -394,7 +416,8 @@ gtk_inspector_a11y_set_object (GtkInspectorA11y *sl, if (sl->object && GTK_IS_ACCESSIBLE (sl->object)) { context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (sl->object)); - g_signal_handlers_disconnect_by_func (context, refresh_all, sl); + if (context) + g_signal_handlers_disconnect_by_func (context, refresh_all, sl); } g_set_object (&sl->object, object); @@ -405,9 +428,11 @@ gtk_inspector_a11y_set_object (GtkInspectorA11y *sl, if (GTK_IS_ACCESSIBLE (object)) { context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (sl->object)); - g_signal_connect_swapped (context, "state-change", G_CALLBACK (refresh_all), sl); + if (context) + g_signal_connect_swapped (context, "state-change", G_CALLBACK (refresh_all), sl); gtk_stack_page_set_visible (page, TRUE); update_role (sl); + update_path (sl); update_attributes (sl); } else @@ -453,6 +478,7 @@ gtk_inspector_a11y_class_init (GtkInspectorA11yClass *klass) gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/a11y.ui"); gtk_widget_class_bind_template_child (widget_class, GtkInspectorA11y, box); gtk_widget_class_bind_template_child (widget_class, GtkInspectorA11y, role); + gtk_widget_class_bind_template_child (widget_class, GtkInspectorA11y, path); gtk_widget_class_bind_template_child (widget_class, GtkInspectorA11y, attributes); gtk_widget_class_bind_template_callback (widget_class, setup_cell_cb); diff --git a/gtk/inspector/a11y.ui b/gtk/inspector/a11y.ui index 957453aa2c..6c212e9d86 100644 --- a/gtk/inspector/a11y.ui +++ b/gtk/inspector/a11y.ui @@ -29,6 +29,30 @@ </object> </child> <child> + <object class="GtkBox"> + <property name="margin-start">10</property> + <property name="margin-end">10</property> + <property name="margin-top">10</property> + <property name="margin-bottom">10</property> + <property name="spacing">40</property> + <child> + <object class="GtkLabel"> + <property name="label" translatable="yes">Object path</property> + <property name="halign">start</property> + <property name="valign">baseline</property> + <property name="xalign">0.0</property> + </object> + </child> + <child> + <object class="GtkLabel" id="path"> + <property name="selectable">1</property> + <property name="halign">end</property> + <property name="valign">baseline</property> + </object> + </child> + </object> + </child> + <child> <object class="GtkSeparator"/> </child> <child> diff --git a/testsuite/a11y/button.c b/testsuite/a11y/button.c index f78207fb31..a5e44280a4 100644 --- a/testsuite/a11y/button.c +++ b/testsuite/a11y/button.c @@ -25,6 +25,24 @@ button_label (void) g_object_unref (button); } +/* Check that we set up a labelled_by relationship between a button + * and its label. + */ +static void +button_relation (void) +{ + GtkWidget *button = gtk_button_new_with_mnemonic ("_Hello"); + GList *list; + + g_object_ref_sink (button); + + list = g_list_append (NULL, gtk_widget_get_first_child (button)); + gtk_test_accessible_assert_relation (GTK_ACCESSIBLE (button), GTK_ACCESSIBLE_RELATION_LABELLED_BY, list); + g_list_free (list); + + g_object_unref (button); +} + static void linkbutton_role (void) { @@ -54,6 +72,7 @@ main (int argc, char *argv[]) g_test_add_func ("/a11y/button/role", button_role); g_test_add_func ("/a11y/button/label", button_label); + g_test_add_func ("/a11y/button/relation", button_relation); g_test_add_func ("/a11y/linkbutton/role", linkbutton_role); g_test_add_func ("/a11y/linkbutton/label", linkbutton_label); |