accessible/src/atk/ApplicationAccessibleWrap.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:b7143e6b3add
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "ApplicationAccessibleWrap.h"
8
9 #include "nsCOMPtr.h"
10 #include "nsMai.h"
11 #include "nsAutoPtr.h"
12 #include "nsAccessibilityService.h"
13
14 #include <gtk/gtk.h>
15 #include <atk/atk.h>
16
17 using namespace mozilla;
18 using namespace mozilla::a11y;
19
20
21 // ApplicationAccessibleWrap
22
23 ApplicationAccessibleWrap::ApplicationAccessibleWrap():
24 ApplicationAccessible()
25 {
26 }
27
28 ApplicationAccessibleWrap::~ApplicationAccessibleWrap()
29 {
30 AccessibleWrap::ShutdownAtkObject();
31 }
32
33 gboolean
34 toplevel_event_watcher(GSignalInvocationHint* ihint,
35 guint n_param_values,
36 const GValue* param_values,
37 gpointer data)
38 {
39 static GQuark sQuark_gecko_acc_obj = 0;
40
41 if (!sQuark_gecko_acc_obj)
42 sQuark_gecko_acc_obj = g_quark_from_static_string("GeckoAccObj");
43
44 if (nsAccessibilityService::IsShutdown())
45 return TRUE;
46
47 GObject* object = reinterpret_cast<GObject*>(g_value_get_object(param_values));
48 if (!GTK_IS_WINDOW(object))
49 return TRUE;
50
51 AtkObject* child = gtk_widget_get_accessible(GTK_WIDGET(object));
52
53 // GTK native dialog
54 if (!IS_MAI_OBJECT(child) &&
55 (atk_object_get_role(child) == ATK_ROLE_DIALOG)) {
56
57 if (data == reinterpret_cast<gpointer>(nsIAccessibleEvent::EVENT_SHOW)) {
58
59 // Attach the dialog accessible to app accessible tree
60 Accessible* windowAcc = GetAccService()->AddNativeRootAccessible(child);
61 g_object_set_qdata(G_OBJECT(child), sQuark_gecko_acc_obj,
62 reinterpret_cast<gpointer>(windowAcc));
63
64 } else {
65
66 // Deattach the dialog accessible
67 Accessible* windowAcc =
68 reinterpret_cast<Accessible*>
69 (g_object_get_qdata(G_OBJECT(child), sQuark_gecko_acc_obj));
70 if (windowAcc) {
71 GetAccService()->RemoveNativeRootAccessible(windowAcc);
72 g_object_set_qdata(G_OBJECT(child), sQuark_gecko_acc_obj, nullptr);
73 }
74
75 }
76 }
77
78 return TRUE;
79 }
80
81 ENameValueFlag
82 ApplicationAccessibleWrap::Name(nsString& aName)
83 {
84 // ATK doesn't provide a way to obtain an application name (for example,
85 // Firefox or Thunderbird) like IA2 does. Thus let's return an application
86 // name as accessible name that was used to get a branding name (for example,
87 // Minefield aka nightly Firefox or Daily aka nightly Thunderbird).
88 GetAppName(aName);
89 return eNameOK;
90 }
91
92 NS_IMETHODIMP
93 ApplicationAccessibleWrap::GetNativeInterface(void** aOutAccessible)
94 {
95 *aOutAccessible = nullptr;
96
97 if (!mAtkObject) {
98 mAtkObject =
99 reinterpret_cast<AtkObject *>
100 (g_object_new(MAI_TYPE_ATK_OBJECT, nullptr));
101 NS_ENSURE_TRUE(mAtkObject, NS_ERROR_OUT_OF_MEMORY);
102
103 atk_object_initialize(mAtkObject, this);
104 mAtkObject->role = ATK_ROLE_INVALID;
105 mAtkObject->layer = ATK_LAYER_INVALID;
106 }
107
108 *aOutAccessible = mAtkObject;
109 return NS_OK;
110 }
111
112 struct AtkRootAccessibleAddedEvent {
113 AtkObject *app_accessible;
114 AtkObject *root_accessible;
115 uint32_t index;
116 };
117
118 gboolean fireRootAccessibleAddedCB(gpointer data)
119 {
120 AtkRootAccessibleAddedEvent* eventData = (AtkRootAccessibleAddedEvent*)data;
121 g_signal_emit_by_name(eventData->app_accessible, "children_changed::add",
122 eventData->index, eventData->root_accessible, nullptr);
123 g_object_unref(eventData->app_accessible);
124 g_object_unref(eventData->root_accessible);
125 free(data);
126
127 return FALSE;
128 }
129
130 bool
131 ApplicationAccessibleWrap::InsertChildAt(uint32_t aIdx, Accessible* aChild)
132 {
133 if (!ApplicationAccessible::InsertChildAt(aIdx, aChild))
134 return false;
135
136 AtkObject* atkAccessible = AccessibleWrap::GetAtkObject(aChild);
137 atk_object_set_parent(atkAccessible, mAtkObject);
138
139 uint32_t count = mChildren.Length();
140
141 // Emit children_changed::add in a timeout
142 // to make sure aRootAccWrap is fully initialized.
143 AtkRootAccessibleAddedEvent* eventData = (AtkRootAccessibleAddedEvent*)
144 malloc(sizeof(AtkRootAccessibleAddedEvent));
145 if (eventData) {
146 eventData->app_accessible = mAtkObject;
147 eventData->root_accessible = atkAccessible;
148 eventData->index = count -1;
149 g_object_ref(mAtkObject);
150 g_object_ref(atkAccessible);
151 g_timeout_add(0, fireRootAccessibleAddedCB, eventData);
152 }
153
154 return true;
155 }
156
157 bool
158 ApplicationAccessibleWrap::RemoveChild(Accessible* aChild)
159 {
160 int32_t index = aChild->IndexInParent();
161
162 AtkObject* atkAccessible = AccessibleWrap::GetAtkObject(aChild);
163 atk_object_set_parent(atkAccessible, nullptr);
164 g_signal_emit_by_name(mAtkObject, "children_changed::remove", index,
165 atkAccessible, nullptr);
166
167 return ApplicationAccessible::RemoveChild(aChild);
168 }
169

mercurial