Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
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#include "qwindowstheme.h"
9#if QT_CONFIG(draganddrop)
10# include "qwindowsdrag.h"
11#endif
12#include "qwindowsscreen.h"
13#include "qwindowsintegration.h"
14#include "qwindowsmenu.h"
16#if QT_CONFIG(dynamicgl)
17# include "qwindowsglcontext.h"
18#else
20#endif
22#ifdef QT_NO_CURSOR
23# include "qwindowscursor.h"
24#endif
25
26#include <QtGui/qguiapplication.h>
27#include <QtGui/qscreen.h>
28#include <QtGui/qwindow.h>
29#include <QtGui/qregion.h>
30#include <QtGui/qopenglcontext.h>
31#include <QtGui/private/qwindowsthemecache_p.h>
32#include <private/qwindow_p.h> // QWINDOWSIZE_MAX
33#include <private/qguiapplication_p.h>
34#include <private/qhighdpiscaling_p.h>
35#include <qpa/qwindowsysteminterface.h>
36
37#include <QtCore/qdebug.h>
38#include <QtCore/qlibraryinfo.h>
39
40#include <dwmapi.h>
41
42#if QT_CONFIG(vulkan)
44#endif
45
46#include <shellscalingapi.h>
47
49
50using QWindowCreationContextPtr = QSharedPointer<QWindowCreationContext>;
51
52enum {
55};
56
57Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &);
58
59static QByteArray debugWinStyle(DWORD style)
60{
61 QByteArray rc = "0x";
62 rc += QByteArray::number(qulonglong(style), 16);
63 if (style & WS_POPUP)
64 rc += " WS_POPUP";
65 if (style & WS_CHILD)
66 rc += " WS_CHILD";
67 if (style & WS_OVERLAPPED)
68 rc += " WS_OVERLAPPED";
69 if (style & WS_CLIPSIBLINGS)
70 rc += " WS_CLIPSIBLINGS";
71 if (style & WS_CLIPCHILDREN)
72 rc += " WS_CLIPCHILDREN";
73 if (style & WS_THICKFRAME)
74 rc += " WS_THICKFRAME";
75 if (style & WS_DLGFRAME)
76 rc += " WS_DLGFRAME";
77 if (style & WS_SYSMENU)
78 rc += " WS_SYSMENU";
79 if (style & WS_MINIMIZEBOX)
80 rc += " WS_MINIMIZEBOX";
81 if (style & WS_MAXIMIZEBOX)
82 rc += " WS_MAXIMIZEBOX";
83 if (style & WS_BORDER)
84 rc += " WS_BORDER";
85 if (style & WS_CAPTION)
86 rc += " WS_CAPTION";
87 if (style & WS_CHILDWINDOW)
88 rc += " WS_CHILDWINDOW";
89 if (style & WS_DISABLED)
90 rc += " WS_DISABLED";
91 if (style & WS_GROUP)
92 rc += " WS_GROUP";
93 if (style & WS_HSCROLL)
94 rc += " WS_HSCROLL";
95 if (style & WS_ICONIC)
96 rc += " WS_ICONIC";
97 if (style & WS_MAXIMIZE)
98 rc += " WS_MAXIMIZE";
99 if (style & WS_MINIMIZE)
100 rc += " WS_MINIMIZE";
101 if (style & WS_SIZEBOX)
102 rc += " WS_SIZEBOX";
103 if (style & WS_TABSTOP)
104 rc += " WS_TABSTOP";
105 if (style & WS_TILED)
106 rc += " WS_TILED";
107 if (style & WS_VISIBLE)
108 rc += " WS_VISIBLE";
109 if (style & WS_VSCROLL)
110 rc += " WS_VSCROLL";
111 return rc;
112}
113
114static QByteArray debugWinExStyle(DWORD exStyle)
115{
116 QByteArray rc = "0x";
117 rc += QByteArray::number(qulonglong(exStyle), 16);
118 if (exStyle & WS_EX_TOOLWINDOW)
119 rc += " WS_EX_TOOLWINDOW";
120 if (exStyle & WS_EX_CONTEXTHELP)
121 rc += " WS_EX_CONTEXTHELP";
122 if (exStyle & WS_EX_LAYERED)
123 rc += " WS_EX_LAYERED";
124 if (exStyle & WS_EX_DLGMODALFRAME)
125 rc += " WS_EX_DLGMODALFRAME";
126 if (exStyle & WS_EX_LAYOUTRTL)
127 rc += " WS_EX_LAYOUTRTL";
128 if (exStyle & WS_EX_NOINHERITLAYOUT)
129 rc += " WS_EX_NOINHERITLAYOUT";
130 if (exStyle & WS_EX_ACCEPTFILES)
131 rc += " WS_EX_ACCEPTFILES";
132 if (exStyle & WS_EX_APPWINDOW)
133 rc += " WS_EX_APPWINDOW";
134 if (exStyle & WS_EX_CLIENTEDGE)
135 rc += " WS_EX_CLIENTEDGE";
136 if (exStyle & WS_EX_COMPOSITED)
137 rc += " WS_EX_COMPOSITED";
138 if (exStyle & WS_EX_CONTROLPARENT)
139 rc += " WS_EX_CONTROLPARENT";
140 if (exStyle & WS_EX_LEFT)
141 rc += " WS_EX_LEFT";
142 if (exStyle & WS_EX_LEFTSCROLLBAR)
143 rc += " WS_EX_LEFTSCROLLBAR";
144 if (exStyle & WS_EX_LTRREADING)
145 rc += " WS_EX_LTRREADING";
146 if (exStyle & WS_EX_MDICHILD)
147 rc += " WS_EX_MDICHILD";
148 if (exStyle & WS_EX_NOACTIVATE)
149 rc += " WS_EX_NOACTIVATE";
150 if (exStyle & WS_EX_NOPARENTNOTIFY)
151 rc += " WS_EX_NOPARENTNOTIFY";
152 if (exStyle & WS_EX_NOREDIRECTIONBITMAP)
153 rc += " WS_EX_NOREDIRECTIONBITMAP";
154 if (exStyle & WS_EX_RIGHT)
155 rc += " WS_EX_RIGHT";
156 if (exStyle & WS_EX_RIGHTSCROLLBAR)
157 rc += " WS_EX_RIGHTSCROLLBAR";
158 if (exStyle & WS_EX_RTLREADING)
159 rc += " WS_EX_RTLREADING";
160 if (exStyle & WS_EX_STATICEDGE)
161 rc += " WS_EX_STATICEDGE";
162 if (exStyle & WS_EX_TOPMOST)
163 rc += " WS_EX_TOPMOST";
164 if (exStyle & WS_EX_TRANSPARENT)
165 rc += " WS_EX_TRANSPARENT";
166 if (exStyle & WS_EX_WINDOWEDGE)
167 rc += " WS_EX_WINDOWEDGE";
168 return rc;
169}
170
172{
173 QByteArray rc = "0x";
174 rc += QByteArray::number(flags, 16);
175 if (flags & SWP_FRAMECHANGED)
176 rc += " SWP_FRAMECHANGED";
177 if (flags & SWP_HIDEWINDOW)
178 rc += " SWP_HIDEWINDOW";
179 if (flags & SWP_NOACTIVATE)
180 rc += " SWP_NOACTIVATE";
181 if (flags & SWP_NOCOPYBITS)
182 rc += " SWP_NOCOPYBITS";
183 if (flags & SWP_NOMOVE)
184 rc += " SWP_NOMOVE";
185 if (flags & SWP_NOOWNERZORDER)
186 rc += " SWP_NOOWNERZORDER";
187 if (flags & SWP_NOREDRAW)
188 rc += " SWP_NOREDRAW";
189 if (flags & SWP_NOSENDCHANGING)
190 rc += " SWP_NOSENDCHANGING";
191 if (flags & SWP_NOSIZE)
192 rc += " SWP_NOSIZE";
193 if (flags & SWP_NOZORDER)
194 rc += " SWP_NOZORDER";
195 if (flags & SWP_SHOWWINDOW)
196 rc += " SWP_SHOWWINDOW";
197 if (flags & SWP_ASYNCWINDOWPOS)
198 rc += " SWP_ASYNCWINDOWPOS";
199 if (flags & SWP_DEFERERASE)
200 rc += " SWP_DEFERERASE";
201 if (flags & SWP_DRAWFRAME)
202 rc += " SWP_DRAWFRAME";
203 if (flags & SWP_NOREPOSITION)
204 rc += " SWP_NOREPOSITION";
205 return rc;
206}
207
208[[nodiscard]] static inline QByteArray debugWindowPlacementFlags(const UINT flags)
209{
210 QByteArray rc = "0x";
211 rc += QByteArray::number(flags, 16);
212 if (flags & WPF_SETMINPOSITION)
213 rc += " WPF_SETMINPOSITION";
214 if (flags & WPF_RESTORETOMAXIMIZED)
215 rc += " WPF_RESTORETOMAXIMIZED";
216 if (flags & WPF_ASYNCWINDOWPLACEMENT)
217 rc += " WPF_ASYNCWINDOWPLACEMENT";
218 return rc;
219}
220
221[[nodiscard]] static inline QByteArray debugShowWindowCmd(const UINT cmd)
222{
223 QByteArray rc = {};
224 rc += QByteArray::number(cmd);
225 if (cmd == SW_HIDE)
226 rc += " SW_HIDE";
227 if (cmd == SW_SHOWNORMAL)
228 rc += " SW_SHOWNORMAL";
229 if (cmd == SW_NORMAL)
230 rc += " SW_NORMAL";
231 if (cmd == SW_SHOWMINIMIZED)
232 rc += " SW_SHOWMINIMIZED";
233 if (cmd == SW_SHOWMAXIMIZED)
234 rc += " SW_SHOWMAXIMIZED";
235 if (cmd == SW_MAXIMIZE)
236 rc += " SW_MAXIMIZE";
237 if (cmd == SW_SHOWNOACTIVATE)
238 rc += " SW_SHOWNOACTIVATE";
239 if (cmd == SW_SHOW)
240 rc += " SW_SHOW";
241 if (cmd == SW_MINIMIZE)
242 rc += " SW_MINIMIZE";
243 if (cmd == SW_SHOWMINNOACTIVE)
244 rc += " SW_SHOWMINNOACTIVE";
245 if (cmd == SW_SHOWNA)
246 rc += " SW_SHOWNA";
247 if (cmd == SW_RESTORE)
248 rc += " SW_RESTORE";
249 if (cmd == SW_SHOWDEFAULT)
250 rc += " SW_SHOWDEFAULT";
251 if (cmd == SW_FORCEMINIMIZE)
252 rc += " SW_FORCEMINIMIZE";
253 return rc;
254}
255
256static inline QSize qSizeOfRect(const RECT &rect)
257{
258 return QSize(rect.right -rect.left, rect.bottom - rect.top);
259}
260
261static inline QRect qrectFromRECT(const RECT &rect)
262{
263 return QRect(QPoint(rect.left, rect.top), qSizeOfRect(rect));
264}
265
266static inline RECT RECTfromQRect(const QRect &rect)
267{
268 const int x = rect.left();
269 const int y = rect.top();
270 RECT result = { x, y, x + rect.width(), y + rect.height() };
271 return result;
272}
273
274
275#ifndef QT_NO_DEBUG_STREAM
277{
278 QDebugStateSaver saver(d);
279 d.nospace();
280 d << "RECT(left=" << r.left << ", top=" << r.top
281 << ", right=" << r.right << ", bottom=" << r.bottom
282 << " (" << r.right - r.left << 'x' << r.bottom - r.top << "))";
283 return d;
284}
285
286QDebug operator<<(QDebug d, const POINT &p)
287{
288 QDebugStateSaver saver(d);
289 d.nospace();
290 d << "POINT(x=" << p.x << ", y=" << p.y << ')';
291 return d;
292}
293
294QDebug operator<<(QDebug d, const WINDOWPOS &wp)
295{
296 QDebugStateSaver saver(d);
297 d.nospace();
298 d.noquote();
299 d << "WINDOWPOS(flags=" << debugWinSwpPos(wp.flags) << ", hwnd="
300 << wp.hwnd << ", hwndInsertAfter=" << wp.hwndInsertAfter << ", x=" << wp.x
301 << ", y=" << wp.y << ", cx=" << wp.cx << ", cy=" << wp.cy << ')';
302 return d;
303}
304
305QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p)
306{
307 QDebugStateSaver saver(d);
308 d.nospace();
309 d << "NCCALCSIZE_PARAMS(rgrc=[" << p.rgrc[0] << ", " << p.rgrc[1] << ", "
310 << p.rgrc[2] << "], lppos=" << *p.lppos << ')';
311 return d;
312}
313
314QDebug operator<<(QDebug d, const MINMAXINFO &i)
315{
316 QDebugStateSaver saver(d);
317 d.nospace();
318 d << "MINMAXINFO(maxSize=" << i.ptMaxSize << ", "
319 << "maxpos=" << i.ptMaxPosition << ", "
320 << "maxtrack=" << i.ptMaxTrackSize << ", "
321 << "mintrack=" << i.ptMinTrackSize << ')';
322 return d;
323}
324
325QDebug operator<<(QDebug d, const WINDOWPLACEMENT &wp)
326{
327 QDebugStateSaver saver(d);
328 d.nospace();
329 d.noquote();
330 d << "WINDOWPLACEMENT(flags=" << debugWindowPlacementFlags(wp.flags) << ", showCmd="
331 << debugShowWindowCmd(wp.showCmd) << ", ptMinPosition=" << wp.ptMinPosition
332 << ", ptMaxPosition=" << wp.ptMaxPosition << ", rcNormalPosition="
333 << wp.rcNormalPosition << ')';
334 return d;
335}
336
337QDebug operator<<(QDebug d, const GUID &guid)
338{
339 QDebugStateSaver saver(d);
340 d.nospace();
341 d << '{' << Qt::hex << Qt::uppercasedigits << qSetPadChar(u'0')
342 << qSetFieldWidth(8) << guid.Data1
343 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4)
344 << guid.Data2 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4)
345 << guid.Data3 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4)
346 << qSetFieldWidth(2) << guid.Data4[0] << guid.Data4[1]
347 << qSetFieldWidth(0) << '-' << qSetFieldWidth(2);
348 for (int i = 2; i < 8; ++i)
349 d << guid.Data4[i];
350 d << qSetFieldWidth(0) << '}';
351 return d;
352}
353#endif // !QT_NO_DEBUG_STREAM
354
355static void formatBriefRectangle(QDebug &d, const QRect &r)
356{
357 d << r.width() << 'x' << r.height() << Qt::forcesign << r.x() << r.y() << Qt::noforcesign;
358}
359
360static void formatBriefMargins(QDebug &d, const QMargins &m)
361{
362 d << m.left() << ", " << m.top() << ", " << m.right() << ", " << m.bottom();
363}
364
365// QTBUG-43872, for windows that do not have WS_EX_TOOLWINDOW set, WINDOWPLACEMENT
366// is in workspace/available area coordinates.
367static QPoint windowPlacementOffset(HWND hwnd, const QPoint &point)
368{
369 if (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)
370 return QPoint(0, 0);
371 const QWindowsScreenManager &screenManager = QWindowsContext::instance()->screenManager();
372 const QWindowsScreen *screen = screenManager.screens().size() == 1
373 ? screenManager.screens().constFirst() : screenManager.screenAtDp(point);
374 if (screen)
376 return QPoint(0, 0);
377}
378
379// Return the frame geometry relative to the parent
380// if there is one.
381static inline QRect frameGeometry(HWND hwnd, bool topLevel)
382{
383 RECT rect = { 0, 0, 0, 0 };
384 if (topLevel) {
385 WINDOWPLACEMENT windowPlacement;
386 windowPlacement.length = sizeof(WINDOWPLACEMENT);
387 GetWindowPlacement(hwnd, &windowPlacement);
388 if (windowPlacement.showCmd == SW_SHOWMINIMIZED) {
389 const QRect result = qrectFromRECT(windowPlacement.rcNormalPosition);
390 return result.translated(windowPlacementOffset(hwnd, result.topLeft()));
391 }
392 }
393 GetWindowRect(hwnd, &rect); // Screen coordinates.
394 const HWND parent = GetParent(hwnd);
395 if (parent && !topLevel) {
396 const int width = rect.right - rect.left;
397 const int height = rect.bottom - rect.top;
398 POINT leftTop = { rect.left, rect.top };
399 screenToClient(parent, &leftTop);
400 rect.left = leftTop.x;
401 rect.top = leftTop.y;
402 rect.right = leftTop.x + width;
403 rect.bottom = leftTop.y + height;
404 }
405 return qrectFromRECT(rect);
406}
407
408// Return the visibility of the Window (except full screen since it is not a window state).
409static QWindow::Visibility windowVisibility_sys(HWND hwnd)
410{
411 if (!IsWindowVisible(hwnd))
412 return QWindow::Hidden;
413 WINDOWPLACEMENT windowPlacement;
414 windowPlacement.length = sizeof(WINDOWPLACEMENT);
415 if (GetWindowPlacement(hwnd, &windowPlacement)) {
416 switch (windowPlacement.showCmd) {
417 case SW_SHOWMINIMIZED:
418 case SW_MINIMIZE:
419 case SW_FORCEMINIMIZE:
420 return QWindow::Minimized;
421 case SW_SHOWMAXIMIZED:
422 return QWindow::Maximized;
423 default:
424 break;
425 }
426 }
427 return QWindow::Windowed;
428}
429
430static inline bool windowIsAccelerated(const QWindow *w)
431{
432 switch (w->surfaceType()) {
436 return true;
437 default:
438 return false;
439 }
440}
441
442static bool applyBlurBehindWindow(HWND hwnd)
443{
444 DWM_BLURBEHIND blurBehind = {0, 0, nullptr, 0};
445
446 blurBehind.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
447 blurBehind.fEnable = TRUE;
448 blurBehind.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
449
450 const bool result = DwmEnableBlurBehindWindow(hwnd, &blurBehind) == S_OK;
451
452 if (blurBehind.hRgnBlur)
453 DeleteObject(blurBehind.hRgnBlur);
454
455 return result;
456}
457
458// from qwidget_win.cpp, pass flags separately in case they have been "autofixed".
459static bool shouldShowMaximizeButton(const QWindow *w, Qt::WindowFlags flags)
460{
462 return false;
463 // if the user explicitly asked for the maximize button, we try to add
464 // it even if the window has fixed size.
465 return (flags & Qt::CustomizeWindowHint) ||
466 w->maximumSize() == QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX);
467}
468
469bool QWindowsWindow::hasNoNativeFrame(HWND hwnd, Qt::WindowFlags flags)
470{
471 const LONG_PTR style = GetWindowLongPtr(hwnd, GWL_STYLE);
472 return (style & WS_CHILD) || (flags & Qt::FramelessWindowHint);
473}
474
475// Set the WS_EX_LAYERED flag on a HWND if required. This is required for
476// translucent backgrounds, not fully opaque windows and for
477// Qt::WindowTransparentForInput (in combination with WS_EX_TRANSPARENT).
478bool QWindowsWindow::setWindowLayered(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, qreal opacity)
479{
480 const LONG_PTR exStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
481 // Native children are frameless by nature, so check for that as well.
482 const bool needsLayered = (flags & Qt::WindowTransparentForInput)
483 || (hasAlpha && hasNoNativeFrame(hwnd, flags)) || opacity < 1.0;
484 const bool isLayered = (exStyle & WS_EX_LAYERED);
485 if (needsLayered != isLayered) {
486 if (needsLayered) {
487 SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED);
488 } else {
489 SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED);
490 }
491 }
492 return needsLayered;
493}
494
495static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, bool accelerated, qreal level)
496{
498 const BYTE alpha = BYTE(qRound(255.0 * level));
499 if (hasAlpha && !accelerated && QWindowsWindow::hasNoNativeFrame(hwnd, flags)) {
500 // Non-GL windows with alpha: Use blend function to update.
501 BLENDFUNCTION blend = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA};
502 UpdateLayeredWindow(hwnd, nullptr, nullptr, nullptr, nullptr, nullptr, 0, &blend, ULW_ALPHA);
503 } else {
504 SetLayeredWindowAttributes(hwnd, 0, alpha, LWA_ALPHA);
505 }
506 } else if (IsWindowVisible(hwnd)) { // Repaint when switching from layered.
507 InvalidateRect(hwnd, nullptr, TRUE);
508 }
509}
510
511static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::WindowFlags flags, qreal opacity)
512{
513 const bool isAccelerated = windowIsAccelerated(w);
514 const bool hasAlpha = w->format().hasAlpha();
515
516 if (isAccelerated && hasAlpha)
518
519 setWindowOpacity(hwnd, flags, hasAlpha, isAccelerated, opacity);
520}
521
522[[nodiscard]] static inline int getResizeBorderThickness(const UINT dpi)
523{
524 // The width of the padded border will always be 0 if DWM composition is
525 // disabled, but since it will always be enabled and can't be programtically
526 // disabled from Windows 8, we are safe to go.
527 return GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
528 + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
529}
530
537{
538 POINT pt = {screenPoint.x(), screenPoint.y()};
539 if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
540 UINT dpiX;
541 UINT dpiY;
542 if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY))) {
543 const int gap = getResizeBorderThickness(dpiX);
544 return QMargins(gap, 0, gap, gap);
545 }
546 }
547 return QMargins();
548}
549
550[[nodiscard]] static inline QMargins invisibleMargins(const HWND hwnd)
551{
552 const UINT dpi = GetDpiForWindow(hwnd);
553 const int gap = getResizeBorderThickness(dpi);
554 return QMargins(gap, 0, gap, gap);
555}
556
586{
588 enum Flags { ForceChild = 0x1, ForceTopLevel = 0x2 };
589
590 void fromWindow(const QWindow *w, const Qt::WindowFlags flags, unsigned creationFlags = 0);
591 inline WindowData create(const QWindow *w, const WindowData &data, QString title) const;
592 inline void applyWindowFlags(HWND hwnd) const;
593 void initialize(const QWindow *w, HWND h, bool frameChange, qreal opacityLevel) const;
594
595 Qt::WindowFlags flags;
596 HWND parentHandle = nullptr;
598 unsigned style = 0;
599 unsigned exStyle = 0;
600 bool topLevel = false;
601 bool popup = false;
602 bool dialog = false;
603 bool tool = false;
604 bool embedded = false;
605 bool hasAlpha = false;
606};
607
609{
610 QDebugStateSaver saver(debug);
611 debug.nospace();
612 debug.noquote();
613 debug << "WindowCreationData: " << d.flags
614 << "\n topLevel=" << d.topLevel;
615 if (d.parentHandle)
616 debug << " parent=" << d.parentHandle;
617 debug << " popup=" << d.popup << " dialog=" << d.dialog
618 << " embedded=" << d.embedded << " tool=" << d.tool
619 << "\n style=" << debugWinStyle(d.style);
620 if (d.exStyle)
621 debug << "\n exStyle=" << debugWinExStyle(d.exStyle);
622 return debug;
623}
624
625// Fix top level window flags in case only the type flags are passed.
626static inline void fixTopLevelWindowFlags(Qt::WindowFlags &flags)
627{
628 // Not supported on Windows, also do correction when it is set.
629 flags &= ~Qt::WindowFullscreenButtonHint;
630 switch (flags) {
631 case Qt::Window:
634 break;
635 case Qt::Dialog:
636 case Qt::Tool:
638 break;
639 default:
640 break;
641 }
644}
645
647{
648 const auto getDeviceName = [](const QScreen *screen) -> QString {
649 if (const auto s = static_cast<const QWindowsScreen *>(screen->handle()))
650 return s->data().deviceName;
651 return {};
652 };
653 QScreen *winScreen = w ? w->screen() : QGuiApplication::primaryScreen();
654 if (winScreen && getDeviceName(winScreen) != name) {
655 const auto screens = winScreen->virtualSiblings();
656 for (QScreen *screen : screens) {
657 if (getDeviceName(screen) == name)
658 return screen;
659 }
660 }
661 return winScreen;
662}
663
664static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &context, const QMargins &invMargins)
665{
666 const QPoint orgPos(context->frameX - invMargins.left(), context->frameY - invMargins.top());
667
668 if (!w || w->type() != Qt::Window)
669 return orgPos;
670
671 // Workaround for QTBUG-50371
673 if (!screenForGL)
674 return orgPos;
675
676 const QPoint posFrame(context->frameX, context->frameY);
677 const QMargins margins = context->margins;
678 const QRect scrGeo = screenForGL->handle()->availableGeometry();
679
680 // Point is already in the required screen.
681 if (scrGeo.contains(orgPos))
682 return orgPos;
683
684 // If the visible part of the window is already in the
685 // required screen, just ignore the invisible offset.
686 if (scrGeo.contains(posFrame))
687 return posFrame;
688
689 // Find the original screen containing the coordinates.
690 const auto screens = screenForGL->virtualSiblings();
691 const QScreen *orgScreen = nullptr;
692 for (QScreen *screen : screens) {
693 if (screen->handle()->availableGeometry().contains(posFrame)) {
694 orgScreen = screen;
695 break;
696 }
697 }
698 const QPoint ctPos = QPoint(qMax(scrGeo.left(), scrGeo.center().x()
699 + (margins.right() - margins.left() - context->frameWidth)/2),
700 qMax(scrGeo.top(), scrGeo.center().y()
701 + (margins.bottom() - margins.top() - context->frameHeight)/2));
702
703 // If initial coordinates were outside all screens, center the window on the required screen.
704 if (!orgScreen)
705 return ctPos;
706
707 const QRect orgGeo = orgScreen->handle()->availableGeometry();
708 const QRect orgFrame(QPoint(context->frameX, context->frameY),
709 QSize(context->frameWidth, context->frameHeight));
710
711 // Window would be centered on orgScreen. Center it on the required screen.
712 if (orgGeo.center() == (orgFrame - margins).center())
713 return ctPos;
714
715 // Transform the coordinates to map them into the required screen.
716 const QPoint newPos(scrGeo.left() + ((posFrame.x() - orgGeo.left()) * scrGeo.width()) / orgGeo.width(),
717 scrGeo.top() + ((posFrame.y() - orgGeo.top()) * scrGeo.height()) / orgGeo.height());
718 const QPoint newPosNoMargin(newPos.x() - invMargins.left(), newPos.y() - invMargins.top());
719
720 return scrGeo.contains(newPosNoMargin) ? newPosNoMargin : newPos;
721}
722
723void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flagsIn,
724 unsigned creationFlags)
725{
726 flags = flagsIn;
727
728 // Sometimes QWindow doesn't have a QWindow parent but does have a native parent window,
729 // e.g. in case of embedded ActiveQt servers. They should not be considered a top-level
730 // windows in such cases.
732 if (prop.isValid()) {
733 embedded = true;
734 parentHandle = reinterpret_cast<HWND>(prop.value<WId>());
735 }
736
737 if (creationFlags & ForceChild) {
738 topLevel = false;
739 } else if (embedded) {
740 // Embedded native windows (for example Active X server windows) are by
741 // definition never toplevel, even though they do not have QWindow parents.
742 topLevel = false;
743 } else {
744 topLevel = (creationFlags & ForceTopLevel) ? true : w->isTopLevel();
745 }
746
747 if (topLevel)
749
750 type = static_cast<Qt::WindowType>(int(flags) & Qt::WindowType_Mask);
751 switch (type) {
752 case Qt::Dialog:
753 case Qt::Sheet:
754 dialog = true;
755 break;
756 case Qt::Drawer:
757 case Qt::Tool:
758 tool = true;
759 break;
760 case Qt::Popup:
761 popup = true;
762 break;
763 default:
764 break;
765 }
767 dialog = true;
768
769 // This causes the title bar to drawn RTL and the close button
770 // to be left. Note that this causes:
771 // - All DCs created on the Window to have RTL layout (see SetLayout)
772 // - ClientToScreen() and ScreenToClient() to work in reverse as well.
773 // - Mouse event coordinates to be mirrored.
774 // - Positioning of child Windows.
777 exStyle |= WS_EX_LAYOUTRTL | WS_EX_NOINHERITLAYOUT;
778 }
779
780 // Parent: Use transient parent for top levels.
781 if (popup) {
782 flags |= Qt::WindowStaysOnTopHint; // a popup stays on top, no parent.
783 } else if (!embedded) {
784 if (const QWindow *parentWindow = topLevel ? w->transientParent() : w->parent())
786 }
787
788 if (popup || (type == Qt::ToolTip) || (type == Qt::SplashScreen)) {
789 style = WS_POPUP;
790 } else if (topLevel) {
792 style = WS_POPUP; // no border
793 else if (flags & Qt::WindowTitleHint)
794 style = WS_OVERLAPPED;
795 else
796 style = 0;
797 } else {
798 style = WS_CHILD;
799 }
800
801 style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN ;
802
803 if (topLevel) {
804 if ((type == Qt::Window || dialog || tool)) {
806 style |= WS_POPUP;
808 style |= WS_DLGFRAME;
809 } else {
810 style |= WS_THICKFRAME;
811 }
813 style |= WS_CAPTION; // Contains WS_DLGFRAME
814 }
816 style |= WS_SYSMENU;
818 style |= WS_SYSMENU | WS_BORDER; // QTBUG-2027, dialogs without system menu.
819 exStyle |= WS_EX_DLGMODALFRAME;
820 }
821 const bool showMinimizeButton = flags & Qt::WindowMinimizeButtonHint;
822 if (showMinimizeButton)
823 style |= WS_MINIMIZEBOX;
824 const bool showMaximizeButton = shouldShowMaximizeButton(w, flags);
825 if (showMaximizeButton)
826 style |= WS_MAXIMIZEBOX;
827 if (showMinimizeButton || showMaximizeButton)
828 style |= WS_SYSMENU;
829 if (tool)
830 exStyle |= WS_EX_TOOLWINDOW;
831 if ((flags & Qt::WindowContextHelpButtonHint) && !showMinimizeButton
832 && !showMaximizeButton)
833 exStyle |= WS_EX_CONTEXTHELP;
834 } else {
835 exStyle |= WS_EX_TOOLWINDOW;
836 }
837
838 // make mouse events fall through this window
839 // NOTE: WS_EX_TRANSPARENT flag can make mouse inputs fall through a layered window
840 if (flagsIn & Qt::WindowTransparentForInput)
841 exStyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT;
842
843 // Currently only compatible with D3D surfaces, use it with care.
844 if (qEnvironmentVariableIntValue("QT_QPA_DISABLE_REDIRECTION_SURFACE"))
845 exStyle |= WS_EX_NOREDIRECTIONBITMAP;
846 }
847}
848
849static inline bool shouldApplyDarkFrame(const QWindow *w)
850{
851 if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint))
852 return false;
853
854 // the user of the application has explicitly opted out of dark frames
855 if (!QWindowsIntegration::instance()->darkModeHandling().testFlag(QWindowsApplication::DarkModeWindowFrames))
856 return false;
857
858 // the application explicitly overrides the color scheme
859 if (const auto requestedColorScheme = QWindowsTheme::instance()->requestedColorScheme();
860 requestedColorScheme != Qt::ColorScheme::Unknown) {
861 return requestedColorScheme == Qt::ColorScheme::Dark;
862 }
863
864 // if the application supports a dark border, and the palette is dark (window background color
865 // is darker than the text), then turn dark-border support on, otherwise use a light border.
866 auto *dWindow = QWindowPrivate::get(const_cast<QWindow*>(w));
867 const QPalette windowPal = dWindow->windowPalette();
868 return windowPal.color(QPalette::WindowText).lightness()
869 > windowPal.color(QPalette::Window).lightness();
870}
871
874{
877
878 const auto appinst = reinterpret_cast<HINSTANCE>(GetModuleHandle(nullptr));
879
880 const QString windowClassName = QWindowsContext::instance()->registerWindowClass(w);
881
882 const QScreen *screen{};
885 &screen);
886
887 if (title.isEmpty() && (result.flags & Qt::WindowTitleHint))
888 title = topLevel ? qAppName() : w->objectName();
889
890 const auto *titleUtf16 = reinterpret_cast<const wchar_t *>(title.utf16());
891 const auto *classNameUtf16 = reinterpret_cast<const wchar_t *>(windowClassName.utf16());
892
893 // Capture events before CreateWindowEx() returns. The context is cleared in
894 // the QWindowsWindow constructor.
896 rect, data.customMargins,
897 style, exStyle));
898 QWindowsContext::instance()->setWindowCreationContext(context);
899
900 const bool hasFrame = (style & (WS_DLGFRAME | WS_THICKFRAME))
901 && !(result.flags & Qt::FramelessWindowHint);
903 ? invisibleMargins(QPoint(context->frameX, context->frameY)) : QMargins();
904
905 qCDebug(lcQpaWindow).nospace()
906 << "CreateWindowEx: " << w << " class=" << windowClassName << " title=" << title
907 << '\n' << *this << "\nrequested: " << rect << ": "
908 << context->frameWidth << 'x' << context->frameHeight
909 << '+' << context->frameX << '+' << context->frameY
910 << " custom margins: " << context->customMargins
911 << " invisible margins: " << invMargins;
912
913
914 QPoint pos = calcPosition(w, context, invMargins);
915
916 // Mirror the position when creating on a parent in RTL mode, ditto for the obtained geometry.
917 int mirrorParentWidth = 0;
918 if (!w->isTopLevel() && QWindowsBaseWindow::isRtlLayout(parentHandle)) {
919 RECT rect;
920 GetClientRect(parentHandle, &rect);
921 mirrorParentWidth = rect.right;
922 }
923 if (mirrorParentWidth != 0 && pos.x() != CW_USEDEFAULT && context->frameWidth != CW_USEDEFAULT)
924 pos.setX(mirrorParentWidth - context->frameWidth - pos.x());
925
926 result.hwnd = CreateWindowEx(exStyle, classNameUtf16, titleUtf16,
927 style,
928 pos.x(), pos.y(),
929 context->frameWidth, context->frameHeight,
930 parentHandle, nullptr, appinst, nullptr);
931 qCDebug(lcQpaWindow).nospace()
932 << "CreateWindowEx: returns " << w << ' ' << result.hwnd << " obtained geometry: "
933 << context->obtainedPos << context->obtainedSize << ' ' << context->margins;
934
935 if (!result.hwnd) {
936 qErrnoWarning("%s: CreateWindowEx failed", __FUNCTION__);
937 return result;
938 }
939
942
943 if (mirrorParentWidth != 0) {
944 context->obtainedPos.setX(mirrorParentWidth - context->obtainedSize.width()
945 - context->obtainedPos.x());
946 }
947
948 QRect obtainedGeometry(context->obtainedPos, context->obtainedSize);
949
950 result.geometry = obtainedGeometry;
951 result.restoreGeometry = frameGeometry(result.hwnd, topLevel);
952 result.fullFrameMargins = context->margins;
953 result.embedded = embedded;
954 result.hasFrame = hasFrame;
955 result.customMargins = context->customMargins;
956
957 return result;
958}
959
961{
962 // Keep enabled and visible from the current style.
963 const LONG_PTR oldStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
964 const LONG_PTR oldExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
965
966 const LONG_PTR newStyle = style | (oldStyle & (WS_DISABLED|WS_VISIBLE));
967 if (oldStyle != newStyle)
968 SetWindowLongPtr(hwnd, GWL_STYLE, newStyle);
969 const LONG_PTR newExStyle = exStyle;
970 if (newExStyle != oldExStyle)
971 SetWindowLongPtr(hwnd, GWL_EXSTYLE, newExStyle);
972 qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << hwnd << *this
973 << "\n Style from " << debugWinStyle(DWORD(oldStyle)) << "\n to "
974 << debugWinStyle(DWORD(newStyle)) << "\n ExStyle from "
975 << debugWinExStyle(DWORD(oldExStyle)) << " to "
976 << debugWinExStyle(DWORD(newExStyle));
977}
978
979void WindowCreationData::initialize(const QWindow *w, HWND hwnd, bool frameChange, qreal opacityLevel) const
980{
981 if (!hwnd)
982 return;
983 UINT swpFlags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER;
984 if (frameChange)
985 swpFlags |= SWP_FRAMECHANGED;
986 if (topLevel) {
987 swpFlags |= SWP_NOACTIVATE;
989 SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, swpFlags);
991 qWarning("QWidget: Incompatible window flags: the window can't be on top and on bottom at the same time");
992 } else if (flags & Qt::WindowStaysOnBottomHint) {
993 SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, swpFlags);
994 } else if (frameChange) { // Force WM_NCCALCSIZE with wParam=1 in case of custom margins.
995 SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, swpFlags);
996 }
998 HMENU systemMenu = GetSystemMenu(hwnd, FALSE);
1000 EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_ENABLED);
1001 else
1002 EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED);
1003 }
1004 updateGLWindowSettings(w, hwnd, flags, opacityLevel);
1005 } else { // child.
1006 SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, swpFlags);
1007 }
1008}
1009
1010
1011// Scaling helpers for size constraints.
1013{
1015 const qreal factor = QHighDpiScaling::factor(s);
1016 if (!qFuzzyCompare(factor, qreal(1))) {
1017 if (dip.width() > 0 && dip.width() < QWINDOWSIZE_MAX)
1018 dip.setWidth(qRound(qreal(dip.width()) * factor));
1019 if (dip.height() > 0 && dip.height() < QWINDOWSIZE_MAX)
1020 dip.setHeight(qRound(qreal(dip.height()) * factor));
1021 }
1022 }
1023 return dip;
1024}
1025
1026// Helper for checking if frame adjustment needs to be skipped
1027// NOTE: Unmaximized frameless windows will skip margins calculation
1028static bool shouldOmitFrameAdjustment(const Qt::WindowFlags flags, DWORD style)
1029{
1030 return flags.testFlag(Qt::FramelessWindowHint) && !(style & WS_MAXIMIZE);
1031}
1032
1033// Helper for checking if frame adjustment needs to be skipped
1034// NOTE: Unmaximized frameless windows will skip margins calculation
1035static bool shouldOmitFrameAdjustment(const Qt::WindowFlags flags, HWND hwnd)
1036{
1037 DWORD style = hwnd != nullptr ? DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)) : 0;
1038 return flags.testFlag(Qt::FramelessWindowHint) && !(style & WS_MAXIMIZE);
1039}
1040
1052{
1053 if (!w->isTopLevel() || shouldOmitFrameAdjustment(w->flags(), style))
1054 return {};
1055 RECT rect = {0,0,0,0};
1056 style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
1057 if (AdjustWindowRectEx(&rect, style, FALSE, exStyle) == FALSE)
1058 qErrnoWarning("%s: AdjustWindowRectEx failed", __FUNCTION__);
1059 const QMargins result(qAbs(rect.left), qAbs(rect.top),
1060 qAbs(rect.right), qAbs(rect.bottom));
1061 qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << " style="
1062 << Qt::showbase << Qt::hex << style << " exStyle=" << exStyle << Qt::dec << Qt::noshowbase
1063 << ' ' << rect << ' ' << result;
1064 return result;
1065}
1066
1068{
1069 return frameOnPrimaryScreen(w, DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)),
1070 DWORD(GetWindowLongPtr(hwnd, GWL_EXSTYLE)));
1071}
1072
1073QMargins QWindowsGeometryHint::frame(const QWindow *w, DWORD style, DWORD exStyle, qreal dpi)
1074{
1075 if (!w->isTopLevel() || shouldOmitFrameAdjustment(w->flags(), style))
1076 return {};
1077 RECT rect = {0,0,0,0};
1078 style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
1079 if (AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE) {
1080 qErrnoWarning("%s: AdjustWindowRectExForDpi failed", __FUNCTION__);
1081 }
1082 const QMargins result(qAbs(rect.left), qAbs(rect.top),
1083 qAbs(rect.right), qAbs(rect.bottom));
1084 qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << " style="
1085 << Qt::showbase << Qt::hex << style << " exStyle=" << exStyle << Qt::dec << Qt::noshowbase
1086 << " dpi=" << dpi
1087 << ' ' << rect << ' ' << result;
1088 return result;
1089}
1090
1091QMargins QWindowsGeometryHint::frame(const QWindow *w, HWND hwnd, DWORD style, DWORD exStyle)
1092{
1093 if (!w->isTopLevel() || shouldOmitFrameAdjustment(w->flags(), style))
1094 return {};
1096 return frameOnPrimaryScreen(w, style, exStyle);
1097 auto &screenManager = QWindowsContext::instance()->screenManager();
1098 auto screen = screenManager.screenForHwnd(hwnd);
1099 if (!screen)
1100 screen = screenManager.screens().value(0);
1101 const auto dpi = screen ? screen->logicalDpi().first : qreal(96);
1102 return frame(w, style, exStyle, dpi);
1103}
1104
1106{
1107 return frame(w, hwnd, DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)),
1108 DWORD(GetWindowLongPtr(hwnd, GWL_EXSTYLE)));
1109}
1110
1111// For newly created windows.
1113 DWORD style, DWORD exStyle)
1114{
1115 if (!w->isTopLevel() || shouldOmitFrameAdjustment(w->flags(), style))
1116 return {};
1119 return frameOnPrimaryScreen(w, style, exStyle);
1120 }
1121 qreal dpi = 96;
1122 auto &screenManager = QWindowsContext::instance()->screenManager();
1123 auto screen = screenManager.screenAtDp(geometry.center());
1124 if (!screen)
1125 screen = screenManager.screens().value(0);
1126 if (screen)
1127 dpi = screen->logicalDpi().first;
1128 return QWindowsGeometryHint::frame(w, style, exStyle, dpi);
1129}
1130
1131bool QWindowsGeometryHint::handleCalculateSize(const QMargins &customMargins, const MSG &msg, LRESULT *result)
1132{
1133 // NCCALCSIZE_PARAMS structure if wParam==TRUE
1134 if (!msg.wParam || customMargins.isNull())
1135 return false;
1136 *result = DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
1137 auto *ncp = reinterpret_cast<NCCALCSIZE_PARAMS *>(msg.lParam);
1138 const RECT oldClientArea = ncp->rgrc[0];
1139 ncp->rgrc[0].left += customMargins.left();
1140 ncp->rgrc[0].top += customMargins.top();
1141 ncp->rgrc[0].right -= customMargins.right();
1142 ncp->rgrc[0].bottom -= customMargins.bottom();
1143 result = nullptr;
1144 qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << oldClientArea << '+' << customMargins << "-->"
1145 << ncp->rgrc[0] << ' ' << ncp->rgrc[1] << ' ' << ncp->rgrc[2]
1146 << ' ' << ncp->lppos->cx << ',' << ncp->lppos->cy;
1147 return true;
1148}
1149
1151 const QMargins &margins,
1152 QSize *minimumSize, QSize *maximumSize)
1153{
1154 *minimumSize = toNativeSizeConstrained(w->minimumSize(), screen);
1155 *maximumSize = toNativeSizeConstrained(w->maximumSize(), screen);
1156
1157 const int maximumWidth = qMax(maximumSize->width(), minimumSize->width());
1158 const int maximumHeight = qMax(maximumSize->height(), minimumSize->height());
1159 const int frameWidth = margins.left() + margins.right();
1160 const int frameHeight = margins.top() + margins.bottom();
1161
1162 if (minimumSize->width() > 0)
1163 minimumSize->rwidth() += frameWidth;
1164 if (minimumSize->height() > 0)
1165 minimumSize->rheight() += frameHeight;
1166 if (maximumWidth < QWINDOWSIZE_MAX)
1167 maximumSize->setWidth(maximumWidth + frameWidth);
1168 if (maximumHeight < QWINDOWSIZE_MAX)
1169 maximumSize->setHeight(maximumHeight + frameHeight);
1170}
1171
1173 const QScreen *screen,
1174 const QMargins &margins,
1175 MINMAXINFO *mmi)
1176{
1177 QSize minimumSize;
1178 QSize maximumSize;
1179 frameSizeConstraints(w, screen, margins, &minimumSize, &maximumSize);
1180 qCDebug(lcQpaWindow).nospace() << '>' << __FUNCTION__ << '<' << " min="
1181 << minimumSize.width() << ',' << minimumSize.height()
1182 << " max=" << maximumSize.width() << ',' << maximumSize.height()
1183 << " margins=" << margins
1184 << " in " << *mmi;
1185
1186 if (minimumSize.width() > 0)
1187 mmi->ptMinTrackSize.x = minimumSize.width();
1188 if (minimumSize.height() > 0)
1189 mmi->ptMinTrackSize.y = minimumSize.height();
1190
1191 if (maximumSize.width() < QWINDOWSIZE_MAX)
1192 mmi->ptMaxTrackSize.x = maximumSize.width();
1193 if (maximumSize.height() < QWINDOWSIZE_MAX)
1194 mmi->ptMaxTrackSize.y = maximumSize.height();
1195 qCDebug(lcQpaWindow).nospace() << '<' << __FUNCTION__ << " out " << *mmi;
1196}
1197
1199 const QMargins &margins,
1200 MINMAXINFO *mmi)
1201{
1202 applyToMinMaxInfo(w, w->screen(), margins, mmi);
1203}
1204
1206{
1207 return qt_window_private(const_cast<QWindow *>(w))->positionPolicy
1209}
1210
1229{
1230 return (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) != 0;
1231}
1232
1234{
1235 if (w) {
1236 if (QPlatformWindow *pw = w->handle())
1237 return static_cast<QWindowsBaseWindow *>(pw);
1238 }
1239 return nullptr;
1240}
1241
1243{
1245 return bw ? bw->handle() : HWND(nullptr);
1246}
1247
1249{
1250 const HWND parent = parentHwnd();
1251 return !parent || parent == GetDesktopWindow();
1252}
1253
1258
1263
1268
1269std::optional<QWindowsBaseWindow::TouchWindowTouchTypes>
1271{
1272 ULONG touchFlags = 0;
1273 if (IsTouchWindow(handle(), &touchFlags) == FALSE)
1274 return {};
1276 if ((touchFlags & TWF_FINETOUCH) != 0)
1277 result.setFlag(TouchWindowTouchType::FineTouch);
1278 if ((touchFlags & TWF_WANTPALM) != 0)
1279 result.setFlag(TouchWindowTouchType::WantPalmTouch);
1280 return result;
1281}
1282
1283void QWindowsBaseWindow::hide_sys() // Normal hide, do not activate other windows.
1284{
1285 SetWindowPos(handle(), nullptr , 0, 0, 0, 0,
1286 SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
1287}
1288
1290{
1291 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window();
1292 const Qt::WindowType type = window()->type();
1293 if (type == Qt::Popup
1294 || type == Qt::SubWindow // Special case for QTBUG-63121: MDI subwindows with WindowStaysOnTopHint
1296 SetWindowPos(handle(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1297 }
1298}
1299
1301{
1302 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window();
1304 SetWindowPos(handle(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1305}
1306
1308{
1309 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window() << title;
1310 SetWindowText(handle(), reinterpret_cast<const wchar_t *>(title.utf16()));
1311}
1312
1317
1322
1327
1329{
1331 return false;
1332}
1333
1335{
1336 return {};
1337}
1338
1343
1365 , m_hwnd(hwnd)
1366 , m_topLevelStyle(0)
1367{
1370}
1371
1373{
1374 const bool wasTopLevel = isTopLevel_sys();
1375 const HWND newParent = newParentWindow ? reinterpret_cast<HWND>(newParentWindow->winId()) : HWND(nullptr);
1376 const bool isTopLevel = !newParent;
1377 const DWORD oldStyle = style();
1378 qCDebug(lcQpaWindow) << __FUNCTION__ << window() << "newParent="
1379 << newParentWindow << newParent << "oldStyle=" << debugWinStyle(oldStyle);
1380 SetParent(m_hwnd, newParent);
1381 if (wasTopLevel != isTopLevel) { // Top level window flags need to be set/cleared manually.
1382 DWORD newStyle = oldStyle;
1383 if (isTopLevel) {
1384 newStyle = m_topLevelStyle;
1385 } else {
1386 m_topLevelStyle = oldStyle;
1387 newStyle &= ~(WS_OVERLAPPEDWINDOW | WS_POPUPWINDOW);
1388 newStyle |= WS_CHILD;
1389 }
1390 SetWindowLongPtr(m_hwnd, GWL_STYLE, newStyle);
1391 }
1392}
1393
1395{
1396 qCDebug(lcQpaWindow) << __FUNCTION__ << window() << visible;
1397 if (visible)
1398 ShowWindow(handle(), SW_SHOWNOACTIVATE);
1399 else
1400 hide_sys();
1401}
1402
1424 const QRect &geometryIn, const QRect &geometry,
1425 const QMargins &cm,
1426 DWORD style, DWORD exStyle) :
1427 window(w),
1428 screen(s),
1429 requestedGeometryIn(geometryIn),
1430 requestedGeometry(geometry),
1431 obtainedPos(geometryIn.topLeft()),
1432 obtainedSize(geometryIn.size()),
1433 margins(QWindowsGeometryHint::frame(w, geometry, style, exStyle))
1434{
1435 // Geometry of toplevels does not consider window frames.
1436 // TODO: No concept of WA_wasMoved yet that would indicate a
1437 // CW_USEDEFAULT unless set. For now, assume that 0,0 means 'default'
1438 // for toplevels.
1439
1440 if (!(w->flags() & Qt::FramelessWindowHint))
1441 customMargins = cm;
1442
1443 if (geometry.isValid()
1444 || !qt_window_private(const_cast<QWindow *>(w))->resizeAutomatic) {
1445 frameX = geometry.x();
1446 frameY = geometry.y();
1447 const QMargins effectiveMargins = margins + customMargins;
1448 frameWidth = effectiveMargins.left() + geometry.width() + effectiveMargins.right();
1449 frameHeight = effectiveMargins.top() + geometry.height() + effectiveMargins.bottom();
1450 if (QWindowsMenuBar::menuBarOf(w) != nullptr) {
1451 menuHeight = GetSystemMetrics(SM_CYMENU);
1453 }
1454 const bool isDefaultPosition = !frameX && !frameY && w->isTopLevel();
1455 if (!QWindowsGeometryHint::positionIncludesFrame(w) && !isDefaultPosition) {
1456 frameX -= effectiveMargins.left();
1457 frameY -= effectiveMargins.top();
1458 }
1459 }
1460
1461 qCDebug(lcQpaWindow).nospace()
1462 << __FUNCTION__ << ' ' << w << ' ' << geometry
1463 << " pos incl. frame=" << QWindowsGeometryHint::positionIncludesFrame(w)
1464 << " frame=" << frameWidth << 'x' << frameHeight << '+'
1465 << frameX << '+' << frameY
1466 << " margins=" << margins << " custom margins=" << customMargins;
1467}
1468
1473
1495const char *QWindowsWindow::embeddedNativeParentHandleProperty = "_q_embedded_native_parent_handle";
1496const char *QWindowsWindow::hasBorderInFullScreenProperty = "_q_has_border_in_fullscreen";
1497bool QWindowsWindow::m_borderInFullScreenDefault = false;
1498bool QWindowsWindow::m_inSetgeometry = false;
1499
1501 QWindowsBaseWindow(aWindow),
1502 m_data(data),
1503 m_cursor(new CursorHandle)
1504#if QT_CONFIG(vulkan)
1505 , m_vkSurface(VK_NULL_HANDLE)
1506#endif
1507{
1508 QWindowsContext::instance()->addWindow(m_data.hwnd, this);
1509 const Qt::WindowType type = aWindow->type();
1510 if (type == Qt::Desktop)
1511 return; // No further handling for Qt::Desktop
1512 if (aWindow->surfaceType() == QWindow::Direct3DSurface)
1514#if QT_CONFIG(opengl)
1515 if (aWindow->surfaceType() == QWindow::OpenGLSurface)
1517#endif
1518#if QT_CONFIG(vulkan)
1519 if (aWindow->surfaceType() == QSurface::VulkanSurface)
1521#endif
1522 updateDropSite(window()->isTopLevel());
1523
1524 // Register touch unless if the flags are already set by a hook
1525 // such as HCBT_CREATEWND
1526 if (!touchWindowTouchTypes_sys().has_value())
1528
1529 const qreal opacity = qt_window_private(aWindow)->opacity;
1530 if (!qFuzzyCompare(opacity, qreal(1.0)))
1532
1534
1535 if (aWindow->isTopLevel())
1536 setWindowIcon(aWindow->icon());
1537 if (m_borderInFullScreenDefault || aWindow->property(hasBorderInFullScreenProperty).toBool())
1540}
1541
1543{
1547 UnregisterTouchWindow(m_data.hwnd);
1548 destroyWindow();
1549 destroyIcon();
1550}
1551
1553{
1554 // Clear the creation context as the window can be found in QWindowsContext's map.
1555 QWindowCreationContextPtr creationContext =
1556 QWindowsContext::instance()->setWindowCreationContext(QWindowCreationContextPtr());
1557
1558 QWindow *w = window();
1559 setWindowState(w->windowStates());
1560
1561 // Trigger geometry change (unless it has a special state in which case setWindowState()
1562 // will send the message) and screen change signals of QWindow.
1563 if (w->type() != Qt::Desktop) {
1564 const Qt::WindowState state = w->windowState();
1565 const QRect obtainedGeometry(creationContext->obtainedPos, creationContext->obtainedSize);
1566 QPlatformScreen *obtainedScreen = screenForGeometry(obtainedGeometry);
1567 if (obtainedScreen && screen() != obtainedScreen)
1568 QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(w, obtainedScreen->screen());
1570 && creationContext->requestedGeometryIn != obtainedGeometry) {
1571 QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(w, obtainedGeometry);
1572 }
1573 }
1574 QWindowsWindow::setSavedDpi(GetDpiForWindow(handle()));
1575}
1576
1578{
1579 return window()->requestedFormat();
1580}
1581
1582void QWindowsWindow::fireExpose(const QRegion &region, bool force)
1583{
1584 if (region.isEmpty() && !force)
1586 else
1589}
1590
1591void QWindowsWindow::fireFullExpose(bool force)
1592{
1593 fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), force);
1594}
1595
1596void QWindowsWindow::destroyWindow()
1597{
1598 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window() << m_data.hwnd;
1599 if (m_data.hwnd) { // Stop event dispatching before Window is destroyed.
1601 // Clear any transient child relationships as Windows will otherwise destroy them (QTBUG-35499, QTBUG-36666)
1602 const auto tlw = QGuiApplication::topLevelWindows();
1603 for (QWindow *w : tlw) {
1604 if (w->transientParent() == window()) {
1606 tw->updateTransientParent();
1607 }
1608 }
1610 if (context->windowUnderMouse() == window())
1611 context->clearWindowUnderMouse();
1612 if (hasMouseCapture())
1613 setMouseGrabEnabled(false);
1614 setDropSiteEnabled(false);
1615#if QT_CONFIG(vulkan)
1616 if (m_vkSurface) {
1617 QVulkanInstance *inst = window()->vulkanInstance();
1618 if (inst)
1619 static_cast<QWindowsVulkanInstance *>(inst->handle())->destroySurface(m_vkSurface);
1620 m_vkSurface = VK_NULL_HANDLE;
1621 }
1622#endif
1623#ifndef QT_NO_OPENGL
1624 if (m_surface) {
1626 staticOpenGLContext->destroyWindowSurface(m_surface);
1627 m_surface = nullptr;
1628 }
1629#endif
1630 DestroyWindow(m_data.hwnd);
1631 context->removeWindow(m_data.hwnd);
1632 m_data.hwnd = nullptr;
1633 }
1634}
1635
1636void QWindowsWindow::updateDropSite(bool topLevel)
1637{
1638 bool enabled = false;
1639 bool parentIsEmbedded = false;
1640
1641 if (!topLevel) {
1642 // if the parent window is a foreign window wrapped via QWindow::fromWinId, we need to enable the drop site
1643 // on the first child window
1644 const QWindow *parent = window()->parent();
1645 if (parent && parent->handle() && parent->handle()->isForeignWindow())
1646 parentIsEmbedded = true;
1647 }
1648
1649 if (topLevel || parentIsEmbedded) {
1650 switch (window()->type()) {
1651 case Qt::Window:
1652 case Qt::Dialog:
1653 case Qt::Sheet:
1654 case Qt::Drawer:
1655 case Qt::Popup:
1656 case Qt::Tool:
1657 enabled = true;
1658 break;
1659 default:
1660 break;
1661 }
1662 }
1663 setDropSiteEnabled(enabled);
1664}
1665
1666void QWindowsWindow::setDropSiteEnabled(bool dropEnabled)
1667{
1668 if (isDropSiteEnabled() == dropEnabled)
1669 return;
1670 qCDebug(lcQpaMime) << __FUNCTION__ << window() << dropEnabled;
1671#if QT_CONFIG(clipboard) && QT_CONFIG(draganddrop)
1672 if (dropEnabled) {
1673 Q_ASSERT(m_data.hwnd);
1674 m_dropTarget = new QWindowsOleDropTarget(window());
1675 RegisterDragDrop(m_data.hwnd, m_dropTarget);
1676 CoLockObjectExternal(m_dropTarget, true, true);
1677 } else {
1678 CoLockObjectExternal(m_dropTarget, false, true);
1679 m_dropTarget->Release();
1680 RevokeDragDrop(m_data.hwnd);
1681 m_dropTarget = nullptr;
1682 }
1683#endif // QT_CONFIG(clipboard) && QT_CONFIG(draganddrop)
1684}
1685
1686bool QWindowsWindow::m_screenForGLInitialized = false;
1687
1689{
1690 m_screenForGLInitialized = false;
1691}
1692
1694{
1695 m_screenForGLInitialized = false;
1696}
1697
1699{
1700 static QString forceToScreen;
1701 if (!m_screenForGLInitialized) {
1702 forceToScreen = GpuDescription::detect().gpuSuitableScreen;
1703 m_screenForGLInitialized = true;
1704 }
1705 return forceToScreen.isEmpty() ? nullptr : screenForDeviceName(w, forceToScreen);
1706}
1707
1708// Returns topmost QWindowsWindow ancestor even if there are embedded windows in the chain.
1709// Returns this window if it is the topmost ancestor.
1711{
1712 while (QWindow *parent = w->parent())
1713 w = parent;
1714
1715 if (const QPlatformWindow *handle = w->handle()) {
1716 const auto *ww = static_cast<const QWindowsWindow *>(handle);
1717 if (ww->isEmbedded()) {
1718 HWND parentHWND = GetAncestor(ww->handle(), GA_PARENT);
1719 const HWND desktopHwnd = GetDesktopWindow();
1721 while (parentHWND && parentHWND != desktopHwnd) {
1722 if (QWindowsWindow *ancestor = ctx->findPlatformWindow(parentHWND))
1723 return topLevelOf(ancestor->window());
1724 parentHWND = GetAncestor(parentHWND, GA_PARENT);
1725 }
1726 }
1727 }
1728 return w;
1729}
1730
1733 const QWindowsWindowData &parameters,
1734 const QString &title)
1735{
1736 WindowCreationData creationData;
1737 creationData.fromWindow(w, parameters.flags);
1738 QWindowsWindowData result = creationData.create(w, parameters, title);
1739 // Force WM_NCCALCSIZE (with wParam=1) via SWP_FRAMECHANGED for custom margin.
1740 creationData.initialize(w, result.hwnd, !parameters.customMargins.isNull(), 1);
1741 return result;
1742}
1743
1745{
1746 const QWindow *win = window();
1747 qCDebug(lcQpaWindow) << __FUNCTION__ << this << win << m_data.hwnd << visible;
1748 if (m_data.hwnd) {
1749 if (visible) {
1750 show_sys();
1751
1752 // When the window is layered, we won't get WM_PAINT, and "we" are in control
1753 // over the rendering of the window
1754 // There is nobody waiting for this, so we don't need to flush afterwards.
1755 if (isLayered())
1756 fireFullExpose();
1757 // QTBUG-44928, QTBUG-7386: This is to resolve the problem where popups are
1758 // opened from the system tray and not being implicitly activated
1759
1760 if (win->type() == Qt::Popup && !win->parent() && !QGuiApplication::focusWindow())
1761 SetForegroundWindow(m_data.hwnd);
1762 } else {
1763 if (hasMouseCapture())
1764 setMouseGrabEnabled(false);
1765 if (window()->flags() & Qt::Popup) // from QWidgetPrivate::hide_sys(), activate other
1766 ShowWindow(m_data.hwnd, SW_HIDE);
1767 else
1768 hide_sys();
1769 fireExpose(QRegion());
1770 }
1771 }
1772}
1773
1775{
1776 return m_data.hwnd && IsWindowVisible(m_data.hwnd);
1777}
1778
1780{
1781 // Check for native windows or children of the active native window.
1782 if (const HWND activeHwnd = GetForegroundWindow())
1783 if (m_data.hwnd == activeHwnd || IsChild(activeHwnd, m_data.hwnd))
1784 return true;
1785 return false;
1786}
1787
1789{
1790 const auto *childWindow = static_cast<const QWindowsWindow *>(child);
1791 return IsChild(m_data.hwnd, childWindow->handle());
1792}
1793
1795{
1796 return m_data.embedded;
1797}
1798
1800{
1801 return m_data.hwnd ? QWindowsGeometryHint::mapToGlobal(m_data.hwnd, pos) : pos;
1802}
1803
1805{
1806 return m_data.hwnd ? QWindowsGeometryHint::mapFromGlobal(m_data.hwnd, pos) : pos;
1807}
1808
1809// Update the transient parent for a toplevel window. The concept does not
1810// really exist on Windows, the relationship is set by passing a parent along with !WS_CHILD
1811// to window creation or by setting the parent using GWL_HWNDPARENT (as opposed to
1812// SetParent, which would make it a real child).
1813
1814#ifndef GWL_HWNDPARENT
1815# define GWL_HWNDPARENT (-8)
1816#endif
1817
1818void QWindowsWindow::updateTransientParent() const
1819{
1820 if (window()->type() == Qt::Popup)
1821 return; // QTBUG-34503, // a popup stays on top, no parent, see also WindowCreationData::fromWindow().
1822 // Update transient parent.
1823 const HWND oldTransientParent = GetWindow(m_data.hwnd, GW_OWNER);
1824 HWND newTransientParent = nullptr;
1825 if (const QWindow *tp = window()->transientParent())
1827 if (!tw->testFlag(WithinDestroy)) // Prevent destruction by parent window (QTBUG-35499, QTBUG-36666)
1828 newTransientParent = tw->handle();
1829
1830 // QTSOLBUG-71: When using the MFC/winmigrate solution, it is possible that a child
1831 // window is found, which can cause issues with modality. Loop up to top level.
1832 while (newTransientParent && (GetWindowLongPtr(newTransientParent, GWL_STYLE) & WS_CHILD) != 0)
1833 newTransientParent = GetParent(newTransientParent);
1834
1835 if (newTransientParent != oldTransientParent)
1836 SetWindowLongPtr(m_data.hwnd, GWL_HWNDPARENT, LONG_PTR(newTransientParent));
1837}
1838
1839static inline bool testShowWithoutActivating(const QWindow *window)
1840{
1841 // QWidget-attribute Qt::WA_ShowWithoutActivating .
1842 const QVariant showWithoutActivating = window->property("_q_showWithoutActivating");
1843 return showWithoutActivating.isValid() && showWithoutActivating.toBool();
1844}
1845
1846static void setMinimizedGeometry(HWND hwnd, const QRect &r)
1847{
1848 WINDOWPLACEMENT windowPlacement;
1849 windowPlacement.length = sizeof(WINDOWPLACEMENT);
1850 if (GetWindowPlacement(hwnd, &windowPlacement)) {
1851 windowPlacement.showCmd = SW_SHOWMINIMIZED;
1852 windowPlacement.rcNormalPosition = RECTfromQRect(r);
1853 SetWindowPlacement(hwnd, &windowPlacement);
1854 }
1855}
1856
1857static void setRestoreMaximizedFlag(HWND hwnd, bool set = true)
1858{
1859 // Let Windows know that we need to restore as maximized
1860 WINDOWPLACEMENT windowPlacement;
1861 windowPlacement.length = sizeof(WINDOWPLACEMENT);
1862 if (GetWindowPlacement(hwnd, &windowPlacement)) {
1863 if (set)
1864 windowPlacement.flags |= WPF_RESTORETOMAXIMIZED;
1865 else
1866 windowPlacement.flags &= ~WPF_RESTORETOMAXIMIZED;
1867 SetWindowPlacement(hwnd, &windowPlacement);
1868 }
1869}
1870
1871// partially from QWidgetPrivate::show_sys()
1872void QWindowsWindow::show_sys() const
1873{
1874 int sm = SW_SHOWNORMAL;
1875 bool fakedMaximize = false;
1876 bool restoreMaximize = false;
1877 const QWindow *w = window();
1878 const Qt::WindowFlags flags = w->flags();
1879 const Qt::WindowType type = w->type();
1880 if (w->isTopLevel()) {
1881 const Qt::WindowStates state = w->windowStates();
1882 if (state & Qt::WindowMinimized) {
1883 sm = SW_SHOWMINIMIZED;
1884 if (!isVisible())
1885 sm = SW_SHOWMINNOACTIVE;
1887 restoreMaximize = true;
1888 } else {
1889 updateTransientParent();
1890 if (state & Qt::WindowMaximized) {
1891 sm = SW_SHOWMAXIMIZED;
1892 // Windows will not behave correctly when we try to maximize a window which does not
1893 // have minimize nor maximize buttons in the window frame. Windows would then ignore
1894 // non-available geometry, and rather maximize the widget to the full screen, minus the
1895 // window frame (caption). So, we do a trick here, by adding a maximize button before
1896 // maximizing the widget, and then remove the maximize button afterwards.
1897 if (flags & Qt::WindowTitleHint &&
1899 fakedMaximize = TRUE;
1900 setStyle(style() | WS_MAXIMIZEBOX);
1901 }
1902 } // Qt::WindowMaximized
1903 } // !Qt::WindowMinimized
1904 }
1906 sm = SW_SHOWNOACTIVATE;
1907
1908 if (w->windowStates() & Qt::WindowMaximized)
1909 setFlag(WithinMaximize); // QTBUG-8361
1910
1911 ShowWindow(m_data.hwnd, sm);
1912
1914
1915 if (fakedMaximize) {
1916 setStyle(style() & ~WS_MAXIMIZEBOX);
1917 SetWindowPos(m_data.hwnd, nullptr, 0, 0, 0, 0,
1918 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER
1919 | SWP_FRAMECHANGED);
1920 }
1921 if (restoreMaximize)
1923}
1924
1926{
1927 qCDebug(lcQpaWindow) << __FUNCTION__ << window() << newParent;
1928
1929 if (m_data.hwnd)
1930 setParent_sys(newParent);
1931}
1932
1933void QWindowsWindow::setParent_sys(const QPlatformWindow *parent)
1934{
1935 // Use GetAncestor instead of GetParent, as GetParent can return owner window for toplevels
1936 HWND oldParentHWND = parentHwnd();
1937 HWND newParentHWND = nullptr;
1938 if (parent) {
1939 const auto *parentW = static_cast<const QWindowsWindow *>(parent);
1940 newParentHWND = parentW->handle();
1941
1942 }
1943
1944 // NULL handle means desktop window, which also has its proper handle -> disambiguate
1945 HWND desktopHwnd = GetDesktopWindow();
1946 if (oldParentHWND == desktopHwnd)
1947 oldParentHWND = nullptr;
1948 if (newParentHWND == desktopHwnd)
1949 newParentHWND = nullptr;
1950
1951 if (newParentHWND != oldParentHWND) {
1952 const bool wasTopLevel = oldParentHWND == nullptr;
1953 const bool isTopLevel = newParentHWND == nullptr;
1954
1956 SetParent(m_data.hwnd, newParentHWND);
1958
1959 // WS_CHILD/WS_POPUP must be manually set/cleared in addition
1960 // to dialog frames, etc (see SetParent() ) if the top level state changes.
1961 // Force toplevel state as QWindow::isTopLevel cannot be relied upon here.
1962 if (wasTopLevel != isTopLevel) {
1963 setDropSiteEnabled(false);
1964 setWindowFlags_sys(window()->flags(), unsigned(isTopLevel ? WindowCreationData::ForceTopLevel : WindowCreationData::ForceChild));
1965 updateDropSite(isTopLevel);
1966 }
1967 }
1968}
1969
1971{
1972 fireExpose(QRegion());
1973}
1974
1976{
1977 const QWindow *w = window();
1978 if ((w->surfaceType() == QWindow::OpenGLSurface
1979 || w->surfaceType() == QWindow::VulkanSurface
1980 || w->surfaceType() == QWindow::Direct3DSurface)
1981 && w->format().hasAlpha())
1982 {
1984 }
1985}
1986
1992
1993void QWindowsWindow::handleDpiScaledSize(WPARAM wParam, LPARAM lParam, LRESULT *result)
1994{
1995 // We want to keep QWindow's device independent size constant across the
1996 // DPI change. To accomplish this, scale QPlatformWindow's native size
1997 // by the change of DPI (e.g. 120 -> 144 = 1.2), also taking any scale
1998 // factor rounding into account. The win32 window size includes the margins;
1999 // add the margins for the new DPI to the window size.
2000 const UINT dpi = UINT(wParam);
2001 const qreal scale = dpiRelativeScale(dpi);
2002 const QMargins margins = fullFrameMargins();
2003 if (!(m_data.flags & Qt::FramelessWindowHint)) {
2004 // We need to update the custom margins to match the current DPI, because
2005 // we don't want our users manually hook into this message just to set a
2006 // new margin, but here we can't call setCustomMargins() directly, that
2007 // function will change the window geometry which conflicts with what we
2008 // are currently doing.
2009 m_data.customMargins *= scale;
2010 }
2011
2012 const QSize windowSize = (geometry().size() * scale).grownBy((margins * scale) + customMargins());
2013 SIZE *size = reinterpret_cast<SIZE *>(lParam);
2014 size->cx = windowSize.width();
2015 size->cy = windowSize.height();
2016 *result = true; // Inform Windows that we've set a size
2017}
2018
2019void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
2020{
2021 const UINT dpi = HIWORD(wParam);
2022 const qreal scale = dpiRelativeScale(dpi);
2023 setSavedDpi(dpi);
2024
2026
2027 // Send screen change first, so that the new screen is set during any following resize
2029
2030 if (!IsZoomed(hwnd))
2032
2033 // We get WM_DPICHANGED in one of two situations:
2034 //
2035 // 1. The DPI change is a "spontaneous" DPI change as a result of e.g.
2036 // the user dragging the window to a new screen. In this case Windows
2037 // first sends WM_GETDPISCALEDSIZE, where we set the new window size,
2038 // followed by this event where we apply the suggested window geometry
2039 // to the native window. This will make sure the window tracks the mouse
2040 // cursor during screen change, and also that the window size is scaled
2041 // according to the DPI change.
2042 //
2043 // 2. The DPI change is a result of a setGeometry() call. In this case
2044 // Qt has already scaled the window size for the new DPI. Further, Windows
2045 // does not call WM_GETDPISCALEDSIZE, and also applies its own scaling
2046 // to the already scaled window size. Since there is no need to set the
2047 // window geometry again, and the provided geometry is incorrect, we omit
2048 // making the SetWindowPos() call.
2049 if (!m_inSetgeometry) {
2051 const auto prcNewWindow = reinterpret_cast<RECT *>(lParam);
2052 SetWindowPos(hwnd, nullptr, prcNewWindow->left, prcNewWindow->top,
2053 prcNewWindow->right - prcNewWindow->left,
2054 prcNewWindow->bottom - prcNewWindow->top, SWP_NOZORDER | SWP_NOACTIVATE);
2055 // If the window does not have a frame, WM_MOVE and WM_SIZE won't be
2056 // called which prevents the content from being scaled appropriately
2057 // after a DPI change.
2058 if (shouldOmitFrameAdjustment(m_data.flags, m_data.hwnd))
2059 handleGeometryChange();
2060 }
2061
2062 // Re-apply mask now that we have a new DPI, which have resulted in
2063 // a new scale factor.
2065}
2066
2068{
2069 const UINT dpi = GetDpiForWindow(hwnd);
2070 const qreal scale = dpiRelativeScale(dpi);
2071 setSavedDpi(dpi);
2072
2074
2075 // Child windows do not get WM_GETDPISCALEDSIZE messages to inform
2076 // Windows about the new size, so we need to manually scale them.
2077 QRect currentGeometry = geometry();
2078 QRect scaledGeometry = QRect(currentGeometry.topLeft() * scale, currentGeometry.size() * scale);
2079 setGeometry(scaledGeometry);
2080}
2081
2083{
2084 WINDOWPLACEMENT wp;
2085 wp.length = sizeof(WINDOWPLACEMENT);
2086 if (GetWindowPlacement(hwnd, &wp)) {
2087 const QRect result = qrectFromRECT(wp.rcNormalPosition);
2088 return result.translated(windowPlacementOffset(hwnd, result.topLeft()));
2089 }
2090 return QRect();
2091}
2092
2094{
2095 // Check for fake 'fullscreen' mode.
2096 const bool fakeFullScreen =
2097 m_savedFrameGeometry.isValid() && (window()->windowStates() & Qt::WindowFullScreen);
2098 const QRect frame = fakeFullScreen ? m_savedFrameGeometry : normalFrameGeometry(m_data.hwnd);
2099 const QMargins margins = fakeFullScreen
2100 ? QWindowsGeometryHint::frame(window(), handle(), m_savedStyle, 0)
2101 : fullFrameMargins();
2102 return frame.isValid() ? frame.marginsRemoved(margins) : frame;
2103}
2104
2105static QString msgUnableToSetGeometry(const QWindowsWindow *platformWindow,
2106 const QRect &requestedRect,
2107 const QRect &obtainedRect,
2108 const QMargins &fullMargins,
2109 const QMargins &customMargins)
2110{
2113 debug.nospace();
2114 debug.noquote();
2115 const auto window = platformWindow->window();
2116 debug << "Unable to set geometry ";
2117 formatBriefRectangle(debug, requestedRect);
2118 debug << " (frame: ";
2119 formatBriefRectangle(debug, requestedRect + fullMargins);
2120 debug << ") on " << window->metaObject()->className() << "/\""
2121 << window->objectName() << "\" on \"" << window->screen()->name()
2122 << "\". Resulting geometry: ";
2123 formatBriefRectangle(debug, obtainedRect);
2124 debug << " (frame: ";
2125 formatBriefRectangle(debug, obtainedRect + fullMargins);
2126 debug << ") margins: ";
2127 formatBriefMargins(debug, fullMargins);
2128 if (!customMargins.isNull()) {
2129 debug << " custom margin: ";
2130 formatBriefMargins(debug, customMargins);
2131 }
2132 const auto minimumSize = window->minimumSize();
2133 const bool hasMinimumSize = !minimumSize.isEmpty();
2134 if (hasMinimumSize)
2135 debug << " minimum size: " << minimumSize.width() << 'x' << minimumSize.height();
2136 const auto maximumSize = window->maximumSize();
2137 const bool hasMaximumSize = maximumSize.width() != QWINDOWSIZE_MAX || maximumSize.height() != QWINDOWSIZE_MAX;
2138 if (hasMaximumSize)
2139 debug << " maximum size: " << maximumSize.width() << 'x' << maximumSize.height();
2140 if (hasMinimumSize || hasMaximumSize) {
2141 MINMAXINFO minmaxInfo;
2142 memset(&minmaxInfo, 0, sizeof(minmaxInfo));
2143 platformWindow->getSizeHints(&minmaxInfo);
2144 debug << ' ' << minmaxInfo;
2145 }
2146 debug << ')';
2147 return result;
2148}
2149
2151{
2152 QBoolBlocker b(m_inSetgeometry);
2153
2154 QRect rect = rectIn;
2155 // This means it is a call from QWindow::setFramePosition() and
2156 // the coordinates include the frame (size is still the contents rectangle).
2158 const QMargins margins = frameMargins();
2159 rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top()));
2160 }
2161
2162 if (m_windowState & Qt::WindowMinimized)
2163 m_data.geometry = rect; // Otherwise set by handleGeometryChange() triggered by event.
2164 else
2165 setWindowState(Qt::WindowNoState);// Update window state to WindowNoState unless minimized
2166
2167 if (m_data.hwnd) {
2168 // A ResizeEvent with resulting geometry will be sent. If we cannot
2169 // achieve that size (for example, window title minimal constraint),
2170 // notify and warn.
2174 if (m_data.geometry != rect && (isVisible() || QLibraryInfo::isDebugBuild())) {
2175 const auto warning =
2176 msgUnableToSetGeometry(this, rectIn, m_data.geometry,
2178 qWarning("%s: %s", __FUNCTION__, qPrintable(warning));
2179 }
2180 } else {
2182 }
2183}
2184
2186{
2187 // Minimize/Set parent can send nonsensical move events.
2188 if (!IsIconic(m_data.hwnd) && !testFlag(WithinSetParent))
2189 handleGeometryChange();
2190}
2191
2192void QWindowsWindow::handleResized(int wParam, LPARAM lParam)
2193{
2194 /* Prevents borderless windows from covering the taskbar when maximized. */
2195 if ((m_data.flags.testFlag(Qt::FramelessWindowHint)
2196 || (m_data.flags.testFlag(Qt::CustomizeWindowHint) && !m_data.flags.testFlag(Qt::WindowTitleHint)))
2197 && IsZoomed(m_data.hwnd)) {
2198 const int resizedWidth = LOWORD(lParam);
2199 const int resizedHeight = HIWORD(lParam);
2200
2201 const HMONITOR monitor = MonitorFromWindow(m_data.hwnd, MONITOR_DEFAULTTOPRIMARY);
2202 MONITORINFO monitorInfo = {};
2203 monitorInfo.cbSize = sizeof(MONITORINFO);
2204 GetMonitorInfoW(monitor, &monitorInfo);
2205
2206 int correctLeft = monitorInfo.rcMonitor.left;
2207 int correctTop = monitorInfo.rcMonitor.top;
2208 int correctWidth = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
2209 int correctHeight = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
2210
2211 if (!m_data.flags.testFlag(Qt::FramelessWindowHint)) {
2212 const int borderWidth = invisibleMargins(m_data.hwnd).left();
2213 correctLeft -= borderWidth;
2214 correctTop -= borderWidth;
2215 correctWidth += borderWidth * 2;
2216 correctHeight += borderWidth * 2;
2217 }
2218
2219 if (resizedWidth != correctWidth || resizedHeight != correctHeight) {
2220 qCDebug(lcQpaWindow) << __FUNCTION__ << "correcting: " << resizedWidth << "x"
2221 << resizedHeight << " -> " << correctWidth << "x" << correctHeight;
2222 SetWindowPos(m_data.hwnd, nullptr, correctLeft, correctTop, correctWidth, correctHeight,
2223 SWP_NOZORDER | SWP_NOACTIVATE);
2224 }
2225 }
2226
2227 switch (wParam) {
2228 case SIZE_MAXHIDE: // Some other window affected.
2229 case SIZE_MAXSHOW:
2230 return;
2231 case SIZE_MINIMIZED: // QTBUG-53577, prevent state change events during programmatic state change
2233 handleWindowStateChange(m_windowState | Qt::WindowMinimized);
2234 return;
2235 case SIZE_MAXIMIZED:
2236 handleGeometryChange();
2238 handleWindowStateChange(Qt::WindowMaximized | (isFullScreen_sys() ? Qt::WindowFullScreen
2240 break;
2241 case SIZE_RESTORED:
2242 handleGeometryChange();
2244 if (isFullScreen_sys())
2245 handleWindowStateChange(
2248 else if (m_windowState != Qt::WindowNoState && !testFlag(MaximizeToFullScreen))
2249 handleWindowStateChange(Qt::WindowNoState);
2250 }
2251 break;
2252 }
2253}
2254
2255static inline bool equalDpi(const QDpi &d1, const QDpi &d2)
2256{
2257 return qFuzzyCompare(d1.first, d2.first) && qFuzzyCompare(d1.second, d2.second);
2258}
2259
2261{
2263 return;
2264
2265 QPlatformScreen *currentScreen = screen();
2266 auto topLevel = isTopLevel_sys() ? m_data.hwnd : GetAncestor(m_data.hwnd, GA_ROOT);
2267 const QWindowsScreen *newScreen =
2268 QWindowsContext::instance()->screenManager().screenForHwnd(topLevel);
2269
2270 if (newScreen == nullptr || newScreen == currentScreen)
2271 return;
2272 // For screens with different DPI: postpone until WM_DPICHANGE
2273 // Check on currentScreen as it can be 0 when resuming a session (QTBUG-80436).
2274 const bool changingDpi = !equalDpi(QDpi(savedDpi(), savedDpi()), newScreen->logicalDpi());
2275 if (mode == FromGeometryChange && currentScreen != nullptr && changingDpi)
2276 return;
2277
2278 qCDebug(lcQpaWindow).noquote().nospace() << __FUNCTION__
2279 << ' ' << window() << " \"" << (currentScreen ? currentScreen->name() : QString())
2280 << "\"->\"" << newScreen->name() << '"';
2282 QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(window(), newScreen->screen());
2283}
2284
2285void QWindowsWindow::handleGeometryChange()
2286{
2287 const QRect previousGeometry = m_data.geometry;
2288 m_data.geometry = geometry_sys();
2291 // QTBUG-32121: OpenGL/normal windows (with exception of ANGLE
2292 // which we no longer support in Qt 6) do not receive expose
2293 // events when shrinking, synthesize.
2294 if (isExposed()
2295 && m_data.geometry.size() != previousGeometry.size() // Exclude plain move
2296 // One dimension grew -> Windows will send expose, no need to synthesize.
2297 && !(m_data.geometry.width() > previousGeometry.width() || m_data.geometry.height() > previousGeometry.height())) {
2298 fireFullExpose(true);
2299 }
2300
2301 const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
2303
2306
2309
2310 if (!wasSync)
2312 qCDebug(lcQpaEvents) << __FUNCTION__ << this << window() << m_data.geometry;
2313}
2314
2316{
2317 const QMargins margins = fullFrameMargins();
2318 const QRect frameGeometry = rect + margins;
2319
2320 qCDebug(lcQpaWindow) << '>' << __FUNCTION__ << window()
2321 << "\n from " << geometry_sys() << " frame: "
2322 << margins << " to " <<rect
2323 << " new frame: " << frameGeometry;
2324
2325 bool result = false;
2326 const HWND hwnd = handle();
2327 WINDOWPLACEMENT windowPlacement;
2328 windowPlacement.length = sizeof(WINDOWPLACEMENT);
2329 GetWindowPlacement(hwnd, &windowPlacement);
2330 // If the window is hidden and in maximized state or minimized, instead of moving the
2331 // window, set the normal position of the window.
2332 if ((windowPlacement.showCmd == SW_MAXIMIZE && !IsWindowVisible(hwnd))
2333 || windowPlacement.showCmd == SW_SHOWMINIMIZED) {
2334 windowPlacement.rcNormalPosition =
2335 RECTfromQRect(frameGeometry.translated(-windowPlacementOffset(hwnd, frameGeometry.topLeft())));
2336 windowPlacement.showCmd = windowPlacement.showCmd == SW_SHOWMINIMIZED ? SW_SHOWMINIMIZED : SW_HIDE;
2337 result = SetWindowPlacement(hwnd, &windowPlacement);
2338 } else {
2339 int x = frameGeometry.x();
2340 if (!window()->isTopLevel()) {
2341 const HWND parentHandle = GetParent(hwnd);
2342 if (isRtlLayout(parentHandle)) {
2343 RECT rect;
2344 GetClientRect(parentHandle, &rect);
2345 x = rect.right - frameGeometry.width() - x;
2346 }
2347 }
2348 result = MoveWindow(hwnd, x, frameGeometry.y(),
2349 frameGeometry.width(), frameGeometry.height(), true);
2350 }
2351 qCDebug(lcQpaWindow) << '<' << __FUNCTION__ << window()
2352 << "\n resulting " << result << geometry_sys();
2353}
2354
2363{
2364 if (!m_hdc) {
2365 m_hdc = GetDC(handle());
2367 SetLayout(m_hdc, 0); // Clear RTL layout
2368 }
2369 return m_hdc;
2370}
2371
2380{
2381 if (m_hdc) {
2382 ReleaseDC(handle(), m_hdc);
2383 m_hdc = nullptr;
2384 }
2385}
2386
2387static inline bool isSoftwareGl()
2388{
2389#if QT_CONFIG(dynamicgl)
2390 return QOpenGLStaticContext::opengl32.moduleIsNotOpengl32()
2392#else
2393 return false;
2394#endif // dynamicgl
2395}
2396
2398 WPARAM, LPARAM, LRESULT *result)
2399{
2400 if (message == WM_ERASEBKGND) { // Backing store - ignored.
2401 *result = 1;
2402 return true;
2403 }
2404 // QTBUG-75455: Suppress WM_PAINT sent to invisible windows when setting WS_EX_LAYERED
2405 if (!window()->isVisible() && (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED) != 0)
2406 return false;
2407 // Ignore invalid update bounding rectangles
2408 if (!GetUpdateRect(m_data.hwnd, 0, FALSE))
2409 return false;
2410 PAINTSTRUCT ps;
2411
2412 // GL software rendering (QTBUG-58178) with some AMD cards
2413 // (QTBUG-60527) need InvalidateRect() to suppress artifacts while resizing.
2415 InvalidateRect(hwnd, nullptr, false);
2416
2417 BeginPaint(hwnd, &ps);
2418
2419 // If the a window is obscured by another window (such as a child window)
2420 // we still need to send isExposed=true, for compatibility.
2421 // Our tests depend on it.
2422 fireExpose(QRegion(qrectFromRECT(ps.rcPaint)), true);
2423 if (!QWindowsContext::instance()->asyncExpose())
2425
2426 EndPaint(hwnd, &ps);
2427 return true;
2428}
2429
2434
2436{
2437 qCDebug(lcQpaWindow) << '>' << __FUNCTION__ << this << window() << "\n from: "
2438 << m_data.flags << "\n to: " << flags;
2439 const QRect oldGeometry = geometry();
2440 if (m_data.flags != flags) {
2441 m_data.flags = flags;
2442 if (m_data.hwnd) {
2443 m_data = setWindowFlags_sys(flags);
2444 updateDropSite(window()->isTopLevel());
2445 }
2446 }
2447 // When switching to a frameless window, geometry
2448 // may change without a WM_MOVE. Report change manually.
2449 // Do not send synchronously as not to clobber the widget
2450 // geometry in a sequence of setting flags and geometry.
2451 const QRect newGeometry = geometry_sys();
2452 if (oldGeometry != newGeometry)
2453 handleGeometryChange();
2454
2455 qCDebug(lcQpaWindow) << '<' << __FUNCTION__ << "\n returns: "
2456 << m_data.flags << " geometry " << oldGeometry << "->" << newGeometry;
2457}
2458
2459QWindowsWindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt,
2460 unsigned flags) const
2461{
2462 WindowCreationData creationData;
2463 creationData.fromWindow(window(), wt, flags);
2464 creationData.applyWindowFlags(m_data.hwnd);
2465 creationData.initialize(window(), m_data.hwnd, true, m_opacity);
2466
2467 QWindowsWindowData result = m_data;
2468 result.flags = creationData.flags;
2469 result.embedded = creationData.embedded;
2470 result.hasFrame = (creationData.style & (WS_DLGFRAME | WS_THICKFRAME))
2471 && !(creationData.flags & Qt::FramelessWindowHint);
2472 return result;
2473}
2474
2475void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
2476{
2477 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window()
2478 << "\n from " << m_windowState << " to " << state;
2479 m_windowState = state;
2481 if (state & Qt::WindowMinimized) {
2482 handleHidden();
2484 } else {
2485 if (state & Qt::WindowMaximized) {
2486 WINDOWPLACEMENT windowPlacement{};
2487 windowPlacement.length = sizeof(WINDOWPLACEMENT);
2488 GetWindowPlacement(m_data.hwnd, &windowPlacement);
2489 const RECT geometry = RECTfromQRect(m_data.restoreGeometry);
2490 windowPlacement.rcNormalPosition = geometry;
2491 SetWindowPlacement(m_data.hwnd, &windowPlacement);
2492 }
2493 // QTBUG-17548: We send expose events when receiving WM_Paint, but for
2494 // layered windows and transient children, we won't receive any WM_Paint.
2495 QWindow *w = window();
2496 bool exposeEventsSent = false;
2497 if (isLayered()) {
2498 fireFullExpose();
2499 exposeEventsSent = true;
2500 }
2501 const QWindowList allWindows = QGuiApplication::allWindows();
2502 for (QWindow *child : allWindows) {
2503 if (child != w && child->isVisible() && child->transientParent() == w) {
2505 if (platformWindow && platformWindow->isLayered()) {
2506 platformWindow->fireFullExpose();
2507 exposeEventsSent = true;
2508 }
2509 }
2510 }
2511 if (exposeEventsSent && !QWindowsContext::instance()->asyncExpose())
2513 }
2514}
2515
2520
2522{
2523 if (m_data.hwnd) {
2524 setWindowState_sys(state);
2525 m_windowState = state;
2526 }
2527}
2528
2529bool QWindowsWindow::isFullScreen_sys() const
2530{
2531 const QWindow *w = window();
2532 if (!w->isTopLevel())
2533 return false;
2536 geometry += QMargins(1, 1, 1, 1);
2538 return screen && geometry == screen->geometry();
2539}
2540
2552void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState)
2553{
2554 const Qt::WindowStates oldState = m_windowState;
2555 if (oldState == newState)
2556 return;
2557 qCDebug(lcQpaWindow) << '>' << __FUNCTION__ << this << window()
2558 << " from " << oldState << " to " << newState;
2559
2560 const bool visible = isVisible();
2561 auto stateChange = oldState ^ newState;
2562
2563 if (stateChange & Qt::WindowFullScreen) {
2565 UINT newStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP;
2566 // Save geometry and style to be restored when fullscreen
2567 // is turned off again, since on Windows, it is not a real
2568 // Window state but emulated by changing geometry and style.
2569 if (!m_savedStyle) {
2570 m_savedStyle = style();
2571 if ((oldState & Qt::WindowMinimized) || (oldState & Qt::WindowMaximized)) {
2572 const QRect nf = normalFrameGeometry(m_data.hwnd);
2573 if (nf.isValid())
2574 m_savedFrameGeometry = nf;
2575 } else {
2576 m_savedFrameGeometry = frameGeometry_sys();
2577 }
2578 }
2581 if (m_savedStyle & WS_SYSMENU)
2582 newStyle |= WS_SYSMENU;
2583 if (visible)
2584 newStyle |= WS_VISIBLE;
2586 newStyle |= WS_BORDER;
2587 setStyle(newStyle);
2588 const HMONITOR monitor = MonitorFromWindow(m_data.hwnd, MONITOR_DEFAULTTONEAREST);
2589 MONITORINFO monitorInfo = {};
2590 monitorInfo.cbSize = sizeof(MONITORINFO);
2591 GetMonitorInfoW(monitor, &monitorInfo);
2592 const QRect screenGeometry(monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top,
2593 monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left,
2594 monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top);
2596 setMinimizedGeometry(m_data.hwnd, screenGeometry);
2597 if (stateChange & Qt::WindowMaximized)
2599 } else {
2600 const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
2601 const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
2603 SetWindowPos(m_data.hwnd, HWND_TOP, screenGeometry.left(), screenGeometry.top(), screenGeometry.width(), screenGeometry.height(), swpf);
2604 if (!wasSync)
2609 }
2610 } else {
2611 // Restore saved state.
2612 unsigned newStyle = m_savedStyle ? m_savedStyle : style();
2613 if (visible)
2614 newStyle |= WS_VISIBLE;
2615 setStyle(newStyle);
2616
2617 const QScreen *screen = window()->screen();
2618 if (!screen)
2620 // That area of the virtual desktop might not be covered by a screen anymore.
2621 if (const auto platformScreen = screen->handle()) {
2622 if (!platformScreen->geometry().intersects(m_savedFrameGeometry))
2623 m_savedFrameGeometry.moveTo(platformScreen->geometry().topLeft());
2624 }
2625
2627 setMinimizedGeometry(m_data.hwnd, m_savedFrameGeometry);
2628 if (stateChange & Qt::WindowMaximized)
2630 } else {
2631 UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE;
2632 if (!m_savedFrameGeometry.isValid())
2633 swpf |= SWP_NOSIZE | SWP_NOMOVE;
2634 const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
2636 // After maximized/fullscreen; the window can be in a maximized state. Clear
2637 // it before applying the normal geometry.
2638 if (windowVisibility_sys(m_data.hwnd) == QWindow::Maximized)
2639 ShowWindow(m_data.hwnd, SW_SHOWNOACTIVATE);
2640 SetWindowPos(m_data.hwnd, nullptr, m_savedFrameGeometry.x(), m_savedFrameGeometry.y(),
2641 m_savedFrameGeometry.width(), m_savedFrameGeometry.height(), swpf);
2642 if (!wasSync)
2644 // preserve maximized state
2645 if (visible) {
2647 ShowWindow(m_data.hwnd,
2648 (newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNA);
2650 }
2651 }
2652 m_savedStyle = 0;
2653 m_savedFrameGeometry = QRect();
2654 }
2655 } else if ((oldState & Qt::WindowMaximized) != (newState & Qt::WindowMaximized)) {
2656 if (visible && !(newState & Qt::WindowMinimized)) {
2660 ShowWindow(m_data.hwnd,
2661 (newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
2664 } else if (visible && (oldState & newState & Qt::WindowMinimized)) {
2665 // change of the maximized state while keeping minimized
2667 }
2668 }
2669
2670 if (stateChange & Qt::WindowMinimized) {
2671 if (visible) {
2672 ShowWindow(m_data.hwnd,
2673 (newState & Qt::WindowMinimized) ? SW_MINIMIZE :
2674 (newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNORMAL);
2675 if ((newState & Qt::WindowMinimized) && (stateChange & Qt::WindowMaximized))
2677 }
2678 }
2679 qCDebug(lcQpaWindow) << '<' << __FUNCTION__ << this << window() << newState;
2680}
2681
2682void QWindowsWindow::setStyle(unsigned s) const
2683{
2684 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window() << debugWinStyle(s);
2686 SetWindowLongPtr(m_data.hwnd, GWL_STYLE, s);
2688}
2689
2690void QWindowsWindow::setExStyle(unsigned s) const
2691{
2692 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window() << debugWinExStyle(s);
2693 SetWindowLongPtr(m_data.hwnd, GWL_EXSTYLE, s);
2694}
2695
2697{
2698 switch (event->type()) {
2701 break;
2702 case QEvent::WindowBlocked: // Blocked by another modal window.
2703 setEnabled(false);
2705 if (hasMouseCapture())
2706 ReleaseCapture();
2707 break;
2709 setEnabled(true);
2711 break;
2712 default:
2713 break;
2714 }
2715
2717}
2718
2720{
2721 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window();
2722}
2723
2725{
2726 auto *windowPos = reinterpret_cast<WINDOWPOS *>(message->lParam);
2727 const QRect suggestedFrameGeometry(windowPos->x, windowPos->y,
2728 windowPos->cx, windowPos->cy);
2729 const QRect suggestedGeometry = suggestedFrameGeometry - margins;
2730
2731 // Tell Windows to discard the entire contents of the client area, as re-using
2732 // parts of the client area would lead to jitter during resize.
2733 // Check the suggestedGeometry against the current one to only discard during
2734 // resize, and not a plain move. We also look for SWP_NOSIZE since that, too,
2735 // implies an identical size, and comparing QRects wouldn't work with null cx/cy
2736 if (!(windowPos->flags & SWP_NOSIZE) && suggestedGeometry.size() != qWindow->geometry().size())
2737 windowPos->flags |= SWP_NOCOPYBITS;
2738
2739 if ((windowPos->flags & SWP_NOZORDER) == 0) {
2740 if (QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(qWindow)) {
2741 QWindow *parentWindow = qWindow->parent();
2742 HWND parentHWND = GetAncestor(windowPos->hwnd, GA_PARENT);
2743 HWND desktopHWND = GetDesktopWindow();
2744 platformWindow->m_data.embedded = !parentWindow && parentHWND && (parentHWND != desktopHWND);
2745 }
2746 if (qWindow->flags().testFlag(Qt::WindowStaysOnBottomHint))
2747 windowPos->hwndInsertAfter = HWND_BOTTOM;
2748 }
2749 if (!qWindow->isTopLevel()) // Implement hasHeightForWidth().
2750 return false;
2751 if (windowPos->flags & SWP_NOSIZE)
2752 return false;
2753 const QRectF correctedGeometryF = QPlatformWindow::closestAcceptableGeometry(qWindow, suggestedGeometry);
2754 if (!correctedGeometryF.isValid())
2755 return false;
2756 const QRect correctedFrameGeometry = correctedGeometryF.toRect() + margins;
2757 if (correctedFrameGeometry == suggestedFrameGeometry)
2758 return false;
2759 windowPos->x = correctedFrameGeometry.left();
2760 windowPos->y = correctedFrameGeometry.top();
2761 windowPos->cx = correctedFrameGeometry.width();
2762 windowPos->cy = correctedFrameGeometry.height();
2763 return true;
2764}
2765
2767{
2768 const QMargins margins = window()->isTopLevel() ? fullFrameMargins() : QMargins();
2770}
2771
2773{
2774 if (shouldOmitFrameAdjustment(m_data.flags, m_data.hwnd))
2775 return;
2776 if (m_data.fullFrameMargins != newMargins) {
2777 qCDebug(lcQpaWindow) << __FUNCTION__ << window() << m_data.fullFrameMargins << "->" << newMargins;
2778 m_data.fullFrameMargins = newMargins;
2779 }
2780}
2781
2783{
2784 // QTBUG-82580: If a native menu is present, force a WM_NCCALCSIZE.
2785 if (GetMenu(m_data.hwnd))
2787 else
2788 calculateFullFrameMargins();
2789}
2790
2791void QWindowsWindow::calculateFullFrameMargins()
2792{
2793 if (shouldOmitFrameAdjustment(m_data.flags, m_data.hwnd))
2794 return;
2795
2796 // QTBUG-113736: systemMargins depends on AdjustWindowRectExForDpi. This doesn't take into
2797 // account possible external modifications to the titlebar, as with ExtendsContentIntoTitleBar()
2798 // from the Windows App SDK. We can fix this by comparing the WindowRect (which includes the
2799 // frame) to the ClientRect. If a 'typical' frame is detected, i.e. only the titlebar has been
2800 // modified, we can safely adjust the frame by deducting the bottom margin to the total Y
2801 // difference between the two rects, to get the actual size of the titlebar and prevent
2802 // unwanted client area slicing.
2803
2804 RECT windowRect{};
2805 RECT clientRect{};
2806 GetWindowRect(handle(), &windowRect);
2807 GetClientRect(handle(), &clientRect);
2808
2809 // QTBUG-117704 It is also possible that the user has manually removed the frame (for example
2810 // by handling WM_NCCALCSIZE). If that is the case, i.e., the client area and the window area
2811 // have identical sizes, we don't want to override the user-defined margins.
2812
2813 if (qrectFromRECT(windowRect).size() == qrectFromRECT(clientRect).size())
2814 return;
2815
2816 // Normally obtained from WM_NCCALCSIZE. This calculation only works
2817 // when no native menu is present.
2818 const auto systemMargins = testFlag(DisableNonClientScaling)
2820 : frameMargins_sys();
2821 const QMargins actualMargins = systemMargins + customMargins();
2822
2823 const int yDiff = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top);
2824 const bool typicalFrame = (actualMargins.left() == actualMargins.right())
2825 && (actualMargins.right() == actualMargins.bottom());
2826
2827 const QMargins adjustedMargins = typicalFrame ?
2828 QMargins(actualMargins.left(), (yDiff - actualMargins.bottom()),
2829 actualMargins.right(), actualMargins.bottom())
2830 : actualMargins;
2831
2832 setFullFrameMargins(adjustedMargins);
2833}
2834
2836{
2838 if (isTopLevel() && m_data.hasFrame)
2839 result -= invisibleMargins(m_data.hwnd);
2840 return result;
2841}
2842
2844{
2845 if (shouldOmitFrameAdjustment(m_data.flags, m_data.hwnd))
2846 return {};
2847 return m_data.fullFrameMargins;
2848}
2849
2851{
2852 qCDebug(lcQpaWindow) << __FUNCTION__ << level;
2853 if (!qFuzzyCompare(m_opacity, level)) {
2854 m_opacity = level;
2855 if (m_data.hwnd)
2856 setWindowOpacity(m_data.hwnd, m_data.flags,
2858 level);
2859 }
2860}
2861
2862static inline HRGN createRectRegion(const QRect &r)
2863{
2864 return CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height());
2865}
2866
2867static inline void addRectToWinRegion(const QRect &rect, HRGN *winRegion)
2868{
2869 if (const HRGN rectRegion = createRectRegion(rect)) {
2870 HRGN result = CreateRectRgn(0, 0, 0, 0);
2871 if (CombineRgn(result, *winRegion, rectRegion, RGN_OR)) {
2872 DeleteObject(*winRegion);
2873 *winRegion = result;
2874 }
2875 DeleteObject(rectRegion);
2876 }
2877}
2878
2879static HRGN qRegionToWinRegion(const QRegion &region)
2880{
2881 auto it = region.begin();
2882 const auto end = region.end();
2883 if (it == end)
2884 return nullptr;
2885 HRGN hRegion = createRectRegion(*it);
2886 while (++it != end)
2887 addRectToWinRegion(*it, &hRegion);
2888 return hRegion;
2889}
2890
2892{
2893 if (region.isEmpty()) {
2894 SetWindowRgn(m_data.hwnd, nullptr, true);
2895 return;
2896 }
2897 const HRGN winRegion = qRegionToWinRegion(region);
2898
2899 // Mask is in client area coordinates, so offset it in case we have a frame
2900 if (window()->isTopLevel()) {
2901 const QMargins margins = fullFrameMargins();
2902 OffsetRgn(winRegion, margins.left(), margins.top());
2903 }
2904
2905 // SetWindowRgn takes ownership.
2906 if (!SetWindowRgn(m_data.hwnd, winRegion, true))
2907 DeleteObject(winRegion);
2908}
2909
2911{
2912 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window();
2913
2914 if (!m_data.hwnd)
2915 return;
2916
2917 const auto activationBehavior = QWindowsIntegration::instance()->windowActivationBehavior();
2919 || activationBehavior != QWindowsApplication::AlwaysActivateWindow) {
2920 SetForegroundWindow(m_data.hwnd);
2921 SetFocus(m_data.hwnd);
2922 return;
2923 }
2924
2925 // Force activate this window. The following code will bring the window to the
2926 // foreground and activate it. If the window is hidden, it will show up. If
2927 // the window is minimized, it will restore to the previous position.
2928
2929 // But first we need some sanity checks.
2930 if (m_data.flags & Qt::WindowStaysOnBottomHint) {
2931 qCWarning(lcQpaWindow) <<
2932 "Windows with Qt::WindowStaysOnBottomHint can't be brought to the foreground.";
2933 return;
2934 }
2935 if (m_data.flags & Qt::WindowStaysOnTopHint) {
2936 qCWarning(lcQpaWindow) <<
2937 "Windows with Qt::WindowStaysOnTopHint will always be on the foreground.";
2938 return;
2939 }
2940 if (window()->type() == Qt::ToolTip) {
2941 qCWarning(lcQpaWindow) << "ToolTip windows should not be activated.";
2942 return;
2943 }
2944
2945 // We need to show the window first, otherwise we won't be able to bring it to front.
2946 if (!IsWindowVisible(m_data.hwnd))
2947 ShowWindow(m_data.hwnd, SW_SHOW);
2948
2949 if (IsIconic(m_data.hwnd)) {
2950 ShowWindow(m_data.hwnd, SW_RESTORE);
2951 // When the window is restored, it will always become the foreground window.
2952 // So return early here, we don't need the following code to bring it to front.
2953 return;
2954 }
2955
2956 // OK, our window is not minimized, so now we will try to bring it to front manually.
2957 const HWND oldForegroundWindow = GetForegroundWindow();
2958 if (!oldForegroundWindow) // It may be NULL, according to MS docs.
2959 return;
2960
2961 // First try to send a message to the current foreground window to check whether
2962 // it is currently hanging or not.
2963 if (SendMessageTimeoutW(oldForegroundWindow, WM_NULL, 0, 0,
2964 SMTO_BLOCK | SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG, 1000, nullptr) == 0) {
2965 qCWarning(lcQpaWindow) << "The foreground window hangs, can't activate current window.";
2966 return;
2967 }
2968
2969 const DWORD windowThreadProcessId = GetWindowThreadProcessId(oldForegroundWindow, nullptr);
2970 const DWORD currentThreadId = GetCurrentThreadId();
2971
2972 AttachThreadInput(windowThreadProcessId, currentThreadId, TRUE);
2973 const auto cleanup = qScopeGuard([windowThreadProcessId, currentThreadId](){
2974 AttachThreadInput(windowThreadProcessId, currentThreadId, FALSE);
2975 });
2976
2977 BringWindowToTop(m_data.hwnd);
2978
2979 // Activate the window too. This will force us to the virtual desktop this
2980 // window is on, if it's on another virtual desktop.
2981 SetActiveWindow(m_data.hwnd);
2982}
2983
2985{
2986 if (!m_data.hwnd) {
2987 qWarning("%s: No handle", __FUNCTION__);
2988 return false;
2989 }
2990 qCDebug(lcQpaWindow) << __FUNCTION__ << this << window() << grab;
2991
2993 if (grab) {
2994 context->setKeyGrabber(window());
2995 } else {
2996 if (context->keyGrabber() == window())
2997 context->setKeyGrabber(nullptr);
2998 }
2999 return true;
3000}
3001
3003{
3004 qCDebug(lcQpaWindow) << __FUNCTION__ << window() << grab;
3005 if (!m_data.hwnd) {
3006 qWarning("%s: No handle", __FUNCTION__);
3007 return false;
3008 }
3009 if (!isVisible() && grab) {
3010 qWarning("%s: Not setting mouse grab for invisible window %s/'%s'",
3011 __FUNCTION__, window()->metaObject()->className(),
3012 qPrintable(window()->objectName()));
3013 return false;
3014 }
3015 // release grab or an explicit grab overriding autocapture: Clear flag.
3017 if (hasMouseCapture() != grab) {
3018 if (grab) {
3019 SetCapture(m_data.hwnd);
3020 } else {
3021 ReleaseCapture();
3022 }
3023 }
3024 return grab;
3025}
3026
3027static inline DWORD edgesToWinOrientation(Qt::Edges edges)
3028{
3029 if (edges == Qt::LeftEdge)
3030 return 0xf001; // SC_SIZELEFT;
3031 else if (edges == (Qt::RightEdge))
3032 return 0xf002; // SC_SIZERIGHT
3033 else if (edges == (Qt::TopEdge))
3034 return 0xf003; // SC_SIZETOP
3035 else if (edges == (Qt::TopEdge | Qt::LeftEdge))
3036 return 0xf004; // SC_SIZETOPLEFT
3037 else if (edges == (Qt::TopEdge | Qt::RightEdge))
3038 return 0xf005; // SC_SIZETOPRIGHT
3039 else if (edges == (Qt::BottomEdge))
3040 return 0xf006; // SC_SIZEBOTTOM
3041 else if (edges == (Qt::BottomEdge | Qt::LeftEdge))
3042 return 0xf007; // SC_SIZEBOTTOMLEFT
3043 else if (edges == (Qt::BottomEdge | Qt::RightEdge))
3044 return 0xf008; // SC_SIZEBOTTOMRIGHT
3045
3046 return 0xf000; // SC_SIZE
3047}
3048
3050{
3052 return false;
3053
3054 ReleaseCapture();
3055 PostMessage(m_data.hwnd, WM_SYSCOMMAND, edgesToWinOrientation(edges), 0);
3057 return true;
3058}
3059
3061{
3062 ReleaseCapture();
3063 PostMessage(m_data.hwnd, WM_SYSCOMMAND, 0xF012 /*SC_DRAGMOVE*/, 0);
3064 return true;
3065}
3066
3075
3076void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
3077{
3079 qCDebug(lcQpaWindow) << __FUNCTION__ << window() << *mmi;
3080}
3081
3082bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *result) const
3083{
3084 // QTBUG-32663, suppress resize cursor for fixed size windows.
3085 const QWindow *w = window();
3086 if (!w->isTopLevel() // Task 105852, minimized windows need to respond to user input.
3087 || (m_windowState != Qt::WindowNoState)
3088 || !isActive()
3089 || (m_data.flags & Qt::FramelessWindowHint)) {
3090 return false;
3091 }
3092 const QSize minimumSize = w->minimumSize();
3093 if (minimumSize.isEmpty())
3094 return false;
3095 const QSize maximumSize = w->maximumSize();
3096 const bool fixedWidth = minimumSize.width() == maximumSize.width();
3097 const bool fixedHeight = minimumSize.height() == maximumSize.height();
3098 if (!fixedWidth && !fixedHeight)
3099 return false;
3100 const QPoint localPos = w->mapFromGlobal(QHighDpi::fromNativePixels(globalPos, w));
3101 const QSize size = w->size();
3102 if (fixedHeight) {
3103 if (localPos.y() >= size.height()) {
3104 *result = HTBORDER; // Unspecified border, no resize cursor.
3105 return true;
3106 }
3107 if (localPos.y() < 0) {
3108 const int topResizeBarPos = invisibleMargins(m_data.hwnd).left() - frameMargins().top();
3109 if (localPos.y() < topResizeBarPos) {
3110 *result = HTCAPTION; // Extend caption over top resize bar, let's user move the window.
3111 return true;
3112 }
3113 }
3114 }
3115 if (fixedWidth && (localPos.x() < 0 || localPos.x() >= size.width())) {
3116 *result = HTBORDER; // Unspecified border, no resize cursor.
3117 return true;
3118 }
3119 return false;
3120}
3121
3122#ifndef QT_NO_CURSOR
3123// Return the default cursor (Arrow) from QWindowsCursor's cache.
3125{
3126 if (QScreen *screen = w->screen())
3127 if (const QPlatformScreen *platformScreen = screen->handle())
3128 if (QPlatformCursor *cursor = platformScreen->cursor())
3129 return static_cast<QWindowsCursor *>(cursor)->standardWindowCursor(Qt::ArrowCursor);
3131}
3132
3133// Check whether to apply a new cursor. Either the window in question is
3134// currently under mouse, or it is the parent of the window under mouse and
3135// there is no other window with an explicitly set cursor in-between.
3136static inline bool applyNewCursor(const QWindow *w)
3137{
3138 const QWindow *underMouse = QWindowsContext::instance()->windowUnderMouse();
3139 if (underMouse == w)
3140 return true;
3141 for (const QWindow *p = underMouse; p ; p = p->parent()) {
3142 if (p == w)
3143 return true;
3144 const QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(p);
3145 if (platformWindow && !platformWindow->cursor()->isNull())
3146 return false;
3147 }
3148 return false;
3149}
3150#endif // !QT_NO_CURSOR
3151
3159{
3161 if (isTopLevel())
3163 return;
3164 }
3165#ifndef QT_NO_CURSOR
3166 if (m_cursor->isNull()) { // Recurse up to parent with non-null cursor. Set default for toplevel.
3167 if (const QWindow *p = window()->parent()) {
3168 if (QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(p))
3169 platformWindow->applyCursor();
3170 } else {
3171 SetCursor(defaultCursor(window())->handle());
3172 }
3173 } else {
3174 SetCursor(m_cursor->handle());
3175 }
3176#endif
3177}
3178
3180{
3181#ifndef QT_NO_CURSOR
3182 bool changed = c->handle() != m_cursor->handle();
3183 // QTBUG-98856: Cursors can get out of sync after restoring override
3184 // cursors on native windows. Force an update.
3187 changed = true;
3188 }
3189 if (changed) {
3190 const bool apply = applyNewCursor(window());
3191 qCDebug(lcQpaWindow) << window() << __FUNCTION__
3192 << c->handle() << " doApply=" << apply;
3193 m_cursor = c;
3194 if (apply)
3195 applyCursor();
3196 }
3197#endif
3198}
3199
3201{
3202 if (isAlertState() == enabled)
3203 return;
3204 if (enabled) {
3205 alertWindow(0);
3207 } else {
3210 }
3211}
3212
3214{
3215 UINT timeOutMs = GetCaretBlinkTime();
3216 if (!timeOutMs || timeOutMs == INFINITE)
3217 timeOutMs = 250;
3218
3219 FLASHWINFO info;
3220 info.cbSize = sizeof(info);
3221 info.hwnd = m_data.hwnd;
3222 info.dwFlags = FLASHW_TRAY;
3223 info.dwTimeout = timeOutMs;
3224 info.uCount = durationMs == 0 ? 10 : UINT(durationMs) / timeOutMs;
3225 FlashWindowEx(&info);
3226}
3227
3229{
3230 FLASHWINFO info;
3231 info.cbSize = sizeof(info);
3232 info.hwnd = m_data.hwnd;
3233 info.dwFlags = FLASHW_STOP;
3234 info.dwTimeout = 0;
3235 info.uCount = 0;
3236 FlashWindowEx(&info);
3237}
3238
3240{
3241 return (style() & WS_DISABLED) == 0;
3242}
3243
3245{
3246 const unsigned oldStyle = style();
3247 unsigned newStyle = oldStyle;
3248 if (enabled) {
3249 newStyle &= ~WS_DISABLED;
3250 } else {
3251 newStyle |= WS_DISABLED;
3252 }
3253 if (newStyle != oldStyle)
3254 setStyle(newStyle);
3255}
3256
3257static HICON createHIcon(const QIcon &icon, int xSize, int ySize)
3258{
3259 if (!icon.isNull()) {
3260 // QTBUG-90363, request DPR=1 for the title bar.
3261 const QPixmap pm = icon.pixmap(icon.actualSize(QSize(xSize, ySize)), 1);
3262 if (!pm.isNull())
3263 return qt_pixmapToWinHICON(pm);
3264 }
3265 return nullptr;
3266}
3267
3269{
3270 if (m_data.hwnd) {
3271 destroyIcon();
3272
3273 m_iconSmall = createHIcon(icon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
3274 m_iconBig = createHIcon(icon, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
3275
3276 if (m_iconBig) {
3277 SendMessage(m_data.hwnd, WM_SETICON, 0 /* ICON_SMALL */, LPARAM(m_iconSmall));
3278 SendMessage(m_data.hwnd, WM_SETICON, 1 /* ICON_BIG */, LPARAM(m_iconBig));
3279 } else {
3280 SendMessage(m_data.hwnd, WM_SETICON, 0 /* ICON_SMALL */, LPARAM(m_iconSmall));
3281 SendMessage(m_data.hwnd, WM_SETICON, 1 /* ICON_BIG */, LPARAM(m_iconSmall));
3282 }
3283 }
3284}
3285
3287{
3288 return window()->isTopLevel() && !m_data.embedded;
3289}
3290
3291enum : WORD {
3295
3297{
3298 const BOOL darkBorder = d ? TRUE : FALSE;
3299 const bool ok =
3300 SUCCEEDED(DwmSetWindowAttribute(hwnd, DwmwaUseImmersiveDarkMode, &darkBorder, sizeof(darkBorder)))
3301 || SUCCEEDED(DwmSetWindowAttribute(hwnd, DwmwaUseImmersiveDarkModeBefore20h1, &darkBorder, sizeof(darkBorder)));
3302 if (!ok)
3303 qCWarning(lcQpaWindow, "%s: Unable to set %s window border.", __FUNCTION__, d ? "dark" : "light");
3304 return ok;
3305}
3306
3308{
3309 // respect explicit opt-out and incompatible palettes or styles
3311
3312 setDarkBorderToWindow(m_data.hwnd, d);
3313}
3314
3316{
3317 return m_menuBar.data();
3318}
3319
3321{
3322 m_menuBar = mb;
3323}
3324
3326{
3327 if (m_data.flags & Qt::FramelessWindowHint)
3328 return {};
3329 return m_data.customMargins;
3330}
3331
3342void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins)
3343{
3344 if (m_data.flags & Qt::FramelessWindowHint) {
3345 qCWarning(lcQpaWindow) << "You should not set custom margins for a frameless window.";
3346 return;
3347 }
3348 if (newCustomMargins != m_data.customMargins) {
3349 const QMargins oldCustomMargins = m_data.customMargins;
3350 m_data.customMargins = newCustomMargins;
3351 // Re-trigger WM_NCALCSIZE with wParam=1 by passing SWP_FRAMECHANGED
3352 const QRect currentFrameGeometry = frameGeometry_sys();
3353 const QPoint topLeft = currentFrameGeometry.topLeft();
3354 QRect newFrame = currentFrameGeometry.marginsRemoved(oldCustomMargins) + m_data.customMargins;
3355 newFrame.moveTo(topLeft);
3356 qCDebug(lcQpaWindow) << __FUNCTION__ << oldCustomMargins << "->" << newCustomMargins
3357 << currentFrameGeometry << "->" << newFrame;
3358 SetWindowPos(m_data.hwnd, nullptr, newFrame.x(), newFrame.y(), newFrame.width(), newFrame.height(), SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE);
3359 }
3360}
3361
3362void *QWindowsWindow::surface(void *nativeConfig, int *err)
3363{
3364#if QT_CONFIG(vulkan)
3365 Q_UNUSED(nativeConfig);
3366 Q_UNUSED(err);
3367 if (window()->surfaceType() == QSurface::VulkanSurface) {
3368 if (!m_vkSurface) {
3369 QVulkanInstance *inst = window()->vulkanInstance();
3370 if (inst)
3371 m_vkSurface = static_cast<QWindowsVulkanInstance *>(inst->handle())->createSurface(handle());
3372 else
3373 qWarning("Attempted to create Vulkan surface without an instance; was QWindow::setVulkanInstance() called?");
3374 }
3375 // Different semantics for VkSurfaces: the return value is the address,
3376 // not the value, given that this is a 64-bit handle even on x86.
3377 return &m_vkSurface;
3378 }
3379#elif defined(QT_NO_OPENGL)
3380 Q_UNUSED(err);
3381 Q_UNUSED(nativeConfig);
3382 return nullptr;
3383#endif
3384#ifndef QT_NO_OPENGL
3385 if (!m_surface) {
3387 m_surface = staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig, err);
3388 }
3389
3390 return m_surface;
3391#else
3392 return nullptr;
3393#endif
3394}
3395
3397{
3398#if QT_CONFIG(vulkan)
3399 if (m_vkSurface) {
3400 QVulkanInstance *inst = window()->vulkanInstance();
3401 if (inst)
3402 static_cast<QWindowsVulkanInstance *>(inst->handle())->destroySurface(m_vkSurface);
3403 m_vkSurface = VK_NULL_HANDLE;
3404 }
3405#endif
3406#ifndef QT_NO_OPENGL
3407 if (m_surface) {
3409 staticOpenGLContext->destroyWindowSurface(m_surface);
3410 m_surface = nullptr;
3411 }
3412#endif // QT_NO_OPENGL
3413}
3414
3416{
3418 return;
3419
3420 // Initially register or re-register to change the flags
3421 const auto touchTypes = QWindowsIntegration::instance()->touchWindowTouchType();
3423 const auto currentTouchTypes = touchWindowTouchTypes_sys();
3424 if (currentTouchTypes.has_value() && currentTouchTypes.value() == touchTypes)
3425 return;
3426 }
3427
3428 ULONG touchFlags = 0;
3429 if (touchTypes.testFlag(TouchWindowTouchType::FineTouch))
3430 touchFlags |= TWF_FINETOUCH;
3431 if (touchTypes.testFlag(TouchWindowTouchType::WantPalmTouch))
3432 touchFlags |= TWF_WANTPALM;
3433 if (RegisterTouchWindow(m_data.hwnd, touchFlags))
3435 else
3436 qErrnoWarning("RegisterTouchWindow() failed for window '%s'.", qPrintable(window()->objectName()));
3437}
3438
3446
3448{
3449 m_borderInFullScreenDefault = border;
3450}
3451
3456
3458{
3460 return;
3461 if (border)
3463 else
3465 // Directly apply the flag in case we are fullscreen.
3466 if (m_windowState == Qt::WindowFullScreen) {
3467 LONG_PTR style = GetWindowLongPtr(handle(), GWL_STYLE);
3468 if (border)
3469 style |= WS_BORDER;
3470 else
3471 style &= ~WS_BORDER;
3472 SetWindowLongPtr(handle(), GWL_STYLE, style);
3473 }
3474}
3475
3480
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:1019
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:926
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:834
static bool isDebugBuild() noexcept Q_DECL_CONST_FUNCTION
qsizetype size() const noexcept
Definition qlist.h:397
const T & constFirst() const noexcept
Definition qlist.h:647
\inmodule QtCore
Definition qmargins.h:24
constexpr int bottom() const noexcept
Returns the bottom margin.
Definition qmargins.h:115
constexpr bool isNull() const noexcept
Returns true if all margins are is 0; otherwise returns false.
Definition qmargins.h:103
constexpr int left() const noexcept
Returns the left margin.
Definition qmargins.h:106
constexpr int right() const noexcept
Returns the right margin.
Definition qmargins.h:112
constexpr int top() const noexcept
Returns the top margin.
Definition qmargins.h:109
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
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:67
@ WindowText
Definition qpalette.h:51
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:456
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.
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 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:25
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:130
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:135
T * data() const noexcept
Definition qpointer.h:73
\inmodule QtCore\reentrant
Definition qrect.h:484
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
constexpr bool isValid() const noexcept
Returns true if the rectangle is valid, otherwise returns false.
Definition qrect.h:170
constexpr QRect marginsRemoved(const QMargins &margins) const noexcept
Removes the margins from the rectangle, shrinking it.
Definition qrect.h:454
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:221
constexpr void setSize(const QSize &s) noexcept
Sets the size of the rectangle to the given size.
Definition qrect.h:387
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:185
constexpr QSize size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:242
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:188
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:270
constexpr QPoint center() const noexcept
Returns the center point of the rectangle.
Definition qrect.h:233
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
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:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
constexpr int & rheight() noexcept
Returns a reference to the height.
Definition qsize.h:157
constexpr void setWidth(int w) noexcept
Sets the width to the given width.
Definition qsize.h:136
constexpr int & rwidth() noexcept
Returns a reference to the width.
Definition qsize.h:154
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:124
constexpr void setHeight(int h) noexcept
Sets the height to the given height.
Definition qsize.h:139
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
Definition qstring.cpp:6995
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1240
The QSurfaceFormat class represents the format of a QSurface. \inmodule QtGui.
@ OpenGLSurface
Definition qsurface.h:32
@ VulkanSurface
Definition qsurface.h:35
@ Direct3DSurface
Definition qsurface.h:37
\inmodule QtCore
Definition qvariant.h:65
T value() const &
Definition qvariant.h:516
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:714
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:106
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
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)
Singleton container for all relevant information.
static bool shouldHaveNonClientDpiScaling(const QWindow *window)
static void forceNcCalcSize(HWND hwnd)
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 * screenAtDp(const QPoint &p) const
const WindowsScreenList & screens() const
Windows screen.
static int baseDpi
static QWindowsTheme * instance()
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 ...
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.
static bool hasNoNativeFrame(HWND hwnd, Qt::WindowFlags flags)
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.
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...
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 fromNativePixels(const T &value, const C *context)
QRegion toNativeLocalRegion(const QRegion &pointRegion, const QWindow *window)
Combined button and popup list for selecting options.
Q_GUI_EXPORT void clearThemeCache(HWND hwnd)
Definition qcompare.h:63
WindowState
Definition qnamespace.h:251
@ WindowFullScreen
Definition qnamespace.h:255
@ WindowNoState
Definition qnamespace.h:252
@ WindowMinimized
Definition qnamespace.h:253
@ WindowMaximized
Definition qnamespace.h:254
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:266
WindowType
Definition qnamespace.h:205
@ CustomizeWindowHint
Definition qnamespace.h:239
@ Desktop
Definition qnamespace.h:215
@ Widget
Definition qnamespace.h:206
@ FramelessWindowHint
Definition qnamespace.h:225
@ WindowContextHelpButtonHint
Definition qnamespace.h:231
@ WindowStaysOnBottomHint
Definition qnamespace.h:240
@ ToolTip
Definition qnamespace.h:213
@ MSWindowsFixedSizeDialogHint
Definition qnamespace.h:221
@ Drawer
Definition qnamespace.h:210
@ Popup
Definition qnamespace.h:211
@ WindowType_Mask
Definition qnamespace.h:220
@ Window
Definition qnamespace.h:207
@ SplashScreen
Definition qnamespace.h:214
@ WindowStaysOnTopHint
Definition qnamespace.h:233
@ WindowMaximizeButtonHint
Definition qnamespace.h:229
@ WindowMinimizeButtonHint
Definition qnamespace.h:228
@ Dialog
Definition qnamespace.h:208
@ WindowMinMaxButtonsHint
Definition qnamespace.h:230
@ Sheet
Definition qnamespace.h:209
@ WindowTransparentForInput
Definition qnamespace.h:234
@ SubWindow
Definition qnamespace.h:216
@ Tool
Definition qnamespace.h:212
@ WindowTitleHint
Definition qnamespace.h:226
@ WindowSystemMenuHint
Definition qnamespace.h:227
@ WindowCloseButtonHint
Definition qnamespace.h:241
static void * context
#define Q_UNLIKELY(x)
QString qAppName()
static bool initialize()
Definition qctf.cpp:94
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
QPair< qreal, qreal > QDpi
#define qWarning
Definition qlogging.h:166
#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 GLsizei GLsizei GLenum GLenum GLsizei void * data
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
GLuint name
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLint y
GLfloat GLfloat GLfloat GLfloat h
struct _cl_event * event
GLdouble s
[6]
Definition qopenglext.h:235
const GLubyte * c
GLuint64EXT * result
[6]
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
QDebug warning(QAnyStringView fileName, int lineNumber)
#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:1531
#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:64
double qreal
Definition qtypes.h:187
Q_GUI_EXPORT QWindowPrivate * qt_window_private(QWindow *window)
Definition qwindow.cpp:2950
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 bool shouldOmitFrameAdjustment(const Qt::WindowFlags flags, DWORD style)
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)
@ defaultWindowHeight
@ defaultWindowWidth
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)
@ DwmwaUseImmersiveDarkMode
@ DwmwaUseImmersiveDarkModeBefore20h1
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)
static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &context, const QMargins &invMargins)
static QRect qrectFromRECT(const RECT &rect)
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]
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]
QHostInfo info
[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)
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