summaryrefslogtreecommitdiff
path: root/gtk/a11y
diff options
context:
space:
mode:
Diffstat (limited to 'gtk/a11y')
-rw-r--r--gtk/a11y/gtkatspicache.c54
-rw-r--r--gtk/a11y/gtkatspicacheprivate.h3
-rw-r--r--gtk/a11y/gtkatspicontext.c68
-rw-r--r--gtk/a11y/gtkatspiroot.c2
-rw-r--r--gtk/a11y/gtkatspitext.c5
5 files changed, 120 insertions, 12 deletions
diff --git a/gtk/a11y/gtkatspicache.c b/gtk/a11y/gtkatspicache.c
index 9e3b22b281..6e85c5663f 100644
--- a/gtk/a11y/gtkatspicache.c
+++ b/gtk/a11y/gtkatspicache.c
@@ -27,6 +27,8 @@
#include "gtkatspiutilsprivate.h"
#include "gtkdebug.h"
+#include "a11y/atspi/atspi-accessible.h"
+#include "a11y/atspi/atspi-application.h"
#include "a11y/atspi/atspi-cache.h"
/* Cached item:
@@ -61,6 +63,8 @@ struct _GtkAtSpiCache
/* Re-entrancy guard */
gboolean in_get_items;
+
+ GtkAtSpiRoot *root;
};
enum
@@ -145,6 +149,36 @@ collect_object (GtkAtSpiCache *self,
}
static void
+collect_root (GtkAtSpiCache *self,
+ GVariantBuilder *builder)
+{
+ g_variant_builder_add (builder, "@(so)", gtk_at_spi_root_to_ref (self->root));
+ g_variant_builder_add (builder, "@(so)", gtk_at_spi_root_to_ref (self->root));
+
+ g_variant_builder_add (builder, "@(so)", gtk_at_spi_null_ref ());
+
+ g_variant_builder_add (builder, "i", -1);
+ g_variant_builder_add (builder, "i", 0);
+
+ GVariantBuilder interfaces = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("as"));
+
+ g_variant_builder_add (&interfaces, "s", atspi_accessible_interface.name);
+ g_variant_builder_add (&interfaces, "s", atspi_application_interface.name);
+ g_variant_builder_add (builder, "@as", g_variant_builder_end (&interfaces));
+
+ g_variant_builder_add (builder, "s", g_get_prgname () ? g_get_prgname () : "Unnamed");
+
+ g_variant_builder_add (builder, "u", ATSPI_ROLE_APPLICATION);
+
+ g_variant_builder_add (builder, "s", g_get_application_name () ? g_get_application_name () : "No description");
+
+ GVariantBuilder states = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("au"));
+ g_variant_builder_add (&states, "u", 0);
+ g_variant_builder_add (&states, "u", 0);
+ g_variant_builder_add (builder, "@au", g_variant_builder_end (&states));
+}
+
+static void
collect_cached_objects (GtkAtSpiCache *self,
GVariantBuilder *builder)
{
@@ -160,6 +194,10 @@ collect_cached_objects (GtkAtSpiCache *self,
while (g_hash_table_iter_next (&iter, &key_p, &value_p))
g_hash_table_add (collection, value_p);
+ g_variant_builder_open (builder, G_VARIANT_TYPE ("(" ITEM_SIGNATURE ")"));
+ collect_root (self, builder);
+ g_variant_builder_close (builder);
+
g_hash_table_iter_init (&iter, collection);
while (g_hash_table_iter_next (&iter, &key_p, &value_p))
{
@@ -355,15 +393,21 @@ gtk_at_spi_cache_init (GtkAtSpiCache *self)
GtkAtSpiCache *
gtk_at_spi_cache_new (GDBusConnection *connection,
- const char *cache_path)
+ const char *cache_path,
+ GtkAtSpiRoot *root)
{
+ GtkAtSpiCache *cache;
+
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
g_return_val_if_fail (cache_path != NULL, NULL);
- return g_object_new (GTK_TYPE_AT_SPI_CACHE,
- "connection", connection,
- "cache-path", cache_path,
- NULL);
+ cache = g_object_new (GTK_TYPE_AT_SPI_CACHE,
+ "connection", connection,
+ "cache-path", cache_path,
+ NULL);
+ cache->root = root;
+
+ return cache;
}
void
diff --git a/gtk/a11y/gtkatspicacheprivate.h b/gtk/a11y/gtkatspicacheprivate.h
index 63f797ce5a..85fecdcd5c 100644
--- a/gtk/a11y/gtkatspicacheprivate.h
+++ b/gtk/a11y/gtkatspicacheprivate.h
@@ -31,7 +31,8 @@ G_DECLARE_FINAL_TYPE (GtkAtSpiCache, gtk_at_spi_cache, GTK, AT_SPI_CACHE, GObjec
GtkAtSpiCache *
gtk_at_spi_cache_new (GDBusConnection *connection,
- const char *cache_path);
+ const char *cache_path,
+ GtkAtSpiRoot *root);
void
gtk_at_spi_cache_add_context (GtkAtSpiCache *self,
diff --git a/gtk/a11y/gtkatspicontext.c b/gtk/a11y/gtkatspicontext.c
index 3ee0bcb35c..7c5e967145 100644
--- a/gtk/a11y/gtkatspicontext.c
+++ b/gtk/a11y/gtkatspicontext.c
@@ -25,7 +25,6 @@
#include "gtkaccessibleprivate.h"
#include "gtkatspiactionprivate.h"
-#include "gtkatspicacheprivate.h"
#include "gtkatspieditabletextprivate.h"
#include "gtkatspiprivate.h"
#include "gtkatspirootprivate.h"
@@ -91,9 +90,6 @@ struct _GtkAtSpiContext
/* The root object, used as a entry point */
GtkAtSpiRoot *root;
- /* The cache object, used to retrieve ATContexts */
- GtkAtSpiCache *cache;
-
/* The address for the ATSPI accessibility bus */
char *bus_address;
@@ -154,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)
@@ -862,6 +865,43 @@ emit_children_changed (GtkAtSpiContext *self,
}
static void
+emit_focus (GtkAtSpiContext *self,
+ gboolean focus_in)
+{
+ if (self->connection == NULL)
+ return;
+
+ if (focus_in)
+ g_dbus_connection_emit_signal (self->connection,
+ NULL,
+ self->context_path,
+ "org.a11y.atspi.Event.Focus",
+ "Focus",
+ g_variant_new ("(siiva{sv})",
+ "", 0, 0, g_variant_new_string ("0"), NULL),
+ NULL);
+}
+
+static void
+emit_window_event (GtkAtSpiContext *self,
+ const char *event_type)
+{
+ if (self->connection == NULL)
+ return;
+
+ g_dbus_connection_emit_signal (self->connection,
+ NULL,
+ self->context_path,
+ "org.a11y.atspi.Event.Window",
+ event_type,
+ g_variant_new ("(siiva{sv})",
+ "", 0, 0,
+ g_variant_new_string("0"),
+ NULL),
+ NULL);
+}
+
+static void
gtk_at_spi_context_state_change (GtkATContext *ctx,
GtkAccessibleStateChange changed_states,
GtkAccessiblePropertyChange changed_properties,
@@ -892,6 +932,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
{
@@ -1087,6 +1128,25 @@ gtk_at_spi_context_platform_change (GtkATContext *ctx,
gboolean state = gtk_accessible_get_platform_state (GTK_ACCESSIBLE (widget),
GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED);
emit_state_changed (self, "focused", state);
+ emit_focus (self, 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);
+
+ /* Orca tracks the window:activate and window:deactivate events on top
+ * levels to decide whether to track other AT-SPI events
+ */
+ if (gtk_accessible_get_accessible_role (accessible) == GTK_ACCESSIBLE_ROLE_WINDOW)
+ {
+ if (state)
+ emit_window_event (self, "activate");
+ else
+ emit_window_event (self, "deactivate");
+ }
}
}
diff --git a/gtk/a11y/gtkatspiroot.c b/gtk/a11y/gtkatspiroot.c
index 0b3e5044d4..1deafba927 100644
--- a/gtk/a11y/gtkatspiroot.c
+++ b/gtk/a11y/gtkatspiroot.c
@@ -503,7 +503,7 @@ on_registration_reply (GObject *gobject,
}
/* Register the cache object */
- self->cache = gtk_at_spi_cache_new (self->connection, ATSPI_CACHE_PATH);
+ self->cache = gtk_at_spi_cache_new (self->connection, ATSPI_CACHE_PATH, self);
/* Drain the list of queued GtkAtSpiContexts, and add them to the cache */
if (self->queued_contexts != NULL)
diff --git a/gtk/a11y/gtkatspitext.c b/gtk/a11y/gtkatspitext.c
index 7cf08fdf06..44a5605716 100644
--- a/gtk/a11y/gtkatspitext.c
+++ b/gtk/a11y/gtkatspitext.c
@@ -1326,9 +1326,12 @@ update_selection (TextChanged *changed,
int selection_bound)
{
gboolean caret_moved, bound_moved;
+ gboolean had_selection, has_selection;
caret_moved = cursor_position != changed->cursor_position;
bound_moved = selection_bound != changed->selection_bound;
+ had_selection = changed->cursor_position != changed->selection_bound;
+ has_selection = cursor_position != selection_bound;
if (!caret_moved && !bound_moved)
return;
@@ -1339,7 +1342,7 @@ update_selection (TextChanged *changed,
if (caret_moved)
changed->selection_changed (changed->data, "text-caret-moved", changed->cursor_position);
- if (caret_moved || bound_moved)
+ if (had_selection || has_selection)
changed->selection_changed (changed->data, "text-selection-changed", 0);
}