[gtk/a11y-debug: 3/3] a11y: Track window states more closely




commit 6d11bb33f5626013bea58d2e4b6ea43ba5a7e25f
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Apr 17 15:23:04 2021 -0400

    a11y: Track window states more closely
    
    Orca ignores events unless the object is inside an object
    with role window and states ACTIVE and SHOWING. To arrange
    for this, introduce a new ACTIVE platform state, and set it
    for windows when they are active.
    
    This gets orca to be a lot more talkative.

 gtk/a11y/gtkatspicontext.c | 15 +++++++++++++++
 gtk/gtkatcontextprivate.h  |  2 ++
 gtk/gtkentry.c             |  2 ++
 gtk/gtktestatcontext.c     |  3 +++
 gtk/gtkwidget.c            |  2 ++
 gtk/gtkwindow.c            | 34 ++++++++++++++++++++++++++++++++++
 6 files changed, 58 insertions(+)
---
diff --git a/gtk/a11y/gtkatspicontext.c b/gtk/a11y/gtkatspicontext.c
index a4c15ba41e..9891a4da69 100644
--- a/gtk/a11y/gtkatspicontext.c
+++ b/gtk/a11y/gtkatspicontext.c
@@ -150,6 +150,13 @@ collect_states (GtkAtSpiContext    *self,
 
   set_atspi_state (&states, ATSPI_STATE_VISIBLE);
 
+  if (ctx->accessible_role == GTK_ACCESSIBLE_ROLE_WINDOW)
+    {
+      set_atspi_state (&states, ATSPI_STATE_SHOWING);
+      if (gtk_accessible_get_platform_state (accessible, GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE))
+        set_atspi_state (&states, ATSPI_STATE_ACTIVE);
+    }
+
   if (ctx->accessible_role == GTK_ACCESSIBLE_ROLE_TEXT_BOX ||
       ctx->accessible_role == GTK_ACCESSIBLE_ROLE_SEARCH_BOX ||
       ctx->accessible_role == GTK_ACCESSIBLE_ROLE_SPIN_BUTTON)
@@ -888,6 +895,7 @@ gtk_at_spi_context_state_change (GtkATContext                *ctx,
       if (GTK_IS_ROOT (accessible))
         {
           gtk_at_spi_root_child_changed (self->root, change, accessible);
+          emit_state_changed (self, "showing", gtk_boolean_accessible_value_get (value));
         }
       else
         {
@@ -1084,6 +1092,13 @@ gtk_at_spi_context_platform_change (GtkATContext                *ctx,
                                                           GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED);
       emit_state_changed (self, "focused", state);
     }
+
+  if (changed_platform & GTK_ACCESSIBLE_PLATFORM_CHANGE_ACTIVE)
+    {
+      gboolean state = gtk_accessible_get_platform_state (GTK_ACCESSIBLE (widget),
+                                                          GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE);
+      emit_state_changed (self, "active", state);
+    }
 }
 
 static void
diff --git a/gtk/gtkatcontextprivate.h b/gtk/gtkatcontextprivate.h
index d9678cbea5..c05c04948f 100644
--- a/gtk/gtkatcontextprivate.h
+++ b/gtk/gtkatcontextprivate.h
@@ -83,11 +83,13 @@ typedef enum {
 typedef enum {
   GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSABLE,
   GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED,
+  GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE
 } GtkAccessiblePlatformState;
 
 typedef enum {
   GTK_ACCESSIBLE_PLATFORM_CHANGE_FOCUSABLE = 1 << GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSABLE,
   GTK_ACCESSIBLE_PLATFORM_CHANGE_FOCUSED   = 1 << GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED,
+  GTK_ACCESSIBLE_PLATFORM_CHANGE_ACTIVE    = 1 << GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE,
 } GtkAccessiblePlatformChange;
 
 typedef enum {
diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c
index 8a1262bf14..e5a4de8255 100644
--- a/gtk/gtkentry.c
+++ b/gtk/gtkentry.c
@@ -351,6 +351,8 @@ gtk_entry_accessible_get_platform_state (GtkAccessible              *self,
       return gtk_widget_get_focusable (GTK_WIDGET (priv->text));
     case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED:
       return gtk_widget_has_focus (GTK_WIDGET (priv->text));
+    case GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE:
+      return FALSE;
     default:
       g_assert_not_reached ();
     }
diff --git a/gtk/gtktestatcontext.c b/gtk/gtktestatcontext.c
index a093fe6222..e8f3754ea9 100644
--- a/gtk/gtktestatcontext.c
+++ b/gtk/gtktestatcontext.c
@@ -96,6 +96,9 @@ gtk_test_at_context_platform_change (GtkATContext                *self,
       if (changed_platform & GTK_ACCESSIBLE_PLATFORM_CHANGE_FOCUSED)
         g_print ("***    focused = %d\n",
                  gtk_accessible_get_platform_state (accessible, GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED));
+      if (changed_platform & GTK_ACCESSIBLE_PLATFORM_CHANGE_ACTIVE)
+        g_print ("***    active = %d\n",
+                 gtk_accessible_get_platform_state (accessible, GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE));
     }
 }
 
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 3f641a6d08..b9088cd3ef 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -8492,6 +8492,8 @@ gtk_widget_accessible_get_platform_state (GtkAccessible              *self,
       return gtk_widget_get_focusable (GTK_WIDGET (self));
     case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED:
       return gtk_widget_has_focus (GTK_WIDGET (self));
+    case GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE:
+      return FALSE;
     default:
       g_assert_not_reached ();
     }
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 17beb19fa3..b8ea6e3e21 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -26,6 +26,7 @@
 
 #include "gtkwindowprivate.h"
 
+#include "gtkaccessibleprivate.h"
 #include "gtkaccelgroupprivate.h"
 #include "gtkactionable.h"
 #include "gtkapplicationprivate.h"
@@ -479,6 +480,9 @@ static void             gtk_window_shortcut_manager_interface_init      (GtkShor
 static void             gtk_window_root_interface_init (GtkRootInterface *iface);
 static void             gtk_window_native_interface_init  (GtkNativeInterface  *iface);
 
+static void             gtk_window_accessible_interface_init (GtkAccessibleInterface *iface);
+
+
 static void ensure_state_flag_backdrop (GtkWidget *widget);
 static void unset_titlebar (GtkWindow *window);
 
@@ -493,6 +497,8 @@ gtk_window_update_csd_size (GtkWindow *window,
 
 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_WIDGET,
                          G_ADD_PRIVATE (GtkWindow)
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_ACCESSIBLE,
+                                               gtk_window_accessible_interface_init)
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
                                                gtk_window_buildable_interface_init)
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_NATIVE,
@@ -502,6 +508,32 @@ G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_WIDGET,
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_ROOT,
                                                gtk_window_root_interface_init))
 
+static GtkAccessibleInterface *parent_accessible_iface;
+
+static gboolean
+gtk_window_accessible_get_platform_state (GtkAccessible              *self,
+                                          GtkAccessiblePlatformState  state)
+{
+  switch (state)
+    {
+    case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSABLE:
+    case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED:
+      return parent_accessible_iface->get_platform_state (self, state);
+    case GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE:
+      return gtk_window_is_active (GTK_WINDOW (self));
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static void
+gtk_window_accessible_interface_init (GtkAccessibleInterface *iface)
+{
+  parent_accessible_iface = g_type_interface_peek_parent (iface);
+  iface->get_at_context = parent_accessible_iface->get_at_context;
+  iface->get_platform_state = gtk_window_accessible_get_platform_state;
+}
+
 static void
 add_tab_bindings (GtkWidgetClass   *widget_class,
                  GdkModifierType   modifiers,
@@ -5828,6 +5860,8 @@ _gtk_window_set_is_active (GtkWindow *window,
       g_object_unref (focus);
     }
 
+  gtk_accessible_platform_changed (GTK_ACCESSIBLE (window), GTK_ACCESSIBLE_PLATFORM_CHANGE_ACTIVE);
+
   g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_IS_ACTIVE]);
 }
 


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