a11y: Add bounds rectangle to GtkAccessible
authorLukáš Tyrychtr <lukastyrychtr@gmail.com>
Mon, 12 Sep 2022 09:55:06 +0000 (11:55 +0200)
committerEmmanuele Bassi <ebassi@gnome.org>
Fri, 3 Feb 2023 10:49:17 +0000 (11:49 +0100)
Make the bounds calculation part of the accessible interface.

Bounds are used by ATs like Orca to implement features like Flat Review:

https://help.gnome.org/users/orca/stable/howto_flat_review.html.en

Or to determine the area of a non-presentational widget.

gtk/a11y/gtkatspicontext.c
gtk/gtkaccessible.c
gtk/gtkaccessibleprivate.h
gtk/gtkwidget.c

index adddbd58514e4771ac6dfe54c1df26bae5a20f3e..c915281722b8ecf182073ed983b911f0b76c2903 100644 (file)
@@ -1099,29 +1099,9 @@ gtk_at_spi_context_bounds_change (GtkATContext *ctx)
 {
   GtkAtSpiContext *self = GTK_AT_SPI_CONTEXT (ctx);
   GtkAccessible *accessible = gtk_at_context_get_accessible (ctx);
-  GtkWidget *widget;
-  GtkWidget *parent;
-  double x, y;
-  int width, height;
-
-  if (!GTK_IS_WIDGET (accessible))
-    return;
-
-  widget = GTK_WIDGET (accessible);
-  if (!gtk_widget_get_realized (widget))
-    return;
-
-  parent = gtk_widget_get_parent (widget);
-
-  if (parent)
-    gtk_widget_translate_coordinates (widget, parent, 0., 0., &x, &y);
-  else
-    x = y = 0.;
-
-  width = gtk_widget_get_width (widget);
-  height = gtk_widget_get_height (widget);
-
-  emit_bounds_changed (self, (int)x, (int)y, width, height);
+  int x, y, width, height;
+  if (gtk_accessible_get_bounds (accessible, &x, &y, &width, &height))
+    emit_bounds_changed (self, x, y, width, height);
 }
 
 static void
index 20ee867242238673610ced3f5d288366777c1624..6e9faf46d44b900e396ffe779fd25f043e9a1269 100644 (file)
@@ -805,6 +805,31 @@ gtk_accessible_bounds_changed (GtkAccessible *self)
   gtk_at_context_bounds_changed (context);
 }
 
+/*
+ * gtk_accessible_get_bounds:
+ * @self: a `GtkAccessible`
+ * @x: the x coordinate of the top left corner of the accessible
+ * @y: the y coordinate of the top left corner of the widget
+ * @width: the width of the widget
+ * @height: the height of the widget
+ *
+ * Query the coordinates and dimensions of this accessible
+ *
+ * See gtk_accessible_bounds_changed().
+ *
+ * This functionality can be overridden by `GtkAccessible`
+ * implementations, e.g. to get the bounds from an ignored
+ * child widget.
+ *
+ * Returns: whether the bounds should be considered valid
+ */
+gboolean
+gtk_accessible_get_bounds (GtkAccessible              *self,
+                                   int *x, int *y, int *width, int *height)
+{
+  return GTK_ACCESSIBLE_GET_IFACE (self)->get_bounds (self, x, y, width, height);
+}
+
 /*<private>
  * gtk_accessible_should_present:
  * @self: a `GtkAccessible`
index ddd94d7dff2f1627a0e6d558c24c68a0a913e259..dda06c67dd475c9f584b79af895a5e4b800f7698 100644 (file)
@@ -36,6 +36,9 @@ struct _GtkAccessibleInterface
 
   GtkAccessible *       (* get_parent)  (GtkAccessible *self);
   GtkAccessible *       (* get_child_at_index)  (GtkAccessible *self, guint index);
+
+  gboolean              (* get_bounds) (GtkAccessible *self, int *x, int *y,
+                                        int *width, int *height);
 };
 
 GtkATContext *  gtk_accessible_get_at_context   (GtkAccessible *self);
@@ -56,6 +59,8 @@ GtkAccessible * gtk_accessible_get_parent(GtkAccessible *self);
 
 GtkAccessible * gtk_accessible_get_child_at_index(GtkAccessible *self, guint index);
 
+gboolean gtk_accessible_get_bounds (GtkAccessible *self, int *x, int *y, int *width, int *height);
+
 void            gtk_accessible_bounds_changed   (GtkAccessible *self);
 
 void            gtk_accessible_update_children  (GtkAccessible           *self,
index c842d1f7a59da5c4a7c57faab322c93b1b45e2ad..4f0c94dc62757f2f8832f40860271abbb7b8a8a4 100644 (file)
@@ -8487,6 +8487,33 @@ gtk_widget_accessible_get_child_at_index (GtkAccessible *self, guint index)
   return NULL;
 }
 
+static gboolean
+gtk_widget_accessible_get_bounds (GtkAccessible *self, int *x, int *y, int *width, int *height) {
+  GtkWidget *widget;
+  GtkWidget *parent;
+  double translated_x, translated_y;
+   
+  widget = GTK_WIDGET (self);
+  if (!gtk_widget_get_realized (widget))
+    return false;
+
+  parent = gtk_widget_get_parent (widget);
+
+  if (parent)
+    {
+      gtk_widget_translate_coordinates (widget, parent, 0., 0., &translated_x, &translated_y);
+      *x = (int)translated_x;
+      *y = (int)translated_y;
+    }
+  else
+    *x = *y = 0;
+
+  *width = gtk_widget_get_width (widget);
+  *height = gtk_widget_get_height (widget);
+
+  return true;
+}
+
 static void
 gtk_widget_accessible_interface_init (GtkAccessibleInterface *iface)
 {
@@ -8494,6 +8521,7 @@ gtk_widget_accessible_interface_init (GtkAccessibleInterface *iface)
   iface->get_platform_state = gtk_widget_accessible_get_platform_state;
   iface->get_parent = gtk_widget_accessible_get_parent;
   iface->get_child_at_index = gtk_widget_accessible_get_child_at_index;
+  iface->get_bounds = gtk_widget_accessible_get_bounds;
 }
 
 static void