[gtk/matthiasc/for-master: 6/7] modelbutton: Recreate our AT context




commit 6e788be228e395118a4a2b9619c6c0e9022e2ce2
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Oct 21 20:28:30 2020 -0400

    modelbutton: Recreate our AT context
    
    When the button role changes, we want to update the
    accessible role to match. Since accessible roles are
    unchangeable post-creation of the AT context, we have
    to cheat a bit and recreate the whole context.

 gtk/gtkmodelbutton.c | 111 +++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 90 insertions(+), 21 deletions(-)
---
diff --git a/gtk/gtkmodelbutton.c b/gtk/gtkmodelbutton.c
index 7a7b10d76a..31d0bf10c5 100644
--- a/gtk/gtkmodelbutton.c
+++ b/gtk/gtkmodelbutton.c
@@ -45,6 +45,7 @@
 #include "gtkshortcuttrigger.h"
 #include "gtkshortcutcontroller.h"
 #include "gtkshortcut.h"
+#include "gtkaccessibleprivate.h"
 
 /**
  * SECTION:gtkmodelbutton
@@ -175,6 +176,8 @@ struct _GtkModelButton
   guint open_timeout;
   GtkEventController *controller;
 
+  GtkATContext *at_context;
+
   guint active : 1;
   guint centered : 1;
   guint iconic : 1;
@@ -190,7 +193,11 @@ struct _GtkModelButtonClass
 };
 
 static void gtk_model_button_actionable_iface_init (GtkActionableInterface *iface);
+
+static void gtk_model_button_accessible_iface_init (GtkAccessibleInterface *iface);
+
 G_DEFINE_TYPE_WITH_CODE (GtkModelButton, gtk_model_button, GTK_TYPE_WIDGET,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_ACCESSIBLE, gtk_model_button_accessible_iface_init)
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIONABLE, gtk_model_button_actionable_iface_init))
 
 GType
@@ -295,6 +302,50 @@ gtk_model_button_actionable_iface_init (GtkActionableInterface *iface)
   iface->set_action_target_value = gtk_model_button_set_action_target_value;
 }
 
+static GtkATContext *
+create_at_context (GtkModelButton *button)
+{
+  GdkDisplay *display = _gtk_widget_get_display (GTK_WIDGET (button));
+  GtkAccessibleRole role;
+
+  switch (button->role)
+    {
+    default:
+    case GTK_BUTTON_ROLE_NORMAL:
+    case GTK_BUTTON_ROLE_TITLE:
+      role = GTK_ACCESSIBLE_ROLE_MENU_ITEM;
+      break;
+    case GTK_BUTTON_ROLE_CHECK:
+      role = GTK_ACCESSIBLE_ROLE_MENU_ITEM_CHECKBOX;
+      break;
+    case GTK_BUTTON_ROLE_RADIO:
+      role = GTK_ACCESSIBLE_ROLE_MENU_ITEM_RADIO;
+      break;
+    }
+
+  return gtk_at_context_create (role, GTK_ACCESSIBLE (button), display);
+}
+
+static GtkATContext *
+gtk_model_button_get_at_context (GtkAccessible *accessible)
+{
+  GtkModelButton *button = GTK_MODEL_BUTTON (accessible);
+
+  if (button->at_context == NULL)
+    button->at_context = create_at_context (button);
+
+  return button->at_context;
+}
+
+static void
+gtk_model_button_accessible_iface_init (GtkAccessibleInterface *iface)
+{
+  GtkAccessibleInterface *parent_iface = g_type_interface_peek_parent (iface);
+
+  iface->get_at_context = gtk_model_button_get_at_context;
+  iface->get_platform_state = parent_iface->get_platform_state;
+}
+
 static void
 update_node_ordering (GtkModelButton *button)
 {
@@ -518,6 +569,35 @@ update_node_name (GtkModelButton *self)
     }
 }
 
+static void
+update_accessible_properties (GtkModelButton *button)
+{
+  if (button->menu_name || button->popover)
+    gtk_accessible_update_property (GTK_ACCESSIBLE (button),
+                                    GTK_ACCESSIBLE_PROPERTY_HAS_POPUP, TRUE,
+                                    -1);
+  else
+    gtk_accessible_reset_property (GTK_ACCESSIBLE (button),
+                                   GTK_ACCESSIBLE_PROPERTY_HAS_POPUP);
+
+  if (button->popover)
+    gtk_accessible_update_relation (GTK_ACCESSIBLE (button),
+                                    GTK_ACCESSIBLE_RELATION_CONTROLS, g_list_append (NULL, button->popover),
+                                    -1);
+  else
+    gtk_accessible_reset_relation (GTK_ACCESSIBLE (button),
+                                   GTK_ACCESSIBLE_RELATION_CONTROLS);
+
+  if (button->role == GTK_BUTTON_ROLE_CHECK ||
+      button->role == GTK_BUTTON_ROLE_RADIO)
+    gtk_accessible_update_state (GTK_ACCESSIBLE (button),
+                                 GTK_ACCESSIBLE_STATE_CHECKED, button->active,
+                                 -1);
+  else
+    gtk_accessible_reset_state (GTK_ACCESSIBLE (button),
+                                GTK_ACCESSIBLE_STATE_CHECKED);
+}
+
 static void
 gtk_model_button_set_role (GtkModelButton *self,
                            GtkButtonRole   role)
@@ -541,6 +621,10 @@ gtk_model_button_set_role (GtkModelButton *self,
   update_node_name (self);
   gtk_model_button_update_state (self);
 
+  g_set_object (&self->at_context, create_at_context (self));
+
+  update_accessible_properties (self);
+
   g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ROLE]);
 }
 
@@ -622,31 +706,14 @@ gtk_model_button_set_active (GtkModelButton *button,
     return;
 
   button->active = active;
+
+  update_accessible_properties (button);
+
   gtk_model_button_update_state (button);
   gtk_widget_queue_draw (GTK_WIDGET (button));
   g_object_notify_by_pspec (G_OBJECT (button), properties[PROP_ACTIVE]);
 }
 
-static void
-update_accessible_properties (GtkModelButton *button)
-{
-  if (button->menu_name || button->popover)
-    gtk_accessible_update_property (GTK_ACCESSIBLE (button),
-                                    GTK_ACCESSIBLE_PROPERTY_HAS_POPUP, TRUE,
-                                    -1);
-  else
-    gtk_accessible_reset_property (GTK_ACCESSIBLE (button),
-                                   GTK_ACCESSIBLE_PROPERTY_HAS_POPUP);
-
-  if (button->popover)
-    gtk_accessible_update_relation (GTK_ACCESSIBLE (button),
-                                    GTK_ACCESSIBLE_RELATION_CONTROLS, g_list_append (NULL, button->popover),
-                                    -1);
-  else
-    gtk_accessible_reset_relation (GTK_ACCESSIBLE (button),
-                                   GTK_ACCESSIBLE_RELATION_CONTROLS);
-}
-
 static void
 gtk_model_button_set_menu_name (GtkModelButton *button,
                                 const char     *menu_name)
@@ -942,12 +1009,14 @@ gtk_model_button_set_property (GObject      *object,
 }
 
 static void
-gtk_model_button_dispose (GObject  *object)
+gtk_model_button_dispose (GObject *object)
 {
   GtkModelButton *model_button = GTK_MODEL_BUTTON (object);
 
   g_clear_pointer (&model_button->menu_name, g_free);
 
+  g_clear_object (&model_button->at_context);
+
   G_OBJECT_CLASS (gtk_model_button_parent_class)->dispose (object);
 }
 


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