From f693beab5742d145f62aa91b512c84c55db91ed4 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 19 Jun 2023 21:43:18 -0400 Subject: [PATCH 1/7] NEWS: Updates --- NEWS | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/NEWS b/NEWS index 7f9ae2ed7d..d5c011576f 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,62 @@ Overview of Changes in 4.11.4, xx-xx-xxxx ========================================= +* GtkFileChooser: + - Default to sorting folders first + - Fix a crash when visiting recent files + +* GtkTextView: + - Fix corner cases in word navigation + +* GtkMenuButton: + - Normalize label layout + +* GtkDropDown: + - Add support for sections + +* GtkVideo: + - Make the overlay icon clickable + +* GtkWindow: + - Clear the resize cursors to avoid artifacts + +* Accessibility: + - Improvements all over the place: GtkButton, GtkPasswordEntry, + GtkFontChooserDialog, GtkColorChooserDialog, GtkShortcutsWindow, + GtkMenuButton, GtkAboutDialog, GtkFileChooserDialog, GtkStackSidebar, + GtkMediaControls, GtkColorDialogButton, GtkDropDown, GtkInfoBar, + GtkNotebook, GtkPrintUnixDialog, GtkModelButton + - Make name computation follow the ARIA spec more closely + - Change many containers to use `generic` instead of `group` + - Use `generic` as the default role + - Use `application` instead of `window` for windows + +* X11: + - Fix regressions in GLX setup + +* Windows: + - Center newly created transient windows + +* Vulkan: + - Add antialising for gradients + - Do less work on clipped away nodes + - Redo image uploading + - Support different image depths and formats + +* Demos: + - gtk4-demo: Improve window sizing + - gtk4-demo: Improve focus behavior + - gtk4-demo: Add many missing a11y properties +` +* Inspector: + - Show more information in the a11y tab + - Add an accessibility overlay + - Limit the width of the a11y tab + +* Translation updates: + Czech + + Overview of Changes in 4.11.3, 05-06-2023 ========================================= From e836e3380e1f2a78010c8caa530b449212075469 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 20 Jun 2023 06:53:34 -0400 Subject: [PATCH 2/7] Add a comment about accessible naming Put a note on why there are a few differences to ARIA. --- gtk/gtkatcontext.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gtk/gtkatcontext.c b/gtk/gtkatcontext.c index 42f0c2717e..efbc572665 100644 --- a/gtk/gtkatcontext.c +++ b/gtk/gtkatcontext.c @@ -1010,7 +1010,12 @@ gtk_at_context_get_accessible_relation (GtkATContext *self, /* See ARIA 5.2.8.4, 5.2.8.5 and 5.2.8.6 for the prohibited, from author * and from content parts, and the table in * https://www.w3.org/WAI/ARIA/apg/practices/names-and-descriptions/ - * for the recommended / not recommended parts. + * for the recommended / not recommended parts. We've made a few changes + * to the recommendations: + * - We don't recommend against labelling listitems, sincd GtkListView + * will put the focus on listitems sometimes. + * - We don't recommend tab lists being labelled, since GtkNotebook does + * not have a practical way of doing that. */ #define NAME_FROM_AUTHOR (1 << 6) From 63534fd9eb532d8a37ce0762d206885c53c5919a Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 20 Jun 2023 10:40:12 -0400 Subject: [PATCH 3/7] widget: Fix accessible hidden state Make this track the widgets' mapped state instead of visible. Also, set hidden to FALSE initially, since the accessible name computation checks for hidden==FALSE. --- gtk/gtkwidget.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 4f0b1f0be9..e8225cdbbf 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -2380,6 +2380,10 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class) } priv->at_context = create_at_context (widget); + + gtk_accessible_update_state (GTK_ACCESSIBLE (widget), + GTK_ACCESSIBLE_STATE_HIDDEN, TRUE, + -1); } static void @@ -2708,10 +2712,6 @@ gtk_widget_show (GtkWidget *widget) g_signal_emit (widget, widget_signals[SHOW], 0); g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_VISIBLE]); - gtk_accessible_update_state (GTK_ACCESSIBLE (widget), - GTK_ACCESSIBLE_STATE_HIDDEN, FALSE, - -1); - gtk_widget_pop_verify_invariants (widget); g_object_unref (widget); } @@ -2775,10 +2775,6 @@ gtk_widget_hide (GtkWidget *widget) g_signal_emit (widget, widget_signals[HIDE], 0); g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_VISIBLE]); - gtk_accessible_update_state (GTK_ACCESSIBLE (widget), - GTK_ACCESSIBLE_STATE_HIDDEN, TRUE, - -1); - parent = gtk_widget_get_parent (widget); if (parent) gtk_widget_queue_resize (parent); @@ -2851,6 +2847,10 @@ gtk_widget_map (GtkWidget *widget) gtk_widget_queue_draw (widget); + gtk_accessible_update_state (GTK_ACCESSIBLE (widget), + GTK_ACCESSIBLE_STATE_HIDDEN, FALSE, + -1); + gtk_widget_pop_verify_invariants (widget); } } @@ -2880,6 +2880,10 @@ gtk_widget_unmap (GtkWidget *widget) update_cursor_on_state_change (widget); + gtk_accessible_update_state (GTK_ACCESSIBLE (widget), + GTK_ACCESSIBLE_STATE_HIDDEN, TRUE, + -1); + gtk_widget_pop_verify_invariants (widget); g_object_unref (widget); } From 95cd6fe206256802efd9db2876f9919b1e07972e Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 20 Jun 2023 10:56:41 -0400 Subject: [PATCH 4/7] menubutton: Remove all the labelled-by relations This was a bit much, and should not be necessary anymore, now that our name computation handles nested buttons. --- gtk/gtkmenubutton.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/gtk/gtkmenubutton.c b/gtk/gtkmenubutton.c index 59fb9394e5..e162470cf9 100644 --- a/gtk/gtkmenubutton.c +++ b/gtk/gtkmenubutton.c @@ -689,11 +689,6 @@ gtk_menu_button_init (GtkMenuButton *self) gtk_widget_set_sensitive (self->button, FALSE); gtk_widget_add_css_class (GTK_WIDGET (self), "popup"); - - gtk_accessible_update_relation (GTK_ACCESSIBLE (self->button), - GTK_ACCESSIBLE_RELATION_LABELLED_BY, self, NULL, - GTK_ACCESSIBLE_RELATION_DESCRIBED_BY, self, NULL, - -1); } static GtkBuildableIface *parent_buildable_iface; @@ -1046,15 +1041,6 @@ gtk_menu_button_set_icon_name (GtkMenuButton *menu_button, box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_widget_set_halign (box, GTK_ALIGN_CENTER); - /* Because we are setting only an icon, let the inner button be labelled by us - * so the accessible label can be overridden from, for example, an UI file - * using GtkMenuButton as a child of something. - */ - gtk_accessible_update_relation (GTK_ACCESSIBLE (menu_button->button), - GTK_ACCESSIBLE_RELATION_LABELLED_BY, menu_button, NULL, - GTK_ACCESSIBLE_RELATION_DESCRIBED_BY, menu_button, NULL, - -1); - image_widget = g_object_new (GTK_TYPE_IMAGE, "accessible-role", GTK_ACCESSIBLE_ROLE_PRESENTATION, "icon-name", icon_name, @@ -1192,11 +1178,6 @@ gtk_menu_button_set_label (GtkMenuButton *menu_button, gtk_button_set_child (GTK_BUTTON (menu_button->button), box); menu_button->label_widget = label_widget; - gtk_accessible_update_relation (GTK_ACCESSIBLE (menu_button->button), - GTK_ACCESSIBLE_RELATION_LABELLED_BY, menu_button->label_widget, NULL, - GTK_ACCESSIBLE_RELATION_DESCRIBED_BY, menu_button->label_widget, NULL, - -1); - menu_button->image_widget = NULL; menu_button->child = NULL; From 891462e5afa1dcad96ca0d4a307fcbb3ee1f288a Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 20 Jun 2023 11:05:22 -0400 Subject: [PATCH 5/7] Add some more a11y tests Check that the hidden state is as it should be. --- testsuite/a11y/button.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/testsuite/a11y/button.c b/testsuite/a11y/button.c index b32682f755..7e79dc00e8 100644 --- a/testsuite/a11y/button.c +++ b/testsuite/a11y/button.c @@ -42,6 +42,26 @@ button_relation (void) g_object_unref (button); } +static void +button_state (void) +{ + GtkWidget *button = gtk_button_new_with_mnemonic ("_Hello"); + + g_object_ref_sink (button); + + gtk_test_accessible_assert_state (GTK_ACCESSIBLE (button), + GTK_ACCESSIBLE_STATE_HIDDEN, button, FALSE, + -1); + + gtk_widget_set_visible (button, FALSE); + + gtk_test_accessible_assert_state (GTK_ACCESSIBLE (button), + GTK_ACCESSIBLE_STATE_HIDDEN, button, TRUE, + -1); + + g_object_unref (button); +} + static void linkbutton_role (void) { @@ -73,6 +93,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/button/state", button_state); g_test_add_func ("/a11y/linkbutton/role", linkbutton_role); g_test_add_func ("/a11y/linkbutton/label", linkbutton_label); From cca6a66518e33779f37ad7853f7408d06bd5926d Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 20 Jun 2023 12:33:02 -0400 Subject: [PATCH 6/7] a11y: Fix tests The change to make hidden follow mappedness means that we now need to arrange for our test cases to be mapped. --- testsuite/a11y/general.c | 14 ++++---- testsuite/a11y/names.c | 75 ++++++++++++++++++++++++++++------------ 2 files changed, 61 insertions(+), 28 deletions(-) diff --git a/testsuite/a11y/general.c b/testsuite/a11y/general.c index 006023919d..78c7c55a54 100644 --- a/testsuite/a11y/general.c +++ b/testsuite/a11y/general.c @@ -8,18 +8,20 @@ static void test_hidden (void) { + GtkWidget *window; GtkWidget *widget; + window = gtk_window_new (); widget = gtk_button_new (); - g_object_ref_sink (widget); - - gtk_test_accessible_assert_state (widget, GTK_ACCESSIBLE_STATE_HIDDEN, FALSE); - - gtk_widget_set_visible (widget, FALSE); + gtk_window_set_child (GTK_WINDOW (window), widget); gtk_test_accessible_assert_state (widget, GTK_ACCESSIBLE_STATE_HIDDEN, TRUE); - g_object_unref (widget); + gtk_window_present (GTK_WINDOW (window)); + + gtk_test_accessible_assert_state (widget, GTK_ACCESSIBLE_STATE_HIDDEN, FALSE); + + gtk_window_destroy (GTK_WINDOW (window)); } static void diff --git a/testsuite/a11y/names.c b/testsuite/a11y/names.c index 4a76b03420..2eba20edea 100644 --- a/testsuite/a11y/names.c +++ b/testsuite/a11y/names.c @@ -5,7 +5,7 @@ static void test_name_content (void) { - GtkWidget *label1, *label2, *box, *button; + GtkWidget *window, *label1, *label2, *box, *button; char *name; label1 = gtk_label_new ("a"); @@ -16,13 +16,10 @@ test_name_content (void) gtk_box_append (GTK_BOX (box), label1); gtk_box_append (GTK_BOX (box), label2); gtk_button_set_child (GTK_BUTTON (button), box); - g_object_ref_sink (button); - /* gtk_at_context_get_name only works on realized contexts */ - gtk_widget_realize_at_context (label1); - gtk_widget_realize_at_context (label2); - gtk_widget_realize_at_context (box); - gtk_widget_realize_at_context (button); + window = gtk_window_new (); + gtk_window_set_child (GTK_WINDOW (window), button); + gtk_window_present (GTK_WINDOW (window)); name = gtk_at_context_get_name (gtk_accessible_get_at_context (GTK_ACCESSIBLE (label1))); g_assert_cmpstr (name, ==, "a"); @@ -43,17 +40,20 @@ test_name_content (void) g_assert_cmpstr (name, ==, "a"); g_free (name); - g_object_unref (button); + gtk_window_destroy (GTK_WINDOW (window)); } static void test_name_tooltip (void) { - GtkWidget *image = gtk_image_new (); + GtkWidget *window, *image; char *name; - g_object_ref_sink (image); - gtk_widget_realize_at_context (image); + image = gtk_image_new (); + + window = gtk_window_new (); + gtk_window_set_child (GTK_WINDOW (window), image); + gtk_window_present (GTK_WINDOW (window)); gtk_widget_set_tooltip_text (image, "tooltip"); @@ -61,16 +61,44 @@ test_name_tooltip (void) g_assert_cmpstr (name, ==, "tooltip"); g_free (name); - g_object_unref (image); + gtk_window_destroy (GTK_WINDOW (window)); +} + +static void +test_name_menubutton (void) +{ + GtkWidget *window, *widget; + char *name; + + widget = gtk_menu_button_new (); + gtk_menu_button_set_popover (GTK_MENU_BUTTON (widget), gtk_popover_new ()); + + window = gtk_window_new (); + gtk_window_set_child (GTK_WINDOW (window), widget); + gtk_window_present (GTK_WINDOW (window)); + + gtk_widget_set_tooltip_text (widget, "tooltip"); + + name = gtk_at_context_get_name (gtk_accessible_get_at_context (GTK_ACCESSIBLE (widget))); + g_assert_cmpstr (name, ==, "tooltip"); + g_free (name); + + gtk_window_destroy (GTK_WINDOW (window)); } static void test_name_label (void) { - GtkWidget *image = gtk_image_new (); + GtkWidget *window, *image; char *name; char *desc; + image = gtk_image_new (); + + window = gtk_window_new (); + gtk_window_set_child (GTK_WINDOW (window), image); + gtk_window_present (GTK_WINDOW (window)); + g_object_ref_sink (image); gtk_widget_realize_at_context (image); @@ -89,13 +117,13 @@ test_name_label (void) g_free (name); g_free (desc); - g_object_unref (image); + gtk_window_destroy (GTK_WINDOW (window)); } static void test_name_prohibited (void) { - GtkWidget *widget; + GtkWidget *window, *widget; char *name; char *desc; @@ -104,8 +132,9 @@ test_name_prohibited (void) "label", "too late", NULL); - g_object_ref_sink (widget); - gtk_widget_realize_at_context (widget); + window = gtk_window_new (); + gtk_window_set_child (GTK_WINDOW (window), widget); + gtk_window_present (GTK_WINDOW (window)); name = gtk_at_context_get_name (gtk_accessible_get_at_context (GTK_ACCESSIBLE (widget))); desc = gtk_at_context_get_description (gtk_accessible_get_at_context (GTK_ACCESSIBLE (widget))); @@ -116,19 +145,20 @@ test_name_prohibited (void) g_free (name); g_free (desc); - g_object_unref (widget); + gtk_window_destroy (GTK_WINDOW (window)); } static void test_name_range (void) { - GtkWidget *scale; + GtkWidget *window, *scale; char *name; scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0, 100, 10); - g_object_ref_sink (scale); - gtk_widget_realize_at_context (scale); + window = gtk_window_new (); + gtk_window_set_child (GTK_WINDOW (window), scale); + gtk_window_present (GTK_WINDOW (window)); g_assert_true (gtk_accessible_get_accessible_role (GTK_ACCESSIBLE (scale)) == GTK_ACCESSIBLE_ROLE_SLIDER); g_assert_true (gtk_at_context_get_accessible_role (gtk_accessible_get_at_context (GTK_ACCESSIBLE (scale))) == GTK_ACCESSIBLE_ROLE_SLIDER); @@ -140,7 +170,7 @@ test_name_range (void) g_free (name); - g_object_unref (scale); + gtk_window_destroy (GTK_WINDOW (window)); } int @@ -150,6 +180,7 @@ main (int argc, char *argv[]) g_test_add_func ("/a11y/name/content", test_name_content); g_test_add_func ("/a11y/name/tooltip", test_name_tooltip); + g_test_add_func ("/a11y/name/menubutton", test_name_menubutton); g_test_add_func ("/a11y/name/label", test_name_label); g_test_add_func ("/a11y/name/prohibited", test_name_prohibited); g_test_add_func ("/a11y/name/range", test_name_range); From 7331683c01bed94ec8285d494658a0a2985659aa Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 20 Jun 2023 12:34:01 -0400 Subject: [PATCH 7/7] a11y: Improve name computation We only want to settle on subtree content if it provides nonempty text. Otherwise, the tooltip should still win. This was clarified in the current Editor Draft of the accessible name computation spec. --- gtk/gtkatcontext.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/gtk/gtkatcontext.c b/gtk/gtkatcontext.c index efbc572665..4d86184644 100644 --- a/gtk/gtkatcontext.c +++ b/gtk/gtkatcontext.c @@ -1321,7 +1321,7 @@ gtk_at_context_get_text_accumulate (GtkATContext *self, { if (GTK_IS_WIDGET (self->accessible)) { - gboolean has_child = FALSE; + GString *s = g_string_new (""); for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self->accessible)); child != NULL; @@ -1330,13 +1330,17 @@ gtk_at_context_get_text_accumulate (GtkATContext *self, GtkAccessible *rel = GTK_ACCESSIBLE (child); GtkATContext *rel_context = gtk_accessible_get_at_context (rel); - gtk_at_context_get_text_accumulate (rel_context, nodes, res, property, relation, FALSE, TRUE); - - has_child = TRUE; + gtk_at_context_get_text_accumulate (rel_context, nodes, s, property, relation, FALSE, TRUE); } - if (has_child) - return; + if (s->len > 0) + { + g_string_append (res, s->str); + g_string_free (s, TRUE); + return; + } + + g_string_free (s, TRUE); } }