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
qwindowsuiaaccessibility.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 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#include <QtGui/qtguiglobal.h>
6#if QT_CONFIG(accessibility)
7
8#include "qwindowsuiaaccessibility.h"
9#include "qwindowsuiautomation.h"
10#include "qwindowsuiamainprovider.h"
11#include "qwindowsuiautils.h"
12
13#include <QtGui/qaccessible.h>
14#include <QtGui/qwindow.h>
15#include <QtGui/qguiapplication.h>
16#include <QtGui/private/qguiapplication_p.h>
17#include <QtCore/qt_windows.h>
18#include <qpa/qplatformintegration.h>
19
20#include <QtCore/private/qwinregistry_p.h>
21
22QT_BEGIN_NAMESPACE
23
24using namespace QWindowsUiAutomation;
25using namespace Qt::StringLiterals;
26
27bool QWindowsUiaAccessibility::m_accessibleActive = false;
28
29QWindowsUiaAccessibility::QWindowsUiaAccessibility()
30{
31}
32
33QWindowsUiaAccessibility::~QWindowsUiaAccessibility()
34{
35}
36
37// Handles UI Automation window messages.
38bool QWindowsUiaAccessibility::handleWmGetObject(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult)
39{
40 // Start handling accessibility internally
41 QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true);
42 m_accessibleActive = true;
43
44 // Ignoring all requests while starting up / shutting down
45 if (QCoreApplication::startingUp() || QCoreApplication::closingDown())
46 return false;
47
48 if (QWindow *window = QWindowsContext::instance()->findWindow(hwnd)) {
49 if (QAccessibleInterface *accessible = window->accessibleRoot()) {
50 auto provider = QWindowsUiaMainProvider::providerForAccessible(accessible);
51 *lResult = UiaReturnRawElementProvider(hwnd, wParam, lParam, provider.Get());
52 return true;
53 }
54 }
55 return false;
56}
57
58// Retrieve sound name by checking the icon property of a message box
59// should it be the event object.
60static QString alertSound(const QObject *object)
61{
62 if (object->inherits("QMessageBox")) {
63 enum MessageBoxIcon { // Keep in sync with QMessageBox::Icon
64 Information = 1,
65 Warning = 2,
66 Critical = 3
67 };
68 switch (object->property("icon").toInt()) {
69 case Information:
70 return QStringLiteral("SystemAsterisk");
71 case Warning:
72 return QStringLiteral("SystemExclamation");
73 case Critical:
74 return QStringLiteral("SystemHand");
75 }
76 return QString();
77 }
78 return QStringLiteral("SystemAsterisk");
79}
80
81static QString soundFileName(const QString &soundName)
82{
83 const QString key = "AppEvents\\Schemes\\Apps\\.Default\\"_L1
84 + soundName + "\\.Current"_L1;
85 return QWinRegistryKey(HKEY_CURRENT_USER, key).stringValue(L"");
86}
87
88static void playSystemSound(const QString &soundName)
89{
90 if (!soundName.isEmpty() && !soundFileName(soundName).isEmpty()) {
91 PlaySound(reinterpret_cast<const wchar_t *>(soundName.utf16()), nullptr,
92 SND_ALIAS | SND_ASYNC | SND_NODEFAULT | SND_NOWAIT);
93 }
94}
95
96// Handles accessibility update notifications.
97void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
98{
99 if (!event)
100 return;
101
102 // Always handle system sound events
103 switch (event->type()) {
104 case QAccessible::PopupMenuStart:
105 playSystemSound(QStringLiteral("MenuPopup"));
106 break;
107 case QAccessible::MenuCommand:
108 playSystemSound(QStringLiteral("MenuCommand"));
109 break;
110 case QAccessible::Alert:
111 playSystemSound(alertSound(event->object()));
112 break;
113 default:
114 break;
115 }
116
117 // Ignore events sent before the first UI Automation
118 // request or while QAccessible is being activated.
119 if (!m_accessibleActive)
120 return;
121
122 QAccessibleInterface *accessible = event->accessibleInterface();
123 if (!isActive() || !accessible || !accessible->isValid())
124 return;
125
126 // No need to do anything when nobody is listening.
127 if (!UiaClientsAreListening())
128 return;
129
130 switch (event->type()) {
131 case QAccessible::Announcement:
132 QWindowsUiaMainProvider::raiseNotification(static_cast<QAccessibleAnnouncementEvent *>(event));
133 break;
134 case QAccessible::Focus:
135 QWindowsUiaMainProvider::notifyFocusChange(event);
136 break;
137 case QAccessible::StateChanged:
138 QWindowsUiaMainProvider::notifyStateChange(static_cast<QAccessibleStateChangeEvent *>(event));
139 break;
140 case QAccessible::ValueChanged:
141 QWindowsUiaMainProvider::notifyValueChange(static_cast<QAccessibleValueChangeEvent *>(event));
142 break;
143 case QAccessible::NameChanged:
144 QWindowsUiaMainProvider::notifyNameChange(event);
145 break;
146 case QAccessible::RoleChanged:
147 QWindowsUiaMainProvider::notifyRoleChange(event);
148 break;
149 case QAccessible::SelectionAdd:
150 QWindowsUiaMainProvider::notifySelectionChange(event);
151 break;
152 case QAccessible::TextAttributeChanged:
153 case QAccessible::TextColumnChanged:
154 case QAccessible::TextInserted:
155 case QAccessible::TextRemoved:
156 case QAccessible::TextUpdated:
157 case QAccessible::TextSelectionChanged:
158 case QAccessible::TextCaretMoved:
159 QWindowsUiaMainProvider::notifyTextChange(event);
160 break;
161 default:
162 break;
163 }
164}
165
166QT_END_NAMESPACE
167
168#endif // QT_CONFIG(accessibility)