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
qwasmwindowstack.inc
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#ifndef QWASMWINDOWSTACK_INC
5#define QWASMWINDOWSTACK_INC
6
7template <typename Window>
8QWasmWindowStack<Window>::QWasmWindowStack(
9 WindowOrderChangedCallbackType windowOrderChangedCallback)
10 : m_windowOrderChangedCallback(std::move(windowOrderChangedCallback)),
11 m_regularWindowsBegin(m_windowStack.begin()),
12 m_alwaysOnTopWindowsBegin(m_windowStack.begin())
13{
14 invariant();
15}
16
17template <typename Window>
19{
20 invariant();
21}
22
23template <typename Window>
24void QWasmWindowStack<Window>::invariant()
25{
26 Q_ASSERT(m_regularWindowsBegin >= m_windowStack.begin());
27 Q_ASSERT(m_regularWindowsBegin <= m_alwaysOnTopWindowsBegin);
28 Q_ASSERT(m_alwaysOnTopWindowsBegin <= m_windowStack.end());
29}
30
31/* insert a window at the correct location.
32 *
33 * There are three groups
34 * StayOnBottom
35 * Regular
36 * StayOnTop
37 *
38 * In addition there is StayAboveParent which
39 * can place the window in either of the
40 * three above groups, depending on which
41 * group the transient parent resides in.
42 *
43 * insertAtRegionBegin controls the placement
44 * within each of the groups. Either at the end
45 * or at the beginning.
46 *
47*/
48template <typename Window>
50 bool insertAtRegionBegin, bool callCallbacks)
51{
52 invariant();
53 Q_ASSERT(m_windowStack.count(window) == 0);
54
55 auto regularDistance = std::distance(m_windowStack.begin(), m_regularWindowsBegin);
56 auto stayOnTopDistance = std::distance(m_windowStack.begin(), m_alwaysOnTopWindowsBegin);
57
58 if (position == PositionPreference::StayAboveTransientParent) {
59 Q_ASSERT(window->transientParent());
60 const auto it =
61 std::find(m_windowStack.begin(), m_windowStack.end(), window->transientParent());
62 if (it == m_windowStack.end()) {
63 qWarning() << "QWasmWindowStack<Window>::pushWindow - missing parent"
64 << window->transientParent();
65 pushWindow(window, PositionPreference::Regular, insertAtRegionBegin, callCallbacks);
66 return;
67 } else {
68 if (it >= m_alwaysOnTopWindowsBegin)
69 ;
70 else if (it >= m_regularWindowsBegin)
71 ++stayOnTopDistance;
72 else {
73 ++regularDistance;
74 ++stayOnTopDistance;
75 }
76 m_windowStack.insert(it + 1, window);
77 }
78 } else if (position == PositionPreference::StayOnTop) {
79 if (insertAtRegionBegin)
80 m_windowStack.insert(m_alwaysOnTopWindowsBegin, window);
81 else
82 m_windowStack.insert(m_windowStack.end(), window);
83
84 } else if (position == PositionPreference::Regular) {
85 ++stayOnTopDistance;
86 if (insertAtRegionBegin)
87 m_windowStack.insert(m_regularWindowsBegin, window);
88 else
89 m_windowStack.insert(m_alwaysOnTopWindowsBegin, window);
90
91 } else {
92 // StayOnBottom
93 ++regularDistance;
94 ++stayOnTopDistance;
95
96 if (insertAtRegionBegin)
97 m_windowStack.insert(m_windowStack.begin(), window);
98 else
99 m_windowStack.insert(m_regularWindowsBegin, window);
100 }
101
102 m_regularWindowsBegin = m_windowStack.begin() + regularDistance;
103 m_alwaysOnTopWindowsBegin = m_windowStack.begin() + stayOnTopDistance;
104
105 if (callCallbacks)
106 m_windowOrderChangedCallback();
107
108 Q_ASSERT(m_windowStack.count(window) == 1);
109 invariant();
110}
111
112template <typename Window>
114{
115 invariant();
116 Q_ASSERT(m_windowStack.count(window) == 1);
117
118 auto regularDistance = std::distance(m_windowStack.begin(), m_regularWindowsBegin);
119 auto stayOnTopDistance = std::distance(m_windowStack.begin(), m_alwaysOnTopWindowsBegin);
120
121 auto it = std::find(m_windowStack.begin(), m_windowStack.end(), window);
122
123 Q_ASSERT(it != m_windowStack.end());
124
125 if (it < m_regularWindowsBegin)
126 --regularDistance;
127 if (it < m_alwaysOnTopWindowsBegin)
128 --stayOnTopDistance;
129
130 m_windowStack.erase(it);
131
132 m_regularWindowsBegin = m_windowStack.begin() + regularDistance;
133 m_alwaysOnTopWindowsBegin = m_windowStack.begin() + stayOnTopDistance;
134
135 if (callCallbacks)
136 m_windowOrderChangedCallback();
137
138 Q_ASSERT(m_windowStack.count(window) == 0);
139 invariant();
140}
141
142template <typename Window>
144{
145 if (raiseImpl(window))
146 m_windowOrderChangedCallback();
147}
148
149template <typename Window>
150bool QWasmWindowStack<Window>::raiseImpl(Window *window)
151{
152 invariant();
153 Q_ASSERT(m_windowStack.count(window) == 1);
154
155 {
156 const auto it = std::find(m_windowStack.begin(), m_windowStack.end(), window);
157 const auto itEnd = ([this, it]() {
158 if (it < m_regularWindowsBegin)
159 return m_regularWindowsBegin;
160 if (it < m_alwaysOnTopWindowsBegin)
161 return m_alwaysOnTopWindowsBegin;
162 return m_windowStack.end();
163 })();
164
165 if (it + 1 == itEnd)
166 return false;
167
168 std::rotate(it, it + 1, itEnd);
169 }
170
171 std::vector<Window *> windowsToRaise;
172 {
173 for (auto trit = m_windowStack.begin(); trit != m_windowStack.end(); ++trit) {
174 const auto w = *trit;
175 if ((w != window) &&
176 (getWindowPositionPreference(trit) == PositionPreference::StayAboveTransientParent) &&
177 (w->transientParent() == window)) {
178 windowsToRaise.push_back(w);
179 }
180 }
181 }
182
183 for (const auto w : windowsToRaise)
184 {
185 raiseImpl(w);
186 }
187 invariant();
188 return true;
189}
190
191template <typename Window>
193{
194 if (lowerImpl(window))
195 m_windowOrderChangedCallback();
196}
197
198template <typename Window>
199bool QWasmWindowStack<Window>::lowerImpl(Window *window)
200{
201 invariant();
202 Q_ASSERT(m_windowStack.count(window) == 1);
203
204 {
205 const auto it = std::find(m_windowStack.begin(), m_windowStack.end(), window);
206 const auto itBegin = ([this, it]() {
207 if (it >= m_alwaysOnTopWindowsBegin)
208 return m_alwaysOnTopWindowsBegin;
209 if (it >= m_regularWindowsBegin)
210 return m_regularWindowsBegin;
211 return m_windowStack.begin();
212 })();
213
214 if (itBegin == it)
215 return false;
216
217 std::rotate(itBegin, it, it + 1);
218 }
219
220 std::vector<Window *> windowsToLower;
221 {
222 for (auto trit = m_windowStack.begin(); trit != m_windowStack.end(); ++trit) {
223 const auto w = *trit;
224 if ((w != window) &&
225 (getWindowPositionPreference(trit) == PositionPreference::StayAboveTransientParent) &&
226 (w->transientParent() == window)) {
227 windowsToLower.push_back(w);
228 }
229 }
230 }
231
232 for (const auto w : windowsToLower)
233 {
234 lowerImpl(w);
235 }
236 invariant();
237 return true;
238}
239
240template <typename Window>
242 PositionPreference position)
243{
244 invariant();
245
246 auto it = std::find(m_windowStack.begin(), m_windowStack.end(), window);
247 const auto currentPosition = getWindowPositionPreference(it);
248
249 if (position == currentPosition) {
250 ;
251 } else if (currentPosition == PositionPreference::StayAboveTransientParent) {
252 // Keep position if possible
253 const bool isStayOnBottom ( it < m_regularWindowsBegin);
254 const bool isRegular( !isStayOnBottom && (it < m_alwaysOnTopWindowsBegin));
255 const bool isStayOnTop(!isStayOnBottom && !isRegular);
256
257 if (isStayOnBottom && (position == PositionPreference::StayOnBottom))
258 ;
259 else if (isRegular && (position == PositionPreference::Regular))
260 ;
261 else if (isStayOnTop && (position == PositionPreference::StayOnTop))
262 ;
263 else {
264 auto current = *it;
265 removeWindow(current, false);
266 pushWindow(current, position, false, false);
267 m_windowOrderChangedCallback();
268 }
269 } else {
270 const bool insertAtRegionBegin = (
271 (currentPosition != PositionPreference::StayAboveTransientParent) &&
272 (position != PositionPreference::StayAboveTransientParent) &&
273 ((currentPosition == PositionPreference::StayOnBottom) ||
274 (position == PositionPreference::StayOnTop)));
275
276 auto current = *it;
277 removeWindow(current, false);
278 pushWindow(current, position, insertAtRegionBegin, false);
279 m_windowOrderChangedCallback();
280 }
281 invariant();
282}
283
284template <typename Window>
286{
287 return m_windowStack.rbegin();
288}
289
290template <typename Window>
292{
293 return m_windowStack.rend();
294}
295
296template <typename Window>
298{
299 return m_windowStack.rbegin();
300}
301
302template <typename Window>
304{
305 return m_windowStack.rend();
306}
307
308template <typename Window>
311{
312 return m_windowStack.begin();
313}
314
315template <typename Window>
318{
319 return m_windowStack.end();
320}
321
322template <typename Window>
324{
325 return m_windowStack.empty();
326}
327
328template <typename Window>
330{
331 return m_windowStack.size();
332}
333
334template <typename Window>
336{
337 return m_windowStack.empty() ? nullptr : m_windowStack.last();
338}
339
340template <typename Window>
341bool QWasmWindowStack<Window>::shouldBeAboveTransientParentFlags(Qt::WindowFlags flags) const
342{
343 if (flags.testFlag(Qt::Tool) ||
344 flags.testFlag(Qt::SplashScreen) ||
345 flags.testFlag(Qt::ToolTip) ||
346 flags.testFlag(Qt::Popup))
347 {
348 return true;
349 }
350
351 return false;
352}
353
354template <typename Window>
355bool QWasmWindowStack<Window>::shouldBeAboveTransientParent(const Window *window) const
356{
357 if (!window->transientParent())
358 return false;
359
360 if (window->isModal())
361 return true;
362
363 if (shouldBeAboveTransientParentFlags(window->windowFlags()))
364 return true;
365
366 return false;
367}
368
369template <typename Window>
372 typename StorageType::const_iterator windowIt, bool testStayAbove) const
373{
374 Window *window = *windowIt;
375 if (testStayAbove && shouldBeAboveTransientParent(window))
376 return PositionPreference::StayAboveTransientParent;
377 if (windowIt >= m_alwaysOnTopWindowsBegin)
378 return PositionPreference::StayOnTop;
379 if (windowIt >= m_regularWindowsBegin)
380 return PositionPreference::Regular;
381 return PositionPreference::StayOnBottom;
382}
383
384#endif /* QWASMWINDOWSTACK_INC */
void removeWindow(Window *window, bool callCallbacks=true)
void windowPositionPreferenceChanged(Window *window, PositionPreference position)
typename StorageType::const_reverse_iterator const_iterator
const_reverse_iterator rbegin() const
bool empty() const
typename StorageType::const_iterator const_reverse_iterator
Window * topWindow() const
iterator end()
typename StorageType::reverse_iterator iterator
const_reverse_iterator rend() const
void lower(Window *window)
void pushWindow(Window *window, PositionPreference position, bool insertAtRegionBegin=false, bool callCallbacks=true)
size_t size() const
void raise(Window *window)
PositionPreference getWindowPositionPreference(typename StorageType::const_iterator windowIt, bool testStayAbove=true) const
iterator begin()
[Window class with invokable method]
Definition window.h:11
@ ToolTip
Definition qnamespace.h:219
@ Popup
Definition qnamespace.h:217
@ SplashScreen
Definition qnamespace.h:220
@ Tool
Definition qnamespace.h:218
#define qWarning
Definition qlogging.h:170
GLfloat GLfloat GLfloat w
[0]
GLbitfield flags
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define Q_ASSERT(cond)
Definition qrandom.cpp:48
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
aWidget window() -> setWindowTitle("New Window Title")
[2]
QJSValueIterator it(object)