1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtWebEngine module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
41 // Use of this source code is governed by a BSD-style license that can be
42 // found in the LICENSE.Chromium file.
43
44 #include "browser_accessibility_qt.h"
45
46 #if QT_CONFIG(accessibility)
47
48 #include "ui/accessibility/ax_enums.mojom.h"
49
50 #include "browser_accessibility_manager_qt.h"
51 #include "qtwebenginecoreglobal_p.h"
52 #include "type_conversion.h"
53
54 using namespace blink;
55 using QtWebEngineCore::toQt;
56
57 namespace content {
58
ToBrowserAccessibilityQt(const BrowserAccessibility * obj)59 const BrowserAccessibilityQt *ToBrowserAccessibilityQt(const BrowserAccessibility *obj)
60 {
61 return static_cast<const BrowserAccessibilityQt *>(obj);
62 }
63
toQAccessibleInterface(BrowserAccessibility * obj)64 QAccessibleInterface *toQAccessibleInterface(BrowserAccessibility *obj)
65 {
66 return static_cast<BrowserAccessibilityQt *>(obj);
67 }
68
BrowserAccessibilityQt()69 BrowserAccessibilityQt::BrowserAccessibilityQt()
70 {
71 QAccessible::registerAccessibleInterface(this);
72 }
73
isValid() const74 bool BrowserAccessibilityQt::isValid() const
75 {
76 auto managerQt = static_cast<BrowserAccessibilityManagerQt *>(manager_);
77 return managerQt && managerQt->isValid();
78 }
79
object() const80 QObject *BrowserAccessibilityQt::object() const
81 {
82 return 0;
83 }
84
childAt(int x,int y) const85 QAccessibleInterface *BrowserAccessibilityQt::childAt(int x, int y) const
86 {
87 for (int i = 0; i < childCount(); ++i) {
88 QAccessibleInterface *childIface = child(i);
89 Q_ASSERT(childIface);
90 if (childIface->rect().contains(x,y))
91 return childIface;
92 }
93 return 0;
94 }
95
interface_cast(QAccessible::InterfaceType type)96 void *BrowserAccessibilityQt::interface_cast(QAccessible::InterfaceType type)
97 {
98 switch (type) {
99 case QAccessible::ActionInterface:
100 if (!actionNames().isEmpty())
101 return static_cast<QAccessibleActionInterface*>(this);
102 break;
103 case QAccessible::TextInterface:
104 if (HasState(ax::mojom::State::kEditable))
105 return static_cast<QAccessibleTextInterface*>(this);
106 break;
107 case QAccessible::ValueInterface: {
108 QAccessible::Role r = role();
109 if (r == QAccessible::ProgressBar ||
110 r == QAccessible::Slider ||
111 r == QAccessible::ScrollBar ||
112 r == QAccessible::SpinBox)
113 return static_cast<QAccessibleValueInterface*>(this);
114 break;
115 }
116 case QAccessible::TableInterface: {
117 QAccessible::Role r = role();
118 if (r == QAccessible::Table ||
119 r == QAccessible::List ||
120 r == QAccessible::Tree)
121 return static_cast<QAccessibleTableInterface*>(this);
122 break;
123 }
124 case QAccessible::TableCellInterface: {
125 QAccessible::Role r = role();
126 if (r == QAccessible::Cell ||
127 r == QAccessible::ListItem ||
128 r == QAccessible::TreeItem)
129 return static_cast<QAccessibleTableCellInterface*>(this);
130 break;
131 }
132 default:
133 break;
134 }
135 return 0;
136 }
137
parent() const138 QAccessibleInterface *BrowserAccessibilityQt::parent() const
139 {
140 BrowserAccessibility *p = PlatformGetParent();
141 if (p)
142 return static_cast<BrowserAccessibilityQt*>(p);
143 return static_cast<BrowserAccessibilityManagerQt*>(manager())->rootParentAccessible();
144 }
145
child(int index) const146 QAccessibleInterface *BrowserAccessibilityQt::child(int index) const
147 {
148 return static_cast<BrowserAccessibilityQt*>(BrowserAccessibility::PlatformGetChild(index));
149 }
150
focusChild() const151 QAccessibleInterface *BrowserAccessibilityQt::focusChild() const
152 {
153 if (state().focused)
154 return const_cast<BrowserAccessibilityQt *>(this);
155
156 for (int i = 0; i < childCount(); ++i) {
157 if (QAccessibleInterface *iface = child(i)->focusChild())
158 return iface;
159 }
160
161 return nullptr;
162 }
163
childCount() const164 int BrowserAccessibilityQt::childCount() const
165 {
166 return PlatformChildCount();
167 }
168
indexOfChild(const QAccessibleInterface * iface) const169 int BrowserAccessibilityQt::indexOfChild(const QAccessibleInterface *iface) const
170 {
171
172 const BrowserAccessibilityQt *child = static_cast<const BrowserAccessibilityQt*>(iface);
173 return const_cast<BrowserAccessibilityQt *>(child)->GetIndexInParent();
174 }
175
text(QAccessible::Text t) const176 QString BrowserAccessibilityQt::text(QAccessible::Text t) const
177 {
178 switch (t) {
179 case QAccessible::Name:
180 return toQt(GetStringAttribute(ax::mojom::StringAttribute::kName));
181 case QAccessible::Description:
182 return toQt(GetStringAttribute(ax::mojom::StringAttribute::kDescription));
183 case QAccessible::Value:
184 return toQt(GetStringAttribute(ax::mojom::StringAttribute::kValue));
185 case QAccessible::Accelerator:
186 return toQt(GetStringAttribute(ax::mojom::StringAttribute::kKeyShortcuts));
187 default:
188 break;
189 }
190 return QString();
191 }
192
setText(QAccessible::Text t,const QString & text)193 void BrowserAccessibilityQt::setText(QAccessible::Text t, const QString &text)
194 {
195 }
196
rect() const197 QRect BrowserAccessibilityQt::rect() const
198 {
199 if (!manager()) // needed implicitly by GetScreenBoundsRect()
200 return QRect();
201 gfx::Rect bounds = GetUnclippedScreenBoundsRect();
202 return QRect(bounds.x(), bounds.y(), bounds.width(), bounds.height());
203 }
204
role() const205 QAccessible::Role BrowserAccessibilityQt::role() const
206 {
207 switch (GetRole()) {
208 case ax::mojom::Role::kNone:
209 case ax::mojom::Role::kUnknown:
210 return QAccessible::NoRole;
211
212 // Used by Chromium to distinguish between the root of the tree
213 // for this page, and a web area for a frame within this page.
214 case ax::mojom::Role::kWebArea:
215 case ax::mojom::Role::kWebView:
216 case ax::mojom::Role::kRootWebArea: // not sure if we need to make a diff here, but this seems common
217 return QAccessible::WebDocument;
218
219 // These roles all directly correspond to blink accessibility roles,
220 // keep these alphabetical.
221 case ax::mojom::Role::kAbbr:
222 return QAccessible::StaticText;
223 case ax::mojom::Role::kAlert:
224 case ax::mojom::Role::kAlertDialog:
225 return QAccessible::AlertMessage;
226 case ax::mojom::Role::kAnchor:
227 return QAccessible::Link;
228 case ax::mojom::Role::kApplication:
229 return QAccessible::Document; // returning Application here makes Qt return the top level app object
230 case ax::mojom::Role::kArticle:
231 return QAccessible::Section;
232 case ax::mojom::Role::kAudio:
233 return QAccessible::Sound;
234 case ax::mojom::Role::kBanner:
235 return QAccessible::Section;
236 case ax::mojom::Role::kBlockquote:
237 return QAccessible::Section;
238 case ax::mojom::Role::kButton:
239 return QAccessible::Button;
240 case ax::mojom::Role::kCanvas:
241 return QAccessible::Canvas;
242 case ax::mojom::Role::kCaption:
243 return QAccessible::Heading;
244 case ax::mojom::Role::kCaret:
245 return QAccessible::NoRole; // FIXME: https://codereview.chromium.org/2781613003
246 case ax::mojom::Role::kCell:
247 return QAccessible::Cell;
248 case ax::mojom::Role::kCheckBox:
249 return QAccessible::CheckBox;
250 case ax::mojom::Role::kClient:
251 return QAccessible::Client;
252 case ax::mojom::Role::kCode:
253 return QAccessible::StaticText;
254 case ax::mojom::Role::kColorWell:
255 return QAccessible::ColorChooser;
256 case ax::mojom::Role::kColumn:
257 return QAccessible::Column;
258 case ax::mojom::Role::kColumnHeader:
259 return QAccessible::ColumnHeader;
260 case ax::mojom::Role::kComboBoxGrouping:
261 case ax::mojom::Role::kComboBoxMenuButton:
262 case ax::mojom::Role::kTextFieldWithComboBox:
263 return QAccessible::ComboBox;
264 case ax::mojom::Role::kComplementary:
265 return QAccessible::ComplementaryContent;
266 case ax::mojom::Role::kComment:
267 return QAccessible::Section;
268 case ax::mojom::Role::kContentDeletion:
269 case ax::mojom::Role::kContentInsertion:
270 return QAccessible::Grouping;
271 case ax::mojom::Role::kContentInfo:
272 return QAccessible::Section;
273 case ax::mojom::Role::kDate:
274 case ax::mojom::Role::kDateTime:
275 return QAccessible::Clock;
276 case ax::mojom::Role::kDefinition:
277 return QAccessible::Paragraph;
278 case ax::mojom::Role::kDescriptionList:
279 return QAccessible::List;
280 case ax::mojom::Role::kDescriptionListDetail:
281 return QAccessible::Paragraph;
282 case ax::mojom::Role::kDescriptionListTerm:
283 return QAccessible::ListItem;
284 case ax::mojom::Role::kDetails:
285 return QAccessible::Grouping;
286 case ax::mojom::Role::kDesktop:
287 return QAccessible::Pane;
288 case ax::mojom::Role::kDialog:
289 return QAccessible::Dialog;
290 case ax::mojom::Role::kDirectory:
291 return QAccessible::List;
292 case ax::mojom::Role::kDisclosureTriangle:
293 return QAccessible::Button;
294 case ax::mojom::Role::kGenericContainer:
295 return QAccessible::Section;
296 case ax::mojom::Role::kDocCover:
297 return QAccessible::Graphic;
298 case ax::mojom::Role::kDocBackLink:
299 case ax::mojom::Role::kDocBiblioRef:
300 case ax::mojom::Role::kDocGlossRef:
301 case ax::mojom::Role::kDocNoteRef:
302 return QAccessible::Link;
303 case ax::mojom::Role::kDocBiblioEntry:
304 case ax::mojom::Role::kDocEndnote:
305 case ax::mojom::Role::kDocFootnote:
306 return QAccessible::ListItem;
307 case ax::mojom::Role::kDocPageBreak:
308 return QAccessible::Separator;
309 case ax::mojom::Role::kDocAbstract:
310 case ax::mojom::Role::kDocAcknowledgments:
311 case ax::mojom::Role::kDocAfterword:
312 case ax::mojom::Role::kDocAppendix:
313 case ax::mojom::Role::kDocBibliography:
314 case ax::mojom::Role::kDocChapter:
315 case ax::mojom::Role::kDocColophon:
316 case ax::mojom::Role::kDocConclusion:
317 case ax::mojom::Role::kDocCredit:
318 case ax::mojom::Role::kDocCredits:
319 case ax::mojom::Role::kDocDedication:
320 case ax::mojom::Role::kDocEndnotes:
321 case ax::mojom::Role::kDocEpigraph:
322 case ax::mojom::Role::kDocEpilogue:
323 case ax::mojom::Role::kDocErrata:
324 case ax::mojom::Role::kDocExample:
325 case ax::mojom::Role::kDocForeword:
326 case ax::mojom::Role::kDocGlossary:
327 case ax::mojom::Role::kDocIndex:
328 case ax::mojom::Role::kDocIntroduction:
329 case ax::mojom::Role::kDocNotice:
330 case ax::mojom::Role::kDocPageList:
331 case ax::mojom::Role::kDocPart:
332 case ax::mojom::Role::kDocPreface:
333 case ax::mojom::Role::kDocPrologue:
334 case ax::mojom::Role::kDocPullquote:
335 case ax::mojom::Role::kDocQna:
336 return QAccessible::Section;
337 case ax::mojom::Role::kDocSubtitle:
338 return QAccessible::Heading;
339 case ax::mojom::Role::kDocTip:
340 case ax::mojom::Role::kDocToc:
341 return QAccessible::Section;
342 case ax::mojom::Role::kDocument:
343 return QAccessible::Document;
344 case ax::mojom::Role::kEmbeddedObject:
345 return QAccessible::Grouping;
346 case ax::mojom::Role::kEmphasis:
347 return QAccessible::StaticText;
348 case ax::mojom::Role::kFeed:
349 return QAccessible::Section;
350 case ax::mojom::Role::kFigcaption:
351 return QAccessible::Heading;
352 case ax::mojom::Role::kFigure:
353 return QAccessible::Section;
354 case ax::mojom::Role::kFooter:
355 return QAccessible::Footer;
356 case ax::mojom::Role::kFooterAsNonLandmark:
357 return QAccessible::Section;
358 case ax::mojom::Role::kForm:
359 return QAccessible::Form;
360 case ax::mojom::Role::kGraphicsDocument:
361 return QAccessible::Document;
362 case ax::mojom::Role::kGraphicsObject:
363 return QAccessible::Pane;
364 case ax::mojom::Role::kGraphicsSymbol:
365 return QAccessible::Graphic;
366 case ax::mojom::Role::kGrid:
367 return QAccessible::Table;
368 case ax::mojom::Role::kGroup:
369 return QAccessible::Grouping;
370 case ax::mojom::Role::kHeader:
371 case ax::mojom::Role::kHeaderAsNonLandmark:
372 return QAccessible::Section;
373 case ax::mojom::Role::kHeading:
374 return QAccessible::Heading;
375 case ax::mojom::Role::kIframe:
376 return QAccessible::WebDocument;
377 case ax::mojom::Role::kIframePresentational:
378 return QAccessible::Grouping;
379 case ax::mojom::Role::kIgnored:
380 return QAccessible::NoRole;
381 case ax::mojom::Role::kImage:
382 return QAccessible::Graphic;
383 case ax::mojom::Role::kImageMap:
384 return QAccessible::Document;
385 case ax::mojom::Role::kInlineTextBox:
386 return QAccessible::StaticText;
387 case ax::mojom::Role::kInputTime:
388 return QAccessible::SpinBox;
389 case ax::mojom::Role::kKeyboard:
390 return QAccessible::NoRole; // FIXME
391 case ax::mojom::Role::kLabelText:
392 return QAccessible::StaticText;
393 case ax::mojom::Role::kLayoutTable:
394 case ax::mojom::Role::kLayoutTableCell:
395 case ax::mojom::Role::kLayoutTableRow:
396 return QAccessible::Section;
397 case ax::mojom::Role::kLegend:
398 return QAccessible::StaticText;
399 case ax::mojom::Role::kLineBreak:
400 return QAccessible::Separator;
401 case ax::mojom::Role::kLink:
402 return QAccessible::Link;
403 case ax::mojom::Role::kList:
404 return QAccessible::List;
405 case ax::mojom::Role::kListBox:
406 return QAccessible::ComboBox;
407 case ax::mojom::Role::kListBoxOption:
408 return QAccessible::ListItem;
409 case ax::mojom::Role::kListItem:
410 return QAccessible::ListItem;
411 case ax::mojom::Role::kListGrid:
412 return QAccessible::List;
413 case ax::mojom::Role::kListMarker:
414 return QAccessible::StaticText;
415 case ax::mojom::Role::kLog:
416 return QAccessible::Section;
417 case ax::mojom::Role::kMain:
418 return QAccessible::Grouping;
419 case ax::mojom::Role::kMark:
420 return QAccessible::StaticText;
421 case ax::mojom::Role::kMarquee:
422 return QAccessible::Section;
423 case ax::mojom::Role::kMath:
424 return QAccessible::Equation;
425 case ax::mojom::Role::kMenu:
426 return QAccessible::PopupMenu;
427 case ax::mojom::Role::kMenuBar:
428 return QAccessible::MenuBar;
429 case ax::mojom::Role::kMenuItem:
430 return QAccessible::MenuItem;
431 case ax::mojom::Role::kMenuItemCheckBox:
432 return QAccessible::CheckBox;
433 case ax::mojom::Role::kMenuItemRadio:
434 return QAccessible::RadioButton;
435 case ax::mojom::Role::kMenuButton:
436 return QAccessible::MenuItem;
437 case ax::mojom::Role::kMenuListOption:
438 return QAccessible::MenuItem;
439 case ax::mojom::Role::kMenuListPopup:
440 return QAccessible::PopupMenu;
441 case ax::mojom::Role::kMeter:
442 return QAccessible::Chart;
443 case ax::mojom::Role::kNavigation:
444 return QAccessible::Section;
445 case ax::mojom::Role::kNote:
446 return QAccessible::Note;
447 case ax::mojom::Role::kPane:
448 return QAccessible::Pane;
449 case ax::mojom::Role::kParagraph:
450 return QAccessible::Paragraph;
451 case ax::mojom::Role::kPdfActionableHighlight:
452 return QAccessible::Button;
453 case ax::mojom::Role::kPluginObject:
454 return QAccessible::Grouping;
455 case ax::mojom::Role::kPopUpButton:
456 return QAccessible::ComboBox;
457 case ax::mojom::Role::kPortal:
458 return QAccessible::Button;
459 case ax::mojom::Role::kPre:
460 return QAccessible::Section;
461 case ax::mojom::Role::kPresentational:
462 return QAccessible::NoRole; // FIXME
463 case ax::mojom::Role::kProgressIndicator:
464 return QAccessible::ProgressBar;
465 case ax::mojom::Role::kRadioButton:
466 return QAccessible::RadioButton;
467 case ax::mojom::Role::kRadioGroup:
468 return QAccessible::Grouping;
469 case ax::mojom::Role::kRegion:
470 return QAccessible::Section;
471 case ax::mojom::Role::kRow:
472 return QAccessible::Row;
473 case ax::mojom::Role::kRowGroup:
474 return QAccessible::Section;
475 case ax::mojom::Role::kRowHeader:
476 return QAccessible::RowHeader;
477 case ax::mojom::Role::kRuby:
478 return QAccessible::StaticText;
479 case ax::mojom::Role::kRubyAnnotation:
480 return QAccessible::StaticText;
481 case ax::mojom::Role::kScrollBar:
482 return QAccessible::ScrollBar;
483 case ax::mojom::Role::kScrollView:
484 return QAccessible::Pane;
485 case ax::mojom::Role::kSearch:
486 return QAccessible::Section;
487 case ax::mojom::Role::kSearchBox:
488 return QAccessible::EditableText;
489 case ax::mojom::Role::kSection:
490 return QAccessible::Section;
491 case ax::mojom::Role::kSlider:
492 case ax::mojom::Role::kSliderThumb:
493 return QAccessible::Slider;
494 case ax::mojom::Role::kSpinButton:
495 return QAccessible::SpinBox;
496 case ax::mojom::Role::kSplitter:
497 return QAccessible::Splitter;
498 case ax::mojom::Role::kStaticText:
499 return QAccessible::StaticText;
500 case ax::mojom::Role::kStatus:
501 return QAccessible::Indicator;
502 case ax::mojom::Role::kStrong:
503 return QAccessible::StaticText;
504 case ax::mojom::Role::kSuggestion:
505 return QAccessible::Section;
506 case ax::mojom::Role::kSvgRoot:
507 return QAccessible::Graphic;
508 case ax::mojom::Role::kSwitch:
509 return QAccessible::Button;
510 case ax::mojom::Role::kTable:
511 return QAccessible::Table;
512 case ax::mojom::Role::kTableHeaderContainer:
513 return QAccessible::Section;
514 case ax::mojom::Role::kTab:
515 return QAccessible::PageTab;
516 case ax::mojom::Role::kTabList:
517 return QAccessible::PageTabList;
518 case ax::mojom::Role::kTabPanel:
519 return QAccessible::Pane;
520 case ax::mojom::Role::kTerm:
521 return QAccessible::StaticText;
522 case ax::mojom::Role::kTextField:
523 return QAccessible::EditableText;
524 case ax::mojom::Role::kTime:
525 case ax::mojom::Role::kTimer:
526 return QAccessible::Clock;
527 case ax::mojom::Role::kTitleBar:
528 return QAccessible::Document;
529 case ax::mojom::Role::kToggleButton:
530 return QAccessible::Button;
531 case ax::mojom::Role::kToolbar:
532 return QAccessible::ToolBar;
533 case ax::mojom::Role::kTooltip:
534 return QAccessible::ToolTip;
535 case ax::mojom::Role::kTree:
536 return QAccessible::Tree;
537 case ax::mojom::Role::kTreeGrid:
538 return QAccessible::Tree;
539 case ax::mojom::Role::kTreeItem:
540 return QAccessible::TreeItem;
541 case ax::mojom::Role::kVideo:
542 return QAccessible::Animation;
543 case ax::mojom::Role::kWindow:
544 return QAccessible::Window;
545 }
546 return QAccessible::NoRole;
547 }
548
state() const549 QAccessible::State BrowserAccessibilityQt::state() const
550 {
551 QAccessible::State state = QAccessible::State();
552 if (HasState(ax::mojom::State::kCollapsed))
553 state.collapsed = true;
554 if (HasState(ax::mojom::State::kDefault))
555 state.defaultButton = true;
556 if (HasState(ax::mojom::State::kEditable))
557 state.editable = true;
558 if (HasState(ax::mojom::State::kExpanded))
559 state.expanded = true;
560 if (HasState(ax::mojom::State::kFocusable))
561 state.focusable = true;
562 if (HasState(ax::mojom::State::kHorizontal))
563 {} // FIXME
564 if (HasState(ax::mojom::State::kHovered))
565 state.hotTracked = true;
566 if (HasState(ax::mojom::State::kIgnored))
567 {} // FIXME
568 if (HasState(ax::mojom::State::kInvisible))
569 state.invisible = true;
570 if (HasState(ax::mojom::State::kLinked))
571 state.linked = true;
572 if (HasState(ax::mojom::State::kMultiline))
573 state.multiLine = true;
574 if (HasState(ax::mojom::State::kMultiselectable))
575 state.multiSelectable = true;
576 if (HasState(ax::mojom::State::kProtected))
577 state.passwordEdit = true;
578 if (HasState(ax::mojom::State::kRequired))
579 {} // FIXME
580 if (HasState(ax::mojom::State::kRichlyEditable))
581 {} // FIXME
582 if (HasState(ax::mojom::State::kVertical))
583 {} // FIXME
584 if (HasState(ax::mojom::State::kVisited))
585 state.traversed = true;
586
587 if (IsOffscreen())
588 state.offscreen = true;
589 if (manager()->GetFocus() == this)
590 state.focused = true;
591 if (GetBoolAttribute(ax::mojom::BoolAttribute::kBusy))
592 state.busy = true;
593 if (GetBoolAttribute(ax::mojom::BoolAttribute::kModal))
594 state.modal = true;
595 if (HasBoolAttribute(ax::mojom::BoolAttribute::kSelected)) {
596 state.selectable = true;
597 state.selected = GetBoolAttribute(ax::mojom::BoolAttribute::kSelected);
598 }
599 if (HasIntAttribute(ax::mojom::IntAttribute::kCheckedState)) {
600 state.checkable = true;
601 const ax::mojom::CheckedState checkedState =
602 static_cast<ax::mojom::CheckedState>(GetIntAttribute(ax::mojom::IntAttribute::kCheckedState));
603 switch (checkedState) {
604 case ax::mojom::CheckedState::kTrue:
605 if (GetRole() == ax::mojom::Role::kToggleButton)
606 state.pressed = true;
607 else
608 state.checked = true;
609 break;
610 case ax::mojom::CheckedState::kMixed:
611 state.checkStateMixed = true;
612 break;
613 case ax::mojom::CheckedState::kFalse:
614 case ax::mojom::CheckedState::kNone:
615 break;
616 }
617 }
618 if (HasIntAttribute(ax::mojom::IntAttribute::kRestriction)) {
619 const ax::mojom::Restriction restriction = static_cast<ax::mojom::Restriction>(GetIntAttribute(ax::mojom::IntAttribute::kRestriction));
620 switch (restriction) {
621 case ax::mojom::Restriction::kReadOnly:
622 state.readOnly = true;
623 break;
624 case ax::mojom::Restriction::kDisabled:
625 state.disabled = true;
626 break;
627 case ax::mojom::Restriction::kNone:
628 break;
629 }
630 }
631 if (HasIntAttribute(ax::mojom::IntAttribute::kHasPopup)) {
632 const ax::mojom::HasPopup hasPopup = static_cast<ax::mojom::HasPopup>(GetIntAttribute(ax::mojom::IntAttribute::kHasPopup));
633 switch (hasPopup) {
634 case ax::mojom::HasPopup::kFalse:
635 break;
636 case ax::mojom::HasPopup::kTrue:
637 case ax::mojom::HasPopup::kMenu:
638 case ax::mojom::HasPopup::kListbox:
639 case ax::mojom::HasPopup::kTree:
640 case ax::mojom::HasPopup::kGrid:
641 case ax::mojom::HasPopup::kDialog:
642 state.hasPopup = true;
643 break;
644 }
645 }
646 return state;
647 }
648
649 // Qt does not reference count accessibles
NativeAddReference()650 void BrowserAccessibilityQt::NativeAddReference()
651 {
652 }
653
654 // there is no reference counting, but BrowserAccessibility::Destroy
655 // calls this (and that is the only place in the chromium sources,
656 // so we can safely use it to dispose of ourselves here
657 // (the default implementation of this function just contains a "delete this")
NativeReleaseReference()658 void BrowserAccessibilityQt::NativeReleaseReference()
659 {
660 // delete this
661 QAccessible::Id interfaceId = QAccessible::uniqueId(this);
662 QAccessible::deleteAccessibleInterface(interfaceId);
663 }
664
actionNames() const665 QStringList BrowserAccessibilityQt::actionNames() const
666 {
667 QStringList actions;
668 if (HasState(ax::mojom::State::kFocusable))
669 actions << QAccessibleActionInterface::setFocusAction();
670 return actions;
671 }
672
doAction(const QString & actionName)673 void BrowserAccessibilityQt::doAction(const QString &actionName)
674 {
675 if (actionName == QAccessibleActionInterface::setFocusAction())
676 manager()->SetFocus(*this);
677 }
678
keyBindingsForAction(const QString & actionName) const679 QStringList BrowserAccessibilityQt::keyBindingsForAction(const QString &actionName) const
680 {
681 QT_NOT_YET_IMPLEMENTED
682 return QStringList();
683 }
684
addSelection(int startOffset,int endOffset)685 void BrowserAccessibilityQt::addSelection(int startOffset, int endOffset)
686 {
687 manager()->SetSelection(AXPlatformRange(CreatePositionAt(startOffset), CreatePositionAt(endOffset)));
688 }
689
attributes(int offset,int * startOffset,int * endOffset) const690 QString BrowserAccessibilityQt::attributes(int offset, int *startOffset, int *endOffset) const
691 {
692 *startOffset = offset;
693 *endOffset = offset;
694 return QString();
695 }
696
cursorPosition() const697 int BrowserAccessibilityQt::cursorPosition() const
698 {
699 int pos = 0;
700 GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart, &pos);
701 return pos;
702 }
703
characterRect(int) const704 QRect BrowserAccessibilityQt::characterRect(int /*offset*/) const
705 {
706 QT_NOT_YET_IMPLEMENTED
707 return QRect();
708 }
709
selectionCount() const710 int BrowserAccessibilityQt::selectionCount() const
711 {
712 int start = 0;
713 int end = 0;
714 GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart, &start);
715 GetIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, &end);
716 if (start != end)
717 return 1;
718 return 0;
719 }
720
offsetAtPoint(const QPoint &) const721 int BrowserAccessibilityQt::offsetAtPoint(const QPoint &/*point*/) const
722 {
723 QT_NOT_YET_IMPLEMENTED
724 return 0;
725 }
726
selection(int selectionIndex,int * startOffset,int * endOffset) const727 void BrowserAccessibilityQt::selection(int selectionIndex, int *startOffset, int *endOffset) const
728 {
729 Q_ASSERT(startOffset && endOffset);
730 *startOffset = 0;
731 *endOffset = 0;
732 if (selectionIndex != 0)
733 return;
734 GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart, startOffset);
735 GetIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, endOffset);
736 }
737
text(int startOffset,int endOffset) const738 QString BrowserAccessibilityQt::text(int startOffset, int endOffset) const
739 {
740 return text(QAccessible::Value).mid(startOffset, endOffset - startOffset);
741 }
742
removeSelection(int selectionIndex)743 void BrowserAccessibilityQt::removeSelection(int selectionIndex)
744 {
745 manager()->SetSelection(AXPlatformRange(CreatePositionAt(0), CreatePositionAt(0)));
746 }
747
setCursorPosition(int position)748 void BrowserAccessibilityQt::setCursorPosition(int position)
749 {
750 manager()->SetSelection(AXPlatformRange(CreatePositionAt(position), CreatePositionAt(position)));
751 }
752
setSelection(int selectionIndex,int startOffset,int endOffset)753 void BrowserAccessibilityQt::setSelection(int selectionIndex, int startOffset, int endOffset)
754 {
755 if (selectionIndex != 0)
756 return;
757 manager()->SetSelection(AXPlatformRange(CreatePositionAt(startOffset), CreatePositionAt(endOffset)));
758 }
759
characterCount() const760 int BrowserAccessibilityQt::characterCount() const
761 {
762 return text(QAccessible::Value).length();
763 }
764
scrollToSubstring(int startIndex,int endIndex)765 void BrowserAccessibilityQt::scrollToSubstring(int startIndex, int endIndex)
766 {
767 int count = characterCount();
768 if (startIndex < endIndex && endIndex < count)
769 manager()->ScrollToMakeVisible(*this,
770 GetRootFrameHypertextRangeBoundsRect(
771 startIndex,
772 endIndex - startIndex,
773 ui::AXClippingBehavior::kUnclipped));
774 }
775
currentValue() const776 QVariant BrowserAccessibilityQt::currentValue() const
777 {
778 QVariant result;
779 float value;
780 if (GetFloatAttribute(ax::mojom::FloatAttribute::kValueForRange, &value)) {
781 result = (double) value;
782 }
783 return result;
784 }
785
setCurrentValue(const QVariant & value)786 void BrowserAccessibilityQt::setCurrentValue(const QVariant &value)
787 {
788 // not yet implemented anywhere in blink
789 QT_NOT_YET_IMPLEMENTED
790 }
791
maximumValue() const792 QVariant BrowserAccessibilityQt::maximumValue() const
793 {
794 QVariant result;
795 float value;
796 if (GetFloatAttribute(ax::mojom::FloatAttribute::kMaxValueForRange, &value)) {
797 result = (double) value;
798 }
799 return result;
800 }
801
minimumValue() const802 QVariant BrowserAccessibilityQt::minimumValue() const
803 {
804 QVariant result;
805 float value;
806 if (GetFloatAttribute(ax::mojom::FloatAttribute::kMinValueForRange, &value)) {
807 result = (double) value;
808 }
809 return result;
810 }
811
minimumStepSize() const812 QVariant BrowserAccessibilityQt::minimumStepSize() const
813 {
814 QVariant result;
815 float value;
816 if (GetFloatAttribute(ax::mojom::FloatAttribute::kStepValueForRange, &value)) {
817 result = (double) value;
818 }
819 return result;
820 }
821
cellAt(int row,int column) const822 QAccessibleInterface *BrowserAccessibilityQt::cellAt(int row, int column) const
823 {
824 int columns = 0;
825 int rows = 0;
826 if (!GetIntAttribute(ax::mojom::IntAttribute::kTableColumnCount, &columns) ||
827 !GetIntAttribute(ax::mojom::IntAttribute::kTableRowCount, &rows) ||
828 columns <= 0 ||
829 rows <= 0) {
830 return 0;
831 }
832
833 if (row < 0 || row >= rows || column < 0 || column >= columns)
834 return 0;
835
836 base::Optional<int> cell_id = GetCellId(row, column);
837 BrowserAccessibility* cell = cell_id ? manager()->GetFromID(*cell_id) : nullptr;
838 if (cell) {
839 QAccessibleInterface *iface = static_cast<BrowserAccessibilityQt*>(cell);
840 return iface;
841 }
842
843 return nullptr;
844 }
845
caption() const846 QAccessibleInterface *BrowserAccessibilityQt::caption() const
847 {
848 return nullptr;
849 }
850
summary() const851 QAccessibleInterface *BrowserAccessibilityQt::summary() const
852 {
853 return nullptr;
854 }
855
columnDescription(int column) const856 QString BrowserAccessibilityQt::columnDescription(int column) const
857 {
858 return QString();
859 }
860
rowDescription(int row) const861 QString BrowserAccessibilityQt::rowDescription(int row) const
862 {
863 return QString();
864 }
865
columnCount() const866 int BrowserAccessibilityQt::columnCount() const
867 {
868 int columns = 0;
869 if (GetIntAttribute(ax::mojom::IntAttribute::kTableColumnCount, &columns))
870 return columns;
871
872 return 0;
873 }
874
rowCount() const875 int BrowserAccessibilityQt::rowCount() const
876 {
877 int rows = 0;
878 if (GetIntAttribute(ax::mojom::IntAttribute::kTableRowCount, &rows))
879 return rows;
880 return 0;
881 }
882
selectedCellCount() const883 int BrowserAccessibilityQt::selectedCellCount() const
884 {
885 return 0;
886 }
887
selectedColumnCount() const888 int BrowserAccessibilityQt::selectedColumnCount() const
889 {
890 return 0;
891 }
892
selectedRowCount() const893 int BrowserAccessibilityQt::selectedRowCount() const
894 {
895 return 0;
896 }
897
selectedCells() const898 QList<QAccessibleInterface *> BrowserAccessibilityQt::selectedCells() const
899 {
900 return QList<QAccessibleInterface *>();
901 }
902
selectedColumns() const903 QList<int> BrowserAccessibilityQt::selectedColumns() const
904 {
905 return QList<int>();
906 }
907
selectedRows() const908 QList<int> BrowserAccessibilityQt::selectedRows() const
909 {
910 return QList<int>();
911 }
912
isColumnSelected(int) const913 bool BrowserAccessibilityQt::isColumnSelected(int /*column*/) const
914 {
915 return false;
916 }
917
isRowSelected(int) const918 bool BrowserAccessibilityQt::isRowSelected(int /*row*/) const
919 {
920 return false;
921 }
922
selectRow(int)923 bool BrowserAccessibilityQt::selectRow(int /*row*/)
924 {
925 return false;
926 }
927
selectColumn(int)928 bool BrowserAccessibilityQt::selectColumn(int /*column*/)
929 {
930 return false;
931 }
932
unselectRow(int)933 bool BrowserAccessibilityQt::unselectRow(int /*row*/)
934 {
935 return false;
936 }
937
unselectColumn(int)938 bool BrowserAccessibilityQt::unselectColumn(int /*column*/)
939 {
940 return false;
941 }
942
columnExtent() const943 int BrowserAccessibilityQt::columnExtent() const
944 {
945 return 1;
946 }
947
columnHeaderCells() const948 QList<QAccessibleInterface *> BrowserAccessibilityQt::columnHeaderCells() const
949 {
950 return QList<QAccessibleInterface*>();
951 }
952
columnIndex() const953 int BrowserAccessibilityQt::columnIndex() const
954 {
955 int column = 0;
956 if (GetIntAttribute(ax::mojom::IntAttribute::kTableCellColumnIndex, &column))
957 return column;
958 return 0;
959 }
960
rowExtent() const961 int BrowserAccessibilityQt::rowExtent() const
962 {
963 return 1;
964 }
965
rowHeaderCells() const966 QList<QAccessibleInterface *> BrowserAccessibilityQt::rowHeaderCells() const
967 {
968 return QList<QAccessibleInterface*>();
969 }
970
rowIndex() const971 int BrowserAccessibilityQt::rowIndex() const
972 {
973 int row = 0;
974 if (GetIntAttribute(ax::mojom::IntAttribute::kTableCellRowIndex, &row))
975 return row;
976 return 0;
977 }
978
isSelected() const979 bool BrowserAccessibilityQt::isSelected() const
980 {
981 return false;
982 }
983
table() const984 QAccessibleInterface *BrowserAccessibilityQt::table() const
985 {
986 BrowserAccessibility* find_table = PlatformGetParent();
987 while (find_table && find_table->GetRole() != ax::mojom::Role::kTable)
988 find_table = find_table->PlatformGetParent();
989 if (!find_table)
990 return 0;
991 return static_cast<BrowserAccessibilityQt*>(find_table);
992 }
993
modelChange(QAccessibleTableModelChangeEvent *)994 void BrowserAccessibilityQt::modelChange(QAccessibleTableModelChangeEvent *)
995 {
996
997 }
998
999 } // namespace content
1000
1001 #endif // QT_CONFIG(accessibility)
1002