summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2020-10-21 11:43:58 +0000
committerMatthias Clasen <mclasen@redhat.com>2020-10-21 11:43:58 +0000
commit8880e3bd2e060874aba303595303624116c883e0 (patch)
tree95fda5bc4862e91b3418bf20c844212fba4eba8a
parent0b5b908a741d9795dbd38f05f2657f1043e6b29e (diff)
parentcbb6828657d84485af8806845f53e943f0873ddb (diff)
downloadgtk+-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.md25
-rw-r--r--gtk/a11y/gtkatspicontext.c24
-rw-r--r--gtk/gtkatcontext.c2
-rw-r--r--gtk/gtkcolumnview.c7
-rw-r--r--gtk/gtkflowbox.c5
-rw-r--r--gtk/gtkgridview.c5
-rw-r--r--gtk/gtklinkbutton.c2
-rw-r--r--gtk/gtklistbox.c5
-rw-r--r--gtk/gtklistview.c5
-rw-r--r--gtk/gtktext.c6
-rw-r--r--gtk/gtkwidget.c14
-rw-r--r--gtk/inspector/a11y.c30
-rw-r--r--gtk/inspector/a11y.ui24
-rw-r--r--testsuite/a11y/button.c19
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);