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 "WebKitWebViewAccessible.h"
22
23#if HAVE(ACCESSIBILITY)
24
25#include <wtf/glib/WTFGType.h>
26
27struct _WebKitWebViewAccessiblePrivate {
28 gpointer webView;
29};
30
31WEBKIT_DEFINE_TYPE(WebKitWebViewAccessible, webkit_web_view_accessible, ATK_TYPE_SOCKET)
32
33static void webkitWebViewAccessibleInitialize(AtkObject* atkObject, gpointer data)
34{
35 if (ATK_OBJECT_CLASS(webkit_web_view_accessible_parent_class)->initialize)
36 ATK_OBJECT_CLASS(webkit_web_view_accessible_parent_class)->initialize(atkObject, data);
37
38 webkitWebViewAccessibleSetWebView(WEBKIT_WEB_VIEW_ACCESSIBLE(atkObject), data);
39 atk_object_set_role(atkObject, ATK_ROLE_FILLER);
40}
41
42static AtkStateSet* webkitWebViewAccessibleRefStateSet(AtkObject* atkObject)
43{
44 WebKitWebViewAccessible* accessible = WEBKIT_WEB_VIEW_ACCESSIBLE(atkObject);
45
46 AtkStateSet* stateSet;
47 if (accessible->priv->webView) {
48 // Use the implementation of AtkSocket if the web view is still alive.
49 stateSet = ATK_OBJECT_CLASS(webkit_web_view_accessible_parent_class)->ref_state_set(atkObject);
50 if (!atk_socket_is_occupied(ATK_SOCKET(atkObject)))
51 atk_state_set_add_state(stateSet, ATK_STATE_TRANSIENT);
52 } else {
53 // If the web view is no longer alive, save some remote calls
54 // (because of AtkSocket's implementation of ref_state_set())
55 // and just return that this AtkObject is defunct.
56 stateSet = atk_state_set_new();
57 atk_state_set_add_state(stateSet, ATK_STATE_DEFUNCT);
58 }
59
60 return stateSet;
61}
62
63static gint webkitWebViewAccessibleGetIndexInParent(AtkObject* atkObject)
64{
65 AtkObject* atkParent = atk_object_get_parent(atkObject);
66 if (!atkParent)
67 return -1;
68
69 guint count = atk_object_get_n_accessible_children(atkParent);
70 for (guint i = 0; i < count; ++i) {
71 AtkObject* child = atk_object_ref_accessible_child(atkParent, i);
72 bool childIsObject = child == atkObject;
73 g_object_unref(child);
74 if (childIsObject)
75 return i;
76 }
77
78 return -1;
79}
80
81static void webkit_web_view_accessible_class_init(WebKitWebViewAccessibleClass* klass)
82{
83 // No need to implement get_n_children() and ref_child() here
84 // since this is a subclass of AtkSocket and all the logic related
85 // to those functions will be implemented by the ATK bridge.
86 AtkObjectClass* atkObjectClass = ATK_OBJECT_CLASS(klass);
87 atkObjectClass->initialize = webkitWebViewAccessibleInitialize;
88 atkObjectClass->ref_state_set = webkitWebViewAccessibleRefStateSet;
89 atkObjectClass->get_index_in_parent = webkitWebViewAccessibleGetIndexInParent;
90}
91
92WebKitWebViewAccessible* webkitWebViewAccessibleNew(gpointer webView)
93{
94 AtkObject* object = ATK_OBJECT(g_object_new(WEBKIT_TYPE_WEB_VIEW_ACCESSIBLE, nullptr));
95 atk_object_initialize(object, webView);
96 return WEBKIT_WEB_VIEW_ACCESSIBLE(object);
97}
98
99void webkitWebViewAccessibleSetWebView(WebKitWebViewAccessible* accessible, gpointer webView)
100{
101 g_return_if_fail(WEBKIT_IS_WEB_VIEW_ACCESSIBLE(accessible));
102
103 if (accessible->priv->webView == webView)
104 return;
105
106 if (accessible->priv->webView && !webView)
107 atk_object_notify_state_change(ATK_OBJECT(accessible), ATK_STATE_DEFUNCT, TRUE);
108
109 bool didHaveWebView = accessible->priv->webView;
110 accessible->priv->webView = webView;
111
112 if (!didHaveWebView && webView)
113 atk_object_notify_state_change(ATK_OBJECT(accessible), ATK_STATE_DEFUNCT, FALSE);
114}
115
116#endif // HAVE(ACCESSIBILITY)
117