Qt 6.x
The Qt SDK
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
4#include <QtGui/qtguiglobal.h>
5#if QT_CONFIG(accessibility)
6
9#include "qwindowsuiautils.h"
10
11#include <QtGui/qaccessible.h>
12#include <QtGui/qwindow.h>
13#include <QtGui/qguiapplication.h>
14#include <QtGui/private/qguiapplication_p.h>
15#include <QtCore/qt_windows.h>
16#include <qpa/qplatformintegration.h>
17#include <QtGui/private/qwindowsuiawrapper_p.h>
18
19#include <QtCore/private/qwinregistry_p.h>
20
22
23using namespace QWindowsUiAutomation;
24
25bool QWindowsUiaAccessibility::m_accessibleActive = false;
26
27QWindowsUiaAccessibility::QWindowsUiaAccessibility()
28{
29}
30
31QWindowsUiaAccessibility::~QWindowsUiaAccessibility()
32{
33}
34
35// Handles UI Automation window messages.
36bool QWindowsUiaAccessibility::handleWmGetObject(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult)
37{
38 // Start handling accessibility internally
39 QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true);
40 m_accessibleActive = true;
41
42 // Ignoring all requests while starting up / shutting down
44 return false;
45
46 if (QWindow *window = QWindowsContext::instance()->findWindow(hwnd)) {
47 if (QAccessibleInterface *accessible = window->accessibleRoot()) {
48 QWindowsUiaMainProvider *provider = QWindowsUiaMainProvider::providerForAccessible(accessible);
49 *lResult = QWindowsUiaWrapper::instance()->returnRawElementProvider(hwnd, wParam, lParam, provider);
50 return true;
51 }
52 }
53 return false;
54}
55
56// Retrieve sound name by checking the icon property of a message box
57// should it be the event object.
58static QString alertSound(const QObject *object)
59{
60 if (object->inherits("QMessageBox")) {
61 enum MessageBoxIcon { // Keep in sync with QMessageBox::Icon
62 Information = 1,
63 Warning = 2,
64 Critical = 3
65 };
66 switch (object->property("icon").toInt()) {
67 case Information:
68 return QStringLiteral("SystemAsterisk");
69 case Warning:
70 return QStringLiteral("SystemExclamation");
71 case Critical:
72 return QStringLiteral("SystemHand");
73 }
74 return QString();
75 }
76 return QStringLiteral("SystemAsterisk");
77}
78
79static QString soundFileName(const QString &soundName)
80{
81 const QString key = QStringLiteral("AppEvents\\Schemes\\Apps\\.Default\\")
82 + soundName + QStringLiteral("\\.Current");
83 return QWinRegistryKey(HKEY_CURRENT_USER, key).stringValue(L"");
84}
85
86static void playSystemSound(const QString &soundName)
87{
88 if (!soundName.isEmpty() && !soundFileName(soundName).isEmpty()) {
89 PlaySound(reinterpret_cast<const wchar_t *>(soundName.utf16()), nullptr,
90 SND_ALIAS | SND_ASYNC | SND_NODEFAULT | SND_NOWAIT);
91 }
92}
93
94// Handles accessibility update notifications.
95void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
96{
97 if (!event)
98 return;
99
100 // Ignore events sent before the first UI Automation
101 // request or while QAccessible is being activated.
102 if (!m_accessibleActive)
103 return;
104
105 switch (event->type()) {
106 case QAccessible::PopupMenuStart:
107 playSystemSound(QStringLiteral("MenuPopup"));
108 break;
109 case QAccessible::MenuCommand:
110 playSystemSound(QStringLiteral("MenuCommand"));
111 break;
112 case QAccessible::Alert:
113 playSystemSound(alertSound(event->object()));
114 break;
115 default:
116 break;
117 }
118
119 QAccessibleInterface *accessible = event->accessibleInterface();
120 if (!isActive() || !accessible || !accessible->isValid())
121 return;
122
123 // Ensures QWindowsUiaWrapper is properly initialized.
124 if (!QWindowsUiaWrapper::instance()->ready())
125 return;
126
127 // No need to do anything when nobody is listening.
128 if (!QWindowsUiaWrapper::instance()->clientsAreListening())
129 return;
130
131 switch (event->type()) {
132 case QAccessible::Focus:
133 QWindowsUiaMainProvider::notifyFocusChange(event);
134 break;
135 case QAccessible::StateChanged:
136 QWindowsUiaMainProvider::notifyStateChange(static_cast<QAccessibleStateChangeEvent *>(event));
137 break;
138 case QAccessible::ValueChanged:
139 QWindowsUiaMainProvider::notifyValueChange(static_cast<QAccessibleValueChangeEvent *>(event));
140 break;
141 case QAccessible::NameChanged:
142 QWindowsUiaMainProvider::notifyNameChange(event);
143 break;
144 case QAccessible::SelectionAdd:
145 QWindowsUiaMainProvider::notifySelectionChange(event);
146 break;
147 case QAccessible::TextAttributeChanged:
148 case QAccessible::TextColumnChanged:
149 case QAccessible::TextInserted:
150 case QAccessible::TextRemoved:
151 case QAccessible::TextUpdated:
152 case QAccessible::TextSelectionChanged:
153 case QAccessible::TextCaretMoved:
154 QWindowsUiaMainProvider::notifyTextChange(event);
155 break;
156 default:
157 break;
158 }
159}
160
162
163#endif // QT_CONFIG(accessibility)
bool isActive
static bool closingDown()
Returns true if the application objects are being destroyed; otherwise returns false.
static bool startingUp()
Returns true if an application object has not been created yet; otherwise returns false.
static QPlatformIntegration * platformIntegration()
\inmodule QtCore
Definition qobject.h:90
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
Definition qstring.cpp:6737
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QString stringValue(QStringView subKey) const
\inmodule QtGui
Definition qwindow.h:63
static QWindowsContext * instance()
static QWindowsUiaWrapper * instance()
LRESULT returnRawElementProvider(HWND hwnd, WPARAM wParam, LPARAM lParam, IRawElementProviderSimple *el)
Combined button and popup list for selecting options.
GLuint64 key
GLuint object
[3]
struct _cl_event * event
#define QStringLiteral(str)
aWidget window() -> setWindowTitle("New Window Title")
[2]