Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qwindowswindow.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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 <QtCore/qt_windows.h>
5
6#include "qwindowswindow.h"
7#include "qwindowscontext.h"
8#if QT_CONFIG(draganddrop)
9# include "qwindowsdrag.h"
10#endif
11#include "qwindowsscreen.h"
12#include "qwindowsintegration.h"
13#include "qwindowsmenu.h"
15#if QT_CONFIG(dynamicgl)
16# include "qwindowsglcontext.h"
17#else
19#endif
21#ifdef QT_NO_CURSOR
22# include "qwindowscursor.h"
23#endif
24
25#include <QtGui/qguiapplication.h>
26#include <QtGui/qscreen.h>
27#include <QtGui/qwindow.h>
28#include <QtGui/qregion.h>
29#include <QtGui/qopenglcontext.h>
30#include <private/qwindow_p.h> // QWINDOWSIZE_MAX
31#include <private/qguiapplication_p.h>
32#include <private/qhighdpiscaling_p.h>
33#include <qpa/qwindowsysteminterface.h>
34
35#include <QtCore/qdebug.h>
36#include <QtCore/qlibraryinfo.h>
37
38#include <dwmapi.h>
39
40#if QT_CONFIG(vulkan)
42#endif
43
44#include <shellscalingapi.h>
45
47
49
50enum {
53};
54
55Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &);
56
57static QByteArray debugWinStyle(DWORD style)
58{
59 QByteArray rc = "0x";
60 rc += QByteArray::number(qulonglong(style), 16);
61 if (style & WS_POPUP)
62 rc += " WS_POPUP";
63 if (style & WS_CHILD)
64 rc += " WS_CHILD";
65 if (style & WS_OVERLAPPED)
66 rc += " WS_OVERLAPPED";
67 if (style & WS_CLIPSIBLINGS)
68 rc += " WS_CLIPSIBLINGS";
69 if (style & WS_CLIPCHILDREN)
70 rc += " WS_CLIPCHILDREN";
71 if (style & WS_THICKFRAME)
72 rc += " WS_THICKFRAME";
73 if (style & WS_DLGFRAME)
74 rc += " WS_DLGFRAME";
75 if (style & WS_SYSMENU)
76 rc += " WS_SYSMENU";
77 if (style & WS_MINIMIZEBOX)
78 rc += " WS_MINIMIZEBOX";
79 if (style & WS_MAXIMIZEBOX)
80 rc += " WS_MAXIMIZEBOX";
81 if (style & WS_BORDER)
82 rc += " WS_BORDER";
83 if (style & WS_CAPTION)
84 rc += " WS_CAPTION";
85 if (style & WS_CHILDWINDOW)
86 rc += " WS_CHILDWINDOW";
87 if (style & WS_DISABLED)
88 rc += " WS_DISABLED";
89 if (style & WS_GROUP)
90 rc += " WS_GROUP";
91 if (style & WS_HSCROLL)
92 rc += " WS_HSCROLL";
93 if (style & WS_ICONIC)
94 rc += " WS_ICONIC";
95 if (style & WS_MAXIMIZE)
96 rc += " WS_MAXIMIZE";
97 if (style & WS_MINIMIZE)
98 rc += " WS_MINIMIZE";
99 if (style & WS_SIZEBOX)
100 rc += " WS_SIZEBOX";
101 if (style & WS_TABSTOP)
102 rc += " WS_TABSTOP";
103 if (style & WS_TILED)
104 rc += " WS_TILED";
105 if (style & WS_VISIBLE)
106 rc += " WS_VISIBLE";
107 if (style & WS_VSCROLL)
108 rc += " WS_VSCROLL";
109 return rc;
110}
111
112static QByteArray debugWinExStyle(DWORD exStyle)
113{
114 QByteArray rc = "0x";
115 rc += QByteArray::number(qulonglong(exStyle), 16);
116 if (exStyle & WS_EX_TOOLWINDOW)
117 rc += " WS_EX_TOOLWINDOW";
118 if (exStyle & WS_EX_CONTEXTHELP)
119 rc += " WS_EX_CONTEXTHELP";
120 if (exStyle & WS_EX_LAYERED)
121 rc += " WS_EX_LAYERED";
122 if (exStyle & WS_EX_DLGMODALFRAME)
123 rc += " WS_EX_DLGMODALFRAME";
124 if (exStyle & WS_EX_LAYOUTRTL)
125 rc += " WS_EX_LAYOUTRTL";
126 if (exStyle & WS_EX_NOINHERITLAYOUT)
127 rc += " WS_EX_NOINHERITLAYOUT";
128 if (exStyle & WS_EX_ACCEPTFILES)
129 rc += " WS_EX_ACCEPTFILES";
130 if (exStyle & WS_EX_APPWINDOW)
131 rc += " WS_EX_APPWINDOW";
132 if (exStyle & WS_EX_CLIENTEDGE)
133 rc += " WS_EX_CLIENTEDGE";
134 if (exStyle & WS_EX_COMPOSITED)
135 rc += " WS_EX_COMPOSITED";
136 if (exStyle & WS_EX_CONTROLPARENT)
137 rc += " WS_EX_CONTROLPARENT";
138 if (exStyle & WS_EX_LEFT)
139 rc += " WS_EX_LEFT";
140 if (exStyle & WS_EX_LEFTSCROLLBAR)
141 rc += " WS_EX_LEFTSCROLLBAR";
142 if (exStyle & WS_EX_LTRREADING)
143 rc += " WS_EX_LTRREADING";
144 if (exStyle & WS_EX_MDICHILD)
145 rc += " WS_EX_MDICHILD";
146 if (exStyle & WS_EX_NOACTIVATE)
147 rc += " WS_EX_NOACTIVATE";
148 if (exStyle & WS_EX_NOPARENTNOTIFY)
149 rc += " WS_EX_NOPARENTNOTIFY";
150 if (exStyle & WS_EX_NOREDIRECTIONBITMAP)
151 rc += " WS_EX_NOREDIRECTIONBITMAP";
152 if (exStyle & WS_EX_RIGHT)
153 rc += " WS_EX_RIGHT";
154 if (exStyle & WS_EX_RIGHTSCROLLBAR)
155 rc += " WS_EX_RIGHTSCROLLBAR";
156 if (exStyle & WS_EX_RTLREADING)
157 rc += " WS_EX_RTLREADING";
158 if (exStyle & WS_EX_STATICEDGE)
159 rc += " WS_EX_STATICEDGE";
160 if (exStyle & WS_EX_TOPMOST)
161 rc += " WS_EX_TOPMOST";
162 if (exStyle & WS_EX_TRANSPARENT)
163 rc += " WS_EX_TRANSPARENT";
164 if (exStyle & WS_EX_WINDOWEDGE)
165 rc += " WS_EX_WINDOWEDGE";
166 return rc;
167}
168
170{
171 QByteArray rc = "0x";
172 rc += QByteArray::number(flags, 16);
173 if (flags & SWP_FRAMECHANGED)
174 rc += " SWP_FRAMECHANGED";
175 if (flags & SWP_HIDEWINDOW)
176 rc += " SWP_HIDEWINDOW";
177 if (flags & SWP_NOACTIVATE)
178 rc += " SWP_NOACTIVATE";
179 if (flags & SWP_NOCOPYBITS)
180 rc += " SWP_NOCOPYBITS";
181 if (flags & SWP_NOMOVE)
182 rc += " SWP_NOMOVE";
183 if (flags & SWP_NOOWNERZORDER)
184 rc += " SWP_NOOWNERZORDER";
185 if (flags & SWP_NOREDRAW)
186 rc += " SWP_NOREDRAW";
187 if (flags & SWP_NOSENDCHANGING)
188 rc += " SWP_NOSENDCHANGING";
189 if (flags & SWP_NOSIZE)
190 rc += " SWP_NOSIZE";
191 if (flags & SWP_NOZORDER)
192 rc += " SWP_NOZORDER";
193 if (flags & SWP_SHOWWINDOW)
194 rc += " SWP_SHOWWINDOW";
195 if (flags & SWP_ASYNCWINDOWPOS)
196 rc += " SWP_ASYNCWINDOWPOS";
197 if (flags & SWP_DEFERERASE)
198 rc += " SWP_DEFERERASE";
199 if (flags & SWP_DRAWFRAME)
200 rc += " SWP_DRAWFRAME";
201 if (flags & SWP_NOREPOSITION)
202 rc += " SWP_NOREPOSITION";
203 return rc;
204}
205
206[[nodiscard]] static inline QByteArray debugWindowPlacementFlags(const UINT flags)
207{
208 QByteArray rc = "0x";
209 rc += QByteArray::number(flags, 16);
210 if (flags & WPF_SETMINPOSITION)
211 rc += " WPF_SETMINPOSITION";
212 if (flags & WPF_RESTORETOMAXIMIZED)
213 rc += " WPF_RESTORETOMAXIMIZED";
214 if (flags & WPF_ASYNCWINDOWPLACEMENT)
215 rc += " WPF_ASYNCWINDOWPLACEMENT";
216 return rc;
217}
218
219[[nodiscard]] static inline QByteArray debugShowWindowCmd(const UINT cmd)
220{
221 QByteArray rc = {};
222 rc += QByteArray::number(cmd);
223 if (cmd == SW_HIDE)
224 rc += " SW_HIDE";
225 if (cmd == SW_SHOWNORMAL)
226 rc += " SW_SHOWNORMAL";
227 if (cmd == SW_NORMAL)
228 rc += " SW_NORMAL";
229 if (cmd == SW_SHOWMINIMIZED)
230 rc += " SW_SHOWMINIMIZED";
231 if (cmd == SW_SHOWMAXIMIZED)
232 rc += " SW_SHOWMAXIMIZED";
233 if (cmd == SW_MAXIMIZE)
234 rc += " SW_MAXIMIZE";
235 if (cmd == SW_SHOWNOACTIVATE)
236 rc += " SW_SHOWNOACTIVATE";
237 if (cmd == SW_SHOW)
238 rc += " SW_SHOW";
239 if (cmd == SW_MINIMIZE)
240 rc += " SW_MINIMIZE";
241 if (cmd == SW_SHOWMINNOACTIVE)
242 rc += " SW_SHOWMINNOACTIVE";
243 if (cmd == SW_SHOWNA)
244 rc += " SW_SHOWNA";
245 if (cmd == SW_RESTORE)
246 rc += " SW_RESTORE";
247 if (cmd == SW_SHOWDEFAULT)
248 rc += " SW_SHOWDEFAULT";
249 if (cmd == SW_FORCEMINIMIZE)
250 rc += " SW_FORCEMINIMIZE";
251 return rc;
252}
253
254static inline QSize qSizeOfRect(const RECT &rect)
255{
256 return QSize(rect.right -rect.left, rect.bottom - rect.top);
257}
258
259static inline QRect qrectFromRECT(const RECT &rect)
260{
261 return QRect(QPoint(rect.left, rect.top), qSizeOfRect(rect));
262}
263
264static inline RECT RECTfromQRect(const QRect &rect)
265{
266 const int x = rect.left();
267 const int y = rect.top();
268 RECT result = { x, y, x + rect.width(), y + rect.height() };
269 return result;
270}
271
272
273#ifndef QT_NO_DEBUG_STREAM
275{
276 QDebugStateSaver saver(d);
277 d.nospace();
278 d << "RECT(left=" << r.left << ", top=" << r.top
279 << ", right=" << r.right << ", bottom=" << r.bottom
280 << " (" << r.right - r.left << 'x' << r.bottom - r.top << "))";
281 return d;
282}
283
284QDebug operator<<(QDebug d, const POINT &p)
285{
286 QDebugStateSaver saver(d);
287 d.nospace();
288 d << "POINT(x=" << p.x << ", y=" << p.y << ')';
289 return d;
290}
291
292QDebug operator<<(QDebug d, const WINDOWPOS &wp)
293{
294 QDebugStateSaver saver(d);
295 d.nospace();
296 d.noquote();
297 d << "WINDOWPOS(flags=" << debugWinSwpPos(wp.flags) << ", hwnd="
298 << wp.hwnd << ", hwndInsertAfter=" << wp.hwndInsertAfter << ", x=" << wp.x
299 << ", y=" << wp.y << ", cx=" << wp.cx << ", cy=" << wp.cy << ')';
300 return d;
301}
302
303QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p)
304{
305 QDebugStateSaver saver(d);
306 d.nospace();
307 d << "NCCALCSIZE_PARAMS(rgrc=[" << p.rgrc[0] << ", " << p.rgrc[1] << ", "
308 << p.rgrc[2] << "], lppos=" << *p.lppos << ')';
309 return d;
310}
311
312QDebug operator<<(QDebug d, const MINMAXINFO &i)
313{
314 QDebugStateSaver saver(d);
315 d.nospace();
316 d << "MINMAXINFO(maxSize=" << i.ptMaxSize << ", "
317 << "maxpos=" << i.ptMaxPosition << ", "
318 << "maxtrack=" << i.ptMaxTrackSize << ", "
319 << "mintrack=" << i.ptMinTrackSize << ')';
320 return d;
321}
322
323QDebug operator<<(QDebug d, const WINDOWPLACEMENT &wp)
324{
325 QDebugStateSaver saver(d);
326 d.nospace();
327 d.noquote();
328 d << "WINDOWPLACEMENT(flags=" << debugWindowPlacementFlags(wp.flags) << ", showCmd="
329 << debugShowWindowCmd(wp.showCmd) << ", ptMinPosition=" << wp.ptMinPosition
330 << ", ptMaxPosition=" << wp.ptMaxPosition << ", rcNormalPosition="
331 << wp.rcNormalPosition << ')';
332 return d;
333}
334
335QDebug operator<<(QDebug d, const GUID &guid)
336{
337 QDebugStateSaver saver(d);
338 d.nospace();
339 d << '{' << Qt::hex << Qt::uppercasedigits << qSetPadChar(u'0')
340 << qSetFieldWidth(8) << guid.Data1
341 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4)
342 << guid.Data2 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4)
343 << guid.Data3 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4)
344 << qSetFieldWidth(2) << guid.Data4[0] << guid.Data4[1]
345 << qSetFieldWidth(0) << '-' << qSetFieldWidth(2);
346 for (int i = 2; i < 8; ++i)
347 d << guid.Data4[i];
348 d << qSetFieldWidth(0) << '}';
349 return d;
350}
351#endif // !QT_NO_DEBUG_STREAM
352
353static void formatBriefRectangle(QDebug &d, const QRect &r)
354{
355 d << r.width() << 'x' << r.height() << Qt::forcesign << r.x() << r.y() << Qt::noforcesign;
356}
357
358static void formatBriefMargins(QDebug &d, const QMargins &m)
359{
360 d << m.left() << ", " << m.top() << ", " << m.right() << ", " << m.bottom();
361}
362
363// QTBUG-43872, for windows that do not have WS_EX_TOOLWINDOW set, WINDOWPLACEMENT
364// is in workspace/available area coordinates.
365static QPoint windowPlacementOffset(HWND hwnd, const QPoint &point)
366{
367 if (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)
368 return QPoint(0, 0);
370 const QWindowsScreen *screen = screenManager.screens().size() == 1
371 ? screenManager.screens().constFirst() : screenManager.screenAtDp(point);
372 if (screen)
374 return QPoint(0, 0);
375}
376
377// Return the frame geometry relative to the parent
378// if there is one.
379static inline QRect frameGeometry(HWND hwnd, bool topLevel)
380{
381 RECT rect = { 0, 0, 0, 0 };
382 if (topLevel) {
383 WINDOWPLACEMENT windowPlacement;
384 windowPlacement.length = sizeof(WINDOWPLACEMENT);
385 GetWindowPlacement(hwnd, &windowPlacement);
386 if (windowPlacement.showCmd == SW_SHOWMINIMIZED) {
387 const QRect result = qrectFromRECT(windowPlacement.rcNormalPosition);
388 return result.translated(windowPlacementOffset(hwnd, result.topLeft()));
389 }
390 }
391 GetWindowRect(hwnd, &rect); // Screen coordinates.
392 const HWND parent = GetParent(hwnd);
393 if (parent && !topLevel) {
394 const int width = rect.right - rect.left;
395 const int height = rect.bottom - rect.top;
396 POINT leftTop = { rect.left, rect.top };
397 screenToClient(parent, &leftTop);
398 rect.left = leftTop.x;
399 rect.top = leftTop.y;
400 rect.right = leftTop.x + width;
401 rect.bottom = leftTop.y + height;
402 }
403 return qrectFromRECT(rect);
404}
405
406// Return the visibility of the Window (except full screen since it is not a window state).
407static QWindow::Visibility windowVisibility_sys(HWND hwnd)
408{
409 if (!IsWindowVisible(hwnd))
410 return QWindow::Hidden;
411 WINDOWPLACEMENT windowPlacement;
412 windowPlacement.length = sizeof(WINDOWPLACEMENT);
413 if (GetWindowPlacement(hwnd, &windowPlacement)) {
414 switch (windowPlacement.showCmd) {
415 case SW_SHOWMINIMIZED:
416 case SW_MINIMIZE:
417 case SW_FORCEMINIMIZE:
418 return QWindow::Minimized;
419 case SW_SHOWMAXIMIZED:
420 return QWindow::Maximized;
421 default:
422 break;
423 }
424 }
425 return QWindow::Windowed;
426}
427
428static inline bool windowIsAccelerated(const QWindow *w)
429{
430 switch (w->surfaceType()) {
432 return true;
434 return qt_window_private(const_cast<QWindow *>(w))->compositing;
436 return true;
438 return true;
439 default:
440 return false;
441 }
442}
443
444static bool applyBlurBehindWindow(HWND hwnd)
445{
446 DWM_BLURBEHIND blurBehind = {0, 0, nullptr, 0};
447
448 blurBehind.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
449 blurBehind.fEnable = TRUE;
450 blurBehind.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
451
452 const bool result = DwmEnableBlurBehindWindow(hwnd, &blurBehind) == S_OK;
453
454 if (blurBehind.hRgnBlur)
455 DeleteObject(blurBehind.hRgnBlur);
456
457 return result;
458}
459
460// from qwidget_win.cpp, pass flags separately in case they have been "autofixed".
461static bool shouldShowMaximizeButton(const QWindow *w, Qt::WindowFlags flags)
462{
464 return false;
465 // if the user explicitly asked for the maximize button, we try to add
466 // it even if the window has fixed size.
467 return (flags & Qt::CustomizeWindowHint) ||
468 w->maximumSize() == QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX);
469}
470
471// Set the WS_EX_LAYERED flag on a HWND if required. This is required for
472// translucent backgrounds, not fully opaque windows and for
473// Qt::WindowTransparentForInput (in combination with WS_EX_TRANSPARENT).
474bool QWindowsWindow::setWindowLayered(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, qreal opacity)
475{
476 const LONG_PTR exStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
477 const bool needsLayered = (flags & Qt::WindowTransparentForInput)
478 || (hasAlpha && (flags & Qt::FramelessWindowHint)) || opacity < 1.0;
479 const bool isLayered = (exStyle & WS_EX_LAYERED);
480 if (needsLayered != isLayered) {
481 if (needsLayered) {
482 SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED);
483 } else {
484 SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED);
485 }
486 }
487 return needsLayered;
488}
489
490static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, bool accelerated, qreal level)
491{
493 const BYTE alpha = BYTE(qRound(255.0 * level));
494 if (hasAlpha && !accelerated && (flags & Qt::FramelessWindowHint)) {
495 // Non-GL windows with alpha: Use blend function to update.
496 BLENDFUNCTION blend = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA};
497 UpdateLayeredWindow(hwnd, nullptr, nullptr, nullptr, nullptr, nullptr, 0, &blend, ULW_ALPHA);
498 } else {
499 SetLayeredWindowAttributes(hwnd, 0, alpha, LWA_ALPHA);
500 }
501 } else if (IsWindowVisible(hwnd)) { // Repaint when switching from layered.
502 InvalidateRect(hwnd, nullptr, TRUE);
503 }
504}
505
506static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::WindowFlags flags, qreal opacity)
507{
508 const bool isAccelerated = windowIsAccelerated(w);
509 const bool hasAlpha = w->format().hasAlpha();
510
511 if (isAccelerated && hasAlpha)
513
514 setWindowOpacity(hwnd, flags, hasAlpha, isAccelerated, opacity);
515}
516
517[[nodiscard]] static inline int getResizeBorderThickness(const UINT dpi)
518{
519 // The width of the padded border will always be 0 if DWM composition is
520 // disabled, but since it will always be enabled and can't be programtically
521 // disabled from Windows 8, we are safe to go.
522 return GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
523 + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
524}
525
532{
533 POINT pt = {screenPoint.x(), screenPoint.y()};
534 if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
535 UINT dpiX;
536 UINT dpiY;
537 if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY))) {
538 const int gap = getResizeBorderThickness(dpiX);
539 return QMargins(gap, 0, gap, gap);
540 }
541 }
542 return QMargins();
543}
544
545[[nodiscard]] static inline QMargins invisibleMargins(const HWND hwnd)
546{
547 const UINT dpi = GetDpiForWindow(hwnd);
548 const int gap = getResizeBorderThickness(dpi);
549 return QMargins(gap, 0, gap, gap);
550}
551
581{
583 enum Flags { ForceChild = 0x1, ForceTopLevel = 0x2 };
584
585 void fromWindow(const QWindow *w, const Qt::WindowFlags flags, unsigned creationFlags = 0);
586 inline WindowData create(const QWindow *w, const WindowData &data, QString title) const;
587 inline void applyWindowFlags(HWND hwnd) const;
588 void initialize(const QWindow *w, HWND h, bool frameChange, qreal opacityLevel) const;
589
590 Qt::WindowFlags flags;
591 HWND parentHandle = nullptr;
593 unsigned style = 0;
594 unsigned exStyle = 0;
595 bool topLevel = false;
596 bool popup = false;
597 bool dialog = false;
598 bool tool = false;
599 bool embedded = false;
600 bool hasAlpha = false;
601};
602
604{
605 QDebugStateSaver saver(debug);
606 debug.nospace();
607 debug.noquote();
608 debug << "WindowCreationData: " << d.flags
609 << "\n topLevel=" << d.topLevel;
610 if (d.parentHandle)
611 debug << " parent=" << d.parentHandle;
612 debug << " popup=" << d.popup << " dialog=" << d.dialog
613 << " embedded=" << d.embedded << " tool=" << d.tool
614 << "\n style=" << debugWinStyle(d.style);
615 if (d.exStyle)
616 debug << "\n exStyle=" << debugWinExStyle(d.exStyle);
617 return debug;
618}
619
620// Fix top level window flags in case only the type flags are passed.
621static inline void fixTopLevelWindowFlags(Qt::WindowFlags &flags)
622{
623 // Not supported on Windows, also do correction when it is set.
624 flags &= ~Qt::WindowFullscreenButtonHint;
625 switch (flags) {
626 case Qt::Window:
629 break;
630 case Qt::Dialog:
631 case Qt::Tool:
633 break;
634 default:
635 break;
636 }
639}
640
642{
643 const auto getDeviceName = [](const QScreen *screen) -> QString {
644 if (const auto s = static_cast<const QWindowsScreen *>(screen->handle()))
645 return s->data().deviceName;
646 return {};
647 };
648 QScreen *winScreen = w ? w->screen() : QGuiApplication::primaryScreen();
649 if (winScreen && getDeviceName(winScreen) != name) {
650 const auto screens = winScreen->virtualSiblings();
651 for (QScreen *screen : screens) {
652 if (getDeviceName(screen) == name)
653 return screen;
654 }
655 }
656 return winScreen;
657}
658
659static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &context, const QMargins &invMargins)
660{
661 const QPoint orgPos(context->frameX - invMargins.left(), context->frameY - invMargins.top());
662
663 if (!w || w->type() != Qt::Window)
664 return orgPos;
665
666 // Workaround for QTBUG-50371
668 if (!screenForGL)
669 return orgPos;
670
671 const QPoint posFrame(context->frameX, context->frameY);
672 const QMargins margins = context->margins;
673 const QRect scrGeo = screenForGL->handle()->availableGeometry();
674
675 // Point is already in the required screen.
676 if (scrGeo.contains(orgPos))
677 return orgPos;
678
679 // If the visible part of the window is already in the
680 // required screen, just ignore the invisible offset.
681 if (scrGeo.contains(posFrame))
682 return posFrame;
683
684 // Find the original screen containing the coordinates.
685 const auto screens = screenForGL->virtualSiblings();
686 const QScreen *orgScreen = nullptr;
687 for (QScreen *screen : screens) {
688 if (screen->handle()->availableGeometry().contains(posFrame)) {
689 orgScreen = screen;
690 break;
691 }
692 }
693 const QPoint ctPos = QPoint(qMax(scrGeo.left(), scrGeo.center().x()
694 + (margins.right() - margins.left() - context->frameWidth)/2),
695 qMax(scrGeo.top(), scrGeo.center().y()
696 + (margins.bottom() - margins.top() - context->frameHeight)/2));
697
698 // If initial coordinates were outside all screens, center the window on the required screen.
699 if (!orgScreen)
700 return ctPos;
701
702 const QRect orgGeo = orgScreen->handle()->availableGeometry();
703 const QRect orgFrame(QPoint(context->frameX, context->frameY),
704 QSize(context->frameWidth, context->frameHeight));
705
706 // Window would be centered on orgScreen. Center it on the required screen.
707 if (orgGeo.center() == (orgFrame - margins).center())
708 return ctPos;
709
710 // Transform the coordinates to map them into the required screen.
711 const QPoint newPos(scrGeo.left() + ((posFrame.x() - orgGeo.left()) * scrGeo.width()) / orgGeo.width(),
712 scrGeo.top() + ((posFrame.y() - orgGeo.top()) * scrGeo.height()) / orgGeo.height());
713 const QPoint newPosNoMargin(newPos.x() - invMargins.left(), newPos.y() - invMargins.top());
714
715 return scrGeo.contains(newPosNoMargin) ? newPosNoMargin : newPos;
716}
717
718void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flagsIn,
719 unsigned creationFlags)
720{
721 flags = flagsIn;
722
723 // Sometimes QWindow doesn't have a QWindow parent but does have a native parent window,
724 // e.g. in case of embedded ActiveQt servers. They should not be considered a top-level
725 // windows in such cases.
727 if (prop.isValid()) {
728 embedded = true;
729 parentHandle = reinterpret_cast<HWND>(prop.value<WId>());
730 }
731
732 if (creationFlags & ForceChild) {
733 topLevel = false;
734 } else if (embedded) {
735 // Embedded native windows (for example Active X server windows) are by
736 // definition never toplevel, even though they do not have QWindow parents.
737 topLevel = false;
738 } else {
739 topLevel = (creationFlags & ForceTopLevel) ? true : w->isTopLevel();
740 }
741
742 if (topLevel)
744
745 type = static_cast<Qt::WindowType>(int(flags) & Qt::WindowType_Mask);
746 switch (type) {
747 case Qt::Dialog:
748 case Qt::Sheet:
749 dialog = true;
750 break;
751 case Qt::Drawer:
752 case Qt::Tool:
753 tool = true;
754 break;
755 case Qt::Popup:
756 popup = true;
757 break;
758 default:
759 break;
760 }
762 dialog = true;
763
764 // This causes the title bar to drawn RTL and the close button
765 // to be left. Note that this causes:
766 // - All DCs created on the Window to have RTL layout (see SetLayout)
767 // - ClientToScreen() and ScreenToClient() to work in reverse as well.
768 // - Mouse event coordinates to be mirrored.
769 // - Positioning of child Windows.
772 exStyle |= WS_EX_LAYOUTRTL | WS_EX_NOINHERITLAYOUT;
773 }
774
775 // Parent: Use transient parent for top levels.
776 if (popup) {
777 flags |= Qt::WindowStaysOnTopHint; // a popup stays on top, no parent.
778 } else if (!embedded) {
779 if (const QWindow *parentWindow = topLevel ? w->transientParent() : w->parent())
781 }
782
783 if (popup || (type == Qt::ToolTip) || (type == Qt::SplashScreen)) {
784 style = WS_POPUP;
785 } else if (topLevel) {
787 style = WS_POPUP; // no border
788 else if (flags & Qt::WindowTitleHint)
789 style = WS_OVERLAPPED;
790 else
791 style = 0;
792 } else {
793 style = WS_CHILD;
794 }
795
796 style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN ;
797
798 if (topLevel) {
799 if ((type == Qt::Window || dialog || tool)) {
801 style |= WS_POPUP;
803 style |= WS_DLGFRAME;
804 } else {
805 style |= WS_THICKFRAME;
806 }
808 style |= WS_CAPTION; // Contains WS_DLGFRAME
809 }
811 style |= WS_SYSMENU;
813 style |= WS_SYSMENU | WS_BORDER; // QTBUG-2027, dialogs without system menu.
814 exStyle |= WS_EX_DLGMODALFRAME;
815 }
816 const bool showMinimizeButton = flags & Qt::WindowMinimizeButtonHint;
817 if (showMinimizeButton)
818 style |= WS_MINIMIZEBOX;
819 const bool showMaximizeButton = shouldShowMaximizeButton(w, flags);
820 if (showMaximizeButton)
821 style |= WS_MAXIMIZEBOX;
822 if (showMinimizeButton || showMaximizeButton)
823 style |= WS_SYSMENU;
824 if (tool)
825 exStyle |= WS_EX_TOOLWINDOW;
826 if ((flags & Qt::WindowContextHelpButtonHint) && !showMinimizeButton
827 && !showMaximizeButton)
828 exStyle |= WS_EX_CONTEXTHELP;
829 } else {
830 exStyle |= WS_EX_TOOLWINDOW;
831 }
832
833 // make mouse events fall through this window
834 // NOTE: WS_EX_TRANSPARENT flag can make mouse inputs fall through a layered window
835 if (flagsIn & Qt::WindowTransparentForInput)
836 exStyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT;
837
838 // Currently only compatible with D3D surfaces, use it with care.
839 if (qEnvironmentVariableIntValue("QT_QPA_DISABLE_REDIRECTION_SURFACE"))
840 exStyle |= WS_EX_NOREDIRECTIONBITMAP;
841 }
842}
843
844static inline bool shouldApplyDarkFrame(const QWindow *w)
845{
846 if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint))
847 return false;
848 // the application has explicitly opted out of dark frames
849 if (!QWindowsIntegration::instance()->darkModeHandling().testFlag(QWindowsApplication::DarkModeWindowFrames))
850 return false;
851
852 // if the application supports a dark border, and the palette is dark (window background color
853 // is darker than the text), then turn dark-border support on, otherwise use a light border.
854 auto *dWindow = QWindowPrivate::get(const_cast<QWindow*>(w));
855 const QPalette windowPal = dWindow->windowPalette();
856 return windowPal.color(QPalette::WindowText).lightness()
857 > windowPal.color(QPalette::Window).lightness();
858}
859
862{
864 result.flags = flags;
865
866 const auto appinst = reinterpret_cast<HINSTANCE>(GetModuleHandle(nullptr));
867
869
870 const QScreen *screen{};
873 &screen);
874
875 if (title.isEmpty() && (result.flags & Qt::WindowTitleHint))
876 title = topLevel ? qAppName() : w->objectName();
877
878 const auto *titleUtf16 = reinterpret_cast<const wchar_t *>(title.utf16());
879 const auto *classNameUtf16 = reinterpret_cast<const wchar_t *>(windowClassName.utf16());
880
881 // Capture events before CreateWindowEx() returns. The context is cleared in
882 // the QWindowsWindow constructor.
884 rect, data.customMargins,
885 style, exStyle));
887
888 const bool hasFrame = (style & (WS_DLGFRAME | WS_THICKFRAME))
889 && !(result.flags & Qt::FramelessWindowHint);
891 ? invisibleMargins(QPoint(context->frameX, context->frameY)) : QMargins();
892
893 qCDebug(lcQpaWindow).nospace()
894 << "CreateWindowEx: " << w << " class=" << windowClassName << " title=" << title
895 << '\n' << *this << "\nrequested: " << rect << ": "
896 << context->frameWidth << 'x' << context->frameHeight
897 << '+' << context->frameX << '+' << context->frameY
898 << " custom margins: " << context->customMargins
899 << " invisible margins: " << invMargins;
900
901
902 QPoint pos = calcPosition(w, context, invMargins);
903
904 // Mirror the position when creating on a parent in RTL mode, ditto for the obtained geometry.
905 int mirrorParentWidth = 0;
906 if (!w->isTopLevel() && QWindowsBaseWindow::isRtlLayout(parentHandle)) {
907 RECT rect;
908 GetClientRect(parentHandle, &rect);
909 mirrorParentWidth = rect.right;
910 }
911 if (mirrorParentWidth != 0 && pos.x() != CW_USEDEFAULT && context->frameWidth != CW_USEDEFAULT)
912 pos.setX(mirrorParentWidth - context->frameWidth - pos.x());
913
914 result.hwnd = CreateWindowEx(exStyle, classNameUtf16, titleUtf16,
915 style,
916 pos.x(), pos.y(),
917 context->frameWidth, context->frameHeight,
918 parentHandle, nullptr, appinst, nullptr);
919 qCDebug(lcQpaWindow).nospace()
920 << "CreateWindowEx: returns " << w << ' ' << result.hwnd << " obtained geometry: "
921 << context->obtainedPos << context->obtainedSize << ' ' << context->margins;
922
923 if (!result.hwnd) {
924 qErrnoWarning("%s: CreateWindowEx failed", __FUNCTION__);
925 return result;
926 }
927
930
931 if (mirrorParentWidth != 0) {
932 context->obtainedPos.setX(mirrorParentWidth - context->obtainedSize.width()
933 - context->obtainedPos.x());
934 }
935
936 QRect obtainedGeometry(context->obtainedPos, context->obtainedSize);
937
938 result.geometry = obtainedGeometry;
939 result.restoreGeometry = frameGeometry(result.hwnd, topLevel);
940 result.preMoveGeometry = obtainedGeometry;
941 result.fullFrameMargins = context->margins;
942 result.embedded = embedded;
943 result.hasFrame = hasFrame;
944 result.customMargins = context->customMargins;
945
946 return result;
947}
948
950{
951 // Keep enabled and visible from the current style.
952 const LONG_PTR oldStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
953 const LONG_PTR oldExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
954
955 const LONG_PTR newStyle = style | (oldStyle & (WS_DISABLED|WS_VISIBLE));
956 if (oldStyle != newStyle)
957 SetWindowLongPtr(hwnd, GWL_STYLE, newStyle);
958 const LONG_PTR newExStyle = exStyle;
959 if (newExStyle != oldExStyle)
960 SetWindowLongPtr(hwnd, GWL_EXSTYLE, newExStyle);
961 qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << hwnd << *this
962 << "\n Style from " << debugWinStyle(DWORD(oldStyle)) << "\n to "
963 << debugWinStyle(DWORD(newStyle)) << "\n ExStyle from "
964 << debugWinExStyle(DWORD(oldExStyle)) << " to "
965 << debugWinExStyle(DWORD(newExStyle));
966}
967
968void WindowCreationData::initialize(const QWindow *w, HWND hwnd, bool frameChange, qreal opacityLevel) const
969{
970 if (!hwnd)
971 return;
972 UINT swpFlags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER;
973 if (frameChange)
974 swpFlags |= SWP_FRAMECHANGED;
975 if (topLevel) {
976 swpFlags |= SWP_NOACTIVATE;
978 SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, swpFlags);
980 qWarning("QWidget: Incompatible window flags: the window can't be on top and on bottom at the same time");
981 } else if (flags & Qt::WindowStaysOnBottomHint) {
982 SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, swpFlags);
983 } else if (frameChange) { // Force WM_NCCALCSIZE with wParam=1 in case of custom margins.
984 SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, swpFlags);
985 }
987 HMENU systemMenu = GetSystemMenu(hwnd, FALSE);
989 EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_ENABLED);
990 else
991 EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED);
992 }
993 updateGLWindowSettings(w, hwnd, flags, opacityLevel);
994 } else { // child.
995 SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, swpFlags);
996 }
997}
998
999
1000// Scaling helpers for size constraints.
1002{
1004 const qreal factor = QHighDpiScaling::factor(s);
1005 if (!qFuzzyCompare(factor, qreal(1))) {
1006 if (dip.width() > 0 && dip.width() < QWINDOWSIZE_MAX)
1007 dip.setWidth(qRound(qreal(dip.width()) * factor));
1008 if (dip.height() > 0 && dip.height() < QWINDOWSIZE_MAX)
1009 dip.setHeight(qRound(qreal(dip.height()) * factor));
1010 }
1011 }
1012 return dip;
1013}
1014
1026{
1027 if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint))
1028 return {};
1029 RECT rect = {0,0,0,0};
1030 style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
1031 if (AdjustWindowRectEx(&rect, style, FALSE, exStyle) == FALSE)
1032 qErrnoWarning("%s: AdjustWindowRectEx failed", __FUNCTION__);
1033 const QMargins result(qAbs(rect.left), qAbs(rect.top),
1034 qAbs(rect.right), qAbs(rect.bottom));
1035 qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << " style="
1036 << Qt::showbase << Qt::hex << style << " exStyle=" << exStyle << Qt::dec << Qt::noshowbase
1037 << ' ' << rect << ' ' << result;
1038 return result;
1039}
1040
1042{
1043 if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint))
1044 return {};
1045 return frameOnPrimaryScreen(w, DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)),
1046 DWORD(GetWindowLongPtr(hwnd, GWL_EXSTYLE)));
1047}
1048
1049QMargins QWindowsGeometryHint::frame(const QWindow *w, DWORD style, DWORD exStyle, qreal dpi)
1050{
1051 if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint))
1052 return {};
1053 RECT rect = {0,0,0,0};
1054 style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
1055 if (AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE) {
1056 qErrnoWarning("%s: AdjustWindowRectExForDpi failed", __FUNCTION__);
1057 }
1058 const QMargins result(qAbs(rect.left), qAbs(rect.top),
1059 qAbs(rect.right), qAbs(rect.bottom));
1060 qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << " style="
1061 << Qt::showbase << Qt::hex << style << " exStyle=" << exStyle << Qt::dec << Qt::noshowbase
1062 << " dpi=" << dpi
1063 << ' ' << rect << ' ' << result;
1064 return result;
1065}
1066
1067QMargins QWindowsGeometryHint::frame(const QWindow *w, HWND hwnd, DWORD style, DWORD exStyle)
1068{
1069 if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint))
1070 return {};
1072 return frameOnPrimaryScreen(w, style, exStyle);
1073 auto &screenManager = QWindowsContext::instance()->screenManager();
1074 auto screen = screenManager.screenForHwnd(hwnd);
1075 if (!screen)
1076 screen = screenManager.screens().value(0);
1077 const auto dpi = screen ? screen->logicalDpi().first : qreal(96);
1078 return frame(w, style, exStyle, dpi);
1079}
1080
1082{
1083 if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint))
1084 return {};
1085 return frame(w, hwnd, DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)),
1086 DWORD(GetWindowLongPtr(hwnd, GWL_EXSTYLE)));
1087}
1088
1089// For newly created windows.
1091 DWORD style, DWORD exStyle)
1092{
1093 if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint))
1094 return {};
1097 return frameOnPrimaryScreen(w, style, exStyle);
1098 }
1099 qreal dpi = 96;
1100 auto &screenManager = QWindowsContext::instance()->screenManager();
1101 auto screen = screenManager.screenAtDp(geometry.center());
1102 if (!screen)
1103 screen = screenManager.screens().value(0);
1104 if (screen)
1105 dpi = screen->logicalDpi().first;
1106 return QWindowsGeometryHint::frame(w, style, exStyle, dpi);
1107}
1108
1109bool QWindowsGeometryHint::handleCalculateSize(const QMargins &customMargins, const MSG &msg, LRESULT *result)
1110{
1111 // NCCALCSIZE_PARAMS structure if wParam==TRUE
1112 if (!msg.wParam || customMargins.isNull())
1113 return false;
1114 *result = DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
1115 auto *ncp = reinterpret_cast<NCCALCSIZE_PARAMS *>(msg.lParam);
1116 const RECT oldClientArea = ncp->rgrc[0];
1117 ncp->rgrc[0].left += customMargins.left();
1118 ncp->rgrc[0].top += customMargins.top();
1119 ncp->rgrc[0].right -= customMargins.right();
1120 ncp->rgrc[0].bottom -= customMargins.bottom();
1121 result = nullptr;
1122 qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << oldClientArea << '+' << customMargins << "-->"
1123 << ncp->rgrc[0] << ' ' << ncp->rgrc[1] << ' ' << ncp->rgrc[2]
1124 << ' ' << ncp->lppos->cx << ',' << ncp->lppos->cy;
1125 return true;
1126}
1127
1129 const QMargins &margins,
1130 QSize *minimumSize, QSize *maximumSize)
1131{
1132 *minimumSize = toNativeSizeConstrained(w->minimumSize(), screen);
1133 *maximumSize = toNativeSizeConstrained(w->maximumSize(), screen);
1134
1135 const int maximumWidth = qMax(maximumSize->width(), minimumSize->width());
1136 const int maximumHeight = qMax(maximumSize->height(), minimumSize->height());
1137 const int frameWidth = margins.left() + margins.right();
1138 const int frameHeight = margins.top() + margins.bottom();
1139
1140 if (minimumSize->width() > 0)
1141 minimumSize->rwidth() += frameWidth;
1142 if (minimumSize->height() > 0)
1143 minimumSize->rheight() += frameHeight;
1144 if (maximumWidth < QWINDOWSIZE_MAX)
1145 maximumSize->setWidth(maximumWidth + frameWidth);
1146 if (maximumHeight < QWINDOWSIZE_MAX)
1147 maximumSize->setHeight(maximumHeight + frameHeight);
1148}
1149
1151 const QScreen *screen,
1152 const QMargins &margins,
1153 MINMAXINFO *mmi)
1154{
1155 QSize minimumSize;
1156 QSize maximumSize;
1157 frameSizeConstraints(w, screen, margins, &minimumSize, &maximumSize);
1158 qCDebug(lcQpaWindow).nospace() << '>' << __FUNCTION__ << '<' << " min="
1159 << minimumSize.width() << ',' << minimumSize.height()
1160 << " max=" << maximumSize.width() << ',' << maximumSize.height()
1161 << " margins=" << margins
1162 << " in " << *mmi;
1163
1164 if (minimumSize.width() > 0)
1165 mmi->ptMinTrackSize.x = minimumSize.width();
1166 if (minimumSize.height() > 0)
1167 mmi->ptMinTrackSize.y = minimumSize.height();
1168
1169 if (maximumSize.width() < QWINDOWSIZE_MAX)
1170 mmi->ptMaxTrackSize.x = maximumSize.width();
1171 if (maximumSize.height() < QWINDOWSIZE_MAX)
1172 mmi->ptMaxTrackSize.y = maximumSize.height();
1173 qCDebug(lcQpaWindow).nospace() << '<' << __FUNCTION__ << " out " << *mmi;
1174}
1175
1177 const QMargins &margins,
1178 MINMAXINFO *mmi)
1179{
1180 applyToMinMaxInfo(w, w->screen(), margins, mmi);
1181}
1182
1184{
1185 return qt_window_private(const_cast<QWindow *>(w))->positionPolicy
1187}
1188
1207{
1208 return (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) != 0;
1209}
1210
1212{
1213 if (w) {
1214 if (QPlatformWindow *pw = w->handle())
1215 return static_cast<QWindowsBaseWindow *>(pw);
1216 }
1217 return nullptr;
1218}
1219
1221{
1223 return bw ? bw->handle() : HWND(nullptr);
1224}
1225
1227{
1228 const HWND parent = parentHwnd();
1229 return !parent || parent == GetDesktopWindow();
1230}
1231
1233{
1234 return frameGeometry(handle(), isTopLevel());
1235}
1236
1238{
1240}
1241
1243{
1245}
1246
1247std::optional<QWindowsBaseWindow::TouchWindowTouchTypes>
1249{
1250 ULONG touchFlags = 0;
1251 if (IsTouchWindow(handle(), &touchFlags) == FALSE)
1252 return {};
1254 if ((touchFlags & TWF_FINETOUCH) != 0)
1255 result.setFlag(TouchWindowTouchType::FineTouch);
1256 if ((touchFlags & TWF_WANTPALM) != 0)
1257 result.setFlag(TouchWindowTouchType::WantPalmTouch);
1258 return result;
1259}
1260
1261void QWindowsBaseWindow::hide_sys() // Normal hide, do not activate other windows.
1262{
1263 SetWindowPos(handle(), nullptr , 0, 0, 0, 0,
1264 SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
1265}
1266
1268{
1269 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window();
1270 const Qt::WindowType type = window()->type();
1271 if (type == Qt::Popup
1272 || type == Qt::SubWindow // Special case for QTBUG-63121: MDI subwindows with WindowStaysOnTopHint
1274 SetWindowPos(handle(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1275 }
1276}
1277
1279{
1280 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window();
1282 SetWindowPos(handle(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1283}
1284
1286{
1287 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window() << title;
1288 SetWindowText(handle(), reinterpret_cast<const wchar_t *>(title.utf16()));
1289}
1290
1292{
1294}
1295
1297{
1299}
1300
1302{
1304}
1305
1307{
1309 return false;
1310}
1311
1313{
1314 return {};
1315}
1316
1318{
1320}
1321
1343 , m_hwnd(hwnd)
1344 , m_topLevelStyle(0)
1345{
1346}
1347
1349{
1350 const bool wasTopLevel = isTopLevel_sys();
1351 const HWND newParent = newParentWindow ? reinterpret_cast<HWND>(newParentWindow->winId()) : HWND(nullptr);
1352 const bool isTopLevel = !newParent;
1353 const DWORD oldStyle = style();
1354 qCDebug(lcQpaWindow) << __FUNCTION__ << window() << "newParent="
1355 << newParentWindow << newParent << "oldStyle=" << debugWinStyle(oldStyle);
1356 SetParent(m_hwnd, newParent);
1357 if (wasTopLevel != isTopLevel) { // Top level window flags need to be set/cleared manually.
1358 DWORD newStyle = oldStyle;
1359 if (isTopLevel) {
1360 newStyle = m_topLevelStyle;
1361 } else {
1362 m_topLevelStyle = oldStyle;
1363 newStyle &= ~(WS_OVERLAPPEDWINDOW | WS_POPUPWINDOW);
1364 newStyle |= WS_CHILD;
1365 }
1366 SetWindowLongPtr(m_hwnd, GWL_STYLE, newStyle);
1367 }
1368}
1369
1371{
1372 qCDebug(lcQpaWindow) << __FUNCTION__ << window() << visible;
1373 if (visible)
1374 ShowWindow(handle(), SW_SHOWNOACTIVATE);
1375 else
1376 hide_sys();
1377}
1378
1400 const QRect &geometryIn, const QRect &geometry,
1401 const QMargins &cm,
1402 DWORD style, DWORD exStyle) :
1403 window(w),
1404 screen(s),
1405 requestedGeometryIn(geometryIn),
1406 requestedGeometry(geometry),
1407 obtainedPos(geometryIn.topLeft()),
1408 obtainedSize(geometryIn.size()),
1409 margins(QWindowsGeometryHint::frame(w, geometry, style, exStyle))
1410{
1411 // Geometry of toplevels does not consider window frames.
1412 // TODO: No concept of WA_wasMoved yet that would indicate a
1413 // CW_USEDEFAULT unless set. For now, assume that 0,0 means 'default'
1414 // for toplevels.
1415
1416 if (!(w->flags() & Qt::FramelessWindowHint))
1417 customMargins = cm;
1418
1419 if (geometry.isValid()
1420 || !qt_window_private(const_cast<QWindow *>(w))->resizeAutomatic) {
1421 frameX = geometry.x();
1422 frameY = geometry.y();
1423 const QMargins effectiveMargins = margins + customMargins;
1424 frameWidth = effectiveMargins.left() + geometry.width() + effectiveMargins.right();
1425 frameHeight = effectiveMargins.top() + geometry.height() + effectiveMargins.bottom();
1426 if (QWindowsMenuBar::menuBarOf(w) != nullptr) {
1427 menuHeight = GetSystemMetrics(SM_CYMENU);
1429 }
1430 const bool isDefaultPosition = !frameX && !frameY && w->isTopLevel();
1431 if (!QWindowsGeometryHint::positionIncludesFrame(w) && !isDefaultPosition) {
1432 frameX -= effectiveMargins.left();
1433 frameY -= effectiveMargins.top();
1434 }
1435 }
1436
1437 qCDebug(lcQpaWindow).nospace()
1438 << __FUNCTION__ << ' ' << w << ' ' << geometry
1439 << " pos incl. frame=" << QWindowsGeometryHint::positionIncludesFrame(w)
1440 << " frame=" << frameWidth << 'x' << frameHeight << '+'
1441 << frameX << '+' << frameY
1442 << " margins=" << margins << " custom margins=" << customMargins;
1443}
1444
1446{
1448}
1449
1471const char *QWindowsWindow::embeddedNativeParentHandleProperty = "_q_embedded_native_parent_handle";
1472const char *QWindowsWindow::hasBorderInFullScreenProperty = "_q_has_border_in_fullscreen";
1473bool QWindowsWindow::m_borderInFullScreenDefault = false;
1474bool QWindowsWindow::m_inSetgeometry = false;
1475
1477 QWindowsBaseWindow(aWindow),
1478 m_data(data),
1479 m_cursor(new CursorHandle)
1480#if QT_CONFIG(vulkan)
1481 , m_vkSurface(VK_NULL_HANDLE)
1482#endif
1483{
1484 QWindowsContext::instance()->addWindow(m_data.hwnd, this);
1485 const Qt::WindowType type = aWindow->type();
1486 if (type == Qt::Desktop)
1487 return; // No further handling for Qt::Desktop
1488 if (aWindow->surfaceType() == QWindow::Direct3DSurface)
1490#if QT_CONFIG(opengl)
1491 if (aWindow->surfaceType() == QWindow::OpenGLSurface)
1493#endif
1494#if QT_CONFIG(vulkan)
1495 if (aWindow->surfaceType() == QSurface::VulkanSurface)
1497#endif
1498 updateDropSite(window()->isTopLevel());
1499
1500 // Register touch unless if the flags are already set by a hook
1501 // such as HCBT_CREATEWND
1502 if (!touchWindowTouchTypes_sys().has_value())
1504
1505 const qreal opacity = qt_window_private(aWindow)->opacity;
1506 if (!qFuzzyCompare(opacity, qreal(1.0)))
1508
1510
1511 if (aWindow->isTopLevel())
1512 setWindowIcon(aWindow->icon());
1513 if (m_borderInFullScreenDefault || aWindow->property(hasBorderInFullScreenProperty).toBool())
1516}
1517
1519{
1522 UnregisterTouchWindow(m_data.hwnd);
1523 destroyWindow();
1524 destroyIcon();
1525}
1526
1528{
1529 // Clear the creation context as the window can be found in QWindowsContext's map.
1530 QWindowCreationContextPtr creationContext =
1532
1533 QWindow *w = window();
1534 setWindowState(w->windowStates());
1535
1536 // Trigger geometry change (unless it has a special state in which case setWindowState()
1537 // will send the message) and screen change signals of QWindow.
1538 if (w->type() != Qt::Desktop) {
1539 const Qt::WindowState state = w->windowState();
1540 const QRect obtainedGeometry(creationContext->obtainedPos, creationContext->obtainedSize);
1541 QPlatformScreen *obtainedScreen = screenForGeometry(obtainedGeometry);
1542 if (obtainedScreen && screen() != obtainedScreen)
1543 QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(w, obtainedScreen->screen());
1545 && creationContext->requestedGeometryIn != obtainedGeometry) {
1546 QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(w, obtainedGeometry);
1547 }
1548 }
1549 QWindowsWindow::setSavedDpi(GetDpiForWindow(handle()));
1550}
1551
1553{
1554 return window()->requestedFormat();
1555}
1556
1557void QWindowsWindow::fireExpose(const QRegion &region, bool force)
1558{
1559 if (region.isEmpty() && !force)
1561 else
1564}
1565
1566void QWindowsWindow::fireFullExpose(bool force)
1567{
1568 fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), force);
1569}
1570
1571void QWindowsWindow::destroyWindow()
1572{
1573 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window() << m_data.hwnd;
1574 if (m_data.hwnd) { // Stop event dispatching before Window is destroyed.
1576 // Clear any transient child relationships as Windows will otherwise destroy them (QTBUG-35499, QTBUG-36666)
1577 const auto tlw = QGuiApplication::topLevelWindows();
1578 for (QWindow *w : tlw) {
1579 if (w->transientParent() == window()) {
1581 tw->updateTransientParent();
1582 }
1583 }
1585 if (context->windowUnderMouse() == window())
1586 context->clearWindowUnderMouse();
1587 if (hasMouseCapture())
1588 setMouseGrabEnabled(false);
1589 setDropSiteEnabled(false);
1590#if QT_CONFIG(vulkan)
1591 if (m_vkSurface) {
1592 QVulkanInstance *inst = window()->vulkanInstance();
1593 if (inst)
1594 static_cast<QWindowsVulkanInstance *>(inst->handle())->destroySurface(m_vkSurface);
1595 m_vkSurface = VK_NULL_HANDLE;
1596 }
1597#endif
1598#ifndef QT_NO_OPENGL
1599 if (m_surface) {
1601 staticOpenGLContext->destroyWindowSurface(m_surface);
1602 m_surface = nullptr;
1603 }
1604#endif
1605 DestroyWindow(m_data.hwnd);
1606 context->removeWindow(m_data.hwnd);
1607 m_data.hwnd = nullptr;
1608 }
1609}
1610
1611void QWindowsWindow::updateDropSite(bool topLevel)
1612{
1613 bool enabled = false;
1614 bool parentIsEmbedded = false;
1615
1616 if (!topLevel) {
1617 // if the parent window is a foreign window wrapped via QWindow::fromWinId, we need to enable the drop site
1618 // on the first child window
1619 const QWindow *parent = window()->parent();
1620 if (parent && parent->handle() && parent->handle()->isForeignWindow())
1621 parentIsEmbedded = true;
1622 }
1623
1624 if (topLevel || parentIsEmbedded) {
1625 switch (window()->type()) {
1626 case Qt::Window:
1627 case Qt::Dialog:
1628 case Qt::Sheet:
1629 case Qt::Drawer:
1630 case Qt::Popup:
1631 case Qt::Tool:
1632 enabled = true;
1633 break;
1634 default:
1635 break;
1636 }
1637 }
1638 setDropSiteEnabled(enabled);
1639}
1640
1641void QWindowsWindow::setDropSiteEnabled(bool dropEnabled)
1642{
1643 if (isDropSiteEnabled() == dropEnabled)
1644 return;
1645 qCDebug(lcQpaMime) << __FUNCTION__ << window() << dropEnabled;
1646#if QT_CONFIG(clipboard) && QT_CONFIG(draganddrop)
1647 if (dropEnabled) {
1648 Q_ASSERT(m_data.hwnd);
1649 m_dropTarget = new QWindowsOleDropTarget(window());
1650 RegisterDragDrop(m_data.hwnd, m_dropTarget);
1651 CoLockObjectExternal(m_dropTarget, true, true);
1652 } else {
1653 CoLockObjectExternal(m_dropTarget, false, true);
1654 m_dropTarget->Release();
1655 RevokeDragDrop(m_data.hwnd);
1656 m_dropTarget = nullptr;
1657 }
1658#endif // QT_CONFIG(clipboard) && QT_CONFIG(draganddrop)
1659}
1660
1661bool QWindowsWindow::m_screenForGLInitialized = false;
1662
1664{
1665 m_screenForGLInitialized = false;
1666}
1667
1669{
1670 m_screenForGLInitialized = false;
1671}
1672
1674{
1675 static QString forceToScreen;
1676 if (!m_screenForGLInitialized) {
1677 forceToScreen = GpuDescription::detect().gpuSuitableScreen;
1678 m_screenForGLInitialized = true;
1679 }
1680 return forceToScreen.isEmpty() ? nullptr : screenForDeviceName(w, forceToScreen);
1681}
1682
1683// Returns topmost QWindowsWindow ancestor even if there are embedded windows in the chain.
1684// Returns this window if it is the topmost ancestor.
1686{
1687 while (QWindow *parent = w->parent())
1688 w = parent;
1689
1690 if (const QPlatformWindow *handle = w->handle()) {
1691 const auto *ww = static_cast<const QWindowsWindow *>(handle);
1692 if (ww->isEmbedded()) {
1693 HWND parentHWND = GetAncestor(ww->handle(), GA_PARENT);
1694 const HWND desktopHwnd = GetDesktopWindow();
1696 while (parentHWND && parentHWND != desktopHwnd) {
1697 if (QWindowsWindow *ancestor = ctx->findPlatformWindow(parentHWND))
1698 return topLevelOf(ancestor->window());
1699 parentHWND = GetAncestor(parentHWND, GA_PARENT);
1700 }
1701 }
1702 }
1703 return w;
1704}
1705
1708 const QWindowsWindowData &parameters,
1709 const QString &title)
1710{
1711 WindowCreationData creationData;
1712 creationData.fromWindow(w, parameters.flags);
1713 QWindowsWindowData result = creationData.create(w, parameters, title);
1714 // Force WM_NCCALCSIZE (with wParam=1) via SWP_FRAMECHANGED for custom margin.
1715 creationData.initialize(w, result.hwnd, !parameters.customMargins.isNull(), 1);
1716 return result;
1717}
1718
1720{
1721 const QWindow *win = window();
1722 qCDebug(lcQpaWindow) << __FUNCTION__ << this << win << m_data.hwnd << visible;
1723 if (m_data.hwnd) {
1724 if (visible) {
1725 show_sys();
1726
1727 // When the window is layered, we won't get WM_PAINT, and "we" are in control
1728 // over the rendering of the window
1729 // There is nobody waiting for this, so we don't need to flush afterwards.
1730 if (isLayered())
1731 fireFullExpose();
1732 // QTBUG-44928, QTBUG-7386: This is to resolve the problem where popups are
1733 // opened from the system tray and not being implicitly activated
1734
1735 if (win->type() == Qt::Popup && !win->parent() && !QGuiApplication::focusWindow())
1736 SetForegroundWindow(m_data.hwnd);
1737 } else {
1738 if (hasMouseCapture())
1739 setMouseGrabEnabled(false);
1740 if (window()->flags() & Qt::Popup) // from QWidgetPrivate::hide_sys(), activate other
1741 ShowWindow(m_data.hwnd, SW_HIDE);
1742 else
1743 hide_sys();
1744 fireExpose(QRegion());
1745 }
1746 }
1747}
1748
1750{
1751 return m_data.hwnd && IsWindowVisible(m_data.hwnd);
1752}
1753
1755{
1756 // Check for native windows or children of the active native window.
1757 if (const HWND activeHwnd = GetForegroundWindow())
1758 if (m_data.hwnd == activeHwnd || IsChild(activeHwnd, m_data.hwnd))
1759 return true;
1760 return false;
1761}
1762
1764{
1765 const auto *childWindow = static_cast<const QWindowsWindow *>(child);
1766 return IsChild(m_data.hwnd, childWindow->handle());
1767}
1768
1770{
1771 return m_data.embedded;
1772}
1773
1775{
1776 return m_data.hwnd ? QWindowsGeometryHint::mapToGlobal(m_data.hwnd, pos) : pos;
1777}
1778
1780{
1781 return m_data.hwnd ? QWindowsGeometryHint::mapFromGlobal(m_data.hwnd, pos) : pos;
1782}
1783
1784// Update the transient parent for a toplevel window. The concept does not
1785// really exist on Windows, the relationship is set by passing a parent along with !WS_CHILD
1786// to window creation or by setting the parent using GWL_HWNDPARENT (as opposed to
1787// SetParent, which would make it a real child).
1788
1789#ifndef GWL_HWNDPARENT
1790# define GWL_HWNDPARENT (-8)
1791#endif
1792
1793void QWindowsWindow::updateTransientParent() const
1794{
1795 if (window()->type() == Qt::Popup)
1796 return; // QTBUG-34503, // a popup stays on top, no parent, see also WindowCreationData::fromWindow().
1797 // Update transient parent.
1798 const HWND oldTransientParent = GetWindow(m_data.hwnd, GW_OWNER);
1799 HWND newTransientParent = nullptr;
1800 if (const QWindow *tp = window()->transientParent())
1802 if (!tw->testFlag(WithinDestroy)) // Prevent destruction by parent window (QTBUG-35499, QTBUG-36666)
1803 newTransientParent = tw->handle();
1804
1805 // QTSOLBUG-71: When using the MFC/winmigrate solution, it is possible that a child
1806 // window is found, which can cause issues with modality. Loop up to top level.
1807 while (newTransientParent && (GetWindowLongPtr(newTransientParent, GWL_STYLE) & WS_CHILD) != 0)
1808 newTransientParent = GetParent(newTransientParent);
1809
1810 if (newTransientParent != oldTransientParent)
1811 SetWindowLongPtr(m_data.hwnd, GWL_HWNDPARENT, LONG_PTR(newTransientParent));
1812}
1813
1814static inline bool testShowWithoutActivating(const QWindow *window)
1815{
1816 // QWidget-attribute Qt::WA_ShowWithoutActivating .
1817 const QVariant showWithoutActivating = window->property("_q_showWithoutActivating");
1818 return showWithoutActivating.isValid() && showWithoutActivating.toBool();
1819}
1820
1821static void setMinimizedGeometry(HWND hwnd, const QRect &r)
1822{
1823 WINDOWPLACEMENT windowPlacement;
1824 windowPlacement.length = sizeof(WINDOWPLACEMENT);
1825 if (GetWindowPlacement(hwnd, &windowPlacement)) {
1826 windowPlacement.showCmd = SW_SHOWMINIMIZED;
1827 windowPlacement.rcNormalPosition = RECTfromQRect(r);
1828 SetWindowPlacement(hwnd, &windowPlacement);
1829 }
1830}
1831
1832static void setRestoreMaximizedFlag(HWND hwnd, bool set = true)
1833{
1834 // Let Windows know that we need to restore as maximized
1835 WINDOWPLACEMENT windowPlacement;
1836 windowPlacement.length = sizeof(WINDOWPLACEMENT);
1837 if (GetWindowPlacement(hwnd, &windowPlacement)) {
1838 if (set)
1839 windowPlacement.flags |= WPF_RESTORETOMAXIMIZED;
1840 else
1841 windowPlacement.flags &= ~WPF_RESTORETOMAXIMIZED;
1842 SetWindowPlacement(hwnd, &windowPlacement);
1843 }
1844}
1845
1846// partially from QWidgetPrivate::show_sys()
1847void QWindowsWindow::show_sys() const
1848{
1849 int sm = SW_SHOWNORMAL;
1850 bool fakedMaximize = false;
1851 bool restoreMaximize = false;
1852 const QWindow *w = window();
1853 const Qt::WindowFlags flags = w->flags();
1854 const Qt::WindowType type = w->type();
1855 if (w->isTopLevel()) {
1856 const Qt::WindowStates state = w->windowStates();
1857 if (state & Qt::WindowMinimized) {
1858 sm = SW_SHOWMINIMIZED;
1859 if (!isVisible())
1860 sm = SW_SHOWMINNOACTIVE;
1862 restoreMaximize = true;
1863 } else {
1864 updateTransientParent();
1865 if (state & Qt::WindowMaximized) {
1866 sm = SW_SHOWMAXIMIZED;
1867 // Windows will not behave correctly when we try to maximize a window which does not
1868 // have minimize nor maximize buttons in the window frame. Windows would then ignore
1869 // non-available geometry, and rather maximize the widget to the full screen, minus the
1870 // window frame (caption). So, we do a trick here, by adding a maximize button before
1871 // maximizing the widget, and then remove the maximize button afterwards.
1872 if (flags & Qt::WindowTitleHint &&
1874 fakedMaximize = TRUE;
1875 setStyle(style() | WS_MAXIMIZEBOX);
1876 }
1877 } // Qt::WindowMaximized
1878 } // !Qt::WindowMinimized
1879 }
1881 sm = SW_SHOWNOACTIVATE;
1882
1883 if (w->windowStates() & Qt::WindowMaximized)
1884 setFlag(WithinMaximize); // QTBUG-8361
1885
1886 ShowWindow(m_data.hwnd, sm);
1887
1889
1890 if (fakedMaximize) {
1891 setStyle(style() & ~WS_MAXIMIZEBOX);
1892 SetWindowPos(m_data.hwnd, nullptr, 0, 0, 0, 0,
1893 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER
1894 | SWP_FRAMECHANGED);
1895 }
1896 if (restoreMaximize)
1898}
1899
1901{
1902 qCDebug(lcQpaWindow) << __FUNCTION__ << window() << newParent;
1903
1904 if (m_data.hwnd)
1905 setParent_sys(newParent);
1906}
1907
1908void QWindowsWindow::setParent_sys(const QPlatformWindow *parent)
1909{
1910 // Use GetAncestor instead of GetParent, as GetParent can return owner window for toplevels
1911 HWND oldParentHWND = parentHwnd();
1912 HWND newParentHWND = nullptr;
1913 if (parent) {
1914 const auto *parentW = static_cast<const QWindowsWindow *>(parent);
1915 newParentHWND = parentW->handle();
1916
1917 }
1918
1919 // NULL handle means desktop window, which also has its proper handle -> disambiguate
1920 HWND desktopHwnd = GetDesktopWindow();
1921 if (oldParentHWND == desktopHwnd)
1922 oldParentHWND = nullptr;
1923 if (newParentHWND == desktopHwnd)
1924 newParentHWND = nullptr;
1925
1926 if (newParentHWND != oldParentHWND) {
1927 const bool wasTopLevel = oldParentHWND == nullptr;
1928 const bool isTopLevel = newParentHWND == nullptr;
1929
1931 SetParent(m_data.hwnd, newParentHWND);
1933
1934 // WS_CHILD/WS_POPUP must be manually set/cleared in addition
1935 // to dialog frames, etc (see SetParent() ) if the top level state changes.
1936 // Force toplevel state as QWindow::isTopLevel cannot be relied upon here.
1937 if (wasTopLevel != isTopLevel) {
1938 setDropSiteEnabled(false);
1939 setWindowFlags_sys(window()->flags(), unsigned(isTopLevel ? WindowCreationData::ForceTopLevel : WindowCreationData::ForceChild));
1940 updateDropSite(isTopLevel);
1941 }
1942 }
1943}
1944
1946{
1947 fireExpose(QRegion());
1948}
1949
1951{
1952 const QWindow *w = window();
1953 if ((w->surfaceType() == QWindow::OpenGLSurface
1954 || w->surfaceType() == QWindow::VulkanSurface
1955 || w->surfaceType() == QWindow::Direct3DSurface)
1956 && w->format().hasAlpha())
1957 {
1959 }
1960}
1961
1963{
1966}
1967
1968void QWindowsWindow::handleDpiScaledSize(WPARAM wParam, LPARAM lParam, LRESULT *result)
1969{
1970 // We want to keep QWindow's device independent size constant across the
1971 // DPI change. To accomplish this, scale QPlatformWindow's native size
1972 // by the change of DPI (e.g. 120 -> 144 = 1.2), also taking any scale
1973 // factor rounding into account. The win32 window size includes the margins;
1974 // add the margins for the new DPI to the window size.
1975 const UINT dpi = UINT(wParam);
1976 const qreal scale = dpiRelativeScale(dpi);
1977 const QMargins margins = QWindowsGeometryHint::frame(window(), style(), exStyle(), dpi);
1978 if (!(m_data.flags & Qt::FramelessWindowHint)) {
1979 // We need to update the custom margins to match the current DPI, because
1980 // we don't want our users manually hook into this message just to set a
1981 // new margin, but here we can't call setCustomMargins() directly, that
1982 // function will change the window geometry which conflicts with what we
1983 // are currently doing.
1984 m_data.customMargins *= scale;
1985 }
1986
1987 const QSize windowSize = (geometry().size() * scale).grownBy(margins + customMargins());
1988 SIZE *size = reinterpret_cast<SIZE *>(lParam);
1989 size->cx = windowSize.width();
1990 size->cy = windowSize.height();
1991 *result = true; // Inform Windows that we've set a size
1992}
1993
1994void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
1995{
1996 const UINT dpi = HIWORD(wParam);
1997 const qreal scale = dpiRelativeScale(dpi);
1998 setSavedDpi(dpi);
1999 // Send screen change first, so that the new screen is set during any following resize
2001
2002 if (!IsZoomed(hwnd))
2004
2005 // We get WM_DPICHANGED in one of two situations:
2006 //
2007 // 1. The DPI change is a "spontaneous" DPI change as a result of e.g.
2008 // the user dragging the window to a new screen. In this case Windows
2009 // first sends WM_GETDPISCALEDSIZE, where we set the new window size,
2010 // followed by this event where we apply the suggested window geometry
2011 // to the native window. This will make sure the window tracks the mouse
2012 // cursor during screen change, and also that the window size is scaled
2013 // according to the DPI change.
2014 //
2015 // 2. The DPI change is a result of a setGeometry() call. In this case
2016 // Qt has already scaled the window size for the new DPI. Further, Windows
2017 // does not call WM_GETDPISCALEDSIZE, and also applies its own scaling
2018 // to the already scaled window size. Since there is no need to set the
2019 // window geometry again, and the provided geometry is incorrect, we omit
2020 // making the SetWindowPos() call.
2021 if (!m_inSetgeometry) {
2023 const auto prcNewWindow = reinterpret_cast<RECT *>(lParam);
2024 SetWindowPos(hwnd, nullptr, prcNewWindow->left, prcNewWindow->top,
2025 prcNewWindow->right - prcNewWindow->left,
2026 prcNewWindow->bottom - prcNewWindow->top, SWP_NOZORDER | SWP_NOACTIVATE);
2027 // If the window does not have a frame, WM_MOVE and WM_SIZE won't be
2028 // called which prevents the content from being scaled appropriately
2029 // after a DPI change.
2030 if (m_data.flags & Qt::FramelessWindowHint)
2031 handleGeometryChange();
2032 }
2033
2034 // Re-apply mask now that we have a new DPI, which have resulted in
2035 // a new scale factor.
2037}
2038
2040{
2041 const UINT dpi = GetDpiForWindow(hwnd);
2042 const qreal scale = dpiRelativeScale(dpi);
2043 setSavedDpi(dpi);
2044
2046
2047 // Child windows do not get WM_GETDPISCALEDSIZE messages to inform
2048 // Windows about the new size, so we need to manually scale them.
2049 QRect currentGeometry = geometry();
2050 QRect scaledGeometry = QRect(currentGeometry.topLeft() * scale, currentGeometry.size() * scale);
2051 setGeometry(scaledGeometry);
2052}
2053
2055{
2056 WINDOWPLACEMENT wp;
2057 wp.length = sizeof(WINDOWPLACEMENT);
2058 if (GetWindowPlacement(hwnd, &wp)) {
2059 const QRect result = qrectFromRECT(wp.rcNormalPosition);
2060 return result.translated(windowPlacementOffset(hwnd, result.topLeft()));
2061 }
2062 return QRect();
2063}
2064
2066{
2067 // Check for fake 'fullscreen' mode.
2068 const bool fakeFullScreen =
2069 m_savedFrameGeometry.isValid() && (window()->windowStates() & Qt::WindowFullScreen);
2070 const QRect frame = fakeFullScreen ? m_savedFrameGeometry : normalFrameGeometry(m_data.hwnd);
2071 const QMargins margins = fakeFullScreen
2072 ? QWindowsGeometryHint::frame(window(), handle(), m_savedStyle, 0)
2073 : fullFrameMargins();
2074 return frame.isValid() ? frame.marginsRemoved(margins) : frame;
2075}
2076
2077static QString msgUnableToSetGeometry(const QWindowsWindow *platformWindow,
2078 const QRect &requestedRect,
2079 const QRect &obtainedRect,
2080 const QMargins &fullMargins,
2081 const QMargins &customMargins)
2082{
2085 debug.nospace();
2086 debug.noquote();
2087 const auto window = platformWindow->window();
2088 debug << "Unable to set geometry ";
2089 formatBriefRectangle(debug, requestedRect);
2090 debug << " (frame: ";
2091 formatBriefRectangle(debug, requestedRect + fullMargins);
2092 debug << ") on " << window->metaObject()->className() << "/\""
2093 << window->objectName() << "\" on \"" << window->screen()->name()
2094 << "\". Resulting geometry: ";
2095 formatBriefRectangle(debug, obtainedRect);
2096 debug << " (frame: ";
2097 formatBriefRectangle(debug, obtainedRect + fullMargins);
2098 debug << ") margins: ";
2099 formatBriefMargins(debug, fullMargins);
2100 if (!customMargins.isNull()) {
2101 debug << " custom margin: ";
2102 formatBriefMargins(debug, customMargins);
2103 }
2104 const auto minimumSize = window->minimumSize();
2105 const bool hasMinimumSize = !minimumSize.isEmpty();
2106 if (hasMinimumSize)
2107 debug << " minimum size: " << minimumSize.width() << 'x' << minimumSize.height();
2108 const auto maximumSize = window->maximumSize();
2109 const bool hasMaximumSize = maximumSize.width() != QWINDOWSIZE_MAX || maximumSize.height() != QWINDOWSIZE_MAX;
2110 if (hasMaximumSize)
2111 debug << " maximum size: " << maximumSize.width() << 'x' << maximumSize.height();
2112 if (hasMinimumSize || hasMaximumSize) {
2113 MINMAXINFO minmaxInfo;
2114 memset(&minmaxInfo, 0, sizeof(minmaxInfo));
2115 platformWindow->getSizeHints(&minmaxInfo);
2116 debug << ' ' << minmaxInfo;
2117 }
2118 debug << ')';
2119 return result;
2120}
2121
2123{
2124 QBoolBlocker b(m_inSetgeometry);
2125
2126 QRect rect = rectIn;
2127 // This means it is a call from QWindow::setFramePosition() and
2128 // the coordinates include the frame (size is still the contents rectangle).
2130 const QMargins margins = frameMargins();
2131 rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top()));
2132 }
2133
2134 if (m_windowState & Qt::WindowMinimized)
2135 m_data.geometry = rect; // Otherwise set by handleGeometryChange() triggered by event.
2136 else
2137 setWindowState(Qt::WindowNoState);// Update window state to WindowNoState unless minimized
2138
2139 if (m_data.hwnd) {
2140 // A ResizeEvent with resulting geometry will be sent. If we cannot
2141 // achieve that size (for example, window title minimal constraint),
2142 // notify and warn.
2146 if (m_data.geometry != rect && (isVisible() || QLibraryInfo::isDebugBuild())) {
2147 const auto warning =
2148 msgUnableToSetGeometry(this, rectIn, m_data.geometry,
2150 qWarning("%s: %s", __FUNCTION__, qPrintable(warning));
2151 }
2152 } else {
2154 }
2155}
2156
2158{
2159 while (QWindow *transientParent = w->transientParent())
2160 w = transientParent;
2161 return w;
2162}
2163
2165{
2166 // We need the topmost Transient parent since it is the window that will initiate
2167 // the chain of moves, and is the only one with an already up to date DPI, which we
2168 // need for the scaling.
2170
2171 const QWindow *currentWindow = window();
2172 const QWindowList allWindows = QGuiApplication::allWindows();
2173 for (QWindow *w : allWindows) {
2174 if (w->transientParent() == currentWindow && w != currentWindow && w->isVisible()) {
2176
2177 RECT oldChildPos{};
2178 GetWindowRect(transientChild->handle(), &oldChildPos);
2179 const RECT oldParentPos = RECTfromQRect(preMoveRect());
2180
2181 const qreal scale =
2184
2185 const RECT offset =
2186 RECTfromQRect(QRect(scale * (oldChildPos.left - oldParentPos.left),
2187 scale * (oldChildPos.top - oldParentPos.top), 0, 0));
2188 const RECT newParentPos = RECTfromQRect(m_data.geometry);
2189 const RECT newChildPos { newParentPos.left + offset.left,
2190 newParentPos.top + offset.top,
2191 transientChild->geometry().width(),
2192 transientChild->geometry().height() };
2193
2194 SetWindowPos(transientChild->handle(), nullptr, newChildPos.left, newChildPos.top,
2195 newChildPos.right, newChildPos.bottom, SWP_NOZORDER | SWP_NOACTIVATE);
2196 }
2197 }
2198}
2199
2201{
2203 // Minimize/Set parent can send nonsensical move events.
2204 if (!IsIconic(m_data.hwnd) && !testFlag(WithinSetParent))
2205 handleGeometryChange();
2207}
2208
2209void QWindowsWindow::handleResized(int wParam, LPARAM lParam)
2210{
2211 /* Prevents borderless windows from covering the taskbar when maximized. */
2212 if ((m_data.flags.testFlag(Qt::FramelessWindowHint)
2213 || (m_data.flags.testFlag(Qt::CustomizeWindowHint) && !m_data.flags.testFlag(Qt::WindowTitleHint)))
2214 && IsZoomed(m_data.hwnd)) {
2215 const int resizedWidth = LOWORD(lParam);
2216 const int resizedHeight = HIWORD(lParam);
2217
2218 const HMONITOR monitor = MonitorFromWindow(m_data.hwnd, MONITOR_DEFAULTTOPRIMARY);
2219 MONITORINFO monitorInfo = {};
2220 monitorInfo.cbSize = sizeof(MONITORINFO);
2221 GetMonitorInfoW(monitor, &monitorInfo);
2222
2223 int correctLeft = monitorInfo.rcMonitor.left;
2224 int correctTop = monitorInfo.rcMonitor.top;
2225 int correctWidth = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
2226 int correctHeight = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
2227
2228 if (!m_data.flags.testFlag(Qt::FramelessWindowHint)) {
2229 const int borderWidth = invisibleMargins(m_data.hwnd).left();
2230 correctLeft -= borderWidth;
2231 correctTop -= borderWidth;
2232 correctWidth += borderWidth * 2;
2233 correctHeight += borderWidth * 2;
2234 }
2235
2236 if (resizedWidth != correctWidth || resizedHeight != correctHeight) {
2237 qCDebug(lcQpaWindow) << __FUNCTION__ << "correcting: " << resizedWidth << "x"
2238 << resizedHeight << " -> " << correctWidth << "x" << correctHeight;
2239 SetWindowPos(m_data.hwnd, nullptr, correctLeft, correctTop, correctWidth, correctHeight,
2240 SWP_NOZORDER | SWP_NOACTIVATE);
2241 }
2242 }
2243
2244 switch (wParam) {
2245 case SIZE_MAXHIDE: // Some other window affected.
2246 case SIZE_MAXSHOW:
2247 return;
2248 case SIZE_MINIMIZED: // QTBUG-53577, prevent state change events during programmatic state change
2250 handleWindowStateChange(m_windowState | Qt::WindowMinimized);
2251 return;
2252 case SIZE_MAXIMIZED:
2253 handleGeometryChange();
2255 handleWindowStateChange(Qt::WindowMaximized | (isFullScreen_sys() ? Qt::WindowFullScreen
2257 break;
2258 case SIZE_RESTORED:
2259 handleGeometryChange();
2261 if (isFullScreen_sys())
2262 handleWindowStateChange(
2265 else if (m_windowState != Qt::WindowNoState && !testFlag(MaximizeToFullScreen))
2266 handleWindowStateChange(Qt::WindowNoState);
2267 }
2268 break;
2269 }
2270}
2271
2272static inline bool equalDpi(const QDpi &d1, const QDpi &d2)
2273{
2274 return qFuzzyCompare(d1.first, d2.first) && qFuzzyCompare(d1.second, d2.second);
2275}
2276
2278{
2280 return;
2281
2282 QPlatformScreen *currentScreen = screen();
2283 auto topLevel = isTopLevel_sys() ? m_data.hwnd : GetAncestor(m_data.hwnd, GA_ROOT);
2284 const QWindowsScreen *newScreen =
2286
2287 if (newScreen == nullptr || newScreen == currentScreen)
2288 return;
2289 // For screens with different DPI: postpone until WM_DPICHANGE
2290 // Check on currentScreen as it can be 0 when resuming a session (QTBUG-80436).
2291 const bool changingDpi = !equalDpi(QDpi(savedDpi(), savedDpi()), newScreen->logicalDpi());
2292 if (mode == FromGeometryChange && currentScreen != nullptr && changingDpi)
2293 return;
2294
2295 qCDebug(lcQpaWindow).noquote().nospace() << __FUNCTION__
2296 << ' ' << window() << " \"" << (currentScreen ? currentScreen->name() : QString())
2297 << "\"->\"" << newScreen->name() << '"';
2299 QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(window(), newScreen->screen());
2300}
2301
2302void QWindowsWindow::handleGeometryChange()
2303{
2304 const QRect previousGeometry = m_data.geometry;
2305 m_data.geometry = geometry_sys();
2307 // QTBUG-32121: OpenGL/normal windows (with exception of ANGLE
2308 // which we no longer support in Qt 6) do not receive expose
2309 // events when shrinking, synthesize.
2310 if (isExposed()
2311 && m_data.geometry.size() != previousGeometry.size() // Exclude plain move
2312 // One dimension grew -> Windows will send expose, no need to synthesize.
2313 && !(m_data.geometry.width() > previousGeometry.width() || m_data.geometry.height() > previousGeometry.height())) {
2314 fireFullExpose(true);
2315 }
2316
2317 const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
2319
2322
2325
2326 if (!wasSync)
2328 qCDebug(lcQpaEvents) << __FUNCTION__ << this << window() << m_data.geometry;
2329}
2330
2332{
2333 const QMargins margins = fullFrameMargins();
2334 const QRect frameGeometry = rect + margins;
2335
2336 qCDebug(lcQpaWindow) << '>' << __FUNCTION__ << window()
2337 << "\n from " << geometry_sys() << " frame: "
2338 << margins << " to " <<rect
2339 << " new frame: " << frameGeometry;
2340
2341 bool result = false;
2342 const HWND hwnd = handle();
2343 WINDOWPLACEMENT windowPlacement;
2344 windowPlacement.length = sizeof(WINDOWPLACEMENT);
2345 GetWindowPlacement(hwnd, &windowPlacement);
2346 // If the window is hidden and in maximized state or minimized, instead of moving the
2347 // window, set the normal position of the window.
2348 if ((windowPlacement.showCmd == SW_MAXIMIZE && !IsWindowVisible(hwnd))
2349 || windowPlacement.showCmd == SW_SHOWMINIMIZED) {
2350 windowPlacement.rcNormalPosition =
2352 windowPlacement.showCmd = windowPlacement.showCmd == SW_SHOWMINIMIZED ? SW_SHOWMINIMIZED : SW_HIDE;
2353 result = SetWindowPlacement(hwnd, &windowPlacement);
2354 } else {
2355 int x = frameGeometry.x();
2356 if (!window()->isTopLevel()) {
2357 const HWND parentHandle = GetParent(hwnd);
2358 if (isRtlLayout(parentHandle)) {
2359 RECT rect;
2360 GetClientRect(parentHandle, &rect);
2361 x = rect.right - frameGeometry.width() - x;
2362 }
2363 }
2364 result = MoveWindow(hwnd, x, frameGeometry.y(),
2366 }
2367 qCDebug(lcQpaWindow) << '<' << __FUNCTION__ << window()
2368 << "\n resulting " << result << geometry_sys();
2369}
2370
2379{
2380 if (!m_hdc) {
2381 m_hdc = GetDC(handle());
2383 SetLayout(m_hdc, 0); // Clear RTL layout
2384 }
2385 return m_hdc;
2386}
2387
2396{
2397 if (m_hdc) {
2398 ReleaseDC(handle(), m_hdc);
2399 m_hdc = nullptr;
2400 }
2401}
2402
2403static inline bool isSoftwareGl()
2404{
2405#if QT_CONFIG(dynamicgl)
2408#else
2409 return false;
2410#endif // dynamicgl
2411}
2412
2414 WPARAM, LPARAM, LRESULT *result)
2415{
2416 if (message == WM_ERASEBKGND) { // Backing store - ignored.
2417 *result = 1;
2418 return true;
2419 }
2420 // QTBUG-75455: Suppress WM_PAINT sent to invisible windows when setting WS_EX_LAYERED
2421 if (!window()->isVisible() && (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED) != 0)
2422 return false;
2423 // Ignore invalid update bounding rectangles
2424 if (!GetUpdateRect(m_data.hwnd, 0, FALSE))
2425 return false;
2426 PAINTSTRUCT ps;
2427
2428 // GL software rendering (QTBUG-58178) with some AMD cards
2429 // (QTBUG-60527) need InvalidateRect() to suppress artifacts while resizing.
2431 InvalidateRect(hwnd, nullptr, false);
2432
2433 BeginPaint(hwnd, &ps);
2434
2435 // If the a window is obscured by another window (such as a child window)
2436 // we still need to send isExposed=true, for compatibility.
2437 // Our tests depend on it.
2438 fireExpose(QRegion(qrectFromRECT(ps.rcPaint)), true);
2439 if (!QWindowsContext::instance()->asyncExpose())
2441
2442 EndPaint(hwnd, &ps);
2443 return true;
2444}
2445
2447{
2449}
2450
2452{
2453 qCDebug(lcQpaWindow) << '>' << __FUNCTION__ << this << window() << "\n from: "
2454 << m_data.flags << "\n to: " << flags;
2455 const QRect oldGeometry = geometry();
2456 if (m_data.flags != flags) {
2457 m_data.flags = flags;
2458 if (m_data.hwnd) {
2459 m_data = setWindowFlags_sys(flags);
2460 updateDropSite(window()->isTopLevel());
2461 }
2462 }
2463 // When switching to a frameless window, geometry
2464 // may change without a WM_MOVE. Report change manually.
2465 // Do not send synchronously as not to clobber the widget
2466 // geometry in a sequence of setting flags and geometry.
2467 const QRect newGeometry = geometry_sys();
2468 if (oldGeometry != newGeometry)
2469 handleGeometryChange();
2470
2471 qCDebug(lcQpaWindow) << '<' << __FUNCTION__ << "\n returns: "
2472 << m_data.flags << " geometry " << oldGeometry << "->" << newGeometry;
2473}
2474
2475QWindowsWindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt,
2476 unsigned flags) const
2477{
2478 WindowCreationData creationData;
2479 creationData.fromWindow(window(), wt, flags);
2480 creationData.applyWindowFlags(m_data.hwnd);
2481 creationData.initialize(window(), m_data.hwnd, true, m_opacity);
2482
2483 QWindowsWindowData result = m_data;
2484 result.flags = creationData.flags;
2485 result.embedded = creationData.embedded;
2486 result.hasFrame = (creationData.style & (WS_DLGFRAME | WS_THICKFRAME))
2487 && !(creationData.flags & Qt::FramelessWindowHint);
2488 return result;
2489}
2490
2491void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
2492{
2493 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window()
2494 << "\n from " << m_windowState << " to " << state;
2495 m_windowState = state;
2497 if (state & Qt::WindowMinimized) {
2498 handleHidden();
2500 } else {
2501 if (state & Qt::WindowMaximized) {
2502 WINDOWPLACEMENT windowPlacement{};
2503 windowPlacement.length = sizeof(WINDOWPLACEMENT);
2504 GetWindowPlacement(m_data.hwnd, &windowPlacement);
2505 const RECT geometry = RECTfromQRect(m_data.restoreGeometry);
2506 windowPlacement.rcNormalPosition = geometry;
2507 SetWindowPlacement(m_data.hwnd, &windowPlacement);
2508 }
2509 // QTBUG-17548: We send expose events when receiving WM_Paint, but for
2510 // layered windows and transient children, we won't receive any WM_Paint.
2511 QWindow *w = window();
2512 bool exposeEventsSent = false;
2513 if (isLayered()) {
2514 fireFullExpose();
2515 exposeEventsSent = true;
2516 }
2517 const QWindowList allWindows = QGuiApplication::allWindows();
2518 for (QWindow *child : allWindows) {
2519 if (child != w && child->isVisible() && child->transientParent() == w) {
2521 if (platformWindow && platformWindow->isLayered()) {
2522 platformWindow->fireFullExpose();
2523 exposeEventsSent = true;
2524 }
2525 }
2526 }
2527 if (exposeEventsSent && !QWindowsContext::instance()->asyncExpose())
2529 }
2530}
2531
2533{
2534 m_data.restoreGeometry = normalFrameGeometry(m_data.hwnd);
2535}
2536
2538{
2539 if (m_data.hwnd) {
2540 setWindowState_sys(state);
2541 m_windowState = state;
2542 }
2543}
2544
2545bool QWindowsWindow::isFullScreen_sys() const
2546{
2547 const QWindow *w = window();
2548 if (!w->isTopLevel())
2549 return false;
2552 geometry += QMargins(1, 1, 1, 1);
2554 return screen && geometry == screen->geometry();
2555}
2556
2568void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState)
2569{
2570 const Qt::WindowStates oldState = m_windowState;
2571 if (oldState == newState)
2572 return;
2573 qCDebug(lcQpaWindow) << '>' << __FUNCTION__ << this << window()
2574 << " from " << oldState << " to " << newState;
2575
2576 const bool visible = isVisible();
2577 auto stateChange = oldState ^ newState;
2578
2579 if (stateChange & Qt::WindowFullScreen) {
2581 UINT newStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP;
2582 // Save geometry and style to be restored when fullscreen
2583 // is turned off again, since on Windows, it is not a real
2584 // Window state but emulated by changing geometry and style.
2585 if (!m_savedStyle) {
2586 m_savedStyle = style();
2587 if ((oldState & Qt::WindowMinimized) || (oldState & Qt::WindowMaximized)) {
2588 const QRect nf = normalFrameGeometry(m_data.hwnd);
2589 if (nf.isValid())
2590 m_savedFrameGeometry = nf;
2591 } else {
2592 m_savedFrameGeometry = frameGeometry_sys();
2593 }
2594 }
2597 if (m_savedStyle & WS_SYSMENU)
2598 newStyle |= WS_SYSMENU;
2599 if (visible)
2600 newStyle |= WS_VISIBLE;
2602 newStyle |= WS_BORDER;
2603 setStyle(newStyle);
2604 // Use geometry of QWindow::screen() within creation or the virtual screen the
2605 // window is in (QTBUG-31166, QTBUG-30724).
2606 const QScreen *screen = window()->screen();
2607 if (!screen)
2609 const QRect r = screen ? QHighDpi::toNativePixels(screen->geometry(), window()) : m_savedFrameGeometry;
2610
2612 setMinimizedGeometry(m_data.hwnd, r);
2613 if (stateChange & Qt::WindowMaximized)
2615 } else {
2616 const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
2617 const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
2619 SetWindowPos(m_data.hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf);
2620 if (!wasSync)
2625 }
2626 } else {
2627 // Restore saved state.
2628 unsigned newStyle = m_savedStyle ? m_savedStyle : style();
2629 if (visible)
2630 newStyle |= WS_VISIBLE;
2631 setStyle(newStyle);
2632
2633 const QScreen *screen = window()->screen();
2634 if (!screen)
2636 // That area of the virtual desktop might not be covered by a screen anymore.
2637 if (const auto platformScreen = screen->handle()) {
2638 if (!platformScreen->geometry().intersects(m_savedFrameGeometry))
2639 m_savedFrameGeometry.moveTo(platformScreen->geometry().topLeft());
2640 }
2641
2643 setMinimizedGeometry(m_data.hwnd, m_savedFrameGeometry);
2644 if (stateChange & Qt::WindowMaximized)
2646 } else {
2647 UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE;
2648 if (!m_savedFrameGeometry.isValid())
2649 swpf |= SWP_NOSIZE | SWP_NOMOVE;
2650 const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
2652 // After maximized/fullscreen; the window can be in a maximized state. Clear
2653 // it before applying the normal geometry.
2654 if (windowVisibility_sys(m_data.hwnd) == QWindow::Maximized)
2655 ShowWindow(m_data.hwnd, SW_SHOWNOACTIVATE);
2656 SetWindowPos(m_data.hwnd, nullptr, m_savedFrameGeometry.x(), m_savedFrameGeometry.y(),
2657 m_savedFrameGeometry.width(), m_savedFrameGeometry.height(), swpf);
2658 if (!wasSync)
2660 // preserve maximized state
2661 if (visible) {
2663 ShowWindow(m_data.hwnd,
2664 (newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNA);
2666 }
2667 }
2668 m_savedStyle = 0;
2669 m_savedFrameGeometry = QRect();
2670 }
2671 } else if ((oldState & Qt::WindowMaximized) != (newState & Qt::WindowMaximized)) {
2672 if (visible && !(newState & Qt::WindowMinimized)) {
2676 ShowWindow(m_data.hwnd,
2677 (newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
2680 } else if (visible && (oldState & newState & Qt::WindowMinimized)) {
2681 // change of the maximized state while keeping minimized
2683 }
2684 }
2685
2686 if (stateChange & Qt::WindowMinimized) {
2687 if (visible) {
2688 ShowWindow(m_data.hwnd,
2689 (newState & Qt::WindowMinimized) ? SW_MINIMIZE :
2690 (newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNORMAL);
2691 if ((newState & Qt::WindowMinimized) && (stateChange & Qt::WindowMaximized))
2693 }
2694 }
2695 qCDebug(lcQpaWindow) << '<' << __FUNCTION__ << this << window() << newState;
2696}
2697
2698void QWindowsWindow::setStyle(unsigned s) const
2699{
2700 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window() << debugWinStyle(s);
2702 SetWindowLongPtr(m_data.hwnd, GWL_STYLE, s);
2704}
2705
2706void QWindowsWindow::setExStyle(unsigned s) const
2707{
2708 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window() << debugWinExStyle(s);
2709 SetWindowLongPtr(m_data.hwnd, GWL_EXSTYLE, s);
2710}
2711
2713{
2714 switch (event->type()) {
2717 break;
2718 case QEvent::WindowBlocked: // Blocked by another modal window.
2719 setEnabled(false);
2721 if (hasMouseCapture())
2722 ReleaseCapture();
2723 break;
2725 setEnabled(true);
2727 break;
2728 default:
2729 break;
2730 }
2731
2733}
2734
2736{
2737 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window();
2738}
2739
2741{
2742 auto *windowPos = reinterpret_cast<WINDOWPOS *>(message->lParam);
2743
2744 // Tell Windows to discard the entire contents of the client area, as re-using
2745 // parts of the client area would lead to jitter during resize.
2746 windowPos->flags |= SWP_NOCOPYBITS;
2747
2748 if ((windowPos->flags & SWP_NOZORDER) == 0) {
2749 if (QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(qWindow)) {
2750 QWindow *parentWindow = qWindow->parent();
2751 HWND parentHWND = GetAncestor(windowPos->hwnd, GA_PARENT);
2752 HWND desktopHWND = GetDesktopWindow();
2753 platformWindow->m_data.embedded = !parentWindow && parentHWND && (parentHWND != desktopHWND);
2754 }
2755 if (qWindow->flags().testFlag(Qt::WindowStaysOnBottomHint))
2756 windowPos->hwndInsertAfter = HWND_BOTTOM;
2757 }
2758 if (!qWindow->isTopLevel()) // Implement hasHeightForWidth().
2759 return false;
2760 if (windowPos->flags & SWP_NOSIZE)
2761 return false;
2762 const QRect suggestedFrameGeometry(windowPos->x, windowPos->y,
2763 windowPos->cx, windowPos->cy);
2764 const QRect suggestedGeometry = suggestedFrameGeometry - margins;
2765 const QRectF correctedGeometryF = QPlatformWindow::closestAcceptableGeometry(qWindow, suggestedGeometry);
2766 if (!correctedGeometryF.isValid())
2767 return false;
2768 const QRect correctedFrameGeometry = correctedGeometryF.toRect() + margins;
2769 if (correctedFrameGeometry == suggestedFrameGeometry)
2770 return false;
2771 windowPos->x = correctedFrameGeometry.left();
2772 windowPos->y = correctedFrameGeometry.top();
2773 windowPos->cx = correctedFrameGeometry.width();
2774 windowPos->cy = correctedFrameGeometry.height();
2775 return true;
2776}
2777
2779{
2780 const QMargins margins = window()->isTopLevel() ? fullFrameMargins() : QMargins();
2782}
2783
2785{
2786 if (m_data.flags & Qt::FramelessWindowHint)
2787 return;
2788 if (m_data.fullFrameMargins != newMargins) {
2789 qCDebug(lcQpaWindow) << __FUNCTION__ << window() << m_data.fullFrameMargins << "->" << newMargins;
2790 m_data.fullFrameMargins = newMargins;
2791 }
2792}
2793
2795{
2796 // QTBUG-82580: If a native menu is present, force a WM_NCCALCSIZE.
2797 if (GetMenu(m_data.hwnd))
2799 else
2800 calculateFullFrameMargins();
2801}
2802
2803void QWindowsWindow::calculateFullFrameMargins()
2804{
2805 if (m_data.flags & Qt::FramelessWindowHint)
2806 return;
2807 // Normally obtained from WM_NCCALCSIZE. This calculation only works
2808 // when no native menu is present.
2809 const auto systemMargins = testFlag(DisableNonClientScaling)
2811 : frameMargins_sys();
2812 setFullFrameMargins(systemMargins + customMargins());
2813}
2814
2816{
2818 if (isTopLevel() && m_data.hasFrame)
2819 result -= invisibleMargins(m_data.hwnd);
2820 return result;
2821}
2822
2824{
2825 if (m_data.flags & Qt::FramelessWindowHint)
2826 return {};
2827 return m_data.fullFrameMargins;
2828}
2829
2831{
2832 qCDebug(lcQpaWindow) << __FUNCTION__ << level;
2833 if (!qFuzzyCompare(m_opacity, level)) {
2834 m_opacity = level;
2835 if (m_data.hwnd)
2836 setWindowOpacity(m_data.hwnd, m_data.flags,
2838 level);
2839 }
2840}
2841
2842static inline HRGN createRectRegion(const QRect &r)
2843{
2844 return CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height());
2845}
2846
2847static inline void addRectToWinRegion(const QRect &rect, HRGN *winRegion)
2848{
2849 if (const HRGN rectRegion = createRectRegion(rect)) {
2850 HRGN result = CreateRectRgn(0, 0, 0, 0);
2851 if (CombineRgn(result, *winRegion, rectRegion, RGN_OR)) {
2852 DeleteObject(*winRegion);
2853 *winRegion = result;
2854 }
2855 DeleteObject(rectRegion);
2856 }
2857}
2858
2859static HRGN qRegionToWinRegion(const QRegion &region)
2860{
2861 auto it = region.begin();
2862 const auto end = region.end();
2863 if (it == end)
2864 return nullptr;
2865 HRGN hRegion = createRectRegion(*it);
2866 while (++it != end)
2867 addRectToWinRegion(*it, &hRegion);
2868 return hRegion;
2869}
2870
2872{
2873 if (region.isEmpty()) {
2874 SetWindowRgn(m_data.hwnd, nullptr, true);
2875 return;
2876 }
2877 const HRGN winRegion = qRegionToWinRegion(region);
2878
2879 // Mask is in client area coordinates, so offset it in case we have a frame
2880 if (window()->isTopLevel()) {
2881 const QMargins margins = fullFrameMargins();
2882 OffsetRgn(winRegion, margins.left(), margins.top());
2883 }
2884
2885 // SetWindowRgn takes ownership.
2886 if (!SetWindowRgn(m_data.hwnd, winRegion, true))
2887 DeleteObject(winRegion);
2888}
2889
2891{
2892 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window();
2893
2894 if (!m_data.hwnd)
2895 return;
2896
2897 const auto activationBehavior = QWindowsIntegration::instance()->windowActivationBehavior();
2899 || activationBehavior != QWindowsApplication::AlwaysActivateWindow) {
2900 SetForegroundWindow(m_data.hwnd);
2901 SetFocus(m_data.hwnd);
2902 return;
2903 }
2904
2905 // Force activate this window. The following code will bring the window to the
2906 // foreground and activate it. If the window is hidden, it will show up. If
2907 // the window is minimized, it will restore to the previous position.
2908
2909 // But first we need some sanity checks.
2910 if (m_data.flags & Qt::WindowStaysOnBottomHint) {
2911 qCWarning(lcQpaWindow) <<
2912 "Windows with Qt::WindowStaysOnBottomHint can't be brought to the foreground.";
2913 return;
2914 }
2915 if (m_data.flags & Qt::WindowStaysOnTopHint) {
2916 qCWarning(lcQpaWindow) <<
2917 "Windows with Qt::WindowStaysOnTopHint will always be on the foreground.";
2918 return;
2919 }
2920 if (window()->type() == Qt::ToolTip) {
2921 qCWarning(lcQpaWindow) << "ToolTip windows should not be activated.";
2922 return;
2923 }
2924
2925 // We need to show the window first, otherwise we won't be able to bring it to front.
2926 if (!IsWindowVisible(m_data.hwnd))
2927 ShowWindow(m_data.hwnd, SW_SHOW);
2928
2929 if (IsIconic(m_data.hwnd)) {
2930 ShowWindow(m_data.hwnd, SW_RESTORE);
2931 // When the window is restored, it will always become the foreground window.
2932 // So return early here, we don't need the following code to bring it to front.
2933 return;
2934 }
2935
2936 // OK, our window is not minimized, so now we will try to bring it to front manually.
2937 const HWND oldForegroundWindow = GetForegroundWindow();
2938 if (!oldForegroundWindow) // It may be NULL, according to MS docs.
2939 return;
2940
2941 // First try to send a message to the current foreground window to check whether
2942 // it is currently hanging or not.
2943 if (SendMessageTimeoutW(oldForegroundWindow, WM_NULL, 0, 0,
2944 SMTO_BLOCK | SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG, 1000, nullptr) == 0) {
2945 qCWarning(lcQpaWindow) << "The foreground window hangs, can't activate current window.";
2946 return;
2947 }
2948
2949 const DWORD windowThreadProcessId = GetWindowThreadProcessId(oldForegroundWindow, nullptr);
2950 const DWORD currentThreadId = GetCurrentThreadId();
2951
2952 AttachThreadInput(windowThreadProcessId, currentThreadId, TRUE);
2953 const auto cleanup = qScopeGuard([windowThreadProcessId, currentThreadId](){
2954 AttachThreadInput(windowThreadProcessId, currentThreadId, FALSE);
2955 });
2956
2957 BringWindowToTop(m_data.hwnd);
2958
2959 // Activate the window too. This will force us to the virtual desktop this
2960 // window is on, if it's on another virtual desktop.
2961 SetActiveWindow(m_data.hwnd);
2962}
2963
2965{
2966 if (!m_data.hwnd) {
2967 qWarning("%s: No handle", __FUNCTION__);
2968 return false;
2969 }
2970 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window() << grab;
2971
2973 if (grab) {
2974 context->setKeyGrabber(window());
2975 } else {
2976 if (context->keyGrabber() == window())
2977 context->setKeyGrabber(nullptr);
2978 }
2979 return true;
2980}
2981
2983{
2984 qCDebug(lcQpaWindow) << __FUNCTION__ << window() << grab;
2985 if (!m_data.hwnd) {
2986 qWarning("%s: No handle", __FUNCTION__);
2987 return false;
2988 }
2989 if (!isVisible() && grab) {
2990 qWarning("%s: Not setting mouse grab for invisible window %s/'%s'",
2991 __FUNCTION__, window()->metaObject()->className(),
2992 qPrintable(window()->objectName()));
2993 return false;
2994 }
2995 // release grab or an explicit grab overriding autocapture: Clear flag.
2997 if (hasMouseCapture() != grab) {
2998 if (grab) {
2999 SetCapture(m_data.hwnd);
3000 } else {
3001 ReleaseCapture();
3002 }
3003 }
3004 return grab;
3005}
3006
3007static inline DWORD edgesToWinOrientation(Qt::Edges edges)
3008{
3009 if (edges == Qt::LeftEdge)
3010 return 0xf001; // SC_SIZELEFT;
3011 else if (edges == (Qt::RightEdge))
3012 return 0xf002; // SC_SIZERIGHT
3013 else if (edges == (Qt::TopEdge))
3014 return 0xf003; // SC_SIZETOP
3015 else if (edges == (Qt::TopEdge | Qt::LeftEdge))
3016 return 0xf004; // SC_SIZETOPLEFT
3017 else if (edges == (Qt::TopEdge | Qt::RightEdge))
3018 return 0xf005; // SC_SIZETOPRIGHT
3019 else if (edges == (Qt::BottomEdge))
3020 return 0xf006; // SC_SIZEBOTTOM
3021 else if (edges == (Qt::BottomEdge | Qt::LeftEdge))
3022 return 0xf007; // SC_SIZEBOTTOMLEFT
3023 else if (edges == (Qt::BottomEdge | Qt::RightEdge))
3024 return 0xf008; // SC_SIZEBOTTOMRIGHT
3025
3026 return 0xf000; // SC_SIZE
3027}
3028
3030{
3032 return false;
3033
3034 ReleaseCapture();
3035 PostMessage(m_data.hwnd, WM_SYSCOMMAND, edgesToWinOrientation(edges), 0);
3037 return true;
3038}
3039
3041{
3042 ReleaseCapture();
3043 PostMessage(m_data.hwnd, WM_SYSCOMMAND, 0xF012 /*SC_DRAGMOVE*/, 0);
3044 return true;
3045}
3046
3048{
3049 if (enabled) {
3051 } else {
3053 }
3054}
3055
3056void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
3057{
3059 qCDebug(lcQpaWindow) << __FUNCTION__ << window() << *mmi;
3060}
3061
3062bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *result) const
3063{
3064 // QTBUG-32663, suppress resize cursor for fixed size windows.
3065 const QWindow *w = window();
3066 if (!w->isTopLevel() // Task 105852, minimized windows need to respond to user input.
3067 || (m_windowState != Qt::WindowNoState)
3068 || !isActive()
3069 || (m_data.flags & Qt::FramelessWindowHint)) {
3070 return false;
3071 }
3072 const QSize minimumSize = w->minimumSize();
3073 if (minimumSize.isEmpty())
3074 return false;
3075 const QSize maximumSize = w->maximumSize();
3076 const bool fixedWidth = minimumSize.width() == maximumSize.width();
3077 const bool fixedHeight = minimumSize.height() == maximumSize.height();
3078 if (!fixedWidth && !fixedHeight)
3079 return false;
3080 const QPoint localPos = w->mapFromGlobal(QHighDpi::fromNativePixels(globalPos, w));
3081 const QSize size = w->size();
3082 if (fixedHeight) {
3083 if (localPos.y() >= size.height()) {
3084 *result = HTBORDER; // Unspecified border, no resize cursor.
3085 return true;
3086 }
3087 if (localPos.y() < 0) {
3088 const int topResizeBarPos = invisibleMargins(m_data.hwnd).left() - frameMargins().top();
3089 if (localPos.y() < topResizeBarPos) {
3090 *result = HTCAPTION; // Extend caption over top resize bar, let's user move the window.
3091 return true;
3092 }
3093 }
3094 }
3095 if (fixedWidth && (localPos.x() < 0 || localPos.x() >= size.width())) {
3096 *result = HTBORDER; // Unspecified border, no resize cursor.
3097 return true;
3098 }
3099 return false;
3100}
3101
3102#ifndef QT_NO_CURSOR
3103// Return the default cursor (Arrow) from QWindowsCursor's cache.
3105{
3106 if (QScreen *screen = w->screen())
3107 if (const QPlatformScreen *platformScreen = screen->handle())
3108 if (QPlatformCursor *cursor = platformScreen->cursor())
3109 return static_cast<QWindowsCursor *>(cursor)->standardWindowCursor(Qt::ArrowCursor);
3111}
3112
3113// Check whether to apply a new cursor. Either the window in question is
3114// currently under mouse, or it is the parent of the window under mouse and
3115// there is no other window with an explicitly set cursor in-between.
3116static inline bool applyNewCursor(const QWindow *w)
3117{
3118 const QWindow *underMouse = QWindowsContext::instance()->windowUnderMouse();
3119 if (underMouse == w)
3120 return true;
3121 for (const QWindow *p = underMouse; p ; p = p->parent()) {
3122 if (p == w)
3123 return true;
3124 const QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(p);
3125 if (platformWindow && !platformWindow->cursor()->isNull())
3126 return false;
3127 }
3128 return false;
3129}
3130#endif // !QT_NO_CURSOR
3131
3139{
3141 if (isTopLevel())
3143 return;
3144 }
3145#ifndef QT_NO_CURSOR
3146 if (m_cursor->isNull()) { // Recurse up to parent with non-null cursor. Set default for toplevel.
3147 if (const QWindow *p = window()->parent()) {
3148 if (QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(p))
3149 platformWindow->applyCursor();
3150 } else {
3151 SetCursor(defaultCursor(window())->handle());
3152 }
3153 } else {
3154 SetCursor(m_cursor->handle());
3155 }
3156#endif
3157}
3158
3160{
3161#ifndef QT_NO_CURSOR
3162 bool changed = c->handle() != m_cursor->handle();
3163 // QTBUG-98856: Cursors can get out of sync after restoring override
3164 // cursors on native windows. Force an update.
3167 changed = true;
3168 }
3169 if (changed) {
3170 const bool apply = applyNewCursor(window());
3171 qCDebug(lcQpaWindow) << window() << __FUNCTION__
3172 << c->handle() << " doApply=" << apply;
3173 m_cursor = c;
3174 if (apply)
3175 applyCursor();
3176 }
3177#endif
3178}
3179
3181{
3182 if (isAlertState() == enabled)
3183 return;
3184 if (enabled) {
3185 alertWindow(0);
3187 } else {
3190 }
3191}
3192
3194{
3195 UINT timeOutMs = GetCaretBlinkTime();
3196 if (!timeOutMs || timeOutMs == INFINITE)
3197 timeOutMs = 250;
3198
3199 FLASHWINFO info;
3200 info.cbSize = sizeof(info);
3201 info.hwnd = m_data.hwnd;
3202 info.dwFlags = FLASHW_TRAY;
3203 info.dwTimeout = timeOutMs;
3204 info.uCount = durationMs == 0 ? 10 : UINT(durationMs) / timeOutMs;
3205 FlashWindowEx(&info);
3206}
3207
3209{
3210 FLASHWINFO info;
3211 info.cbSize = sizeof(info);
3212 info.hwnd = m_data.hwnd;
3213 info.dwFlags = FLASHW_STOP;
3214 info.dwTimeout = 0;
3215 info.uCount = 0;
3216 FlashWindowEx(&info);
3217}
3218
3220{
3221 return (style() & WS_DISABLED) == 0;
3222}
3223
3225{
3226 const unsigned oldStyle = style();
3227 unsigned newStyle = oldStyle;
3228 if (enabled) {
3229 newStyle &= ~WS_DISABLED;
3230 } else {
3231 newStyle |= WS_DISABLED;
3232 }
3233 if (newStyle != oldStyle)
3234 setStyle(newStyle);
3235}
3236
3237static HICON createHIcon(const QIcon &icon, int xSize, int ySize)
3238{
3239 if (!icon.isNull()) {
3240 // QTBUG-90363, request DPR=1 for the title bar.
3241 const QPixmap pm = icon.pixmap(icon.actualSize(QSize(xSize, ySize)), 1);
3242 if (!pm.isNull())
3243 return qt_pixmapToWinHICON(pm);
3244 }
3245 return nullptr;
3246}
3247
3249{
3250 if (m_data.hwnd) {
3251 destroyIcon();
3252
3253 m_iconSmall = createHIcon(icon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
3254 m_iconBig = createHIcon(icon, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
3255
3256 if (m_iconBig) {
3257 SendMessage(m_data.hwnd, WM_SETICON, 0 /* ICON_SMALL */, LPARAM(m_iconSmall));
3258 SendMessage(m_data.hwnd, WM_SETICON, 1 /* ICON_BIG */, LPARAM(m_iconBig));
3259 } else {
3260 SendMessage(m_data.hwnd, WM_SETICON, 0 /* ICON_SMALL */, LPARAM(m_iconSmall));
3261 SendMessage(m_data.hwnd, WM_SETICON, 1 /* ICON_BIG */, LPARAM(m_iconSmall));
3262 }
3263 }
3264}
3265
3267{
3268 return window()->isTopLevel() && !m_data.embedded;
3269}
3270
3271enum : WORD {
3275
3276static bool queryDarkBorder(HWND hwnd)
3277{
3278 BOOL result = FALSE;
3279 const bool ok =
3280 SUCCEEDED(DwmGetWindowAttribute(hwnd, DwmwaUseImmersiveDarkMode, &result, sizeof(result)))
3281 || SUCCEEDED(DwmGetWindowAttribute(hwnd, DwmwaUseImmersiveDarkModeBefore20h1, &result, sizeof(result)));
3282 if (!ok)
3283 qCWarning(lcQpaWindow, "%s: Unable to retrieve dark window border setting.", __FUNCTION__);
3284 return result == TRUE;
3285}
3286
3288{
3289 const BOOL darkBorder = d ? TRUE : FALSE;
3290 const bool ok =
3291 SUCCEEDED(DwmSetWindowAttribute(hwnd, DwmwaUseImmersiveDarkMode, &darkBorder, sizeof(darkBorder)))
3292 || SUCCEEDED(DwmSetWindowAttribute(hwnd, DwmwaUseImmersiveDarkModeBefore20h1, &darkBorder, sizeof(darkBorder)));
3293 if (!ok)
3294 qCWarning(lcQpaWindow, "%s: Unable to set %s window border.", __FUNCTION__, d ? "dark" : "light");
3295 return ok;
3296}
3297
3299{
3300 // respect explicit opt-out and incompatible palettes or styles
3302 if (queryDarkBorder(m_data.hwnd) == d)
3303 return;
3304
3305 setDarkBorderToWindow(m_data.hwnd, d);
3306}
3307
3309{
3310 return m_menuBar.data();
3311}
3312
3314{
3315 m_menuBar = mb;
3316}
3317
3319{
3320 if (m_data.flags & Qt::FramelessWindowHint)
3321 return {};
3322 return m_data.customMargins;
3323}
3324
3335void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins)
3336{
3337 if (m_data.flags & Qt::FramelessWindowHint) {
3338 qCWarning(lcQpaWindow) << "You should not set custom margins for a frameless window.";
3339 return;
3340 }
3341 if (newCustomMargins != m_data.customMargins) {
3342 const QMargins oldCustomMargins = m_data.customMargins;
3343 m_data.customMargins = newCustomMargins;
3344 // Re-trigger WM_NCALCSIZE with wParam=1 by passing SWP_FRAMECHANGED
3345 const QRect currentFrameGeometry = frameGeometry_sys();
3346 const QPoint topLeft = currentFrameGeometry.topLeft();
3347 QRect newFrame = currentFrameGeometry.marginsRemoved(oldCustomMargins) + m_data.customMargins;
3348 newFrame.moveTo(topLeft);
3349 qCDebug(lcQpaWindow) << __FUNCTION__ << oldCustomMargins << "->" << newCustomMargins
3350 << currentFrameGeometry << "->" << newFrame;
3351 SetWindowPos(m_data.hwnd, nullptr, newFrame.x(), newFrame.y(), newFrame.width(), newFrame.height(), SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE);
3352 }
3353}
3354
3355void *QWindowsWindow::surface(void *nativeConfig, int *err)
3356{
3357#if QT_CONFIG(vulkan)
3358 Q_UNUSED(nativeConfig);
3359 Q_UNUSED(err);
3360 if (window()->surfaceType() == QSurface::VulkanSurface) {
3361 if (!m_vkSurface) {
3362 QVulkanInstance *inst = window()->vulkanInstance();
3363 if (inst)
3364 m_vkSurface = static_cast<QWindowsVulkanInstance *>(inst->handle())->createSurface(handle());
3365 else
3366 qWarning("Attempted to create Vulkan surface without an instance; was QWindow::setVulkanInstance() called?");
3367 }
3368 // Different semantics for VkSurfaces: the return value is the address,
3369 // not the value, given that this is a 64-bit handle even on x86.
3370 return &m_vkSurface;
3371 }
3372#elif defined(QT_NO_OPENGL)
3373 Q_UNUSED(err);
3374 Q_UNUSED(nativeConfig);
3375 return nullptr;
3376#endif
3377#ifndef QT_NO_OPENGL
3378 if (!m_surface) {
3380 m_surface = staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig, err);
3381 }
3382
3383 return m_surface;
3384#else
3385 return nullptr;
3386#endif
3387}
3388
3390{
3391#if QT_CONFIG(vulkan)
3392 if (m_vkSurface) {
3393 QVulkanInstance *inst = window()->vulkanInstance();
3394 if (inst)
3395 static_cast<QWindowsVulkanInstance *>(inst->handle())->destroySurface(m_vkSurface);
3396 m_vkSurface = VK_NULL_HANDLE;
3397 }
3398#endif
3399#ifndef QT_NO_OPENGL
3400 if (m_surface) {
3402 staticOpenGLContext->destroyWindowSurface(m_surface);
3403 m_surface = nullptr;
3404 }
3405#endif // QT_NO_OPENGL
3406}
3407
3409{
3411 return;
3412
3413 // Initially register or re-register to change the flags
3414 const auto touchTypes = QWindowsIntegration::instance()->touchWindowTouchType();
3416 const auto currentTouchTypes = touchWindowTouchTypes_sys();
3417 if (currentTouchTypes.has_value() && currentTouchTypes.value() == touchTypes)
3418 return;
3419 }
3420
3421 ULONG touchFlags = 0;
3422 if (touchTypes.testFlag(TouchWindowTouchType::FineTouch))
3423 touchFlags |= TWF_FINETOUCH;
3424 if (touchTypes.testFlag(TouchWindowTouchType::WantPalmTouch))
3425 touchFlags |= TWF_WANTPALM;
3426 if (RegisterTouchWindow(m_data.hwnd, touchFlags))
3428 else
3429 qErrnoWarning("RegisterTouchWindow() failed for window '%s'.", qPrintable(window()->objectName()));
3430}
3431
3433{
3434#ifndef QT_NO_OPENGL
3435 // For RasterGLSurface windows, that become OpenGL windows dynamically, it might be
3436 // time to set up some GL specifics. This is particularly important for layered
3437 // windows (WS_EX_LAYERED due to alpha > 0).
3438 const bool isCompositing = qt_window_private(window())->compositing;
3439 if (isCompositing != testFlag(Compositing)) {
3440 if (isCompositing)
3442 else
3444
3445 updateGLWindowSettings(window(), m_data.hwnd, m_data.flags, m_opacity);
3446 }
3447#endif
3448}
3449
3451{
3452 if (QPlatformWindow *handle = window->handle())
3454 else
3456}
3457
3459{
3460 m_borderInFullScreenDefault = border;
3461}
3462
3464{
3466}
3467
3469{
3471 return;
3472 if (border)
3474 else
3476 // Directly apply the flag in case we are fullscreen.
3477 if (m_windowState == Qt::WindowFullScreen) {
3478 LONG_PTR style = GetWindowLongPtr(handle(), GWL_STYLE);
3479 if (border)
3480 style |= WS_BORDER;
3481 else
3482 style &= ~WS_BORDER;
3483 SetWindowLongPtr(handle(), GWL_STYLE, style);
3484 }
3485}
3486
3488{
3490}
3491
NSData * m_data
HCURSOR handle() const
bool isNull() const
\inmodule QtCore
Definition qbytearray.h:57
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
int lightness() const noexcept
Definition qcolor.cpp:1860
\inmodule QtCore
\inmodule QtCore
@ ExcludeUserInputEvents
Definition qeventloop.h:27
\inmodule QtCore
Definition qcoreevent.h:45
@ ApplicationPaletteChange
Definition qcoreevent.h:93
@ WindowBlocked
Definition qcoreevent.h:141
@ WindowUnblocked
Definition qcoreevent.h:142
static Qt::ApplicationState applicationState()
static QWindowList topLevelWindows()
Returns a list of the top-level windows in the application.
static QWindowList allWindows()
Returns a list of all the windows in the application.
QScreen * primaryScreen
the primary (or default) screen of the application.
static QWindow * focusWindow()
Returns the QWindow that receives events tied to focus, such as key events.
Qt::LayoutDirection layoutDirection
the default layout direction for this application
static qreal roundScaleFactor(qreal rawFactor)
static bool isActive()
static qreal factor(C *context)
The QIcon class provides scalable icons in different modes and states.
Definition qicon.h:20
bool isNull() const
Returns true if the icon is empty; otherwise returns false.
Definition qicon.cpp:973
QSize actualSize(const QSize &size, Mode mode=Normal, State state=Off) const
Returns the actual size of the icon for the requested size, mode, and state.
Definition qicon.cpp:880
QPixmap pixmap(const QSize &size, Mode mode=Normal, State state=Off) const
Returns a pixmap with the requested size, mode, and state, generating one if necessary.
Definition qicon.cpp:788
static bool isDebugBuild() noexcept Q_DECL_CONST_FUNCTION
qsizetype size() const noexcept
Definition qlist.h:386
const T & constFirst() const noexcept
Definition qlist.h:630
\inmodule QtCore
Definition qmargins.h:23
constexpr int bottom() const noexcept
Returns the bottom margin.
Definition qmargins.h:119
constexpr bool isNull() const noexcept
Returns true if all margins are is 0; otherwise returns false.
Definition qmargins.h:107
constexpr int left() const noexcept
Returns the left margin.
Definition qmargins.h:110
constexpr int right() const noexcept
Returns the right margin.
Definition qmargins.h:116
constexpr int top() const noexcept
Returns the top margin.
Definition qmargins.h:113
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:311
QVariant property(const char *name) const
Returns the value of the object's name property.
Definition qobject.cpp:4187
bool setProperty(const char *name, const QVariant &value)
Sets the value of the object's name property to value.
static OpenGLModuleType openGLModuleType()
Returns the underlying OpenGL implementation type.
static QWindowsOpengl32DLL opengl32
The QPalette class contains color groups for each widget state.
Definition qpalette.h:19
const QColor & color(ColorGroup cg, ColorRole cr) const
Returns the color in the specified color group, used for the given color role.
Definition qpalette.h:66
@ WindowText
Definition qpalette.h:50
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
Definition qpixmap.h:27
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
Definition qpixmap.cpp:460
The QPlatformCursor class provides information about pointer device events (movement,...
The QPlatformScreen class provides an abstraction for visual displays.
virtual QRect geometry() const =0
Reimplement in subclass to return the pixel geometry of the screen.
QScreen * screen() const
virtual QString name() const
virtual QRect availableGeometry() const
Reimplement in subclass to return the pixel geometry of the available space This normally is the desk...
QSurface * surface() const
The QPlatformWindow class provides an abstraction for top-level windows.
static QString formatWindowTitle(const QString &title, const QString &separator)
Call this method to put together a window title composed of title separator the application display n...
QWindow * window() const
Returns the window which belongs to the QPlatformWindow.
QPlatformScreen * screen() const override
Returns the platform screen handle corresponding to this platform window, or null if the window is no...
virtual bool windowEvent(QEvent *event)
Reimplement this method to be able to do any platform specific event handling.
static QRectF closestAcceptableGeometry(const QWindow *w, const QRectF &nativeRect)
Returns the closest acceptable geometry for a given geometry before a resize/move event for platforms...
QPlatformWindow * parent() const
Returns the parent platform window (or \nullptr if orphan).
virtual void setGeometry(const QRect &rect)
This function is called by Qt whenever a window is moved or resized using the QWindow API.
virtual WId winId() const
Reimplement in subclasses to return a handle to the native window.
virtual bool isForeignWindow() const
static QRect initialGeometry(const QWindow *w, const QRect &initialGeometry, int defaultWidth, int defaultHeight, const QScreen **resultingScreenReturn=nullptr)
Helper function to get initial geometry on windowing systems which do not do smart positioning and al...
\inmodule QtCore\reentrant
Definition qpoint.h:23
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:127
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:132
T * data() const
Definition qpointer.h:56
\inmodule QtCore\reentrant
Definition qrect.h:483
constexpr QRect toRect() const noexcept
Returns a QRect based on the values of this rectangle.
Definition qrect.h:845
constexpr bool isValid() const noexcept
Returns true if the rectangle is valid, otherwise returns false.
Definition qrect.h:652
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:238
constexpr bool isValid() const noexcept
Returns true if the rectangle is valid, otherwise returns false.
Definition qrect.h:169
constexpr QRect marginsRemoved(const QMargins &margins) const noexcept
Removes the margins from the rectangle, shrinking it.
Definition qrect.h:453
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:220
constexpr void setSize(const QSize &s) noexcept
Sets the size of the rectangle to the given size.
Definition qrect.h:386
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:175
bool contains(const QRect &r, bool proper=false) const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qrect.cpp:851
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:172
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:184
constexpr QSize size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:241
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:235
constexpr QRect translated(int dx, int dy) const noexcept
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis,...
Definition qrect.h:260
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:187
constexpr void moveTo(int x, int t) noexcept
Moves the rectangle, leaving the top-left corner at the given position (x, y).
Definition qrect.h:269
constexpr QPoint center() const noexcept
Returns the center point of the rectangle.
Definition qrect.h:232
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
const_iterator end() const noexcept
bool isEmpty() const
Returns true if the region is empty; otherwise returns false.
const_iterator begin() const noexcept
The QScreen class is used to query screen properties. \inmodule QtGui.
Definition qscreen.h:32
QList< QScreen * > virtualSiblings() const
Get the screen's virtual siblings.
Definition qscreen.cpp:357
QRect availableGeometry
the screen's available geometry in pixels
Definition qscreen.h:46
QRect geometry
the screen's geometry in pixels
Definition qscreen.h:45
QPlatformScreen * handle() const
Get the platform screen handle.
Definition qscreen.cpp:83
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:132
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:129
constexpr int & rheight() noexcept
Returns a reference to the height.
Definition qsize.h:156
constexpr void setWidth(int w) noexcept
Sets the width to the given width.
Definition qsize.h:135
constexpr int & rwidth() noexcept
Returns a reference to the width.
Definition qsize.h:153
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
Definition qsize.h:123
constexpr void setHeight(int h) noexcept
Sets the height to the given height.
Definition qsize.h:138
\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
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1095
The QSurfaceFormat class represents the format of a QSurface. \inmodule QtGui.
@ RasterGLSurface
Definition qsurface.h:33
@ OpenGLSurface
Definition qsurface.h:32
@ VulkanSurface
Definition qsurface.h:35
@ Direct3DSurface
Definition qsurface.h:37
\inmodule QtCore
Definition qvariant.h:64
T value() const &
Definition qvariant.h:511
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:707
bool toBool() const
Returns the variant as a bool if the variant has userType() Bool.
The QVulkanInstance class represents a native Vulkan instance, enabling Vulkan rendering onto a QSurf...
static QWindowPrivate * get(QWindow *window)
Definition qwindow_p.h:94
PositionPolicy positionPolicy
Definition qwindow_p.h:116
static bool flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags=QEventLoop::AllEvents)
Make Qt Gui process all events on the event queue immediately.
static void handleGeometryChange(QWindow *window, const QRect &newRect)
static bool handleExposeEvent(QWindow *window, const QRegion &region)
static void handleWindowStateChanged(QWindow *window, Qt::WindowStates newState, int oldState=-1)
\inmodule QtGui
Definition qwindow.h:63
Qt::WindowFlags flags
the window flags of the window
Definition qwindow.h:79
SurfaceType surfaceType() const override
Returns the surface type of the window.
Definition qwindow.cpp:628
TouchWindowTouchTypes touchWindowTouchType() const override
WindowActivationBehavior windowActivationBehavior() const override
Base class for QWindowsForeignWindow, QWindowsWindow.
virtual bool isTopLevel() const
QMargins frameMargins_sys() const
bool isTopLevel_sys() const
unsigned exStyle() const
void setHasBorderInFullScreen(bool border) override
QMargins customMargins() const override
bool hasBorderInFullScreen() const override
static QWindowsBaseWindow * baseWindowOf(const QWindow *w)
HWND parentHwnd() const
virtual QMargins fullFrameMargins() const
unsigned style() const
std::optional< TouchWindowTouchTypes > touchWindowTouchTypes_sys() const
static HWND handleOf(const QWindow *w)
QPoint mapToGlobal(const QPoint &pos) const override
Translates the window coordinate pos to global screen coordinates using native methods.
static bool isRtlLayout(HWND hwnd)
QRect frameGeometry_sys() const
QNativeInterface::Private::QWindowsApplication::TouchWindowTouchTypes TouchWindowTouchTypes
QRect geometry_sys() const
virtual HWND handle() const =0
QPoint mapFromGlobal(const QPoint &pos) const override
Translates the global screen coordinate pos to window coordinates using native methods.
void setCustomMargins(const QMargins &margins) override
void setGeometry_sys(const QRect &rect) const
void setWindowTitle_sys(const QString &title)
ULONG STDMETHODCALLTYPE Release() override
Singleton container for all relevant information.
static bool isDarkMode()
QWindowsScreenManager & screenManager()
void addWindow(HWND, QWindowsWindow *w)
static bool shouldHaveNonClientDpiScaling(const QWindow *window)
QString registerWindowClass(const QWindow *w)
static void forceNcCalcSize(HWND hwnd)
QSharedPointer< QWindowCreationContext > setWindowCreationContext(const QSharedPointer< QWindowCreationContext > &ctx)
QWindow * windowUnderMouse() const
static QWindowsContext * instance()
Platform cursor implementation.
static bool hasOverrideCursor()
static HCURSOR createCursorFromShape(Qt::CursorShape cursorShape, const QPlatformScreen *screen=nullptr)
static void enforceOverrideCursor()
HWND handle() const override
void setVisible(bool visible) override
Reimplemented in subclasses to show the surface if visible is true, and hide it if visible is false.
void setParent(const QPlatformWindow *window) override
This function is called to enable native child window in QPA.
QWindowsForeignWindow(QWindow *window, HWND hwnd)
static QWindowsStaticOpenGLContext * staticOpenGLContext()
static QWindowsIntegration * instance()
Windows native menu bar.
static QWindowsMenuBar * menuBarOf(const QWindow *notYetCreatedWindow)
Implementation of IDropTarget.
Manages a list of QWindowsScreen.
const QWindowsScreen * screenForHwnd(HWND hwnd) const
const QWindowsScreen * screenAtDp(const QPoint &p) const
const WindowsScreenList & screens() const
Windows screen.
QDpi logicalDpi() const override
Reimplement this function in subclass to return the logical horizontal and vertical dots per inch met...
static int baseDpi
QString name() const override
Raster or OpenGL Window.
bool handleNonClientHitTest(const QPoint &globalPos, LRESULT *result) const
void alertWindow(int durationMs=0)
void setWindowFlags(Qt::WindowFlags flags) override
Requests setting the window flags of this surface to flags.
void setCustomMargins(const QMargins &m) override
Sets custom margins to be added to the default margins determined by the windows style in the handlin...
void setMenuBar(QWindowsMenuBar *mb)
static QWindowsWindow * windowsWindowOf(const QWindow *w)
void invalidateSurface() override
Invalidates the window's surface by releasing its surface buffers.
HDC getDC()
Allocates a HDC for the window or returns the temporary one obtained from WinAPI BeginPaint within a ...
void setPreMoveRect(const QRect &rect)
QMargins fullFrameMargins() const override
void initialize() override
Called as part of QWindow::create(), after constructing the window.
void handleDpiChangedAfterParent(HWND hwnd)
static void setHasBorderInFullScreenStatic(QWindow *window, bool border)
int savedDpi() const
void checkForScreenChanged(ScreenChangeMode mode=FromGeometryChange)
bool testFlag(unsigned f) const
static QString formatWindowTitle(const QString &title)
void setFlag(unsigned f) const
void clearFlag(unsigned f) const
void setFrameStrutEventsEnabled(bool enabled) override
Reimplement this method to set whether frame strut events should be sent to enabled.
static void settingsChanged()
static bool handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &marginsDp)
void getSizeHints(MINMAXINFO *mmi) const
static void setHasBorderInFullScreenDefault(bool border)
QPlatformScreen * screenForGeometry(const QRect &newGeometry) const
Helper function for finding the new screen for newGeometry in response to a geometry changed event.
~QWindowsWindow() override
bool handleWmPaint(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result)
void setParent(const QPlatformWindow *window) override
This function is called to enable native child window in QPA.
qreal opacity() const
bool setMouseGrabEnabled(bool grab) override
void propagateSizeHints() override
Reimplement to propagate the size hints of the QWindow.
void applyCursor()
Applies to cursor property set on the window to the global cursor.
bool isExposed() const override
Returns if this window is exposed in the windowing system.
bool handleGeometryChanging(MSG *message) const
bool isActive() const override
Returns true if the window should appear active from a style perspective.
void setStyle(unsigned s) const
static QScreen * forcedScreenForGLWindow(const QWindow *w)
static void displayChanged()
bool setKeyboardGrabEnabled(bool grab) override
static bool setWindowLayered(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, qreal opacity)
bool windowEvent(QEvent *event) override
Reimplement this method to be able to do any platform specific event handling.
void setGeometry(const QRect &rect) override
This function is called by Qt whenever a window is moved or resized using the QWindow API.
QRect preMoveRect() const
void setEnabled(bool enabled)
void setVisible(bool visible) override
Reimplemented in subclasses to show the surface if visible is true, and hide it if visible is false.
QSurfaceFormat format() const override
Returns the actual surface format of the window.
static const char * embeddedNativeParentHandleProperty
QWindowsMenuBar * menuBar() const
bool isLayered() const
void handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
QMargins frameMargins() const override
void setWindowIcon(const QIcon &icon) override
Reimplement to set the window icon to icon.
void handleResized(int wParam, LPARAM lParam)
void setOpacity(qreal level) override
Reimplement to be able to let Qt set the opacity level of a window.
bool isEmbedded() const override
Returns true if the window is a child of a non-Qt window.
QMargins customMargins() const override
bool isEnabled() const
bool isAncestorOf(const QPlatformWindow *child) const override
Returns true if the window is an ancestor of the given child.
QRect normalGeometry() const override
Returns the geometry of a window in 'normal' state (neither maximized, fullscreen nor minimized) for ...
void setExStyle(unsigned s) const
qreal dpiRelativeScale(const UINT dpi) const
void setSavedDpi(int dpi)
void requestActivateWindow() override
Reimplement to let Qt be able to request activation/focus for a window.
static QWindow * topLevelOf(QWindow *w)
void handleDpiScaledSize(WPARAM wParam, LPARAM lParam, LRESULT *result)
static bool setDarkBorderToWindow(HWND hwnd, bool d)
QRect geometry() const override
Returns the current geometry of a window.
@ WithinSetParent
Automatic mouse capture on button press.
QPoint mapToGlobal(const QPoint &pos) const override
Translates the window coordinate pos to global screen coordinates using native methods.
static const char * hasBorderInFullScreenProperty
bool startSystemMove() override
Reimplement this method to start a system move operation if the system supports it and return true to...
bool isTopLevel() const override
void releaseDC()
Releases the HDC for the window or does nothing in case it was obtained from WinAPI BeginPaint within...
static QWindow * topTransientOf(QWindow *w)
void setWindowState(Qt::WindowStates state) override
Requests setting the window state of this surface to type.
void setCursor(const CursorHandlePtr &c)
bool hasBorderInFullScreen() const override
bool hasMouseCapture() const
void setHasBorderInFullScreen(bool border) override
QPoint mapFromGlobal(const QPoint &pos) const override
Translates the global screen coordinate pos to window coordinates using native methods.
CursorHandlePtr cursor() const
bool isVisible() const
void handleCompositionSettingsChanged()
void setWindowTitle(const QString &title) override
Reimplement to set the window title to title.
void setDarkBorder(bool d)
QWindowsWindow(QWindow *window, const QWindowsWindowData &data)
bool startSystemResize(Qt::Edges edges) override
Reimplement this method to start a system resize operation if the system supports it and return true ...
void setFullFrameMargins(const QMargins &newMargins)
void setMask(const QRegion &region) override
Reimplement to be able to let Qt set the mask of a window.
void setAlertState(bool enabled) override
Reimplement this method to set whether the window demands attention (for example, by flashing the tas...
HWND handle() const override
bool isAlertState() const override
Reimplement this method return whether the window is in an alert state.
EGLContext ctx
QCursor cursor
QSet< QString >::iterator it
rect
[4]
else opt state
[0]
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
void qErrnoWarning(const char *msg,...)
T toNativePixels(const T &value, const C *context)
T fromNativePixels(const T &value, const C *context)
QRegion toNativeLocalRegion(const QRegion &pointRegion, const QWindow *window)
Combined button and popup list for selecting options.
void destroySurface(int surfaceId)
WindowState
Definition qnamespace.h:250
@ WindowFullScreen
Definition qnamespace.h:254
@ WindowNoState
Definition qnamespace.h:251
@ WindowMinimized
Definition qnamespace.h:252
@ WindowMaximized
Definition qnamespace.h:253
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
QTextStream & showbase(QTextStream &stream)
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() | QTextStream::ShowBase) on stream and r...
@ RightToLeft
QTextStream & noforcesign(QTextStream &stream)
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() & ~QTextStream::ForceSign) on stream and...
QTextStream & uppercasedigits(QTextStream &stream)
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() | QTextStream::UppercaseDigits) on strea...
@ ArrowCursor
QTextStream & noshowbase(QTextStream &stream)
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() & ~QTextStream::ShowBase) on stream and ...
QTextStream & dec(QTextStream &stream)
Calls QTextStream::setIntegerBase(10) on stream and returns stream.
@ RightEdge
@ TopEdge
@ BottomEdge
@ LeftEdge
QTextStream & forcesign(QTextStream &stream)
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() | QTextStream::ForceSign) on stream and ...
@ ApplicationActive
Definition qnamespace.h:265
WindowType
Definition qnamespace.h:204
@ CustomizeWindowHint
Definition qnamespace.h:238
@ Desktop
Definition qnamespace.h:214
@ Widget
Definition qnamespace.h:205
@ FramelessWindowHint
Definition qnamespace.h:224
@ WindowContextHelpButtonHint
Definition qnamespace.h:230
@ WindowStaysOnBottomHint
Definition qnamespace.h:239
@ ToolTip
Definition qnamespace.h:212
@ MSWindowsFixedSizeDialogHint
Definition qnamespace.h:220
@ Drawer
Definition qnamespace.h:209
@ Popup
Definition qnamespace.h:210
@ WindowType_Mask
Definition qnamespace.h:219
@ Window
Definition qnamespace.h:206
@ SplashScreen
Definition qnamespace.h:213
@ WindowStaysOnTopHint
Definition qnamespace.h:232
@ WindowMaximizeButtonHint
Definition qnamespace.h:228
@ WindowMinimizeButtonHint
Definition qnamespace.h:227
@ Dialog
Definition qnamespace.h:207
@ WindowMinMaxButtonsHint
Definition qnamespace.h:229
@ Sheet
Definition qnamespace.h:208
@ WindowTransparentForInput
Definition qnamespace.h:233
@ SubWindow
Definition qnamespace.h:215
@ Tool
Definition qnamespace.h:211
@ WindowTitleHint
Definition qnamespace.h:225
@ WindowSystemMenuHint
Definition qnamespace.h:226
@ WindowCloseButtonHint
Definition qnamespace.h:240
static void * context
#define Q_UNLIKELY(x)
QString qAppName()
static bool initialize()
Definition qctf.cpp:67
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:287
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:281
QPair< qreal, qreal > QDpi
#define qWarning
Definition qlogging.h:162
#define qCWarning(category,...)
#define qCDebug(category,...)
#define SIZE(large, small, mini)
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
GLboolean GLboolean GLboolean b
GLuint64 GLenum void * handle
GLint GLint GLint GLint GLint x
[0]
GLenum mode
const GLfloat * m
GLenum GLuint GLint level
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLuint GLuint end
GLint GLenum GLsizei GLsizei GLsizei GLint border
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLint GLsizei width
GLenum type
GLbitfield flags
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLuint name
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLint y
GLfloat GLfloat GLfloat GLfloat h
struct _cl_event * event
const GLubyte * c
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
GLfloat GLfloat GLfloat alpha
Definition qopenglext.h:418
GLenum GLenum GLenum GLenum GLenum scale
static bool hasAlpha(const QImage &image)
#define QWINDOWSIZE_MAX
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
#define qPrintable(string)
Definition qstring.h:1391
#define QStringLiteral(str)
QScreen * screen
[1]
Definition main.cpp:29
#define QT_CONFIG(feature)
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
QTextStreamManipulator qSetPadChar(QChar ch)
QTextStreamManipulator qSetFieldWidth(int width)
#define Q_UNIMPLEMENTED()
#define Q_UNUSED(x)
quint64 qulonglong
Definition qtypes.h:59
double qreal
Definition qtypes.h:92
Q_GUI_EXPORT QWindowPrivate * qt_window_private(QWindow *window)
Definition qwindow.cpp:2864
struct tagMSG MSG
QSharedPointer< CursorHandle > CursorHandlePtr
bool testFlag(MaskType mask, FlagType flag)
static const auto windowClassName
static QSize toNativeSizeConstrained(QSize dip, const QScreen *s)
static void fixTopLevelWindowFlags(Qt::WindowFlags &flags)
static QString msgUnableToSetGeometry(const QWindowsWindow *platformWindow, const QRect &requestedRect, const QRect &obtainedRect, const QMargins &fullMargins, const QMargins &customMargins)
static QRect normalFrameGeometry(HWND hwnd)
static void formatBriefRectangle(QDebug &d, const QRect &r)
static bool testShowWithoutActivating(const QWindow *window)
static bool shouldShowMaximizeButton(const QWindow *w, Qt::WindowFlags flags)
Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &)
static void setMinimizedGeometry(HWND hwnd, const QRect &r)
static bool applyNewCursor(const QWindow *w)
static bool isSoftwareGl()
static HICON createHIcon(const QIcon &icon, int xSize, int ySize)
static void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::WindowFlags flags, qreal opacity)
@ defaultWindowHeight
@ defaultWindowWidth
static void addRectToWinRegion(const QRect &rect, HRGN *winRegion)
static QByteArray debugWinSwpPos(UINT flags)
static HRGN createRectRegion(const QRect &r)
static QByteArray debugWinStyle(DWORD style)
static QScreen * screenForDeviceName(const QWindow *w, const QString &name)
static QPoint windowPlacementOffset(HWND hwnd, const QPoint &point)
static bool applyBlurBehindWindow(HWND hwnd)
QDebug operator<<(QDebug d, const RECT &r)
static void setRestoreMaximizedFlag(HWND hwnd, bool set=true)
static RECT RECTfromQRect(const QRect &rect)
static QRect frameGeometry(HWND hwnd, bool topLevel)
static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, bool accelerated, qreal level)
static QMargins invisibleMargins(QPoint screenPoint)
Calculates the dimensions of the invisible borders within the window frames which only exist on Windo...
static int getResizeBorderThickness(const UINT dpi)
static bool windowIsAccelerated(const QWindow *w)
static bool equalDpi(const QDpi &d1, const QDpi &d2)
static void formatBriefMargins(QDebug &d, const QMargins &m)
static QByteArray debugWindowPlacementFlags(const UINT flags)
static QSize qSizeOfRect(const RECT &rect)
static DWORD edgesToWinOrientation(Qt::Edges edges)
static bool shouldApplyDarkFrame(const QWindow *w)
static QByteArray debugWinExStyle(DWORD exStyle)
static CursorHandlePtr defaultCursor(const QWindow *w)
static QByteArray debugShowWindowCmd(const UINT cmd)
#define GWL_HWNDPARENT
static HRGN qRegionToWinRegion(const QRegion &region)
@ DwmwaUseImmersiveDarkMode
@ DwmwaUseImmersiveDarkModeBefore20h1
static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &context, const QMargins &invMargins)
static QRect qrectFromRECT(const RECT &rect)
static bool queryDarkBorder(HWND hwnd)
QSharedPointer< QWindowCreationContext > QWindowCreationContextPtr
static QWindow::Visibility windowVisibility_sys(HWND hwnd)
static void screenToClient(HWND hwnd, POINT *wP)
const char className[16]
[1]
Definition qwizard.cpp:100
QWidget * win
Definition settings.cpp:6
QFuture< QSet< QChar > > set
[10]
if(qFloatDistance(a, b)<(1<< 7))
[0]
QFileInfo info(fileName)
[8]
obj metaObject() -> className()
QObject::connect nullptr
QString title
[35]
QDate d1(1995, 5, 17)
[0]
QDate d2(1995, 5, 20)
QLayoutItem * child
[0]
aWidget window() -> setWindowTitle("New Window Title")
[2]
QFrame frame
[0]
view create()
static GpuDescription detect()
Active Context for creating windows.
const QScreen * screen
const QWindow * window
QWindowCreationContext(const QWindow *w, const QScreen *s, const QRect &geometryIn, const QRect &geometry, const QMargins &customMargins, DWORD style, DWORD exStyle)
void applyToMinMaxInfo(MINMAXINFO *mmi) const
Stores geometry constraints and provides utility functions.
static QMargins frameOnPrimaryScreen(const QWindow *w, DWORD style, DWORD exStyle)
static bool positionIncludesFrame(const QWindow *w)
static void frameSizeConstraints(const QWindow *w, const QScreen *screen, const QMargins &margins, QSize *minimumSize, QSize *maximumSize)
static QMargins frame(const QWindow *w, DWORD style, DWORD exStyle, qreal dpi)
static QPoint mapToGlobal(HWND hwnd, const QPoint &)
static QPoint mapFromGlobal(const HWND hwnd, const QPoint &)
static void applyToMinMaxInfo(const QWindow *w, const QScreen *screen, const QMargins &margins, MINMAXINFO *mmi)
static bool handleCalculateSize(const QMargins &customMargins, const MSG &msg, LRESULT *result)
bool moduleIsNotOpengl32() const
Qt::WindowFlags flags
static QWindowsWindowData create(const QWindow *w, const QWindowsWindowData &parameters, const QString &title)
Window creation code.
void applyWindowFlags(HWND hwnd) const
void initialize(const QWindow *w, HWND h, bool frameChange, qreal opacityLevel) const
QWindowsWindowData WindowData
WindowData create(const QWindow *w, const WindowData &data, QString title) const
void fromWindow(const QWindow *w, const Qt::WindowFlags flags, unsigned creationFlags=0)
Qt::WindowFlags flags
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent
virtual HRESULT STDMETHODCALLTYPE SetFocus()=0