diff options
author | Lukasz Stanislawski <lukasz.stanislawski@gmail.com> | 2017-05-14 23:05:12 +0200 |
---|---|---|
committer | Lukasz Stanislawski <l.stanislaws@samsung.com> | 2017-05-31 16:21:50 +0200 |
commit | 6c22f0ea1fcccc5f1a428061f9b34e7075481178 (patch) | |
tree | dc362aec8040eb67aa47043d7ead2d27048b1715 | |
parent | 8e03d7af3bbc511d181b965f8cdcf0281a274fa6 (diff) | |
download | efl-6c22f0ea1fcccc5f1a428061f9b34e7075481178.tar.gz |
elementary: add atspi plug & socket classes
Change-Id: Ie2f9d8f92b16f10039c14c2de8070d2e4c7a3f51
35 files changed, 1719 insertions, 162 deletions
diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am index b6c0c6e100..4a28d376db 100644 --- a/src/Makefile_Elementary.am +++ b/src/Makefile_Elementary.am @@ -4,7 +4,9 @@ elm_public_eolian_files = \ lib/elementary/elm_atspi_bridge.eo \ lib/elementary/elm_atspi_app_object.eo \ + lib/elementary/elm_atspi_plug.eo \ lib/elementary/elm_atspi_proxy.eo \ + lib/elementary/elm_atspi_socket.eo \ lib/elementary/elm_bg.eo \ lib/elementary/efl_ui_button.eo \ lib/elementary/elm_calendar.eo \ @@ -35,6 +37,7 @@ elm_public_eolian_files = \ lib/elementary/elm_interface_atspi_text_editable.eo \ lib/elementary/elm_interface_atspi_image.eo \ lib/elementary/elm_interface_atspi_selection.eo \ + lib/elementary/elm_interface_atspi_socket.eo \ lib/elementary/elm_interface_atspi_text.eo \ lib/elementary/elm_interface_atspi_value.eo \ lib/elementary/elm_interface_atspi_widget_action.eo \ @@ -205,7 +208,9 @@ includesdir = $(includedir)/elementary-@VMAJ@ includesunstable_HEADERS = \ lib/elementary/elm_gen_common.h \ lib/elementary/elm_atspi_bridge.h \ + lib/elementary/elm_atspi_plug.h \ lib/elementary/elm_atspi_proxy.h \ + lib/elementary/elm_atspi_socket.h \ lib/elementary/elm_interface_atspi_accessible.h \ lib/elementary/elm_interface_atspi_text.h \ lib/elementary/elm_interface_atspi_widget_action.h \ @@ -553,7 +558,9 @@ lib_elementary_libelementary_la_SOURCES = \ lib/elementary/elm_actionslider.c \ lib/elementary/elm_atspi_app_object.c \ lib/elementary/elm_atspi_bridge.c \ + lib/elementary/elm_atspi_plug.c \ lib/elementary/elm_atspi_proxy.c \ + lib/elementary/elm_atspi_socket.c \ lib/elementary/elm_bg.c \ lib/elementary/elm_box.c \ lib/elementary/elm_bubble.c \ @@ -606,6 +613,7 @@ lib_elementary_libelementary_la_SOURCES = \ lib/elementary/elm_interface_atspi_text_editable.c \ lib/elementary/elm_interface_atspi_image.c \ lib/elementary/elm_interface_atspi_selection.c \ + lib/elementary/elm_interface_atspi_socket.c \ lib/elementary/elm_interface_atspi_text.c \ lib/elementary/elm_interface_atspi_value.c \ lib/elementary/elm_interface_atspi_widget_action.c \ diff --git a/src/bin/elementary/test_win_plug.c b/src/bin/elementary/test_win_plug.c index ad94dde91d..8c53f9bbdb 100644 --- a/src/bin/elementary/test_win_plug.c +++ b/src/bin/elementary/test_win_plug.c @@ -5,6 +5,7 @@ #define MAX_TRY 40 +extern char *plugid; static int try_num = 0; static void @@ -171,6 +172,23 @@ _notify_error(Evas_Object *parent, const char *msg) evas_object_show(notif); } +static void +a11y_init(Evas_Object *plug) +{ + // assume bridge is initialized + Elm_Atspi_Socket *socket = efl_add(ELM_ATSPI_SOCKET_CLASS, plug); + Elm_Atspi_Proxy *proxy; + + proxy = efl_add(ELM_ATSPI_PROXY_CLASS, socket, elm_atspi_proxy_id_constructor(efl_added, plugid)); + + // FIXME order seems important! + elm_interface_atspi_accessible_parent_set(socket, plug); + elm_interface_atspi_accessible_parent_set(proxy, socket); + + // FIXME asume bridge is connected + elm_interface_atspi_socket_embed(socket, proxy); +} + void test_win_plug(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { @@ -197,6 +215,9 @@ test_win_plug(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UN return; } + //FIXME oreder seems important + //a11y_init(plug); + evas_object_smart_callback_add(plug, "image,deleted", cb_plug_disconnected, NULL); evas_object_smart_callback_add(plug, "image,resized", cb_plug_resized, NULL); @@ -208,4 +229,6 @@ test_win_plug(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UN evas_object_resize(win, 400, 600); evas_object_show(win); + + a11y_init(plug); } diff --git a/src/bin/elementary/test_win_socket.c b/src/bin/elementary/test_win_socket.c index 664f097bde..ef488b46a2 100644 --- a/src/bin/elementary/test_win_socket.c +++ b/src/bin/elementary/test_win_socket.c @@ -3,6 +3,8 @@ #endif #include <Elementary.h> +char *plugid; + static void _win_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { @@ -140,6 +142,29 @@ fill(Evas_Object *win, Eina_Bool do_bg) evas_object_show(sc); } +static void +_on_plug_id_changed(void *data, const Efl_Event *event) +{ + Elm_Atspi_Plug *plug = event->object; + plugid = elm_interface_atspi_socket_id_get(plug); + // send id using elementary IPC mechanism +} + +static void +a11y_init(Evas_Object *socket_window) +{ + // create a11y plug to get dbus reference to object + Elm_Atspi_Plug *plug = efl_add(ELM_ATSPI_PLUG_CLASS, socket_window); + + // make plug parent of socket_window + elm_interface_atspi_accessible_parent_set(socket_window, plug); + + // get address when bridge gets connected + efl_event_callback_add(plug, ELM_INTERFACE_ATSPI_SOCKET_EVENT_ID_CHANGED, _on_plug_id_changed, NULL); + + plugid = elm_interface_atspi_socket_id_get(plug); +} + void test_win_socket(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { @@ -193,6 +218,7 @@ test_win_socket(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *even elm_win_autodel_set(win_socket, EINA_TRUE); fill(win_socket, EINA_TRUE); + a11y_init(win_socket); evas_object_resize(win_socket, 400, 600); evas_object_show(win_socket); diff --git a/src/examples/elementary/a11y/efl-gtk-integration/plug/Makefile b/src/examples/elementary/a11y/efl-gtk-integration/plug/Makefile new file mode 100644 index 0000000000..712d7732d0 --- /dev/null +++ b/src/examples/elementary/a11y/efl-gtk-integration/plug/Makefile @@ -0,0 +1,30 @@ +CC=gcc +TARGET_GTK=gtk-plug +SOURCES_GTK=ta-plug.c \ + ta-plug-vbox.h \ + ta-plug-vbox.c \ + ta-plug-accessible.h \ + ta-plug-accessible.c + +LIBS_GTK=atk gtk+-3.0 +CFLAGS_GTK=`pkg-config --cflags $(LIBS_GTK)` +LDFLAGS_GTK=`pkg-config --libs $(LIBS_GTK)` + +TARGET_EFL=efl-socket +SOURCES_EFL=efl-socket.c +LIBS_EFL=elementary +CFLAGS_EFL=`pkg-config --cflags $(LIBS_EFL)` +LDFLAGS_EFL=`pkg-config --libs $(LIBS_EFL)` + +all: compile_gtk compile_efl + +compile_gtk: + $(CC) -o $(TARGET_GTK) $(SOURCES_GTK) $(CFLAGS_GTK) $(LDFLAGS_GTK) + +compile_efl: + $(CC) -o $(TARGET_EFL) $(SOURCES_EFL) $(CFLAGS_EFL) $(LDFLAGS_EFL) + +clean: + rm -rf $(TARGET_GTK) + rm -rf $(TARGET_EFL) + rm -rf *~ diff --git a/src/examples/elementary/a11y/efl-gtk-integration/plug/efl-socket.c b/src/examples/elementary/a11y/efl-gtk-integration/plug/efl-socket.c new file mode 100644 index 0000000000..5cb521ec39 --- /dev/null +++ b/src/examples/elementary/a11y/efl-gtk-integration/plug/efl-socket.c @@ -0,0 +1,95 @@ +#define EFL_BETA_API_SUPPORT +#define EFL_EO_API_SUPPORT +#include <Elementary.h> + +static struct app_state { + Evas_Object *entry; + Elm_Atspi_Socket *socket; + Elm_Atspi_Socket *proxy; + Evas_Object *container; +} state; + +static void a11y_init(void) +{ + if (state.socket) + efl_del(state.socket) + + if (!elm_entry_is_empty(state.entry)) + { + printf("Embedded plug: %s\n", elm_object_text_get(state.entry)); + state.socket = efl_add(ELM_ATSPI_SOCKET_CLASS, NULL); + // Weird constructor + state.proxy = efl_add(ELM_ATSPI_PROXY_CLASS, NULL, elm_atspi_proxy_id_constructor(efl_added, elm_object_text_get(state.entry))); + + // fires accessible parent should be set to eo_parent (???) + elm_interface_atspi_accessible_parent_set(state.socket, state.container); + // following line shuold be not necessary: + elm_interface_atspi_accessible_parent_set(state.proxy, state.socket); + + // FIXME order matters = should be fixed!!! + // if state.socket is not attached to tree, embed will have empty + // implemnetation + elm_interface_atspi_socket_embed(state.socket, state.proxy); + } +} + +static void +_connect_clicked_cb(void *data, Evas_Object *obj, void *event_info) +{ + if (elm_config_atspi_mode_get()) + a11y_init(); + else + printf("Atspi mode is not enabled. Adjust elementary configuration using elementary_config app\n"); +} + +static void +_create_layout(Evas_Object *win) +{ + Evas_Object *box = elm_box_add(win); + evas_object_size_hint_expand_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, box); + + Evas_Object *label = elm_label_add(box); + evas_object_size_hint_align_set(label, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_object_text_set(label, "Past Plug Id here:"); + elm_box_pack_end(box, label); + evas_object_show(label); + + Evas_Object *entry = elm_entry_add(box); + elm_entry_single_line_set(entry, EINA_TRUE); + elm_entry_scrollable_set(entry, EINA_TRUE); + evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(box, entry); + evas_object_show(entry); + state.entry = entry; + + Evas_Object *button = elm_button_add(box); + elm_object_text_set(button, "Connect"); + elm_box_pack_end(box, button); + evas_object_smart_callback_add(button, "clicked", _connect_clicked_cb, NULL); + evas_object_show(button); + + state.container = elm_label_add(box); + evas_object_size_hint_align_set(state.container, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_object_text_set(state.container, "Embedded content goes here:"); + elm_box_pack_end(box, state.container); + evas_object_show(state.container); + + evas_object_show(box); +} + +int elm_main(int argc, char **argv) +{ + Evas_Object *win = elm_win_util_standard_add("Efl socket", "Efl socket"); + elm_win_autodel_set(win, EINA_TRUE); + elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); + evas_object_resize(win, 300, 200); + + _create_layout(win); + + evas_object_show(win); + elm_run(); + return 0; +} + +ELM_MAIN(); diff --git a/src/examples/elementary/a11y/efl-gtk-integration/plug/ta-plug-accessible.c b/src/examples/elementary/a11y/efl-gtk-integration/plug/ta-plug-accessible.c new file mode 100644 index 0000000000..46d99f7337 --- /dev/null +++ b/src/examples/elementary/a11y/efl-gtk-integration/plug/ta-plug-accessible.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2011 Igalia S.L. + * Authors: Mario Sanchez Prada <msanchez@igalia.com> + * + * Based on a C# example written in C# by Mike Gorse: + * http://mgorse.freeshell.org/plug-socket-test.tar.gz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ +#include "ta-plug-accessible.h" + +#include <atk/atk.h> +#include <glib.h> +#include <gtk/gtk.h> + +struct _TaPlugAccessiblePrivate { + GtkWidget *widget; +}; + +#define TA_PLUG_ACCESSIBLE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), TA_TYPE_PLUG_ACCESSIBLE, TaPlugAccessiblePrivate)) + +G_DEFINE_TYPE (TaPlugAccessible, ta_plug_accessible, ATK_TYPE_PLUG); + +static void ta_plug_accessible_initialize (AtkObject *object, gpointer data) +{ + g_return_if_fail (TA_IS_PLUG_ACCESSIBLE (object)); + + TaPlugAccessible *plug = NULL; + TaPlugAccessiblePrivate *priv = NULL; + + ATK_OBJECT_CLASS(ta_plug_accessible_parent_class)->initialize(object, data); + + plug = TA_PLUG_ACCESSIBLE (object); + priv = TA_PLUG_ACCESSIBLE_GET_PRIVATE(plug); + priv->widget = NULL; + if (GTK_IS_WIDGET (data)) + priv->widget = GTK_WIDGET (data); +} + +static const gchar *ta_plug_accessible_get_name (AtkObject *object) +{ + g_return_val_if_fail(ATK_IS_OBJECT (object), NULL); + return "The Plug"; +} + +static AtkRole ta_plug_accessible_get_role (AtkObject *object) +{ + g_return_val_if_fail(ATK_IS_OBJECT (object), ATK_ROLE_UNKNOWN); + return ATK_ROLE_PANEL; +} + +static gint ta_plug_accessible_get_n_children (AtkObject *object) +{ + g_return_val_if_fail (TA_IS_PLUG_ACCESSIBLE (object), 0); + + TaPlugAccessible *plug = NULL; + TaPlugAccessiblePrivate *priv = NULL; + GList *children = NULL; + GList *item = NULL; + gint n_children = 0; + + plug = TA_PLUG_ACCESSIBLE (object); + priv = TA_PLUG_ACCESSIBLE_GET_PRIVATE(plug); + + if (!priv->widget) + return 0; + + if (!GTK_IS_CONTAINER (priv->widget)) + return 0; + + children = gtk_container_get_children (GTK_CONTAINER (priv->widget)); + n_children = g_list_length (children); + g_list_free (children); + + return n_children; +} + +static AtkObject *ta_plug_accessible_ref_child (AtkObject *object, gint i) +{ + g_return_val_if_fail (TA_IS_PLUG_ACCESSIBLE (object), NULL); + + TaPlugAccessible *plug = NULL; + TaPlugAccessiblePrivate *priv = NULL; + GList *children = NULL; + GList *item = NULL; + gint n_children = 0; + GtkWidget *child = NULL; + AtkObject *axChild = NULL; + + plug = TA_PLUG_ACCESSIBLE (object); + priv = TA_PLUG_ACCESSIBLE_GET_PRIVATE(plug); + + if (!priv->widget) + return NULL; + + if (!GTK_IS_CONTAINER (priv->widget)) + return NULL; + + children = gtk_container_get_children (GTK_CONTAINER (priv->widget)); + if (i < 0 || i >= g_list_length (children)) + return NULL; + + child = GTK_WIDGET (g_list_nth_data (children, i)); + if (!child) + return NULL; + + g_list_free (children); + + axChild = gtk_widget_get_accessible (child); + return g_object_ref (axChild); +} + +static void ta_plug_accessible_dispose (GObject *object) +{ + TaPlugAccessible *plug = NULL; + TaPlugAccessiblePrivate *priv = NULL; + + plug = TA_PLUG_ACCESSIBLE (object); + priv = TA_PLUG_ACCESSIBLE_GET_PRIVATE(plug); + + if (priv->widget) + { + g_object_unref (priv->widget); + priv->widget = NULL; + } + + G_OBJECT_CLASS(ta_plug_accessible_parent_class)->dispose(object); +} + +static void ta_plug_accessible_class_init (TaPlugAccessibleClass *klass) +{ + GObjectClass *g_object_class = G_OBJECT_CLASS(klass); + AtkObjectClass *atk_object_class = NULL; + + g_object_class->dispose = ta_plug_accessible_dispose; + + atk_object_class = ATK_OBJECT_CLASS (klass); + atk_object_class->initialize = ta_plug_accessible_initialize; + atk_object_class->get_name = ta_plug_accessible_get_name; + atk_object_class->get_role = ta_plug_accessible_get_role; + atk_object_class->get_n_children = ta_plug_accessible_get_n_children; + atk_object_class->get_index_in_parent = NULL; + atk_object_class->ref_child = ta_plug_accessible_ref_child; + + g_type_class_add_private(g_object_class, sizeof(TaPlugAccessiblePrivate)); +} + +static void ta_plug_accessible_init(TaPlugAccessible *plug) +{ +} + +AtkObject *ta_plug_accessible_new () +{ + return ATK_OBJECT (g_object_new(TA_TYPE_PLUG_ACCESSIBLE, 0)); +} diff --git a/src/examples/elementary/a11y/efl-gtk-integration/plug/ta-plug-accessible.h b/src/examples/elementary/a11y/efl-gtk-integration/plug/ta-plug-accessible.h new file mode 100644 index 0000000000..c862db179c --- /dev/null +++ b/src/examples/elementary/a11y/efl-gtk-integration/plug/ta-plug-accessible.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2011 Igalia S.L. + * Authors: Mario Sanchez Prada <msanchez@igalia.com> + * + * Based on a C# example written in C# by Mike Gorse: + * http://mgorse.freeshell.org/plug-socket-test.tar.gz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ +#ifndef TaPlugAccessible_h +#define TaPlugAccessible_h + +#include <atk/atk.h> + +G_BEGIN_DECLS + +#define TA_TYPE_PLUG_ACCESSIBLE (ta_plug_accessible_get_type ()) +#define TA_PLUG_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TA_TYPE_PLUG_ACCESSIBLE, TaPlugAccessible)) +#define TA_PLUG_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TA_TYPE_PLUG_ACCESSIBLE, TaPlugAccessibleClass)) +#define TA_IS_PLUG_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TA_TYPE_PLUG_ACCESSIBLE)) +#define TA_IS_PLUG_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TA_TYPE_PLUG_ACCESSIBLE)) +#define TA_PLUG_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TA_TYPE_PLUG_ACCESSIBLE, TaPlugAccessibleClass)) + +typedef struct _TaPlugAccessible TaPlugAccessible; +typedef struct _TaPlugAccessibleClass TaPlugAccessibleClass; +typedef struct _TaPlugAccessiblePrivate TaPlugAccessiblePrivate; + +struct _TaPlugAccessible { + AtkPlug parent; +}; + +struct _TaPlugAccessibleClass { + AtkPlugClass parentClass; +}; + +GType ta_plug_accessible_get_type(void) G_GNUC_CONST; + +AtkObject *ta_plug_accessible_new (void); + +G_END_DECLS + +#endif // TaPlugAccessible_h diff --git a/src/examples/elementary/a11y/efl-gtk-integration/plug/ta-plug-vbox.c b/src/examples/elementary/a11y/efl-gtk-integration/plug/ta-plug-vbox.c new file mode 100644 index 0000000000..7ec8533054 --- /dev/null +++ b/src/examples/elementary/a11y/efl-gtk-integration/plug/ta-plug-vbox.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2011 Igalia S.L. + * Authors: Mario Sanchez Prada <msanchez@igalia.com> + * + * Based on a C# example written in C# by Mike Gorse: + * http://mgorse.freeshell.org/plug-socket-test.tar.gz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ +#include "ta-plug-vbox.h" + +#include "ta-plug-accessible.h" + +#include <glib.h> +#include <gtk/gtk.h> + +G_DEFINE_TYPE (TaPlugVBox, ta_plug_vbox, GTK_TYPE_VBOX); + +static AtkObject *_get_accessible (GtkWidget *widget) +{ + static AtkObject *new = NULL; + + if (!new) + { + new = ta_plug_accessible_new (); + atk_object_initialize (new, G_OBJECT (widget)); + } + + return new; +} + +static void ta_plug_vbox_class_init (TaPlugVBoxClass *klass) +{ + GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; + + widget_class->get_accessible = _get_accessible; +} + +static void ta_plug_vbox_init(TaPlugVBox *plug) +{ +} + +GtkWidget *ta_plug_vbox_new (gboolean homogeneous, gint spacing) +{ + return GTK_WIDGET (g_object_new(TA_TYPE_PLUG_VBOX, + "homogeneous", homogeneous, + "spacing", spacing, + 0)); +} + +gchar *ta_plug_vbox_get_id (TaPlugVBox *plug) +{ + AtkObject *plugAxObject = NULL; + gchar *text_id = NULL; + + plugAxObject = gtk_widget_get_accessible (GTK_WIDGET (plug)); + if (ATK_IS_PLUG (plugAxObject)) + text_id = atk_plug_get_id (ATK_PLUG (plugAxObject)); + else + g_print ("Not an instance of AtkPlug\n"); + + return text_id; +} diff --git a/src/examples/elementary/a11y/efl-gtk-integration/plug/ta-plug-vbox.h b/src/examples/elementary/a11y/efl-gtk-integration/plug/ta-plug-vbox.h new file mode 100644 index 0000000000..d2e1fac898 --- /dev/null +++ b/src/examples/elementary/a11y/efl-gtk-integration/plug/ta-plug-vbox.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2011 Igalia S.L. + * Authors: Mario Sanchez Prada <msanchez@igalia.com> + * + * Based on a C# example written in C# by Mike Gorse: + * http://mgorse.freeshell.org/plug-socket-test.tar.gz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ +#ifndef TaPlugVBox_h +#define TaPlugVBox_h + +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +#define TA_TYPE_PLUG_VBOX (ta_plug_vbox_get_type ()) +#define TA_PLUG_VBOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TA_TYPE_PLUG_VBOX, TaPlugVBox)) +#define TA_PLUG_VBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TA_TYPE_PLUG_VBOX, TaPlugVBoxClass)) +#define TA_IS_PLUG_VBOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TA_TYPE_PLUG_VBOX)) +#define TA_IS_PLUG_VBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TA_TYPE_PLUG_VBOX)) +#define TA_PLUG_VBOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TA_TYPE_PLUG_VBOX, TaPlugVBoxClass)) + +typedef struct _TaPlugVBox TaPlugVBox; +typedef struct _TaPlugVBoxClass TaPlugVBoxClass; +typedef struct _TaPlugVBoxPrivate TaPlugVBoxPrivate; + +struct _TaPlugVBox { + GtkVBox parent; +}; + +struct _TaPlugVBoxClass { + GtkVBoxClass parentClass; +}; + +GType ta_plug_vbox_get_type(void) G_GNUC_CONST; + +GtkWidget *ta_plug_vbox_new (gboolean homogeneous, gint spacing); + +gchar *ta_plug_vbox_get_id (TaPlugVBox *plug); + +G_END_DECLS + +#endif // TaPlugVBox_h diff --git a/src/examples/elementary/a11y/efl-gtk-integration/plug/ta-plug.c b/src/examples/elementary/a11y/efl-gtk-integration/plug/ta-plug.c new file mode 100644 index 0000000000..ac534825a6 --- /dev/null +++ b/src/examples/elementary/a11y/efl-gtk-integration/plug/ta-plug.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2011 Igalia S.L. + * Authors: Mario Sanchez Prada <msanchez@igalia.com> + * + * Based on a C# example written in C# by Mike Gorse: + * http://mgorse.freeshell.org/plug-socket-test.tar.gz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ +#include "ta-plug-vbox.h" + +#include <gtk/gtk.h> + +#define WINDOW_WIDTH 350 +#define WINDOW_HEIGHT -1 + +static void +_button_clicked_cb (GtkButton *button, gpointer data) +{ + GtkWindow *window = GTK_WINDOW (data); + + GtkWidget *dialog = + gtk_message_dialog_new (window, + GTK_DIALOG_MODAL, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, + "I told you so:\nthe button does ALMOST nothing", + NULL); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); +} + +int +main (int argc, char**argv) +{ + GtkWidget *window = NULL; + GtkWidget *hbox = NULL; + GtkWidget *plug = NULL; + GtkWidget *widget = NULL; + gchar *plug_id = NULL; + gchar *entry_txt = NULL; + + gtk_init (&argc, &argv); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); + + plug = ta_plug_vbox_new (FALSE, 0); + plug_id = ta_plug_vbox_get_id (TA_PLUG_VBOX (plug)); + if (plug_id) + g_print ("[PLUG] Id is %s\n", plug_id); + else + g_print ("Not a valid ID found\n"); + + + hbox = gtk_hbox_new (FALSE, 0); + + widget = gtk_label_new ("Plug ID: "); + gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 6); + + widget = gtk_entry_new (); + entry_txt = g_strdup_printf ("%s", plug_id); + gtk_entry_set_text (GTK_ENTRY (widget), entry_txt); + gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 6); + + gtk_box_pack_start (GTK_BOX (plug), hbox, TRUE, TRUE, 6); + + widget = gtk_button_new_with_label ("A button which does almost nothing"); + g_signal_connect (widget, "clicked", G_CALLBACK (_button_clicked_cb), window); + gtk_box_pack_start (GTK_BOX (plug), widget, FALSE, FALSE, 6); + + g_free (entry_txt); + g_free (plug_id); + + gtk_container_add (GTK_CONTAINER (window), plug); + + gtk_window_set_default_size (GTK_WINDOW (window), + WINDOW_WIDTH, WINDOW_HEIGHT); + gtk_widget_show_all (window); + gtk_main (); +} diff --git a/src/examples/elementary/a11y/efl-gtk-integration/socket/Makefile b/src/examples/elementary/a11y/efl-gtk-integration/socket/Makefile new file mode 100644 index 0000000000..1266623c9b --- /dev/null +++ b/src/examples/elementary/a11y/efl-gtk-integration/socket/Makefile @@ -0,0 +1,20 @@ +CC=gcc +TARGET=ta-socket +SOURCES=ta-socket.c \ + ta-socket-label.h \ + ta-socket-label.c \ + ta-socket-accessible.h \ + ta-socket-accessible.c + +LIBS=atk gtk+-3.0 +CFLAGS=`pkg-config --cflags $(LIBS)` +LDFLAGS=`pkg-config --libs $(LIBS)` + +all: compile + +compile: + $(CC) -o $(TARGET) $(SOURCES) $(CFLAGS) $(LDFLAGS) + +clean: + rm -rf $(TARGET) + rm -rf *~ diff --git a/src/examples/elementary/a11y/efl-gtk-integration/socket/ta-socket-accessible.c b/src/examples/elementary/a11y/efl-gtk-integration/socket/ta-socket-accessible.c new file mode 100644 index 0000000000..01db3ad2a6 --- /dev/null +++ b/src/examples/elementary/a11y/efl-gtk-integration/socket/ta-socket-accessible.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2011 Igalia S.L. + * Authors: Mario Sanchez Prada <msanchez@igalia.com> + * + * Based on a C# example written in C# by Mike Gorse: + * http://mgorse.freeshell.org/plug-socket-test.tar.gz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ +#include "ta-socket-accessible.h" + +#include <atk/atk.h> +#include <glib.h> +#include <gtk/gtk.h> + +G_DEFINE_TYPE (TaSocketAccessible, ta_socket_accessible, ATK_TYPE_SOCKET); + +static const gchar *ta_socket_accessible_get_name (AtkObject *object) +{ + g_return_val_if_fail(ATK_IS_OBJECT (object), NULL); + return "The Socket"; +} + +static AtkRole ta_socket_accessible_get_role (AtkObject *object) +{ + g_return_val_if_fail(ATK_IS_OBJECT (object), ATK_ROLE_UNKNOWN); + return ATK_ROLE_PANEL; +} + +static void ta_socket_accessible_class_init (TaSocketAccessibleClass *klass) +{ + AtkObjectClass *atk_object_class = NULL; + + atk_object_class = ATK_OBJECT_CLASS (klass); + atk_object_class->get_name = ta_socket_accessible_get_name; + atk_object_class->get_role = ta_socket_accessible_get_role; +} + +static void ta_socket_accessible_init(TaSocketAccessible *socket) +{ +} + +AtkObject *ta_socket_accessible_new (void) +{ + return ATK_OBJECT (g_object_new(TA_TYPE_SOCKET_ACCESSIBLE, 0)); +} diff --git a/src/examples/elementary/a11y/efl-gtk-integration/socket/ta-socket-accessible.h b/src/examples/elementary/a11y/efl-gtk-integration/socket/ta-socket-accessible.h new file mode 100644 index 0000000000..55c35f80cd --- /dev/null +++ b/src/examples/elementary/a11y/efl-gtk-integration/socket/ta-socket-accessible.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2011 Igalia S.L. + * Authors: Mario Sanchez Prada <msanchez@igalia.com> + * + * Based on a C# example written in C# by Mike Gorse: + * http://mgorse.freeshell.org/plug-socket-test.tar.gz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ +#ifndef TaSocketAccessible_h +#define TaSocketAccessible_h + +#include <atk/atk.h> + +G_BEGIN_DECLS + +#define TA_TYPE_SOCKET_ACCESSIBLE (ta_socket_accessible_get_type ()) +#define TA_SOCKET_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TA_TYPE_SOCKET_ACCESSIBLE, TaSocketAccessible)) +#define TA_SOCKET_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TA_TYPE_SOCKET_ACCESSIBLE, TaSocketAccessibleClass)) +#define TA_IS_SOCKET_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TA_TYPE_SOCKET_ACCESSIBLE)) +#define TA_IS_SOCKET_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TA_TYPE_SOCKET_ACCESSIBLE)) +#define TA_SOCKET_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TA_TYPE_SOCKET_ACCESSIBLE, TaSocketAccessibleClass)) + +typedef struct _TaSocketAccessible TaSocketAccessible; +typedef struct _TaSocketAccessibleClass TaSocketAccessibleClass; +typedef struct _TaSocketAccessiblePrivate TaSocketAccessiblePrivate; + +struct _TaSocketAccessible { + AtkSocket parent; +}; + +struct _TaSocketAccessibleClass { + AtkSocketClass parentClass; +}; + +GType ta_socket_accessible_get_type(void) G_GNUC_CONST; + +AtkObject *ta_socket_accessible_new (void); + +G_END_DECLS + +#endif // TaSocketAccessible_h diff --git a/src/examples/elementary/a11y/efl-gtk-integration/socket/ta-socket-label.c b/src/examples/elementary/a11y/efl-gtk-integration/socket/ta-socket-label.c new file mode 100644 index 0000000000..4141205c0c --- /dev/null +++ b/src/examples/elementary/a11y/efl-gtk-integration/socket/ta-socket-label.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011 Igalia S.L. + * Authors: Mario Sanchez Prada <msanchez@igalia.com> + * + * Based on a C# example written in C# by Mike Gorse: + * http://mgorse.freeshell.org/plug-socket-test.tar.gz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ +#include "ta-socket-label.h" + +#include "ta-socket-accessible.h" + +#include <glib.h> +#include <gtk/gtk.h> + +G_DEFINE_TYPE (TaSocketLabel, ta_socket_label, GTK_TYPE_LABEL); + + +static AtkObject *_get_accessible (GtkWidget *widget) +{ + static AtkObject *new = NULL; + + if (!new) + { + new = ta_socket_accessible_new (); + atk_object_initialize (new, G_OBJECT (widget)); + } + + return new; +} + +static void ta_socket_label_class_init (TaSocketLabelClass *klass) +{ + GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; + + widget_class->get_accessible = _get_accessible; +} + +static void ta_socket_label_init(TaSocketLabel *socket) +{ +} + +GtkWidget *ta_socket_label_new (const gchar *text) +{ + return GTK_WIDGET (g_object_new(TA_TYPE_SOCKET_LABEL, + "label", text, + 0)); +} diff --git a/src/examples/elementary/a11y/efl-gtk-integration/socket/ta-socket-label.h b/src/examples/elementary/a11y/efl-gtk-integration/socket/ta-socket-label.h new file mode 100644 index 0000000000..a2b60ced6b --- /dev/null +++ b/src/examples/elementary/a11y/efl-gtk-integration/socket/ta-socket-label.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2011 Igalia S.L. + * Authors: Mario Sanchez Prada <msanchez@igalia.com> + * + * Based on a C# example written in C# by Mike Gorse: + * http://mgorse.freeshell.org/plug-socket-test.tar.gz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ +#ifndef TaSocketLabel_h +#define TaSocketLabel_h + +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +#define TA_TYPE_SOCKET_LABEL (ta_socket_label_get_type ()) +#define TA_SOCKET_LABEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TA_TYPE_SOCKET_LABEL, TaSocketLabel)) +#define TA_SOCKET_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TA_TYPE_SOCKET_LABEL, TaSocketLabelClass)) +#define TA_IS_SOCKET_LABEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TA_TYPE_SOCKET_LABEL)) +#define TA_IS_SOCKET_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TA_TYPE_SOCKET_LABEL)) +#define TA_SOCKET_LABEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TA_TYPE_SOCKET_LABEL, TaSocketLabelClass)) + +typedef struct _TaSocketLabel TaSocketLabel; +typedef struct _TaSocketLabelClass TaSocketLabelClass; +typedef struct _TaSocketLabelPrivate TaSocketLabelPrivate; + +struct _TaSocketLabel { + GtkLabel parent; +}; + +struct _TaSocketLabelClass { + GtkLabelClass parentClass; +}; + +GType ta_socket_label_get_type(void) G_GNUC_CONST; + +GtkWidget *ta_socket_label_new (const gchar *text); + +G_END_DECLS + +#endif // TaSocketLabel_h diff --git a/src/examples/elementary/a11y/efl-gtk-integration/socket/ta-socket.c b/src/examples/elementary/a11y/efl-gtk-integration/socket/ta-socket.c new file mode 100644 index 0000000000..700021b924 --- /dev/null +++ b/src/examples/elementary/a11y/efl-gtk-integration/socket/ta-socket.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2011 Igalia S.L. + * Authors: Mario Sanchez Prada <msanchez@igalia.com> + * + * Based on a C# example written in C# by Mike Gorse: + * http://mgorse.freeshell.org/plug-socket-test.tar.gz + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ +#include "ta-socket-label.h" + +#include <gtk/gtk.h> + +#define WINDOW_WIDTH 300 +#define WINDOW_HEIGHT -1 + +static GtkWidget *entry = NULL; +static GtkWidget *button = NULL; +static GtkWidget *socket = NULL; + +static void +_button_clicked_cb (GtkButton *button, gpointer data) +{ + AtkObject *socketAxObject = NULL; + gchar *text_id = NULL; + + text_id = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry))); + + if (text_id && text_id[0] != '\0') + { + socketAxObject = gtk_widget_get_accessible (socket); + + if (ATK_IS_SOCKET (socketAxObject)) + { + g_print ("[SOCKET] Embedding object with ID %s\n", text_id); + atk_socket_embed (ATK_SOCKET (socketAxObject), text_id); + g_print ("[SOCKET] Done\n"); + } + else + g_print ("Not embedding anything: Not an instance of AtkSocket\n"); + } + else + g_print ("Not embedding: you need to provide an ID\n"); + + g_free (text_id); +} + +static void +_create_widgets (GtkWidget *window) +{ + GtkWidget *vbox = NULL; + + vbox = gtk_vbox_new (FALSE, 0); + + /* Label + entry */ + entry = gtk_entry_new (); + gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 6); + + button = gtk_button_new_with_label ("Connect to plug"); + g_signal_connect (button, "clicked", G_CALLBACK (_button_clicked_cb), NULL); + gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 6); + + /* Our socket accessible */ + socket = ta_socket_label_new ("Socket accessible goes here"); + gtk_box_pack_start (GTK_BOX (vbox), socket, FALSE, FALSE, 6); + + gtk_container_add (GTK_CONTAINER (window), vbox); +} + +int +main (int argc, char**argv) +{ + GtkWidget *window = NULL; + + gtk_init (&argc, &argv); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); + + _create_widgets (window); + + gtk_window_set_default_size (GTK_WINDOW (window), + WINDOW_WIDTH, WINDOW_HEIGHT); + gtk_widget_show_all (window); + gtk_main (); +} diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h index e05cd690f1..8690719593 100644 --- a/src/lib/elementary/Elementary.h +++ b/src/lib/elementary/Elementary.h @@ -172,6 +172,7 @@ EAPI extern Elm_Version *elm_version; #include <elm_scroller.h> #include <elm_entry.h> #include <elm_list.h> +#include <elm_atspi_proxy.h> /* Interfaces */ #include <elm_interfaces.h> @@ -190,7 +191,8 @@ EAPI extern Elm_Version *elm_version; #include <elm_actionslider.h> #include <elm_app.h> #include <elm_atspi_app_object.h> -#include <elm_atspi_proxy.h> +#include <elm_atspi_plug.h> +#include <elm_atspi_socket.h> #include <elm_atspi_bridge.h> #include <elm_bg.h> #include <elm_box.h> diff --git a/src/lib/elementary/efl_ui_win.c b/src/lib/elementary/efl_ui_win.c index b7cf93a44f..fa6317fa27 100644 --- a/src/lib/elementary/efl_ui_win.c +++ b/src/lib/elementary/efl_ui_win.c @@ -2273,7 +2273,7 @@ _efl_ui_win_show(Eo *obj, Efl_Ui_Win_Data *sd) TRAP(sd, show); - if (_elm_config->atspi_mode) + if (sd->type != ELM_WIN_SOCKET_IMAGE) { Eo *root = elm_interface_atspi_accessible_root_get(ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN); elm_interface_atspi_accessible_parent_set(obj, root); @@ -6470,7 +6470,6 @@ _on_atspi_bus_connected(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUS Evas_Object *win; Eina_List *l; - Eo *root = elm_interface_atspi_accessible_root_get(ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN); EINA_LIST_FOREACH(_elm_win_list, l, win) { /** @@ -6479,7 +6478,7 @@ _on_atspi_bus_connected(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUS * receive all org.a11y.window events and could keep track of active * windows whithin system. */ - elm_interface_atspi_accessible_parent_set(win, root); + ERR("Reemit created"); elm_interface_atspi_window_created_signal_emit(win); if (elm_win_focus_get(win)) { diff --git a/src/lib/elementary/elm_atspi_app_object.c b/src/lib/elementary/elm_atspi_app_object.c index 00ec5dfb29..a64ac43d81 100644 --- a/src/lib/elementary/elm_atspi_app_object.c +++ b/src/lib/elementary/elm_atspi_app_object.c @@ -8,10 +8,15 @@ #include "elm_widget.h" #include "elm_priv.h" +#include "atspi/atspi-constants.h" + +#define ATSPI_REGISTRYD_ROOT_ID ATSPI_DBUS_NAME_REGISTRY ":" ATSPI_DBUS_PATH_ROOT + typedef struct _Elm_Atspi_App_Object_Data Elm_Atspi_App_Object_Data; struct _Elm_Atspi_App_Object_Data { + Elm_Atspi_Proxy *desktop_proxy; const char *descr; }; @@ -19,10 +24,20 @@ EOLIAN static void _elm_atspi_app_object_efl_object_destructor(Eo *obj EINA_UNUSED, Elm_Atspi_App_Object_Data *_pd) { if (_pd->descr) eina_stringshare_del(_pd->descr); - efl_destructor(efl_super(obj, ELM_ATSPI_APP_OBJECT_CLASS)); } +EOLIAN static Eo* +_elm_atspi_app_object_efl_object_constructor(Eo *obj, Elm_Atspi_App_Object_Data *_pd) +{ + efl_constructor(efl_super(obj, ELM_ATSPI_APP_OBJECT_CLASS)); + _pd->desktop_proxy = efl_add(ELM_ATSPI_PROXY_CLASS, obj, elm_atspi_proxy_id_constructor(efl_added, ATSPI_REGISTRYD_ROOT_ID)); + + elm_interface_atspi_accessible_parent_set(obj, _pd->desktop_proxy); + + return obj; +} + EOLIAN static const char* _elm_atspi_app_object_elm_interface_atspi_accessible_name_get(Eo *obj EINA_UNUSED, Elm_Atspi_App_Object_Data *_pd EINA_UNUSED) { @@ -49,4 +64,30 @@ _elm_atspi_app_object_elm_interface_atspi_accessible_role_get(Eo *obj EINA_UNUSE return ELM_ATSPI_ROLE_APPLICATION; } +EOLIAN static void +_elm_atspi_app_object_elm_interface_atspi_socket_on_connected(Eo *obj, Elm_Atspi_App_Object_Data *_pd) +{ + ERR("On Connected: %s", elm_interface_atspi_socket_id_get(obj)); + elm_interface_atspi_socket_embed_by(obj, _pd->desktop_proxy); +} + +EOLIAN static void +_elm_atspi_app_object_elm_interface_atspi_socket_on_disconnected(Eo *obj EINA_UNUSED, Elm_Atspi_App_Object_Data *_pd EINA_UNUSED) +{ + ERR("On Disconnected: %s", elm_interface_atspi_socket_id_get(obj)); + elm_interface_atspi_socket_unembed_by(obj, _pd->desktop_proxy); +} + +EOLIAN static void +_elm_atspi_app_object_elm_interface_atspi_socket_on_embedded(Eo *obj EINA_UNUSED, Elm_Atspi_App_Object_Data *_pd EINA_UNUSED, Elm_Atspi_Proxy *proxy EINA_UNUSED) +{ + ERR("Application successfully registered as desktop child"); +} + +EOLIAN static int +_elm_atspi_app_object_elm_interface_atspi_accessible_index_in_parent_get(Eo *obj EINA_UNUSED, Elm_Atspi_App_Object_Data *_pd EINA_UNUSED) +{ + return -1; +} + #include "elm_atspi_app_object.eo.c" diff --git a/src/lib/elementary/elm_atspi_app_object.eo b/src/lib/elementary/elm_atspi_app_object.eo index dbcaacd8c9..a48697dae3 100644 --- a/src/lib/elementary/elm_atspi_app_object.eo +++ b/src/lib/elementary/elm_atspi_app_object.eo @@ -1,12 +1,17 @@ -class Elm.Atspi.App.Object (Efl.Object, Elm.Interface.Atspi_Accessible) +class Elm.Atspi.App.Object (Elm.Atspi.Plug, Elm.Interface.Atspi_Accessible) { [[AT-SPI application object class]] legacy_prefix: elm_atspi_app_object; data: Elm_Atspi_App_Object_Data; implements { + Efl.Object.constructor; Efl.Object.destructor; Elm.Interface.Atspi_Accessible.name { get; } Elm.Interface.Atspi_Accessible.description { get; set; } Elm.Interface.Atspi_Accessible.role { get; } + Elm.Interface.Atspi_Accessible.index_in_parent { get; } + Elm.Interface.Atspi.Socket.on_embedded; + Elm.Interface.Atspi.Socket.on_connected; + Elm.Interface.Atspi.Socket.on_disconnected; } } diff --git a/src/lib/elementary/elm_atspi_bridge.c b/src/lib/elementary/elm_atspi_bridge.c index 1f418d47f5..ff89370761 100644 --- a/src/lib/elementary/elm_atspi_bridge.c +++ b/src/lib/elementary/elm_atspi_bridge.c @@ -8,6 +8,7 @@ #define ELM_INTERFACE_ATSPI_VALUE_PROTECTED #define ELM_INTERFACE_ATSPI_IMAGE_PROTECTED #define ELM_INTERFACE_ATSPI_SELECTION_PROTECTED +#define ELM_INTERFACE_ATSPI_SOCKET_PROTECTED #define ELM_INTERFACE_ATSPI_TEXT_PROTECTED #define ELM_INTERFACE_ATSPI_TEXT_EDITABLE_PROTECTED @@ -16,6 +17,7 @@ #include <stdint.h> #include <Elementary.h> #include "elm_priv.h" +#include <assert.h> /* * Accessibility Bus info not defined in atspi-constants.h @@ -92,13 +94,14 @@ typedef struct _Elm_Atspi_Bridge_Data Eldbus_Service_Interface *selection; Eldbus_Service_Interface *text; Eldbus_Service_Interface *value; + Eldbus_Service_Interface *socket; } interfaces; Eo *root; + Eina_List *plugs; Eldbus_Pending *connect_request; Eldbus_Pending *stack_status_request; Eldbus_Proxy *status_proxy; Eina_Bool connected : 1; - Eina_Bool registered: 1; } Elm_Atspi_Bridge_Data; @@ -115,8 +118,12 @@ struct collection_match_rule { Eina_Bool auto_register : 1; }; -static Eo *_instance; -static int _init_count = 0; +struct dbus_address { + char bus[256]; + char path[256]; +}; + +static Elm_Atspi_Bridge *_instance; // Object Event handlers static void _state_changed_signal_send(void *data, const Efl_Event *event); @@ -135,7 +142,7 @@ static void _text_selection_changed_send(void *data, const Efl_Event *event); // bridge private methods static void _bridge_object_register(Eo *bridge, Eo *obj); static void _bridge_object_unregister(Eo *bridge, Eo *obj); -static void _elm_atspi_bridge_address_from_object(Eo *bridge, const Eo *eo, const char **bus, const char **path); +static struct dbus_address _elm_atspi_bridge_address_from_object(Eo *bridge, const Eo *eo); static void _bridge_signal_send(Eo *bridge, Eo *obj, const char *ifc, const Eldbus_Signal *signal, const char *minor, unsigned int det1, unsigned int det2, const char *variant_sig, ...); static Eo * _bridge_object_from_path(Eo *bridge, const char *path); static void _bridge_iter_object_reference_append(Eo *bridge, Eldbus_Message_Iter *iter, const Eo *obj); @@ -144,16 +151,20 @@ static void _elm_atspi_bridge_disconnect(Elm_Atspi_Bridge *bridge); static void _elm_atspi_bridge_on_disconnected(Elm_Atspi_Bridge *bridge); static void _elm_atspi_bridge_connect(Elm_Atspi_Bridge *bridge); static void _elm_atspi_bridge_on_connected(Elm_Atspi_Bridge *bridge); -static void _elm_atspi_bridge_pending_add(Elm_Atspi_Bridge *obj, Eldbus_Pending *pending); +static void _elm_atspi_bridge_pending_add(Elm_Atspi_Bridge *obj, Eldbus_Pending *pending, Eldbus_Free_Cb cb, const void *data); static void _elm_atspi_bridge_pending_del(Elm_Atspi_Bridge *obj, Eldbus_Pending *pending); static void _elm_atspi_bridge_pending_cancel_all(Elm_Atspi_Bridge *obj); +static void _elm_atspi_bridge_socket_hooks_uninstall(Elm_Interface_Atspi_Socket *socket); +static void _elm_atspi_bridge_socket_hooks_install(Elm_Interface_Atspi_Socket *socket); + // utility functions static void _iter_interfaces_append(Eldbus_Message_Iter *iter, const Eo *obj); static Eina_Bool _elm_atspi_bridge_key_filter(void *data, void *loop, int type, void *event); -static void _object_desktop_reference_append(Eldbus_Message_Iter *iter); static void _bridge_object_added_signal_send(Elm_Atspi_Bridge *bridge, Eo *object); static void _bridge_object_removed_signal_send(Elm_Atspi_Bridge *bridge, Eo *object); +static Eina_Bool _elm_atspi_bridge_id_parse(const char *id, struct dbus_address *addr); +static char *_elm_atspi_bridge_id_make(const struct dbus_address *addr); EFL_CALLBACKS_ARRAY_DEFINE(event_handlers, { ELM_INTERFACE_ATSPI_ACCESSIBLE_EVENT_CHILDREN_CHANGED, _children_changed_signal_send}, @@ -1023,6 +1034,26 @@ static const Eldbus_Method selection_methods[] = { }; static Eldbus_Message * +_socket_embedded(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg) +{ + const char *obj_path = eldbus_message_path_get(msg); + Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME); + Eo *obj = _bridge_object_from_path(bridge, obj_path); + + ERR("Recieved embedded request"); + ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_SOCKET_MIXIN, msg); + + elm_interface_atspi_socket_on_embedded(obj, NULL); + + return eldbus_message_method_return_new(msg); +} + +static const Eldbus_Method socket_methods[] = { + { "Embedded", ELDBUS_ARGS({"(so)", "parentObject"}), NULL, _socket_embedded, 0 }, + { NULL, NULL, NULL, NULL, 0 } +}; + +static Eldbus_Message * _action_description_get(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg) { const char *description, *obj_path = eldbus_message_path_get(msg); @@ -2034,35 +2065,39 @@ _bridge_object_from_path(Eo *bridge, const char *path) return ret; } -static void -_elm_atspi_bridge_address_from_object(Eo *bridge, const Eo *eo, const char **bus, const char **path) +static struct dbus_address +_elm_atspi_bridge_address_from_object(Eo *bridge, const Eo *eo) { - static char buf[64]; + struct dbus_address ret = {{0,}}; - ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd); + ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN_VAL(bridge, pd, ret); if (!eo) { - if (bus) *bus = eldbus_connection_unique_name_get(pd->a11y_bus); - if (path) *path = ATSPI_DBUS_PATH_NULL; + snprintf(ret.bus, sizeof(ret.bus), "%s", eldbus_connection_unique_name_get(pd->a11y_bus)); + snprintf(ret.path, sizeof(ret.path), "%s", ATSPI_DBUS_PATH_NULL); } else if (eo == pd->root) { - snprintf(buf, sizeof(buf), "%s%s", ELM_ACCESS_OBJECT_PATH_PREFIX, ELM_ACCESS_OBJECT_PATH_ROOT); - if (bus) *bus = eldbus_connection_unique_name_get(pd->a11y_bus); - if (path) *path = buf; + snprintf(ret.bus, sizeof(ret.bus), "%s", eldbus_connection_unique_name_get(pd->a11y_bus)); + snprintf(ret.path, sizeof(ret.path), "%s%s", ELM_ACCESS_OBJECT_PATH_PREFIX, ELM_ACCESS_OBJECT_PATH_ROOT); } else if (efl_isa(eo, ELM_ATSPI_PROXY_CLASS)) { - if (bus) *bus = elm_atspi_proxy_bus_name_get(eo); - if (path) *path = elm_atspi_proxy_path_get(eo); + if (!_elm_atspi_bridge_id_parse(elm_atspi_proxy_id_get(eo), &ret)) + { + ERR("Unable to parse id: %s", elm_atspi_proxy_id_get(eo)); + snprintf(ret.bus, sizeof(ret.bus), "%s", eldbus_connection_unique_name_get(pd->a11y_bus)); + snprintf(ret.path, sizeof(ret.path), "%s", ATSPI_DBUS_PATH_NULL); + } } else { - snprintf(buf, sizeof(buf), ELM_ACCESS_OBJECT_REFERENCE_TEMPLATE, (unsigned long long)(uintptr_t)eo); - if (bus) *bus = eldbus_connection_unique_name_get(pd->a11y_bus); - if (path) *path = buf; + snprintf(ret.bus, sizeof(ret.bus), "%s", eldbus_connection_unique_name_get(pd->a11y_bus)); + snprintf(ret.path, sizeof(ret.path), ELM_ACCESS_OBJECT_REFERENCE_TEMPLATE, (unsigned long long)(uintptr_t)eo); } + + return ret; } static Eina_Bool @@ -2095,12 +2130,7 @@ _accessible_property_get(const Eldbus_Service_Interface *interface, const char * else if (!strcmp(property, "Parent")) { ret_obj = elm_interface_atspi_accessible_parent_get(obj); - Elm_Atspi_Role role = ELM_ATSPI_ROLE_INVALID; - role = elm_interface_atspi_accessible_role_get(obj); - if ((!ret_obj) && (ELM_ATSPI_ROLE_APPLICATION == role)) - _object_desktop_reference_append(iter); - else - _bridge_iter_object_reference_append(bridge, iter, ret_obj); + _bridge_iter_object_reference_append(bridge, iter, ret_obj); return EINA_TRUE; } else if (!strcmp(property, "ChildCount")) @@ -2404,6 +2434,10 @@ static const Eldbus_Service_Interface_Desc selection_iface_desc = { ATSPI_DBUS_INTERFACE_SELECTION, selection_methods, NULL, selection_properties, NULL, NULL }; +static const Eldbus_Service_Interface_Desc socket_iface_desc = { + ATSPI_DBUS_INTERFACE_SOCKET, socket_methods, NULL, NULL, NULL, NULL +}; + static const Eldbus_Service_Interface_Desc text_iface_desc = { ATSPI_DBUS_INTERFACE_TEXT, text_methods, NULL, text_properties, _text_properties_get, NULL }; @@ -3090,30 +3124,19 @@ static const Eldbus_Service_Interface_Desc collection_iface_desc = { static void _bridge_iter_object_reference_append(Eo *bridge, Eldbus_Message_Iter *iter, const Eo *obj) { - const char *path, *bus; + struct dbus_address addr; ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd); Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL); EINA_SAFETY_ON_NULL_RETURN(iter); - _elm_atspi_bridge_address_from_object(bridge, obj, &bus, &path); + addr = _elm_atspi_bridge_address_from_object(bridge, obj); - eldbus_message_iter_basic_append(iter_struct, 's', bus); - eldbus_message_iter_basic_append(iter_struct, 'o', path); + eldbus_message_iter_basic_append(iter_struct, 's', addr.bus); + eldbus_message_iter_basic_append(iter_struct, 'o', addr.path); eldbus_message_iter_container_close(iter, iter_struct); } static void -_object_desktop_reference_append(Eldbus_Message_Iter *iter) -{ - Eldbus_Message_Iter *iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL); - EINA_SAFETY_ON_NULL_RETURN(iter); - - eldbus_message_iter_basic_append(iter_struct, 's', ATSPI_DBUS_NAME_REGISTRY); - eldbus_message_iter_basic_append(iter_struct, 'o', ATSPI_DBUS_PATH_ROOT); - eldbus_message_iter_container_close(iter, iter_struct); -} - -static void _iter_interfaces_append(Eldbus_Message_Iter *iter, const Eo *obj) { Eldbus_Message_Iter *iter_array; @@ -3167,13 +3190,9 @@ _cache_item_reference_append_cb(Eo *bridge, Eo *data, Eldbus_Message_Iter *iter_ /* Marshall application */ _bridge_iter_object_reference_append(bridge, iter_struct, pd->root); - Eo *parent = NULL; - parent = elm_interface_atspi_accessible_parent_get(data); /* Marshall parent */ - if ((!parent) && (ELM_ATSPI_ROLE_APPLICATION == role)) - _object_desktop_reference_append(iter_struct); - else - _bridge_iter_object_reference_append(bridge, iter_struct, parent); + Eo *parent = parent = elm_interface_atspi_accessible_parent_get(data); + _bridge_iter_object_reference_append(bridge, iter_struct, parent); /* Marshall children */ Eina_List *children_list = NULL, *l; @@ -3258,6 +3277,9 @@ _cache_get_items(const Eldbus_Service_Interface *iface, const Eldbus_Message *ms { Eo *obj = eina_list_data_get(to_process); to_process = eina_list_remove_list(to_process, to_process); + + // FIXME do not return references to non-local objects in cache + if (efl_isa(obj, ELM_ATSPI_PROXY_CLASS)) continue; _cache_item_reference_append_cb(bridge, obj, iter_array); Eina_List *children; @@ -3609,78 +3631,54 @@ static const Eldbus_Service_Interface_Desc component_iface_desc = { }; static void -_on_elm_atspi_bridge_root_register(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending) +_on_elm_atspi_bridge_plug_register(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending) { const char *errname, *errmsg; Elm_Atspi_Bridge *bridge = data; ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd); + _elm_atspi_bridge_pending_del(bridge, pending); + if (eldbus_message_error_get(msg, &errname, &errmsg)) { ERR("%s %s", errname, errmsg); return; } - pd->registered = EINA_TRUE; - _elm_atspi_bridge_pending_del(bridge, pending); - DBG("Application successfuly registered at ATSPI2 bus."); + Eo *obj = eldbus_pending_data_get(pending, "__obj"); + Eo *proxy = eldbus_pending_data_get(pending, "__proxy"); + + // check if object is still in cache, since it may be unregistered + // before dbus request complete + if (eina_hash_find(pd->cache, &obj)) + elm_interface_atspi_socket_on_embedded(obj, proxy); } EAPI void -_elm_atspi_bridge_root_register(Eo *bridge) +_elm_atspi_bridge_plugs_register(Eo *bridge) { ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd); - if (!pd->root) return; - - Eldbus_Pending *register_req; - Eldbus_Message *message = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY, - ATSPI_DBUS_PATH_ROOT, - ATSPI_DBUS_INTERFACE_SOCKET, - "Embed"); - if (!message) return; - Eldbus_Message_Iter *iter = eldbus_message_iter_get(message); - if (!iter) - { - ERR("eldbus_message_iter_get failed"); - eldbus_message_unref(message); - return; - } + assert (pd->connected); + Eina_List *l; + Elm_Atspi_Plug *plug; - _bridge_iter_object_reference_append(bridge, iter, pd->root); - register_req = eldbus_connection_send(pd->a11y_bus, message, _on_elm_atspi_bridge_root_register, bridge, -1); - if (!register_req) + EINA_LIST_FOREACH(pd->plugs, l, plug) { - ERR("eldbus_connection_send failed"); - eldbus_message_unref(message); - return; + _bridge_object_register(bridge, plug); } - - _bridge_object_register(bridge, pd->root); - _elm_atspi_bridge_pending_add(bridge, register_req); } EAPI void -_elm_atspi_bridge_root_unregister(Elm_Atspi_Bridge *bridge) +_elm_atspi_bridge_plugs_unregister(Elm_Atspi_Bridge *bridge) { ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd); + assert (!pd->connected); + Eina_List *l; + Elm_Atspi_Plug *plug; - if (!pd->registered) return; - - Eldbus_Message *message = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY, - ATSPI_DBUS_PATH_ROOT, - ATSPI_DBUS_INTERFACE_SOCKET, - "Unembed"); - if (!message) return; - Eldbus_Message_Iter *iter = eldbus_message_iter_get(message); - if (!iter) + EINA_LIST_FOREACH(pd->plugs, l, plug) { - ERR("eldbus_message_iter_get failed"); - eldbus_message_unref(message); - return; + _bridge_object_unregister(bridge, plug); } - - _bridge_iter_object_reference_append(bridge, iter, pd->root); - _bridge_object_unregister(bridge, pd->root); - eldbus_connection_send(pd->a11y_bus, message, NULL, NULL, -1); } static void @@ -3819,7 +3817,7 @@ _registered_events_list_update(Eo *bridge) msg = eldbus_message_method_call_new(ATSPI_DBUS_NAME_REGISTRY, ATSPI_DBUS_PATH_REGISTRY, ATSPI_DBUS_INTERFACE_REGISTRY, "GetRegisteredEvents"); p = eldbus_connection_send(pd->a11y_bus, msg, _registered_listeners_get, bridge, -1); - _elm_atspi_bridge_pending_add(bridge, p); + _elm_atspi_bridge_pending_add(bridge, p, NULL, NULL); } static void @@ -4053,7 +4051,7 @@ static void _bridge_signal_send(Eo *bridge, Eo *obj, const char *infc, const Eld Eldbus_Message_Iter *iter , *iter_stack[64], *iter_struct; va_list va; Eo *atspi_obj; - const char *path, *bus; + struct dbus_address addr; int top = 0; EINA_SAFETY_ON_NULL_RETURN(infc); @@ -4062,9 +4060,9 @@ static void _bridge_signal_send(Eo *bridge, Eo *obj, const char *infc, const Eld EINA_SAFETY_ON_NULL_RETURN(obj); ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd); - _elm_atspi_bridge_address_from_object(bridge, obj, NULL, &path); + addr = _elm_atspi_bridge_address_from_object(bridge, obj); - msg = eldbus_message_signal_new(path, infc, signal->name); + msg = eldbus_message_signal_new(addr.path, infc, signal->name); if (!msg) return; va_start(va, variant_sig); @@ -4093,8 +4091,8 @@ static void _bridge_signal_send(Eo *bridge, Eo *obj, const char *infc, const Eld break; case 'o': atspi_obj = va_arg(va, Eo*); - _elm_atspi_bridge_address_from_object(bridge, atspi_obj, NULL, &path); - eldbus_message_iter_basic_append(iter_stack[top], 'o', path); + addr = _elm_atspi_bridge_address_from_object(bridge, atspi_obj); + eldbus_message_iter_basic_append(iter_stack[top], 'o', addr.path); break; case ')': eldbus_message_iter_container_close(iter_stack[top - 1], iter_stack[top]); @@ -4120,9 +4118,9 @@ static void _bridge_signal_send(Eo *bridge, Eo *obj, const char *infc, const Eld eldbus_message_iter_container_close(iter, iter_stack[0]); iter_struct = eldbus_message_iter_container_new(iter, 'r', NULL); - _elm_atspi_bridge_address_from_object(bridge, pd->root, &bus, &path); - eldbus_message_iter_basic_append(iter_struct, 's', bus); - eldbus_message_iter_basic_append(iter_struct, 'o', path); + addr = _elm_atspi_bridge_address_from_object(bridge, pd->root); + eldbus_message_iter_basic_append(iter_struct, 's', addr.bus); + eldbus_message_iter_basic_append(iter_struct, 'o', addr.path); eldbus_message_iter_container_close(iter, iter_struct); eldbus_connection_send(pd->a11y_bus, msg, NULL, NULL, -1); @@ -4209,6 +4207,41 @@ _elm_atspi_bridge_event_handlers_unregister(Eo *bridge) } static void +_elm_atspi_bridge_on_object_unregistered(Elm_Atspi_Bridge *bridge, Eo *obj) +{ + efl_event_callback_array_del(obj, event_handlers(), bridge); + _bridge_object_removed_signal_send(bridge, obj); + + if (efl_isa(obj, ELM_INTERFACE_ATSPI_SOCKET_MIXIN)) + { + elm_interface_atspi_socket_on_disconnected(obj); + elm_interface_atspi_socket_id_set(obj, NULL); + _elm_atspi_bridge_socket_hooks_uninstall(obj); + } +} + +static void +_elm_atspi_bridge_on_object_registered(Elm_Atspi_Bridge *bridge, Eo *obj) +{ + struct dbus_address addr; + if (!efl_isa(obj, ELM_ATSPI_PROXY_CLASS)) + { + _bridge_object_added_signal_send(bridge, obj); + efl_event_callback_array_add(obj, event_handlers(), bridge); + } + + if (efl_isa(obj, ELM_INTERFACE_ATSPI_SOCKET_MIXIN)) + { + _elm_atspi_bridge_socket_hooks_install(obj); + addr = _elm_atspi_bridge_address_from_object(bridge, obj); + char *id = _elm_atspi_bridge_id_make(&addr); + elm_interface_atspi_socket_id_set(obj, id); + elm_interface_atspi_socket_on_connected(obj); + free(id); + } +} + +static void _bridge_object_unregister(Eo *bridge, Eo *obj) { ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd); @@ -4224,8 +4257,8 @@ _bridge_object_unregister(Eo *bridge, Eo *obj) continue; eina_hash_del(pd->cache, &o, o); - efl_event_callback_array_del(o, event_handlers(), bridge); - _bridge_object_removed_signal_send(bridge, o); + + _elm_atspi_bridge_on_object_unregistered(bridge, o); Eina_List *children; children = elm_interface_atspi_accessible_children_get(o); @@ -4240,6 +4273,7 @@ _bridge_object_added_signal_send(Elm_Atspi_Bridge *bridge, Eo *object) Eldbus_Message_Iter *iter; ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd); + if (!pd->connected) return; sig = eldbus_service_signal_new(pd->cache_interface, ATSPI_OBJECT_CHILD_ADDED); iter = eldbus_message_iter_get(sig); @@ -4332,6 +4366,9 @@ _elm_atspi_bridge_interfaces_register(Eo *bridge) pd->interfaces.value = eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &value_iface_desc); eldbus_service_object_data_set(pd->interfaces.value, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge); + + pd->interfaces.socket = + eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &socket_iface_desc); } static void @@ -4433,8 +4470,8 @@ static void _bridge_object_register(Eo *bridge, Eo *obj) continue; eina_hash_add(pd->cache, &o, o); - _bridge_object_added_signal_send(bridge, o); - efl_event_callback_array_add(o, event_handlers(), bridge); + + _elm_atspi_bridge_on_object_registered(bridge, o); Eina_List *children; children = elm_interface_atspi_accessible_children_get(o); @@ -4445,12 +4482,13 @@ static void _bridge_object_register(Eo *bridge, Eo *obj) void _elm_atspi_bridge_init(void) { - if (!_init_count) + if (!_instance) { _instance = efl_add(ELM_ATSPI_BRIDGE_CLASS, NULL); Efl_Object *root = elm_interface_atspi_accessible_root_get(ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN); + elm_atspi_bridge_plug_register(_instance, root); elm_atspi_bridge_root_set(_instance, root); - _init_count = 1; + elm_interface_atspi_accessible_observer_install(ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN); } } @@ -4463,10 +4501,11 @@ _elm_atspi_bridge_get(void) void _elm_atspi_bridge_shutdown(void) { - if (_init_count) + if (_instance) { + elm_interface_atspi_accessible_observer_uninstall(ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN); efl_del(_instance); - _init_count = 0; + _instance = NULL; } } @@ -4700,6 +4739,132 @@ _elm_atspi_bridge_platform_a11y_status_monitor_shutdown(Elm_Atspi_Bridge *bridge if (pd->bus_obj) eldbus_object_unref(pd->bus_obj); } +static Eldbus_Message* +_elm_atspi_bridge_method_call_to_proxy_new(Elm_Atspi_Proxy *proxy, const char *interface, const char *method) +{ + struct dbus_address addr = {{0, }}; + + if (!_elm_atspi_bridge_id_parse(elm_atspi_proxy_id_get(proxy), &addr)) + { + ERR("Unable to parset elm_atspi_proxy id: (%s)", elm_atspi_proxy_id_get(proxy)); + return NULL; + } + + return eldbus_message_method_call_new(addr.bus, addr.path, interface, method); +} + +static void +_elm_atspi_bridge_elm_interface_atspi_socket_embed(Eo *obj, void *data, Elm_Atspi_Proxy *proxy) +{ + Elm_Atspi_Bridge *bridge = _elm_atspi_bridge_get(); + + assert (bridge != NULL); + ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd); + if (!pd->connected) return; + + Eldbus_Message *message = + _elm_atspi_bridge_method_call_to_proxy_new(proxy, ATSPI_DBUS_INTERFACE_SOCKET, "Embedded"); + if (!message) return; + Eldbus_Message_Iter *iter = eldbus_message_iter_get(message); + if (!iter) + { + ERR("eldbus_message_iter_get failed"); + eldbus_message_unref(message); + return; + } + + eldbus_connection_send(pd->a11y_bus, message, NULL, NULL, -1); + ERR("Embed on elm_atspi_bridge"); +} + +static void +_elm_atspi_bridge_elm_interface_atspi_socket_unembed(Eo *obj EINA_UNUSED, void *data EINA_UNUSED, Elm_Atspi_Proxy *proxy EINA_UNUSED) +{ + // Currently "Unembedded" is not supported by at-spi protocol. +} + +static void +_elm_atspi_bridge_ref_release(void *data, const void *deadptr EINA_UNUSED) +{ + efl_unref((Eo*)data); +} + +static void +_elm_atspi_bridge_elm_interface_atspi_socket_embed_by(Eo *obj, void *data, Elm_Atspi_Proxy *proxy) +{ + Elm_Atspi_Bridge *bridge = _elm_atspi_bridge_get(); + + assert (bridge != NULL); + ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd); + if (!pd->connected) return; + + Eldbus_Message *message = + _elm_atspi_bridge_method_call_to_proxy_new(proxy, ATSPI_DBUS_INTERFACE_SOCKET, "Embed"); + + if (!message) return; + Eldbus_Message_Iter *iter = eldbus_message_iter_get(message); + if (!iter) + { + ERR("eldbus_message_iter_get failed"); + eldbus_message_unref(message); + return; + } + _bridge_iter_object_reference_append(bridge, iter, obj); + + Eldbus_Pending *req = eldbus_connection_send(pd->a11y_bus, message, _on_elm_atspi_bridge_plug_register, bridge, 100); + eldbus_pending_data_set(req, "__obj", obj); + eldbus_pending_data_set(req, "__proxy", proxy); + if (!req) + ERR("eldbus_connection_send failed"); + else + _elm_atspi_bridge_pending_add(bridge, req, _elm_atspi_bridge_ref_release, efl_ref(proxy)); +} + +static void +_elm_atspi_bridge_elm_interface_atspi_socket_unembed_by(Eo *obj, void *data, Elm_Atspi_Proxy *proxy) +{ + Elm_Atspi_Bridge *bridge = _elm_atspi_bridge_get(); + + ERR("UnEmbed_by on elm_atspi_bridge"); + + assert (bridge != NULL); + ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd); + if (!pd->connected) return; + + Eldbus_Message *message = + _elm_atspi_bridge_method_call_to_proxy_new(proxy, ATSPI_DBUS_INTERFACE_SOCKET, "Unembed"); + + if (!message) return; + Eldbus_Message_Iter *iter = eldbus_message_iter_get(message); + if (!iter) + { + ERR("eldbus_message_iter_get failed"); + eldbus_message_unref(message); + return; + } + + eldbus_connection_send(pd->a11y_bus, message, NULL, NULL, -1); +} + +static void +_elm_atspi_bridge_socket_hooks_uninstall(Elm_Interface_Atspi_Socket *socket) +{ + efl_object_override(socket, NULL); +} + +static void +_elm_atspi_bridge_socket_hooks_install(Elm_Interface_Atspi_Socket *socket) +{ + ERR("Install hooks for %s", efl_class_name_get(socket)); + EFL_OPS_DEFINE(_elm_atspi_bridge_hooks, + EFL_OBJECT_OP_FUNC(elm_interface_atspi_socket_embed, _elm_atspi_bridge_elm_interface_atspi_socket_embed), + EFL_OBJECT_OP_FUNC(elm_interface_atspi_socket_unembed, _elm_atspi_bridge_elm_interface_atspi_socket_unembed), + EFL_OBJECT_OP_FUNC(elm_interface_atspi_socket_embed_by, _elm_atspi_bridge_elm_interface_atspi_socket_embed_by), + EFL_OBJECT_OP_FUNC(elm_interface_atspi_socket_unembed_by, _elm_atspi_bridge_elm_interface_atspi_socket_unembed_by)); + + efl_object_override(socket, &_elm_atspi_bridge_hooks); +} + EOLIAN Efl_Object* _elm_atspi_bridge_efl_object_constructor(Eo *obj, Elm_Atspi_Bridge_Data *pd) { @@ -4715,7 +4880,7 @@ _elm_atspi_bridge_efl_object_constructor(Eo *obj, Elm_Atspi_Bridge_Data *pd) if (!_elm_atspi_bridge_platform_a11y_status_monitor_init(obj)) { - ERR("Unable to get platform's a11y status."); + WRN("Unable to get platform's a11y status. Is a11y stack running?"); eldbus_connection_unref(pd->session_bus); return NULL; } @@ -4723,11 +4888,20 @@ _elm_atspi_bridge_efl_object_constructor(Eo *obj, Elm_Atspi_Bridge_Data *pd) return obj; } +static void +_elm_atspi_bridge_plugs_clean_up(Eo *bridge) +{ + ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd); + eina_list_free(pd->plugs); + pd->plugs = NULL; +} + EOLIAN void _elm_atspi_bridge_efl_object_destructor(Eo *obj, Elm_Atspi_Bridge_Data *pd EINA_UNUSED) { _elm_atspi_bridge_disconnect(obj); elm_atspi_bridge_root_set(obj, NULL); + _elm_atspi_bridge_plugs_clean_up(obj); _elm_atspi_bridge_platform_a11y_status_monitor_shutdown(obj); eldbus_connection_unref(pd->session_bus); @@ -4741,14 +4915,14 @@ _elm_atspi_bridge_root_get(Eo *obj EINA_UNUSED, Elm_Atspi_Bridge_Data *pd) } static void -_elm_atspi_bridge_root_del(void *data, const Efl_Event *event EINA_UNUSED) +_elm_atspi_bridge_plug_del(void *data, const Efl_Event *event) { Elm_Atspi_Bridge *bridge = data; - elm_atspi_bridge_root_set(bridge, NULL); + elm_atspi_bridge_plug_unregister(bridge, event->object); } /** - * triggers re-registration of accassible application + * @brief triggers re-registration of accessible application */ EOLIAN void _elm_atspi_bridge_root_set(Eo *obj, Elm_Atspi_Bridge_Data *pd, Efl_Object *new_root) @@ -4761,9 +4935,7 @@ _elm_atspi_bridge_root_set(Eo *obj, Elm_Atspi_Bridge_Data *pd, Efl_Object *new_r if (pd->connected) _elm_atspi_bridge_disconnect(obj); - if (pd->root) efl_event_callback_del(pd->root, EFL_EVENT_CALLBACK_DEL, _elm_atspi_bridge_root_del, obj); pd->root = new_root; - if (pd->root) efl_event_callback_add(pd->root, EFL_EVENT_CALLBACK_DEL, _elm_atspi_bridge_root_del, obj); if (was_connected) _elm_atspi_bridge_connect(obj); @@ -4815,9 +4987,10 @@ _elm_atspi_bridge_disconnect(Elm_Atspi_Bridge *bridge) } static void -_elm_atspi_bridge_pending_add(Elm_Atspi_Bridge *bridge, Eldbus_Pending *pending) +_elm_atspi_bridge_pending_add(Elm_Atspi_Bridge *bridge, Eldbus_Pending *pending, Eldbus_Free_Cb cb, const void *data) { ELM_ATSPI_BRIDGE_DATA_GET_OR_RETURN(bridge, pd); + if (cb) eldbus_pending_free_cb_add(pending, cb, data); pd->pending_requests = eina_list_append(pd->pending_requests, pending); } @@ -4851,7 +5024,7 @@ _elm_atspi_bridge_on_disconnected(Elm_Atspi_Bridge *bridge) _elm_atspi_bridge_pending_cancel_all(bridge); - _elm_atspi_bridge_root_unregister(bridge); + _elm_atspi_bridge_plugs_unregister(bridge); _elm_atspi_bridge_event_handlers_unregister(bridge); _elm_atspi_bridge_interfaces_unregister(bridge); @@ -4873,7 +5046,7 @@ _elm_atspi_bridge_on_connected(Elm_Atspi_Bridge *bridge) _elm_atspi_bridge_interfaces_register(bridge); _elm_atspi_bridge_event_handlers_register(bridge); - _elm_atspi_bridge_root_register(bridge); + _elm_atspi_bridge_plugs_register(bridge); } static void @@ -4885,4 +5058,79 @@ _elm_atspi_bridge_enabled_set(Elm_Atspi_Bridge *bridge, Eina_Bool value) _elm_atspi_bridge_disconnect(bridge); } +EOLIAN void +_elm_atspi_bridge_plug_register(Eo *obj, Elm_Atspi_Bridge_Data *pd, Elm_Atspi_Plug *plug) +{ + EINA_SAFETY_ON_NULL_RETURN(plug); + + if (!eina_list_data_find(pd->plugs, plug)) + { + if (pd->connected) + _bridge_object_register(obj, plug); + efl_event_callback_add(plug, EFL_EVENT_DEL, _elm_atspi_bridge_plug_del, obj); + pd->plugs = eina_list_append(pd->plugs, plug); + } +} + +EOLIAN void +_elm_atspi_bridge_plug_unregister(Eo *obj, Elm_Atspi_Bridge_Data *pd, Elm_Atspi_Plug *plug) +{ + EINA_SAFETY_ON_NULL_RETURN(plug); + Eina_List *node; + + if ((node = eina_list_data_find_list(pd->plugs, plug))) + { + if (pd->connected) + _bridge_object_unregister(obj, plug); + efl_event_callback_del(plug, EFL_EVENT_DEL, _elm_atspi_bridge_plug_del, obj); + pd->plugs = eina_list_remove_list(pd->plugs, node); + } +} + +static Eina_Bool +_elm_atspi_bridge_id_parse(const char *id, struct dbus_address *addr) +{ + int written; + Eina_Bool ret = EINA_FALSE; + + if (!addr || !id) + return EINA_FALSE; + + char *copy = strdup(id); + if (!copy) + return EINA_FALSE; + + char *split = strrchr(copy, ':'); + if (!split) + goto exit; + + *split = '\0'; + + written = snprintf(addr->bus, sizeof(addr->bus), "%s", copy); + if ((written < 0) || (written >= (int)sizeof(addr->bus))) + goto exit; + + written = snprintf(addr->path, sizeof(addr->path), "%s", split + 1); + if ((written < 0) || (written >= (int)sizeof(addr->path))) + goto exit; + + ret = EINA_TRUE; + +exit: + free(copy); + return ret; +} + +static char* +_elm_atspi_bridge_id_make(const struct dbus_address *address) +{ + char buf[256]; + + int written = snprintf(buf, sizeof(buf), "%s:%s", address->bus, address->path); + if ((written < 0) || (written >= (int)sizeof(buf))) + return NULL; + + return strdup(buf); +} + #include "elm_atspi_bridge.eo.c" diff --git a/src/lib/elementary/elm_atspi_bridge.eo b/src/lib/elementary/elm_atspi_bridge.eo index 3e8ef5dce5..a1fb6a1bfa 100644 --- a/src/lib/elementary/elm_atspi_bridge.eo +++ b/src/lib/elementary/elm_atspi_bridge.eo @@ -20,7 +20,17 @@ class Elm.Atspi.Bridge (Efl.Object) set { } values { - ret: Efl.Object; [[Root accessible object, or null if not set ]] + ret: Elm.Atspi.Plug; [[Root accessible object, or null if not set ]] + } + } + plug_register { + params { + @in plug: Elm.Atspi.Plug; + } + } + plug_unregister { + params { + @in plug: Elm.Atspi.Plug; } } } diff --git a/src/lib/elementary/elm_atspi_plug.c b/src/lib/elementary/elm_atspi_plug.c new file mode 100644 index 0000000000..dbcd83339f --- /dev/null +++ b/src/lib/elementary/elm_atspi_plug.c @@ -0,0 +1,46 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#include <Elementary.h> +#include <elm_priv.h> +#include <assert.h> + + +typedef struct _Elm_Atspi_Plug_Data { + Elm_Atspi_Proxy *proxy_parent; // technical object for keep bridge coherent +} Elm_Atspi_Plug_Data; + +EOLIAN Eo* +_elm_atspi_plug_efl_object_constructor(Eo *obj, Elm_Atspi_Plug_Data *pd) +{ + efl_constructor(efl_super(obj, ELM_ATSPI_PLUG_CLASS)); + + Elm_Atspi_Bridge *bridge = _elm_atspi_bridge_get(); + if (bridge) + elm_atspi_bridge_plug_register(bridge, obj); + + elm_interface_atspi_accessible_role_set(obj, ELM_ATSPI_ROLE_FRAME); + return obj; +} + +EOLIAN void +_elm_atspi_plug_efl_object_destructor(Eo *obj EINA_UNUSED, Elm_Atspi_Plug_Data *pd) +{ + efl_destructor(efl_super(obj, ELM_ATSPI_PLUG_CLASS)); +} + +EOLIAN void +_elm_atspi_plug_elm_interface_atspi_socket_on_embedded(Eo *obj EINA_UNUSED, Elm_Atspi_Plug_Data *pd, Elm_Atspi_Proxy *proxy) +{ + ERR("On embedded"); +} + +EOLIAN void +_elm_atspi_plug_elm_interface_atspi_socket_on_unembedded(Eo *obj EINA_UNUSED, Elm_Atspi_Plug_Data *pd, Elm_Atspi_Proxy *proxy) +{ + ERR("On unembedded"); +} + +#include "elm_atspi_plug.eo.c" + diff --git a/src/lib/elementary/elm_atspi_plug.eo b/src/lib/elementary/elm_atspi_plug.eo new file mode 100644 index 0000000000..e7c133f847 --- /dev/null +++ b/src/lib/elementary/elm_atspi_plug.eo @@ -0,0 +1,13 @@ +class Elm.Atspi.Plug (Efl.Object, Elm.Interface.Atspi_Accessible, + Elm.Interface.Atspi.Socket) +{ + [[AT-SPI Plug class.]] + legacy_prefix: elm_atspi_plug; + eo_prefix: elm_obj_atspi_plug; + implements { + Efl.Object.destructor; + Efl.Object.constructor; + Elm.Interface.Atspi.Socket.on_embedded; + Elm.Interface.Atspi.Socket.on_unembedded; + } +} diff --git a/src/lib/elementary/elm_atspi_plug.h b/src/lib/elementary/elm_atspi_plug.h new file mode 100644 index 0000000000..2b716f0106 --- /dev/null +++ b/src/lib/elementary/elm_atspi_plug.h @@ -0,0 +1,8 @@ +#ifdef EFL_BETA_API_SUPPORT +#ifdef EFL_EO_API_SUPPORT +#include "elm_atspi_plug.eo.h" +#endif +#ifndef EFL_NOLEGACY_API_SUPPORT +#include "elm_atspi_plug.eo.legacy.h" +#endif +#endif diff --git a/src/lib/elementary/elm_atspi_proxy.c b/src/lib/elementary/elm_atspi_proxy.c index 102bcf03d6..0fef9cb21c 100644 --- a/src/lib/elementary/elm_atspi_proxy.c +++ b/src/lib/elementary/elm_atspi_proxy.c @@ -7,35 +7,26 @@ #include <assert.h> typedef struct _Elm_Atspi_Proxy_Data { - const char *bus; - const char *path; + const char *id; } Elm_Atspi_Proxy_Data; EOLIAN void _elm_atspi_proxy_efl_object_destructor(Eo *obj EINA_UNUSED, Elm_Atspi_Proxy_Data *pd) { - eina_stringshare_del(pd->bus); - eina_stringshare_del(pd->path); + if (pd->id) eina_stringshare_del(pd->id); + efl_destructor(efl_super(obj, ELM_ATSPI_PROXY_CLASS)); } EOLIAN const char* -_elm_atspi_proxy_path_get(Eo *obj EINA_UNUSED, Elm_Atspi_Proxy_Data *pd) +_elm_atspi_proxy_id_get(Eo *obj EINA_UNUSED, Elm_Atspi_Proxy_Data *pd) { - return pd->path; -} - -EOLIAN const char* -_elm_atspi_proxy_bus_name_get(Eo *obj EINA_UNUSED, Elm_Atspi_Proxy_Data *pd) -{ - return pd->bus; + return pd->id; } EOLIAN void -_elm_atspi_proxy_constructor(Eo *obj EINA_UNUSED, Elm_Atspi_Proxy_Data *pd, const char *bus, const char *path) +_elm_atspi_proxy_id_constructor(Eo *obj EINA_UNUSED, Elm_Atspi_Proxy_Data *pd, const char *id) { - pd->bus = eina_stringshare_add(bus); - pd->path = eina_stringshare_add(path); + pd->id = eina_stringshare_add(id); } - #include "elm_atspi_proxy.eo.c" diff --git a/src/lib/elementary/elm_atspi_proxy.eo b/src/lib/elementary/elm_atspi_proxy.eo index 43ee235622..ecb8352acb 100644 --- a/src/lib/elementary/elm_atspi_proxy.eo +++ b/src/lib/elementary/elm_atspi_proxy.eo @@ -1,34 +1,28 @@ +import elm_general; + class Elm.Atspi.Proxy (Efl.Object, Elm.Interface.Atspi_Accessible) { - [[AT-SPI Proxy class. Represents out-of-process accessibility object]] + [[AT-SPI Proxy class. Represents accessibility object from external process.]] legacy_prefix: elm_atspi_proxy; eo_prefix: elm_obj_atspi_proxy; methods { - @property path { + @property id { get { - values { - ret: string; - } } - } - @property bus_name { - get { - values { - ret: string; - } + values { + ret: string; } } - constructor { - params { - @in bus: string; - @in path: string; - } + id_constructor { + params { + @in id: string; + } } } implements { Efl.Object.destructor; } constructors { - .constructor; + .id_constructor; } } diff --git a/src/lib/elementary/elm_atspi_socket.c b/src/lib/elementary/elm_atspi_socket.c new file mode 100644 index 0000000000..c925d1d6cb --- /dev/null +++ b/src/lib/elementary/elm_atspi_socket.c @@ -0,0 +1,25 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#include <Elementary.h> +#include <elm_priv.h> + +typedef struct _Elm_Atspi_Socket_Data { +} Elm_Atspi_Socket_Data; + +EOLIAN void +_elm_atspi_socket_efl_object_destructor(Eo *obj EINA_UNUSED, Elm_Atspi_Socket_Data *pd) +{ + efl_destructor(efl_super(obj, ELM_ATSPI_SOCKET_CLASS)); +} + +EOLIAN Eo* +_elm_atspi_socket_efl_object_constructor(Eo *obj, Elm_Atspi_Socket_Data *pd EINA_UNUSED) +{ + efl_constructor(efl_super(obj, ELM_ATSPI_SOCKET_CLASS)); + elm_interface_atspi_accessible_role_set(obj, ELM_ATSPI_ROLE_EMBEDDED); + + return obj; +} +#include "elm_atspi_socket.eo.c" diff --git a/src/lib/elementary/elm_atspi_socket.eo b/src/lib/elementary/elm_atspi_socket.eo new file mode 100644 index 0000000000..12ccab0a72 --- /dev/null +++ b/src/lib/elementary/elm_atspi_socket.eo @@ -0,0 +1,10 @@ +class Elm.Atspi.Socket (Efl.Object, Elm.Interface.Atspi_Accessible, Elm.Interface.Atspi.Socket) +{ + [[AT-SPI Socket class]] + legacy_prefix: elm_atspi_socket; + eo_prefix: elm_obj_atspi_socket; + implements { + Efl.Object.constructor; + Efl.Object.destructor; + } +} diff --git a/src/lib/elementary/elm_atspi_socket.h b/src/lib/elementary/elm_atspi_socket.h new file mode 100644 index 0000000000..6da89489b1 --- /dev/null +++ b/src/lib/elementary/elm_atspi_socket.h @@ -0,0 +1,9 @@ +#ifdef EFL_BETA_API_SUPPORT +#ifdef EFL_EO_API_SUPPORT +#include "elm_atspi_socket.eo.h" +#endif +#ifndef EFL_NOLEGACY_API_SUPPORT +#include "elm_atspi_socket.eo.legacy.h" +#endif +#endif + diff --git a/src/lib/elementary/elm_interface_atspi_accessible.c b/src/lib/elementary/elm_interface_atspi_accessible.c index f6dadf0fd1..5537b1e19a 100644 --- a/src/lib/elementary/elm_interface_atspi_accessible.c +++ b/src/lib/elementary/elm_interface_atspi_accessible.c @@ -128,10 +128,19 @@ struct _Elm_Interface_Atspi_Accessible_Data Eina_Inlist *children; }; + typedef struct _Elm_Interface_Atspi_Accessible_Data Elm_Interface_Atspi_Accessible_Data; +struct Accessibility_Plugin +{ + void *plugin_private_data; +}; + +static void _elm_interface_atspi_accessible_observers_notify(Eo *object); + static Eo *root; +static Eina_List *plugins; EOLIAN static int _elm_interface_atspi_accessible_index_in_parent_get(Eo *obj, Elm_Interface_Atspi_Accessible_Data *pd EINA_UNUSED) @@ -525,7 +534,33 @@ EOLIAN Eo * _elm_interface_atspi_accessible_efl_object_constructor(Eo *obj, Elm_Interface_Atspi_Accessible_Data *pd) { pd->self = obj; + _elm_interface_atspi_accessible_observers_notify(obj); return efl_constructor(efl_super(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN)); } +static void +_elm_interface_atspi_accessible_observers_notify(Eo *object) +{ + if (observers) + { + ERR("Query observer"); + } +} + +EOLIAN void +_elm_interface_atspi_accessible_observer_install(Eo *socket_class, void *data) +{ + ERR("Observer installed"); + observers = 0x1; + if (!observers) + observers = eina_array_new(1); +} + +EOLIAN void +_elm_interface_atspi_accessible_observer_uninstall(Eo *socket_class, void *data) +{ + ERR("Observer uninstalled"); + observers = NULL; +} + #include "elm_interface_atspi_accessible.eo.c" diff --git a/src/lib/elementary/elm_interface_atspi_accessible.eo b/src/lib/elementary/elm_interface_atspi_accessible.eo index 037d02182a..1999d59910 100644 --- a/src/lib/elementary/elm_interface_atspi_accessible.eo +++ b/src/lib/elementary/elm_interface_atspi_accessible.eo @@ -1,6 +1,3 @@ -/* FIXME: This definitely shouldn't be here. */ -type Efl_Event_Cb: __undefined_type; [[Efl event callback type]] - enum Elm.Atspi.Role { [[Describes the role of an object visible to AT-SPI Clients.]] @@ -391,6 +388,8 @@ mixin Elm.Interface.Atspi_Accessible (Efl.Interface, Efl.Object) ret: Efl.Object; [[Root object]] } } + set { + } } } implements { diff --git a/src/lib/elementary/elm_interface_atspi_socket.c b/src/lib/elementary/elm_interface_atspi_socket.c new file mode 100644 index 0000000000..0753306beb --- /dev/null +++ b/src/lib/elementary/elm_interface_atspi_socket.c @@ -0,0 +1,69 @@ +#ifdef HAVE_CONFIG_H + #include "elementary_config.h" +#endif + +#include <Elementary.h> +#include "elm_widget.h" +#include "elm_priv.h" + +typedef struct _Elm_Inteface_Atspi_Socket_Data +{ + const char *id; + Eina_Bool occupied : 1; +} Elm_Interface_Atspi_Socket_Data; + +EOLIAN const char* +_elm_interface_atspi_socket_id_get(Eo *socket EINA_UNUSED, Elm_Interface_Atspi_Socket_Data *pd) +{ + return pd->id; +} + +EOLIAN void +_elm_interface_atspi_socket_id_set(Eo *socket, Elm_Interface_Atspi_Socket_Data *pd, const char *new_id) +{ + const char *id = eina_stringshare_add(new_id); + if (pd->id != id) + { + eina_stringshare_del(pd->id); + pd->id = id; + efl_event_callback_call(socket, ELM_INTERFACE_ATSPI_SOCKET_EVENT_ID_CHANGED, NULL); + } + else + eina_stringshare_del(id); +} + +EOLIAN Eina_Bool +_elm_interface_atspi_socket_occupied_get(Eo *socket EINA_UNUSED, Elm_Interface_Atspi_Socket_Data *pd) +{ + return pd->occupied; +} + +EOLIAN void +_elm_interface_atspi_socket_occupied_set(Eo *socket EINA_UNUSED, Elm_Interface_Atspi_Socket_Data *pd, Eina_Bool val) +{ + pd->occupied = val; +} + +EOLIAN void +_elm_interface_atspi_socket_on_embedded(Eo *socket, Elm_Interface_Atspi_Socket_Data *pd EINA_UNUSED, Elm_Atspi_Proxy *proxy) +{ + efl_event_callback_call(socket, ELM_INTERFACE_ATSPI_SOCKET_EVENT_EMBEDDED, proxy); +} + +EOLIAN void +_elm_interface_atspi_socket_on_unembedded(Eo *socket, Elm_Interface_Atspi_Socket_Data *pd EINA_UNUSED, Elm_Atspi_Proxy *proxy) +{ + efl_event_callback_call(socket, ELM_INTERFACE_ATSPI_SOCKET_EVENT_UNEMBEDDED, proxy); +} + +EOLIAN void +_elm_interface_atspi_socket_on_connected(Eo *socket, Elm_Interface_Atspi_Socket_Data *pd EINA_UNUSED) +{ +} + +EOLIAN void +_elm_interface_atspi_socket_on_disconnected(Eo *socket, Elm_Interface_Atspi_Socket_Data *pd EINA_UNUSED) +{ +} + +#include "elm_interface_atspi_socket.eo.c" diff --git a/src/lib/elementary/elm_interface_atspi_socket.eo b/src/lib/elementary/elm_interface_atspi_socket.eo new file mode 100644 index 0000000000..7efbfa4681 --- /dev/null +++ b/src/lib/elementary/elm_interface_atspi_socket.eo @@ -0,0 +1,69 @@ +import elm_general; + +mixin Elm.Interface.Atspi.Socket(Efl.Interface, Efl.Object) +{ + [[Elementary AT-SPI socket interface]] + eo_prefix: elm_interface_atspi_socket; + methods { + @property id { + get { + } set { + } + values { + ret: string; + } + } + @property occupied { + get { + } + set { + } + values { + ret: bool; + } + } + embed @pure_virtual { + [[ Embed remote accessible object as a child.]] + params { + @in proxy: Elm.Atspi.Proxy; + } + } + unembed @pure_virtual { + // unembed + params { + @in proxy: Elm.Atspi.Proxy; + } + } + embed_by @pure_virtual { + [[ Embed accessible object as a child of remote object.]] + params { + @in proxy: Elm.Atspi.Proxy; + } + } + unembed_by @pure_virtual { + // unembed + params { + @in proxy: Elm.Atspi.Proxy; + } + } + on_embedded { + params { + @in proxy: Elm.Atspi.Proxy; + } + } + on_unembedded { + params { + @in proxy: Elm.Atspi.Proxy; + } + } + on_connected { + } + on_disconnected { + } + } + events { + embedded; + unembedded; + id,changed; + } +} diff --git a/src/lib/elementary/elm_interfaces.h b/src/lib/elementary/elm_interfaces.h index 58ce5c0bae..c0c5a8bfdb 100644 --- a/src/lib/elementary/elm_interfaces.h +++ b/src/lib/elementary/elm_interfaces.h @@ -11,6 +11,7 @@ #include "elm_interface_atspi_text_editable.eo.h" #include "elm_interface_atspi_image.eo.h" #include "elm_interface_atspi_selection.eo.h" +#include "elm_interface_atspi_socket.eo.h" #include "elm_interface_atspi_value.eo.h" #endif #endif @@ -21,6 +22,7 @@ #include "elm_interface_atspi_text_editable.eo.legacy.h" #include "elm_interface_atspi_image.eo.legacy.h" #include "elm_interface_atspi_selection.eo.legacy.h" +#include "elm_interface_atspi_socket.eo.legacy.h" #include "elm_interface_atspi_value.eo.legacy.h" #endif #endif |