Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
* License, v. 2.0. If a copy of the MPL was not distributed with this
4
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
#include "DocAccessible.h"
7
#include "nsObjCExceptions.h"
8
9
#include "Accessible-inl.h"
10
#include "nsAccUtils.h"
11
#include "Role.h"
12
#include "gfxPlatform.h"
13
14
#import "mozAccessible.h"
15
#import "mozActionElements.h"
16
#import "mozHTMLAccessible.h"
17
#import "mozTableAccessible.h"
18
#import "mozTextAccessible.h"
19
20
using namespace mozilla;
21
using namespace mozilla::a11y;
22
23
AccessibleWrap::AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc)
24
: Accessible(aContent, aDoc), mNativeObject(nil), mNativeInited(false) {}
25
26
AccessibleWrap::~AccessibleWrap() {}
27
28
mozAccessible* AccessibleWrap::GetNativeObject() {
29
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
30
31
if (!mNativeInited && !mNativeObject && !IsDefunct() && !AncestorIsFlat()) {
32
uintptr_t accWrap = reinterpret_cast<uintptr_t>(this);
33
mNativeObject = [[GetNativeType() alloc] initWithAccessible:accWrap];
34
}
35
36
mNativeInited = true;
37
38
return mNativeObject;
39
40
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
41
}
42
43
void AccessibleWrap::GetNativeInterface(void** aOutInterface) {
44
*aOutInterface = static_cast<void*>(GetNativeObject());
45
}
46
47
// overridden in subclasses to create the right kind of object. by default we create a generic
48
// 'mozAccessible' node.
49
Class AccessibleWrap::GetNativeType() {
50
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
51
52
if (IsXULTabpanels()) return [mozPaneAccessible class];
53
54
if (IsTable()) return [mozTableAccessible class];
55
56
if (IsTableRow()) return [mozTableRowAccessible class];
57
58
if (IsTableCell()) return [mozTableCellAccessible class];
59
60
return GetTypeFromRole(Role());
61
62
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
63
}
64
65
// this method is very important. it is fired when an accessible object "dies". after this point
66
// the object might still be around (because some 3rd party still has a ref to it), but it is
67
// in fact 'dead'.
68
void AccessibleWrap::Shutdown() {
69
// this ensure we will not try to re-create the native object.
70
mNativeInited = true;
71
72
// we really intend to access the member directly.
73
if (mNativeObject) {
74
[mNativeObject expire];
75
[mNativeObject release];
76
mNativeObject = nil;
77
}
78
79
Accessible::Shutdown();
80
}
81
82
nsresult AccessibleWrap::HandleAccEvent(AccEvent* aEvent) {
83
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
84
85
nsresult rv = Accessible::HandleAccEvent(aEvent);
86
NS_ENSURE_SUCCESS(rv, rv);
87
88
if (IPCAccessibilityActive()) {
89
return NS_OK;
90
}
91
92
uint32_t eventType = aEvent->GetEventType();
93
94
// ignore everything but focus-changed, value-changed, caret, selection
95
// and document load complete events for now.
96
if (eventType != nsIAccessibleEvent::EVENT_FOCUS &&
97
eventType != nsIAccessibleEvent::EVENT_VALUE_CHANGE &&
98
eventType != nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE &&
99
eventType != nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED &&
100
eventType != nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED &&
101
eventType != nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE)
102
return NS_OK;
103
104
Accessible* accessible = aEvent->GetAccessible();
105
NS_ENSURE_STATE(accessible);
106
107
mozAccessible* nativeAcc = nil;
108
accessible->GetNativeInterface((void**)&nativeAcc);
109
if (!nativeAcc) return NS_ERROR_FAILURE;
110
111
FireNativeEvent(nativeAcc, eventType);
112
113
return NS_OK;
114
115
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
116
}
117
118
bool AccessibleWrap::InsertChildAt(uint32_t aIdx, Accessible* aAccessible) {
119
bool inserted = Accessible::InsertChildAt(aIdx, aAccessible);
120
if (inserted && mNativeObject) [mNativeObject appendChild:aAccessible];
121
122
return inserted;
123
}
124
125
bool AccessibleWrap::RemoveChild(Accessible* aAccessible) {
126
bool removed = Accessible::RemoveChild(aAccessible);
127
128
if (removed && mNativeObject) [mNativeObject invalidateChildren];
129
130
return removed;
131
}
132
133
////////////////////////////////////////////////////////////////////////////////
134
// AccessibleWrap protected
135
136
bool AccessibleWrap::AncestorIsFlat() {
137
// We don't create a native object if we're child of a "flat" accessible;
138
// for example, on OS X buttons shouldn't have any children, because that
139
// makes the OS confused.
140
//
141
// To maintain a scripting environment where the XPCOM accessible hierarchy
142
// look the same on all platforms, we still let the C++ objects be created
143
// though.
144
145
Accessible* parent = Parent();
146
while (parent) {
147
if (nsAccUtils::MustPrune(parent)) return true;
148
149
parent = parent->Parent();
150
}
151
// no parent was flat
152
return false;
153
}
154
155
void a11y::FireNativeEvent(mozAccessible* aNativeAcc, uint32_t aEventType) {
156
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
157
158
// Under headless mode we don't have access to a native window, so we skip
159
// dispatching native events.
160
if (gfxPlatform::IsHeadless()) {
161
return;
162
}
163
164
switch (aEventType) {
165
case nsIAccessibleEvent::EVENT_FOCUS:
166
[aNativeAcc didReceiveFocus];
167
break;
168
case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
169
case nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE:
170
[aNativeAcc valueDidChange];
171
break;
172
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED:
173
case nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED:
174
[aNativeAcc selectedTextDidChange];
175
break;
176
case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE:
177
[aNativeAcc documentLoadComplete];
178
break;
179
}
180
181
NS_OBJC_END_TRY_ABORT_BLOCK;
182
}
183
184
Class a11y::GetTypeFromRole(roles::Role aRole) {
185
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
186
187
switch (aRole) {
188
case roles::COMBOBOX:
189
case roles::PUSHBUTTON:
190
case roles::SPLITBUTTON:
191
case roles::TOGGLE_BUTTON: {
192
return [mozButtonAccessible class];
193
}
194
195
case roles::PAGETAB:
196
return [mozButtonAccessible class];
197
198
case roles::CHECKBUTTON:
199
return [mozCheckboxAccessible class];
200
201
case roles::HEADING:
202
return [mozHeadingAccessible class];
203
204
case roles::PAGETABLIST:
205
return [mozTabsAccessible class];
206
207
case roles::ENTRY:
208
case roles::STATICTEXT:
209
case roles::CAPTION:
210
case roles::ACCEL_LABEL:
211
case roles::PASSWORD_TEXT:
212
// normal textfield (static or editable)
213
return [mozTextAccessible class];
214
215
case roles::TEXT_LEAF:
216
return [mozTextLeafAccessible class];
217
218
case roles::LINK:
219
return [mozLinkAccessible class];
220
221
default:
222
return [mozAccessible class];
223
}
224
225
return nil;
226
227
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
228
}