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