Line data Source code
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 "InterfaceInitFuncs.h"
8 :
9 : #include "Accessible-inl.h"
10 : #include "AccessibleWrap.h"
11 : #include "nsAccUtils.h"
12 : #include "TableAccessible.h"
13 : #include "TableCellAccessible.h"
14 : #include "nsMai.h"
15 : #include "ProxyAccessible.h"
16 : #include "nsArrayUtils.h"
17 :
18 : #include "mozilla/Likely.h"
19 :
20 : using namespace mozilla::a11y;
21 :
22 : extern "C" {
23 : static AtkObject*
24 0 : refAtCB(AtkTable* aTable, gint aRowIdx, gint aColIdx)
25 : {
26 0 : if (aRowIdx < 0 || aColIdx < 0) {
27 0 : return nullptr;
28 : }
29 :
30 0 : AtkObject* cellAtkObj = nullptr;
31 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
32 0 : if (accWrap) {
33 0 : Accessible* cell = accWrap->AsTable()->CellAt(aRowIdx, aColIdx);
34 0 : if (!cell) {
35 0 : return nullptr;
36 : }
37 :
38 0 : cellAtkObj = AccessibleWrap::GetAtkObject(cell);
39 0 : } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
40 0 : ProxyAccessible* cell = proxy->TableCellAt(aRowIdx, aColIdx);
41 0 : if (!cell) {
42 0 : return nullptr;
43 : }
44 :
45 0 : cellAtkObj = GetWrapperFor(cell);
46 : }
47 :
48 0 : if (cellAtkObj) {
49 0 : g_object_ref(cellAtkObj);
50 : }
51 :
52 0 : return cellAtkObj;
53 : }
54 :
55 : static gint
56 0 : getIndexAtCB(AtkTable* aTable, gint aRowIdx, gint aColIdx)
57 : {
58 0 : if (aRowIdx < 0 || aColIdx < 0) {
59 0 : return -1;
60 : }
61 :
62 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
63 0 : if (accWrap) {
64 0 : return static_cast<gint>(accWrap->AsTable()->CellIndexAt(aRowIdx, aColIdx));
65 : }
66 :
67 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
68 0 : return static_cast<gint>(proxy->TableCellIndexAt(aRowIdx, aColIdx));
69 : }
70 :
71 0 : return -1;
72 : }
73 :
74 : static gint
75 0 : getColumnAtIndexCB(AtkTable *aTable, gint aIdx)
76 : {
77 0 : if (aIdx < 0) {
78 0 : return -1;
79 : }
80 :
81 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
82 0 : if (accWrap) {
83 0 : return static_cast<gint>(accWrap->AsTable()->ColIndexAt(aIdx));
84 : }
85 :
86 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
87 0 : return static_cast<gint>(proxy->TableColumnIndexAt(aIdx));
88 : }
89 :
90 0 : return -1;
91 : }
92 :
93 : static gint
94 0 : getRowAtIndexCB(AtkTable *aTable, gint aIdx)
95 : {
96 0 : if (aIdx < 0) {
97 0 : return -1;
98 : }
99 :
100 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
101 0 : if (accWrap) {
102 0 : return static_cast<gint>(accWrap->AsTable()->RowIndexAt(aIdx));
103 : }
104 :
105 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
106 0 : return static_cast<gint>(proxy->TableRowIndexAt(aIdx));
107 : }
108 :
109 0 : return -1;
110 : }
111 :
112 : static gint
113 0 : getColumnCountCB(AtkTable *aTable)
114 : {
115 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
116 0 : if (accWrap) {
117 0 : return static_cast<gint>(accWrap->AsTable()->ColCount());
118 : }
119 :
120 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
121 0 : return static_cast<gint>(proxy->TableColumnCount());
122 : }
123 :
124 0 : return -1;
125 : }
126 :
127 : static gint
128 0 : getRowCountCB(AtkTable *aTable)
129 : {
130 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
131 0 : if (accWrap) {
132 0 : return static_cast<gint>(accWrap->AsTable()->RowCount());
133 : }
134 :
135 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
136 0 : return static_cast<gint>(proxy->TableRowCount());
137 : }
138 :
139 0 : return -1;
140 : }
141 :
142 : static gint
143 0 : getColumnExtentAtCB(AtkTable *aTable, gint aRowIdx, gint aColIdx)
144 : {
145 0 : if (aRowIdx < 0 || aColIdx < 0) {
146 0 : return -1;
147 : }
148 :
149 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
150 0 : if (accWrap) {
151 0 : return static_cast<gint>(accWrap->AsTable()->ColExtentAt(aRowIdx, aColIdx));
152 : }
153 :
154 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
155 0 : return static_cast<gint>(proxy->TableColumnExtentAt(aRowIdx, aColIdx));
156 : }
157 :
158 0 : return -1;
159 : }
160 :
161 : static gint
162 0 : getRowExtentAtCB(AtkTable *aTable, gint aRowIdx, gint aColIdx)
163 : {
164 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
165 0 : if (accWrap) {
166 0 : return static_cast<gint>(accWrap->AsTable()->RowExtentAt(aRowIdx, aColIdx));
167 : }
168 :
169 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
170 0 : return static_cast<gint>(proxy->TableRowExtentAt(aRowIdx, aColIdx));
171 : }
172 :
173 0 : return -1;
174 : }
175 :
176 : static AtkObject*
177 0 : getCaptionCB(AtkTable* aTable)
178 : {
179 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
180 0 : if (accWrap) {
181 0 : Accessible* caption = accWrap->AsTable()->Caption();
182 0 : return caption ? AccessibleWrap::GetAtkObject(caption) : nullptr;
183 : }
184 :
185 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
186 0 : ProxyAccessible* caption = proxy->TableCaption();
187 0 : return caption ? GetWrapperFor(caption) : nullptr;
188 : }
189 :
190 0 : return nullptr;
191 : }
192 :
193 : static const gchar*
194 0 : getColumnDescriptionCB(AtkTable *aTable, gint aColumn)
195 : {
196 0 : nsAutoString autoStr;
197 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
198 0 : if (accWrap) {
199 0 : accWrap->AsTable()->ColDescription(aColumn, autoStr);
200 0 : } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
201 0 : proxy->TableColumnDescription(aColumn, autoStr);
202 : } else {
203 0 : return nullptr;
204 : }
205 :
206 0 : return AccessibleWrap::ReturnString(autoStr);
207 : }
208 :
209 : static AtkObject*
210 0 : getColumnHeaderCB(AtkTable *aTable, gint aColIdx)
211 : {
212 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
213 0 : if (accWrap) {
214 : Accessible* header =
215 0 : AccessibleWrap::GetColumnHeader(accWrap->AsTable(), aColIdx);
216 0 : return header ? AccessibleWrap::GetAtkObject(header) : nullptr;
217 : }
218 :
219 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
220 0 : ProxyAccessible* header = proxy->AtkTableColumnHeader(aColIdx);
221 0 : return header ? GetWrapperFor(header) : nullptr;
222 : }
223 :
224 0 : return nullptr;
225 : }
226 :
227 : static const gchar*
228 0 : getRowDescriptionCB(AtkTable *aTable, gint aRow)
229 : {
230 0 : nsAutoString autoStr;
231 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
232 0 : if (accWrap) {
233 0 : accWrap->AsTable()->RowDescription(aRow, autoStr);
234 0 : } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
235 0 : proxy->TableRowDescription(aRow, autoStr);
236 : } else {
237 0 : return nullptr;
238 : }
239 :
240 0 : return AccessibleWrap::ReturnString(autoStr);
241 : }
242 :
243 : static AtkObject*
244 0 : getRowHeaderCB(AtkTable *aTable, gint aRowIdx)
245 : {
246 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
247 0 : if (accWrap) {
248 : Accessible* header =
249 0 : AccessibleWrap::GetRowHeader(accWrap->AsTable(), aRowIdx);
250 0 : return header ? AccessibleWrap::GetAtkObject(header) : nullptr;
251 : }
252 :
253 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
254 0 : ProxyAccessible* header = proxy->AtkTableRowHeader(aRowIdx);
255 0 : return header ? GetWrapperFor(header) : nullptr;
256 : }
257 :
258 0 : return nullptr;
259 : }
260 :
261 : static AtkObject*
262 0 : getSummaryCB(AtkTable *aTable)
263 : {
264 : // Neither html:table nor xul:tree nor ARIA grid/tree have an ability to
265 : // link an accessible object to specify a summary. There is closes method
266 : // in TableAccessible::summary to get a summary as a string which is not
267 : // mapped directly to ATK.
268 0 : return nullptr;
269 : }
270 :
271 : static gint
272 0 : getSelectedColumnsCB(AtkTable *aTable, gint** aSelected)
273 : {
274 0 : *aSelected = nullptr;
275 :
276 0 : AutoTArray<uint32_t, 10> cols;
277 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
278 0 : if (accWrap) {
279 0 : accWrap->AsTable()->SelectedColIndices(&cols);
280 0 : } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
281 0 : proxy->TableSelectedColumnIndices(&cols);
282 : } else {
283 0 : return 0;
284 : }
285 :
286 0 : if (cols.IsEmpty())
287 0 : return 0;
288 :
289 0 : gint* atkColumns = g_new(gint, cols.Length());
290 0 : if (!atkColumns) {
291 0 : NS_WARNING("OUT OF MEMORY");
292 0 : return 0;
293 : }
294 :
295 0 : memcpy(atkColumns, cols.Elements(), cols.Length() * sizeof(uint32_t));
296 0 : *aSelected = atkColumns;
297 0 : return cols.Length();
298 : }
299 :
300 : static gint
301 0 : getSelectedRowsCB(AtkTable *aTable, gint **aSelected)
302 : {
303 0 : AutoTArray<uint32_t, 10> rows;
304 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
305 0 : if (accWrap) {
306 0 : accWrap->AsTable()->SelectedRowIndices(&rows);
307 0 : } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
308 0 : proxy->TableSelectedRowIndices(&rows);
309 : } else {
310 0 : return 0;
311 : }
312 :
313 0 : gint* atkRows = g_new(gint, rows.Length());
314 0 : if (!atkRows) {
315 0 : NS_WARNING("OUT OF MEMORY");
316 0 : return 0;
317 : }
318 :
319 0 : memcpy(atkRows, rows.Elements(), rows.Length() * sizeof(uint32_t));
320 0 : *aSelected = atkRows;
321 0 : return rows.Length();
322 : }
323 :
324 : static gboolean
325 0 : isColumnSelectedCB(AtkTable *aTable, gint aColIdx)
326 : {
327 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
328 0 : if (accWrap) {
329 0 : return static_cast<gboolean>(accWrap->AsTable()->IsColSelected(aColIdx));
330 : }
331 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
332 0 : return static_cast<gboolean>(proxy->TableColumnSelected(aColIdx));
333 : }
334 :
335 0 : return FALSE;
336 : }
337 :
338 : static gboolean
339 0 : isRowSelectedCB(AtkTable *aTable, gint aRowIdx)
340 : {
341 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
342 0 : if (accWrap) {
343 0 : return static_cast<gboolean>(accWrap->AsTable()->IsRowSelected(aRowIdx));
344 : }
345 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
346 0 : return static_cast<gboolean>(proxy->TableRowSelected(aRowIdx));
347 : }
348 :
349 0 : return FALSE;
350 : }
351 :
352 : static gboolean
353 0 : isCellSelectedCB(AtkTable *aTable, gint aRowIdx, gint aColIdx)
354 : {
355 0 : AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
356 0 : if (accWrap) {
357 0 : return static_cast<gboolean>(accWrap->AsTable()->
358 0 : IsCellSelected(aRowIdx, aColIdx));
359 : }
360 0 : if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
361 0 : return static_cast<gboolean>(proxy->TableCellSelected(aRowIdx, aColIdx));
362 : }
363 :
364 0 : return FALSE;
365 : }
366 : }
367 :
368 : void
369 0 : tableInterfaceInitCB(AtkTableIface* aIface)
370 : {
371 0 : NS_ASSERTION(aIface, "no interface!");
372 0 : if (MOZ_UNLIKELY(!aIface))
373 0 : return;
374 :
375 0 : aIface->ref_at = refAtCB;
376 0 : aIface->get_index_at = getIndexAtCB;
377 0 : aIface->get_column_at_index = getColumnAtIndexCB;
378 0 : aIface->get_row_at_index = getRowAtIndexCB;
379 0 : aIface->get_n_columns = getColumnCountCB;
380 0 : aIface->get_n_rows = getRowCountCB;
381 0 : aIface->get_column_extent_at = getColumnExtentAtCB;
382 0 : aIface->get_row_extent_at = getRowExtentAtCB;
383 0 : aIface->get_caption = getCaptionCB;
384 0 : aIface->get_column_description = getColumnDescriptionCB;
385 0 : aIface->get_column_header = getColumnHeaderCB;
386 0 : aIface->get_row_description = getRowDescriptionCB;
387 0 : aIface->get_row_header = getRowHeaderCB;
388 0 : aIface->get_summary = getSummaryCB;
389 0 : aIface->get_selected_columns = getSelectedColumnsCB;
390 0 : aIface->get_selected_rows = getSelectedRowsCB;
391 0 : aIface->is_column_selected = isColumnSelectedCB;
392 0 : aIface->is_row_selected = isRowSelectedCB;
393 0 : aIface->is_selected = isCellSelectedCB;
394 : }
|