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