Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qiosplatformaccessibility.mm
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
6
8
9#if QT_CONFIG(accessibility)
10
11#include <QtGui/QtGui>
12#include "qioswindow.h"
13#include "quiaccessibilityelement.h"
14
15QIOSPlatformAccessibility::QIOSPlatformAccessibility()
16{
17 m_focusObserver = QMacNotificationObserver(
18 nil, UIAccessibilityElementFocusedNotification, [&](NSNotification *notification) {
19 id element = notification.userInfo[UIAccessibilityFocusedElementKey];
20 m_focusElement = static_cast<QMacAccessibilityElement *>(element);
21 });
22}
23
24QIOSPlatformAccessibility::~QIOSPlatformAccessibility()
25{}
26
27
28void invalidateCache(QAccessibleInterface *iface)
29{
30 if (!iface || !iface->isValid()) {
31 qWarning() << "invalid accessible interface: " << iface;
32 return;
33 }
34
35 // This will invalidate everything regardless of what window the
36 // interface belonged to. We might want to revisit this strategy later.
37 // (Therefore this function still takes the interface as argument)
38 foreach (QWindow *win, QGuiApplication::topLevelWindows()) {
39 if (win && win->handle()) {
40 QT_PREPEND_NAMESPACE(QIOSWindow) *window = static_cast<QT_PREPEND_NAMESPACE(QIOSWindow) *>(win->handle());
41 window->clearAccessibleCache();
42 }
43 }
44}
45
46
47void QIOSPlatformAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
48{
49 auto *accessibleInterface = event->accessibleInterface();
50 if (!isActive() || !accessibleInterface)
51 return;
52 switch (event->type()) {
53 case QAccessible::Announcement: {
54 auto *announcementEvent = static_cast<QAccessibleAnnouncementEvent *>(event);
55 UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification,
56 announcementEvent->message().toNSString());
57 break;
58 }
59 case QAccessible::Focus: {
60 auto *element = [QMacAccessibilityElement elementWithId:event->uniqueId()];
61 Q_ASSERT(element);
62 // There's no NSAccessibilityFocusedUIElementChangedNotification, like we have on
63 // macOS. Instead, the documentation for UIAccessibilityLayoutChangedNotification
64 // specifies that the optional argument to UIAccessibilityPostNotification is the
65 // accessibility element for VoiceOver to move to after processing the notification.
66 UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, element);
67 break;
68 }
69 case QAccessible::DescriptionChanged:
70 case QAccessible::NameChanged: {
71 auto *element = [QMacAccessibilityElement elementWithId:event->uniqueId()];
72 if (element == m_focusElement)
73 UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, element);
74 break;
75 }
76 case QAccessible::ObjectCreated:
77 case QAccessible::ObjectShow:
78 case QAccessible::ObjectHide:
79 case QAccessible::ObjectDestroyed:
80 invalidateCache(accessibleInterface);
81 switch (accessibleInterface->role()) {
82 case QAccessible::Window:
83 case QAccessible::Dialog:
84 // Bigger changes to the UI require a full reset of VoiceOver
85 UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil);
86 break;
87 default:
88 // While smaller changes can be handled by re-reading the layout
89 UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);
90 }
91 break;
92 default:
93 break;
94 }
95}
96
97#endif