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
qaccessiblewindow.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 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
6
7#if QT_CONFIG(accessibility)
8
9#include <QtGui/qguiapplication.h>
10#include <QtGui/qwindow.h>
11#include <QtGui/private/qwindow_p.h>
12
13QT_BEGIN_NAMESPACE
14
15/*
16 Accessibility interface for a QWindow.
17
18 Reports the window itself, with the window's child QWindows as its
19 children, so that content Qt hosts in a child window is reachable even
20 on a platform bridge that does not know about native windows.
21
22 A window reaches the accessibility tree only when concrete QWindow
23 subclasses opt in, by registering an accessible factory, and implementing
24 accessibleRoot(). A plain QWindow does not do this, which keeps Qt's own
25 implementation-detail windows out of the tree.
26
27 The node reports window(). A bridge that does know about native windows
28 reads it to find the native handle, and substitutes that handle for the
29 node, in which case the native element supplies its own children.
30*/
31QAccessibleWindow::QAccessibleWindow(QWindow *window)
32 : QAccessibleObject(window)
33{
34}
35
36QWindow *QAccessibleWindow::window() const
37{
38 return static_cast<QWindow *>(object());
39}
40
41/*
42 Resolves the interfaces of the window's child QWindows.
43
44 Each child is resolved through its own accessibleRoot(), so a child that
45 has not opted into the tree contributes nothing, and one that represents
46 something else contributes whatever represents it.
47
48 The children come out in stacking order, bottom first, as a result of the
49 order QWindow::raise() and QWindow::lower() maintains.
50*/
51QList<QAccessibleInterface *> QAccessibleWindow::childInterfaces() const
52{
53 QList<QAccessibleInterface *> interfaces;
54
55 if (!isValid())
56 return interfaces;
57
58 const auto childWindows = window()->findChildren<QWindow *>(Qt::FindDirectChildrenOnly);
59 interfaces.reserve(childWindows.size());
60 for (QWindow *childWindow : childWindows) {
61 if (QAccessibleInterface *iface = childWindow->accessibleRoot())
62 interfaces.append(iface);
63 }
64
65 return interfaces;
66}
67
68int QAccessibleWindow::childCount() const
69{
70 return childInterfaces().size();
71}
72
73int QAccessibleWindow::indexOfChild(const QAccessibleInterface *child) const
74{
75 if (!child)
76 return -1;
77
78 // Compares interfaces, not objects, as a child window's interface is
79 // not necessarily an interface for the window itself.
80 return childInterfaces().indexOf(const_cast<QAccessibleInterface *>(child));
81}
82
83QAccessibleInterface *QAccessibleWindow::child(int index) const
84{
85 const QList<QAccessibleInterface *> children = childInterfaces();
86 if (index >= 0 && index < children.size())
87 return children.at(index);
88 return nullptr;
89}
90
91QAccessibleInterface *QAccessibleWindow::parent() const
92{
93 if (!isValid())
94 return nullptr;
95
96 // A window hosted by a window container reflects the container
97 if (QObject *a11yParent = QWindowPrivate::get(window())->accessibleParent)
98 return QAccessible::queryAccessibleInterface(a11yParent);
99
100 // A child window with no container parent belongs to the window
101 // it is a child of, if that window is in the tree as well.
102 if (QWindow *parentWindow = window()->parent()) {
103 if (QAccessibleInterface *iface = parentWindow->accessibleRoot())
104 return iface;
105 }
106
107 return QAccessible::queryAccessibleInterface(qApp);
108}
109
110QAccessibleInterface *QAccessibleWindow::focusChild() const
111{
112 const QWindow *focusWindow = QGuiApplication::focusWindow();
113
114 for (QAccessibleInterface *child : childInterfaces()) {
115 if (QAccessibleInterface *focus = child->focusChild())
116 return focus;
117 // The child window may hold the focus without reporting anything
118 // within it as focused, in which case the child is the answer.
119 if (child->window() == focusWindow)
120 return child;
121 }
122
123 return nullptr;
124}
125
126QString QAccessibleWindow::text(QAccessible::Text text) const
127{
128 if (!isValid())
129 return {};
130
131 if (text == QAccessible::Name && window()->isTopLevel())
132 return window()->title();
133
134 return {};
135}
136
137QAccessible::Role QAccessibleWindow::role() const
138{
139 if (isValid() && window()->isTopLevel())
140 return QAccessible::Window;
141
142 // A window that is not top level is hosted by something, and presents
143 // a client area rather than a window of its own.
144 return QAccessible::Client;
145}
146
147QAccessible::State QAccessibleWindow::state() const
148{
149 QAccessible::State state;
150
151 if (!isValid()) {
152 state.invalid = true;
153 return state;
154 }
155
156 state.invisible = !window()->isVisible();
157 state.focused = window() == QGuiApplication::focusWindow();
158 state.active = window()->isActive();
159
160 return state;
161}
162
163QRect QAccessibleWindow::rect() const
164{
165 if (!isValid())
166 return {};
167
168 return QRect(window()->mapToGlobal(QPoint(0, 0)), window()->size());
169}
170
171QT_END_NAMESPACE
172
173#endif // QT_CONFIG(accessibility)