[gtk/ebassi/new-a11y: 14/14] Add accessible properties to GtkAccessible



commit c03f5ed0da8ad240040c625344715d2a4051e9ce
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Mon Jul 13 15:51:39 2020 +0100

    Add accessible properties to GtkAccessible
    
    We propagate the accessible state and properties to each ATContext in
    the same virtual function, since they are functionally similar.

 gtk/gtkaccessible.c       | 60 +++++++++++++++++++++++++++++++---
 gtk/gtkaccessible.h       | 16 +++++----
 gtk/gtkatcontext.c        | 83 +++++++++++++++++++++++++++++++++++++++--------
 gtk/gtkatcontextprivate.h | 69 +++++++++++++++++++++++++++++----------
 gtk/gtktestatcontext.c    | 21 ++++++++----
 5 files changed, 200 insertions(+), 49 deletions(-)
---
diff --git a/gtk/gtkaccessible.c b/gtk/gtkaccessible.c
index 47bebc7543..0d6e2bd717 100644
--- a/gtk/gtkaccessible.c
+++ b/gtk/gtkaccessible.c
@@ -116,7 +116,7 @@ gtk_accessible_get_accessible_role (GtkAccessible *self)
  * state change must be communicated to assistive technologies.
  */
 void
-gtk_accessible_update_state (GtkAccessible *self,
+gtk_accessible_update_state (GtkAccessible      *self,
                              GtkAccessibleState  first_state,
                              ...)
 {
@@ -141,13 +141,13 @@ gtk_accessible_update_state (GtkAccessible *self,
       if (value == NULL)
         goto out;
 
-      gtk_at_context_set_state (context, state, value);
+      gtk_at_context_set_accessible_state (context, state, value);
       gtk_accessible_value_unref (value);
 
       state = va_arg (args, int);
     }
 
-  gtk_at_context_update_state (context);
+  gtk_at_context_update (context);
 
 out:
   va_end (args);
@@ -185,7 +185,57 @@ gtk_accessible_update_state_value (GtkAccessible      *self,
   if (real_value == NULL)
     return;
 
-  gtk_at_context_set_state (context, state, real_value);
+  gtk_at_context_set_accessible_state (context, state, real_value);
   gtk_accessible_value_unref (real_value);
-  gtk_at_context_update_state (context);
+  gtk_at_context_update (context);
+}
+
+/**
+ * gtk_accessible_update_property:
+ * @self: a #GtkAccessible
+ * @first_property: the first #GtkAccessibleProperty
+ * @...: a list of property and value pairs, terminated by -1
+ *
+ * Updates a list of accessible properties.
+ *
+ * This function should be called by #GtkWidget types whenever an accessible
+ * property change must be communicated to assistive technologies.
+ */
+void
+gtk_accessible_update_property (GtkAccessible         *self,
+                                GtkAccessibleProperty  first_property,
+                                ...)
+{
+  GtkAccessibleProperty property;
+  GtkATContext *context;
+  va_list args;
+
+  g_return_if_fail (GTK_IS_ACCESSIBLE (self));
+
+  context = gtk_accessible_get_at_context (self);
+  if (context == NULL)
+    return;
+
+  va_start (args, first_property);
+
+  property = first_property;
+
+  while (property != -1)
+    {
+      GtkAccessibleValue *value = gtk_accessible_value_collect_for_property (property, &args);
+
+      /* gtk_accessible_value_collect_for_property() will warn for us */
+      if (value == NULL)
+        goto out;
+
+      gtk_at_context_set_accessible_property (context, property, value);
+      gtk_accessible_value_unref (value);
+
+      property = va_arg (args, int);
+    }
+
+  gtk_at_context_update (context);
+
+out:
+  va_end (args);
 }
diff --git a/gtk/gtkaccessible.h b/gtk/gtkaccessible.h
index 5b943f89a2..f95ba930d2 100644
--- a/gtk/gtkaccessible.h
+++ b/gtk/gtkaccessible.h
@@ -32,15 +32,19 @@ GDK_AVAILABLE_IN_ALL
 G_DECLARE_INTERFACE (GtkAccessible, gtk_accessible, GTK, ACCESSIBLE, GObject)
 
 GDK_AVAILABLE_IN_ALL
-GtkAccessibleRole       gtk_accessible_get_accessible_role      (GtkAccessible *self);
+GtkAccessibleRole       gtk_accessible_get_accessible_role      (GtkAccessible         *self);
 
 GDK_AVAILABLE_IN_ALL
-void                    gtk_accessible_update_state             (GtkAccessible      *self,
-                                                                 GtkAccessibleState  first_state,
+void                    gtk_accessible_update_state             (GtkAccessible         *self,
+                                                                 GtkAccessibleState     first_state,
                                                                  ...);
 GDK_AVAILABLE_IN_ALL
-void                    gtk_accessible_update_state_value       (GtkAccessible      *self,
-                                                                 GtkAccessibleState  state,
-                                                                 const GValue       *value);
+void                    gtk_accessible_update_property          (GtkAccessible         *self,
+                                                                 GtkAccessibleProperty  first_property,
+                                                                 ...);
+GDK_AVAILABLE_IN_ALL
+void                    gtk_accessible_update_state_value       (GtkAccessible         *self,
+                                                                 GtkAccessibleState     state,
+                                                                 const GValue          *value);
 
 G_END_DECLS
diff --git a/gtk/gtkatcontext.c b/gtk/gtkatcontext.c
index 5627160b40..4fe0b8176f 100644
--- a/gtk/gtkatcontext.c
+++ b/gtk/gtkatcontext.c
@@ -57,6 +57,7 @@ gtk_at_context_finalize (GObject *gobject)
   GtkATContext *self = GTK_AT_CONTEXT (gobject);
 
   gtk_accessible_state_set_unref (self->states);
+  gtk_accessible_property_set_unref (self->properties);
 
   G_OBJECT_CLASS (gtk_at_context_parent_class)->finalize (gobject);
 }
@@ -108,9 +109,11 @@ gtk_at_context_get_property (GObject    *gobject,
 }
 
 static void
-gtk_at_context_real_state_change (GtkATContext             *self,
-                                  GtkAccessibleStateChange  change,
-                                  GtkAccessibleStateSet    *states)
+gtk_at_context_real_state_change (GtkATContext                *self,
+                                  GtkAccessibleStateChange     changed_states,
+                                  GtkAccessiblePropertyChange  changed_properies,
+                                  GtkAccessibleStateSet       *states,
+                                  GtkAccessiblePropertySet    *properties)
 {
 }
 
@@ -166,6 +169,7 @@ gtk_at_context_init (GtkATContext *self)
   self->accessible_role = GTK_ACCESSIBLE_ROLE_WIDGET;
 
   self->states = gtk_accessible_state_set_new ();
+  self->properties = gtk_accessible_property_set_new ();
 }
 
 /**
@@ -252,34 +256,87 @@ gtk_at_context_create (GtkAccessibleRole  accessible_role,
 }
 
 /*< private >
- * gtk_at_context_update_state:
+ * gtk_at_context_update:
  * @self: a #GtkATContext
  *
  * Notifies the AT connected to this #GtkATContext that the accessible
- * state has changed.
+ * state and its properties have changed.
  */
 void
-gtk_at_context_update_state (GtkATContext *self)
+gtk_at_context_update (GtkATContext *self)
 {
   g_return_if_fail (GTK_IS_AT_CONTEXT (self));
 
-  GtkAccessibleStateChange change = 0;
+  GtkAccessibleStateChange changed_states = 0;
+  GtkAccessiblePropertyChange changed_properties = 0;
 
   for (int i = 0; i < GTK_ACCESSIBLE_STATE_SELECTED; i++)
     {
       if (gtk_accessible_state_set_contains (self->states, i))
-        change |= (1 << i);
+        changed_states |= (1 << i);
     }
 
-  GTK_AT_CONTEXT_GET_CLASS (self)->state_change (self, change, self->states);
+  for (int i = 0; i < GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT; i++)
+    {
+      if (gtk_accessible_property_set_contains (self->properties, i))
+        changed_properties |= (1 << i);
+    }
+
+  GTK_AT_CONTEXT_GET_CLASS (self)->state_change (self,
+                                                 changed_states,
+                                                 changed_properties,
+                                                 self->states,
+                                                 self->properties);
 }
 
+/*< private >
+ * gtk_at_context_set_state:
+ * @self: a #GtkATContext
+ * @state: a #GtkAccessibleState
+ * @value: (nullable): #GtkAccessibleValue
+ *
+ * Sets the @value for the given @state of a #GtkATContext.
+ *
+ * If @value is %NULL, the state is unset.
+ *
+ * This function will accumulate state changes until gtk_at_context_update_state()
+ * is called.
+ */
+void
+gtk_at_context_set_accessible_state (GtkATContext       *self,
+                                     GtkAccessibleState  state,
+                                     GtkAccessibleValue *value)
+{
+  g_return_if_fail (GTK_IS_AT_CONTEXT (self));
+
+  if (value != NULL)
+    gtk_accessible_state_set_add (self->states, state, value);
+  else
+    gtk_accessible_state_set_remove (self->states, state);
+}
+
+/*< private >
+ * gtk_at_context_set_accessible_property:
+ * @self: a #GtkATContext
+ * @property: a #GtkAccessibleProperty
+ * @value: (nullable): #GtkAccessibleValue
+ *
+ * Sets the @value for the given @property of a #GtkATContext.
+ *
+ * If @value is %NULL, the property is unset.
+ *
+ * This function will accumulate property changes until gtk_at_context_update_state()
+ * is called.
+ */
 void
-gtk_at_context_set_state (GtkATContext       *self,
-                          GtkAccessibleState  state,
-                          GtkAccessibleValue *value)
+gtk_at_context_set_accessible_property (GtkATContext          *self,
+                                        GtkAccessibleProperty  property,
+                                        GtkAccessibleValue    *value)
 {
   g_return_if_fail (GTK_IS_AT_CONTEXT (self));
 
-  gtk_accessible_state_set_add (self->states, state, value);
+  if (value != NULL)
+    gtk_accessible_property_set_add (self->properties, property, value);
+  else
+    gtk_accessible_property_set_remove (self->properties, property);
 }
diff --git a/gtk/gtkatcontextprivate.h b/gtk/gtkatcontextprivate.h
index 8ee334ca86..4df4d26bb5 100644
--- a/gtk/gtkatcontextprivate.h
+++ b/gtk/gtkatcontextprivate.h
@@ -23,21 +23,48 @@
 #include "gtkatcontext.h"
 
 #include "gtkaccessiblestatesetprivate.h"
+#include "gtkaccessiblepropertysetprivate.h"
 
 G_BEGIN_DECLS
 
 typedef enum {
- GTK_ACCESSIBLE_STATE_CHANGE_BUSY     = 1 << GTK_ACCESSIBLE_STATE_BUSY,
- GTK_ACCESSIBLE_STATE_CHANGE_CHECKED  = 1 << GTK_ACCESSIBLE_STATE_CHECKED,
- GTK_ACCESSIBLE_STATE_CHANGE_DISABLED = 1 << GTK_ACCESSIBLE_STATE_DISABLED,
- GTK_ACCESSIBLE_STATE_CHANGE_EXPANDED = 1 << GTK_ACCESSIBLE_STATE_EXPANDED,
- GTK_ACCESSIBLE_STATE_CHANGE_GRABBED  = 1 << GTK_ACCESSIBLE_STATE_GRABBED,
- GTK_ACCESSIBLE_STATE_CHANGE_HIDDEN   = 1 << GTK_ACCESSIBLE_STATE_HIDDEN,
- GTK_ACCESSIBLE_STATE_CHANGE_INVALID  = 1 << GTK_ACCESSIBLE_STATE_INVALID,
- GTK_ACCESSIBLE_STATE_CHANGE_PRESSED  = 1 << GTK_ACCESSIBLE_STATE_PRESSED,
- GTK_ACCESSIBLE_STATE_CHANGE_SELECTED = 1 << GTK_ACCESSIBLE_STATE_SELECTED
+  GTK_ACCESSIBLE_STATE_CHANGE_BUSY     = 1 << GTK_ACCESSIBLE_STATE_BUSY,
+  GTK_ACCESSIBLE_STATE_CHANGE_CHECKED  = 1 << GTK_ACCESSIBLE_STATE_CHECKED,
+  GTK_ACCESSIBLE_STATE_CHANGE_DISABLED = 1 << GTK_ACCESSIBLE_STATE_DISABLED,
+  GTK_ACCESSIBLE_STATE_CHANGE_EXPANDED = 1 << GTK_ACCESSIBLE_STATE_EXPANDED,
+  GTK_ACCESSIBLE_STATE_CHANGE_GRABBED  = 1 << GTK_ACCESSIBLE_STATE_GRABBED,
+  GTK_ACCESSIBLE_STATE_CHANGE_HIDDEN   = 1 << GTK_ACCESSIBLE_STATE_HIDDEN,
+  GTK_ACCESSIBLE_STATE_CHANGE_INVALID  = 1 << GTK_ACCESSIBLE_STATE_INVALID,
+  GTK_ACCESSIBLE_STATE_CHANGE_PRESSED  = 1 << GTK_ACCESSIBLE_STATE_PRESSED,
+  GTK_ACCESSIBLE_STATE_CHANGE_SELECTED = 1 << GTK_ACCESSIBLE_STATE_SELECTED
 } GtkAccessibleStateChange;
 
+typedef enum {
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_ACTIVE_DESCENDANT = 1 << GTK_ACCESSIBLE_PROPERTY_ACTIVE_DESCENDANT,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_AUTOCOMPLETE      = 1 << GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_CONTROLS          = 1 << GTK_ACCESSIBLE_PROPERTY_CONTROLS,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_DESCRIBED_BY      = 1 << GTK_ACCESSIBLE_PROPERTY_DESCRIBED_BY,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_FLOW_TO           = 1 << GTK_ACCESSIBLE_PROPERTY_FLOW_TO,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_HAS_POPUP         = 1 << GTK_ACCESSIBLE_PROPERTY_HAS_POPUP,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_LABEL             = 1 << GTK_ACCESSIBLE_PROPERTY_LABEL,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_LABELLED_BY       = 1 << GTK_ACCESSIBLE_PROPERTY_LABELLED_BY,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_LEVEL             = 1 << GTK_ACCESSIBLE_PROPERTY_LEVEL,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_MULTI_LINE        = 1 << GTK_ACCESSIBLE_PROPERTY_MULTI_LINE,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_MULTI_SELECTABLE  = 1 << GTK_ACCESSIBLE_PROPERTY_MULTI_SELECTABLE,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_ORIENTATION       = 1 << GTK_ACCESSIBLE_PROPERTY_ORIENTATION,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_OWNS              = 1 << GTK_ACCESSIBLE_PROPERTY_OWNS,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_POS_IN_SET        = 1 << GTK_ACCESSIBLE_PROPERTY_POS_IN_SET,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_READ_ONLY         = 1 << GTK_ACCESSIBLE_PROPERTY_READ_ONLY,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_RELEVANT          = 1 << GTK_ACCESSIBLE_PROPERTY_RELEVANT,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_REQUIRED          = 1 << GTK_ACCESSIBLE_PROPERTY_REQUIRED,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_SET_SIZE          = 1 << GTK_ACCESSIBLE_PROPERTY_SET_SIZE,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_SORT              = 1 << GTK_ACCESSIBLE_PROPERTY_SORT,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_VALUE_MAX         = 1 << GTK_ACCESSIBLE_PROPERTY_VALUE_MAX,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_VALUE_MIN         = 1 << GTK_ACCESSIBLE_PROPERTY_VALUE_MIN,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_VALUE_NOW         = 1 << GTK_ACCESSIBLE_PROPERTY_VALUE_NOW,
+  GTK_ACCESSIBLE_PROPERTY_CHANGE_VALUE_TEXT        = 1 << GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT
+} GtkAccessiblePropertyChange;
+
 struct _GtkATContext
 {
   GObject parent_instance;
@@ -46,24 +73,30 @@ struct _GtkATContext
   GtkAccessible *accessible;
 
   GtkAccessibleStateSet *states;
+  GtkAccessiblePropertySet *properties;
 };
 
 struct _GtkATContextClass
 {
   GObjectClass parent_class;
 
-  void (* state_change) (GtkATContext             *self,
-                         GtkAccessibleStateChange  changed,
-                         GtkAccessibleStateSet    *states);
+  void (* state_change) (GtkATContext                *self,
+                         GtkAccessibleStateChange     changed_states,
+                         GtkAccessiblePropertyChange  changed_properties,
+                         GtkAccessibleStateSet       *states,
+                         GtkAccessiblePropertySet    *properties);
 };
 
-GtkATContext *  gtk_at_context_create           (GtkAccessibleRole   accessible_role,
-                                                 GtkAccessible      *accessible);
+GtkATContext *  gtk_at_context_create                   (GtkAccessibleRole      accessible_role,
+                                                         GtkAccessible         *accessible);
 
-void            gtk_at_context_update_state     (GtkATContext       *self);
+void            gtk_at_context_update                   (GtkATContext          *self);
 
-void            gtk_at_context_set_state        (GtkATContext       *self,
-                                                 GtkAccessibleState  state,
-                                                 GtkAccessibleValue *value);
+void            gtk_at_context_set_accessible_state     (GtkATContext          *self,
+                                                         GtkAccessibleState     state,
+                                                         GtkAccessibleValue    *value);
+void            gtk_at_context_set_accessible_property  (GtkATContext          *self,
+                                                         GtkAccessibleProperty  property,
+                                                         GtkAccessibleValue    *value);
 
 G_END_DECLS
diff --git a/gtk/gtktestatcontext.c b/gtk/gtktestatcontext.c
index 8324d44375..f89e354451 100644
--- a/gtk/gtktestatcontext.c
+++ b/gtk/gtktestatcontext.c
@@ -33,20 +33,27 @@ struct _GtkTestATContext
 G_DEFINE_TYPE (GtkTestATContext, gtk_test_at_context, GTK_TYPE_AT_CONTEXT)
 
 static void
-gtk_test_at_context_state_change (GtkATContext             *self,
-                                  GtkAccessibleStateChange  change,
-                                  GtkAccessibleStateSet    *states)
+gtk_test_at_context_state_change (GtkATContext                *self,
+                                  GtkAccessibleStateChange     changed_states,
+                                  GtkAccessiblePropertyChange  changed_properties,
+                                  GtkAccessibleStateSet       *states,
+                                  GtkAccessiblePropertySet    *properties)
 {
   GtkAccessible *accessible = gtk_at_context_get_accessible (self);
   GtkAccessibleRole role = gtk_at_context_get_accessible_role (self);
-  char *state = gtk_accessible_state_set_to_string (states);
+  char *states_str = gtk_accessible_state_set_to_string (states);
+  char *properties_str = gtk_accessible_property_set_to_string (properties);
 
-  g_print ("Accessible state changed for accessible ā€œ%sā€, with role %d: %s\n",
+  g_print ("*** Accessible state changed for accessible ā€œ%sā€, with role %d:\n"
+           "*** states = %s\n"
+           "*** properties = %s\n",
            G_OBJECT_TYPE_NAME (accessible),
            role,
-           state);
+           states_str,
+           properties_str);
 
-  g_free (state);
+  g_free (states_str);
+  g_free (properties_str);
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]