diff --git a/gtk/a11y/gtkatspicache.c b/gtk/a11y/gtkatspicache.c new file mode 100644 index 0000000000..9681fd613e --- /dev/null +++ b/gtk/a11y/gtkatspicache.c @@ -0,0 +1,218 @@ +/* gtkatspicache.c: AT-SPI object cache + * + * Copyright 2020 holder + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "config.h" + +#include "gtkatspicacheprivate.h" + +#include "gtkdebug.h" + +#include "a11y/atspi/atspi-cache.h" + +struct _GtkAtSpiCache +{ + GObject parent_instance; + + char *cache_path; + GDBusConnection *connection; + + GHashTable *contexts; +}; + +enum +{ + PROP_CACHE_PATH = 1, + PROP_CONNECTION, + + N_PROPS +}; + +static GParamSpec *obj_props[N_PROPS]; + +G_DEFINE_TYPE (GtkAtSpiCache, gtk_at_spi_cache, G_TYPE_OBJECT) + +static void +gtk_at_spi_cache_finalize (GObject *gobject) +{ + GtkAtSpiCache *self = GTK_AT_SPI_CACHE (gobject); + + g_clear_pointer (&self->contexts, g_hash_table_unref); + g_clear_object (&self->connection); + g_free (self->cache_path); + + G_OBJECT_CLASS (gtk_at_spi_cache_parent_class)->finalize (gobject); +} + +static void +gtk_at_spi_cache_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkAtSpiCache *self = GTK_AT_SPI_CACHE (gobject); + + switch (prop_id) + { + case PROP_CACHE_PATH: + g_free (self->cache_path); + self->cache_path = g_value_dup_string (value); + break; + + case PROP_CONNECTION: + g_clear_object (&self->connection); + self->connection = g_value_dup_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +handle_cache_method (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + g_printerr ("[Cache] Method '%s' on interface '%s' for object '%s' from '%s'\n", + method_name, interface_name, object_path, sender); + +} + +static GVariant * +handle_cache_get_property (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GError **error, + gpointer user_data) +{ + GVariant *res = NULL; + + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "Unknown property '%s'", property_name); + + return res; +} + + +static const GDBusInterfaceVTable cache_vtable = { + handle_cache_method, + handle_cache_get_property, + NULL, +}; + +static void +gtk_at_spi_cache_constructed (GObject *gobject) +{ + GtkAtSpiCache *self = GTK_AT_SPI_CACHE (gobject); + + g_assert (self->connection); + g_assert (self->cache_path); + + g_dbus_connection_register_object (self->connection, + self->cache_path, + (GDBusInterfaceInfo *) &atspi_cache_interface, + &cache_vtable, + self, + NULL, + NULL); + + GTK_NOTE (A11Y, g_message ("Cache registered at %s", self->cache_path)); + + G_OBJECT_CLASS (gtk_at_spi_cache_parent_class)->constructed (gobject); +} + +static void +gtk_at_spi_cache_class_init (GtkAtSpiCacheClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->constructed = gtk_at_spi_cache_constructed; + gobject_class->set_property = gtk_at_spi_cache_set_property; + gobject_class->finalize = gtk_at_spi_cache_finalize; + + obj_props[PROP_CACHE_PATH] = + g_param_spec_string ("cache-path", NULL, NULL, + NULL, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_props[PROP_CONNECTION] = + g_param_spec_object ("connection", NULL, NULL, + G_TYPE_DBUS_CONNECTION, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gobject_class, N_PROPS, obj_props); +} + +static void +gtk_at_spi_cache_init (GtkAtSpiCache *self) +{ + self->contexts = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, + NULL); +} + +GtkAtSpiCache * +gtk_at_spi_cache_new (GDBusConnection *connection, + const char *cache_path) +{ + 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); +} + +void +gtk_at_spi_cache_add_context (GtkAtSpiCache *self, + const char *path, + GtkATContext *context) +{ + g_return_if_fail (GTK_IS_AT_SPI_CACHE (self)); + g_return_if_fail (path != NULL); + g_return_if_fail (GTK_IS_AT_CONTEXT (context)); + + if (g_hash_table_contains (self->contexts, path)) + return; + + g_hash_table_insert (self->contexts, g_strdup (path), context); +} + +GtkATContext * +gtk_at_spi_cache_get_context (GtkAtSpiCache *self, + const char *path) +{ + g_return_val_if_fail (GTK_IS_AT_SPI_CACHE (self), NULL); + g_return_val_if_fail (path != NULL, NULL); + + return g_hash_table_lookup (self->contexts, path); +} diff --git a/gtk/a11y/gtkatspicacheprivate.h b/gtk/a11y/gtkatspicacheprivate.h new file mode 100644 index 0000000000..12952a3c87 --- /dev/null +++ b/gtk/a11y/gtkatspicacheprivate.h @@ -0,0 +1,44 @@ +/* gtkatspicacheprivate.h: AT-SPI object cache + * + * Copyright 2020 GNOME Foundation + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#pragma once + +#include "gtkatcontextprivate.h" + +G_BEGIN_DECLS + +#define GTK_TYPE_AT_SPI_CACHE (gtk_at_spi_cache_get_type()) + +G_DECLARE_FINAL_TYPE (GtkAtSpiCache, gtk_at_spi_cache, GTK, AT_SPI_CACHE, GObject) + +GtkAtSpiCache * +gtk_at_spi_cache_new (GDBusConnection *connection, + const char *cache_path); + +void +gtk_at_spi_cache_add_context (GtkAtSpiCache *self, + const char *path, + GtkATContext *context); + +GtkATContext * +gtk_at_spi_cache_get_context (GtkAtSpiCache *self, + const char *path); + +G_END_DECLS diff --git a/gtk/a11y/gtkatspicontext.c b/gtk/a11y/gtkatspicontext.c index d2c582d018..31ef9a8842 100644 --- a/gtk/a11y/gtkatspicontext.c +++ b/gtk/a11y/gtkatspicontext.c @@ -22,6 +22,7 @@ #include "gtkatspicontextprivate.h" +#include "gtkatspicacheprivate.h" #include "gtkatspirootprivate.h" #include "gtkdebug.h" #include "gtkwindow.h" @@ -43,6 +44,9 @@ 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; diff --git a/gtk/a11y/gtkatspiroot.c b/gtk/a11y/gtkatspiroot.c index 5d7e5feef7..4cca4e526a 100644 --- a/gtk/a11y/gtkatspiroot.c +++ b/gtk/a11y/gtkatspiroot.c @@ -32,8 +32,11 @@ #include -#define ATSPI_VERSION "2.1" -#define ATSPI_ROOT_PATH "/org/a11y/atspi/accessible/root" +#define ATSPI_VERSION "2.1" + +#define ATSPI_PATH_PREFIX "/org/a11y/atspi" +#define ATSPI_ROOT_PATH ATSPI_PATH_PREFIX "/accessible/root" +#define ATSPI_CACHE_PATH ATSPI_PATH_PREFIX "/cache" struct _GtkAtSpiRoot { @@ -52,6 +55,8 @@ struct _GtkAtSpiRoot char *desktop_path; gint32 application_id; + + GtkAtSpiCache *cache; }; enum @@ -82,6 +87,7 @@ gtk_at_spi_root_dispose (GObject *gobject) { GtkAtSpiRoot *self = GTK_AT_SPI_ROOT (gobject); + g_clear_object (&self->cache); g_clear_object (&self->connection); G_OBJECT_CLASS (gtk_at_spi_root_parent_class)->dispose (gobject); @@ -295,6 +301,9 @@ on_registration_reply (GObject *gobject, self->desktop_name, self->desktop_path)); } + + /* Register the cache object */ + self->cache = gtk_at_spi_cache_new (self->connection, ATSPI_CACHE_PATH); } static void @@ -324,14 +333,14 @@ gtk_at_spi_root_register (GtkAtSpiRoot *self) g_dbus_connection_register_object (self->connection, self->root_path, - atspi_application_interface_info (), + (GDBusInterfaceInfo *) &atspi_application_interface, &root_application_vtable, self, NULL, NULL); g_dbus_connection_register_object (self->connection, self->root_path, - atspi_accessible_interface_info (), + (GDBusInterfaceInfo *) &atspi_accessible_interface, &root_accessible_vtable, self, NULL, @@ -430,3 +439,11 @@ gtk_at_spi_root_get_connection (GtkAtSpiRoot *self) return self->connection; } + +GtkAtSpiCache * +gtk_at_spi_root_get_cache (GtkAtSpiRoot *self) +{ + g_return_val_if_fail (GTK_IS_AT_SPI_ROOT (self), NULL); + + return self->cache; +} diff --git a/gtk/a11y/gtkatspirootprivate.h b/gtk/a11y/gtkatspirootprivate.h index ff30b24670..4e951bbcea 100644 --- a/gtk/a11y/gtkatspirootprivate.h +++ b/gtk/a11y/gtkatspirootprivate.h @@ -22,6 +22,8 @@ #include +#include "gtkatspicacheprivate.h" + G_BEGIN_DECLS #define GTK_TYPE_AT_SPI_ROOT (gtk_at_spi_root_get_type()) @@ -34,4 +36,7 @@ gtk_at_spi_root_new (const char *bus_address); GDBusConnection * gtk_at_spi_root_get_connection (GtkAtSpiRoot *self); +GtkAtSpiCache * +gtk_at_spi_root_get_cache (GtkAtSpiRoot *self); + G_END_DECLS diff --git a/gtk/a11y/meson.build b/gtk/a11y/meson.build index d9c6cdc97c..d18682637a 100644 --- a/gtk/a11y/meson.build +++ b/gtk/a11y/meson.build @@ -9,6 +9,7 @@ if gtk_a11y_backends.contains('atspi') subdir('atspi') gtk_a11y_src += files([ + 'gtkatspicache.c', 'gtkatspicontext.c', 'gtkatspiroot.c', ])