1/*
2 * Copyright (C) 2012 Igalia S.L.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20#include "config.h"
21#include "WebKitWebViewBaseAccessible.h"
22
23#include <gtk/gtk.h>
24#include <wtf/glib/WTFGType.h>
25
26struct _WebKitWebViewBaseAccessiblePrivate {
27 GtkWidget* widget;
28};
29
30WEBKIT_DEFINE_TYPE(WebKitWebViewBaseAccessible, webkit_web_view_base_accessible, ATK_TYPE_SOCKET)
31
32static void webkitWebViewBaseAccessibleWidgetDestroyed(GtkWidget*, WebKitWebViewBaseAccessible* accessible)
33{
34 accessible->priv->widget = 0;
35 atk_object_notify_state_change(ATK_OBJECT(accessible), ATK_STATE_DEFUNCT, TRUE);
36}
37
38static void webkitWebViewBaseAccessibleInitialize(AtkObject* atkObject, gpointer data)
39{
40 if (ATK_OBJECT_CLASS(webkit_web_view_base_accessible_parent_class)->initialize)
41 ATK_OBJECT_CLASS(webkit_web_view_base_accessible_parent_class)->initialize(atkObject, data);
42
43 if (data && GTK_IS_WIDGET(data)) {
44 WebKitWebViewBaseAccessible* accessible = WEBKIT_WEB_VIEW_BASE_ACCESSIBLE(atkObject);
45 accessible->priv->widget = GTK_WIDGET(data);
46
47 g_signal_connect_after(accessible->priv->widget, "destroy",
48 G_CALLBACK(webkitWebViewBaseAccessibleWidgetDestroyed), atkObject);
49 }
50
51 atk_object_set_role(atkObject, ATK_ROLE_FILLER);
52}
53
54static AtkStateSet* webkitWebViewBaseAccessibleRefStateSet(AtkObject* atkObject)
55{
56 WebKitWebViewBaseAccessible* accessible = WEBKIT_WEB_VIEW_BASE_ACCESSIBLE(atkObject);
57
58 AtkStateSet* stateSet;
59 if (accessible->priv->widget) {
60 // Use the implementation of AtkSocket if the widget is still alive.
61 stateSet = ATK_OBJECT_CLASS(webkit_web_view_base_accessible_parent_class)->ref_state_set(atkObject);
62 if (!atk_socket_is_occupied(ATK_SOCKET(atkObject)))
63 atk_state_set_add_state(stateSet, ATK_STATE_TRANSIENT);
64 } else {
65 // If the widget is no longer alive, save some remote calls
66 // (because of AtkSocket's implementation of ref_state_set())
67 // and just return that this AtkObject is defunct.
68 stateSet = atk_state_set_new();
69 atk_state_set_add_state(stateSet, ATK_STATE_DEFUNCT);
70 }
71
72 return stateSet;
73}
74
75static gint webkitWebViewBaseAccessibleGetIndexInParent(AtkObject* atkObject)
76{
77 AtkObject* atkParent = atk_object_get_parent(atkObject);
78 if (!atkParent)
79 return -1;
80
81 guint count = atk_object_get_n_accessible_children(atkParent);
82 for (guint i = 0; i < count; ++i) {
83 AtkObject* child = atk_object_ref_accessible_child(atkParent, i);
84 bool childIsObject = child == atkObject;
85 g_object_unref(child);
86 if (childIsObject)
87 return i;
88 }
89
90 return -1;
91}
92
93static void webkit_web_view_base_accessible_class_init(WebKitWebViewBaseAccessibleClass* klass)
94{
95 // No need to implement get_n_children() and ref_child() here
96 // since this is a subclass of AtkSocket and all the logic related
97 // to those functions will be implemented by the ATK bridge.
98 AtkObjectClass* atkObjectClass = ATK_OBJECT_CLASS(klass);
99 atkObjectClass->initialize = webkitWebViewBaseAccessibleInitialize;
100 atkObjectClass->ref_state_set = webkitWebViewBaseAccessibleRefStateSet;
101 atkObjectClass->get_index_in_parent = webkitWebViewBaseAccessibleGetIndexInParent;
102}
103
104WebKitWebViewBaseAccessible* webkitWebViewBaseAccessibleNew(GtkWidget* widget)
105{
106 AtkObject* object = ATK_OBJECT(g_object_new(WEBKIT_TYPE_WEB_VIEW_BASE_ACCESSIBLE, NULL));
107 atk_object_initialize(object, widget);
108 return WEBKIT_WEB_VIEW_BASE_ACCESSIBLE(object);
109}
110