5#include <QtCore/qt_windows.h>
6#include <QtGui/qstylehints.h>
11#if QT_CONFIG(draganddrop)
12# include "qwindowsdrag.h"
18#if QT_CONFIG(dynamicgl)
19# include "qwindowsglcontext.h"
25# include "qwindowscursor.h"
30#include <QtGui/qguiapplication.h>
31#include <QtGui/qscreen.h>
32#include <QtGui/qwindow.h>
33#include <QtGui/qregion.h>
34#include <QtGui/qopenglcontext.h>
35#include <QtGui/qpainterpath.h>
36#include <QtGui/private/qwindowsthemecache_p.h>
37#include <private/qwindow_p.h>
38#include <private/qguiapplication_p.h>
39#include <private/qhighdpiscaling_p.h>
40#include <qpa/qwindowsysteminterface.h>
41#include <private/qsystemlibrary_p.h>
42#include <private/qwinregistry_p.h>
45#include <QtCore/qdebug.h>
46#include <QtCore/qlibraryinfo.h>
47#include <QtCore/qoperatingsystemversion.h>
52#include "qwindowsvulkaninstance.h"
55#include <shellscalingapi.h>
57#include <private/qdxgivsyncservice_p.h>
60# define GWL_HWNDPARENT (-8
)
65using namespace Qt::StringLiterals;
67using QWindowCreationContextPtr = QSharedPointer<QWindowCreationContext>;
74Q_GUI_EXPORT HICON qt_pixmapToWinHICON(
const QPixmap &);
79 rc += QByteArray::number(qulonglong(style), 16);
84 if (style & WS_OVERLAPPED)
85 rc +=
" WS_OVERLAPPED";
86 if (style & WS_CLIPSIBLINGS)
87 rc +=
" WS_CLIPSIBLINGS";
88 if (style & WS_CLIPCHILDREN)
89 rc +=
" WS_CLIPCHILDREN";
90 if (style & WS_THICKFRAME)
91 rc +=
" WS_THICKFRAME";
92 if (style & WS_DLGFRAME)
94 if (style & WS_SYSMENU)
96 if (style & WS_MINIMIZEBOX)
97 rc +=
" WS_MINIMIZEBOX";
98 if (style & WS_MAXIMIZEBOX)
99 rc +=
" WS_MAXIMIZEBOX";
100 if (style & WS_BORDER)
102 if (style & WS_CAPTION)
104 if (style & WS_CHILDWINDOW)
105 rc +=
" WS_CHILDWINDOW";
106 if (style & WS_DISABLED)
107 rc +=
" WS_DISABLED";
108 if (style & WS_GROUP)
110 if (style & WS_HSCROLL)
112 if (style & WS_ICONIC)
114 if (style & WS_MAXIMIZE)
115 rc +=
" WS_MAXIMIZE";
116 if (style & WS_MINIMIZE)
117 rc +=
" WS_MINIMIZE";
118 if (style & WS_SIZEBOX)
120 if (style & WS_TABSTOP)
122 if (style & WS_TILED)
124 if (style & WS_VISIBLE)
126 if (style & WS_VSCROLL)
133 QByteArray rc =
"0x";
134 rc += QByteArray::number(qulonglong(exStyle), 16);
135 if (exStyle & WS_EX_TOOLWINDOW)
136 rc +=
" WS_EX_TOOLWINDOW";
137 if (exStyle & WS_EX_CONTEXTHELP)
138 rc +=
" WS_EX_CONTEXTHELP";
139 if (exStyle & WS_EX_LAYERED)
140 rc +=
" WS_EX_LAYERED";
141 if (exStyle & WS_EX_DLGMODALFRAME)
142 rc +=
" WS_EX_DLGMODALFRAME";
143 if (exStyle & WS_EX_LAYOUTRTL)
144 rc +=
" WS_EX_LAYOUTRTL";
145 if (exStyle & WS_EX_NOINHERITLAYOUT)
146 rc +=
" WS_EX_NOINHERITLAYOUT";
147 if (exStyle & WS_EX_ACCEPTFILES)
148 rc +=
" WS_EX_ACCEPTFILES";
149 if (exStyle & WS_EX_APPWINDOW)
150 rc +=
" WS_EX_APPWINDOW";
151 if (exStyle & WS_EX_CLIENTEDGE)
152 rc +=
" WS_EX_CLIENTEDGE";
153 if (exStyle & WS_EX_COMPOSITED)
154 rc +=
" WS_EX_COMPOSITED";
155 if (exStyle & WS_EX_CONTROLPARENT)
156 rc +=
" WS_EX_CONTROLPARENT";
157 if (exStyle & WS_EX_LEFT)
159 if (exStyle & WS_EX_LEFTSCROLLBAR)
160 rc +=
" WS_EX_LEFTSCROLLBAR";
161 if (exStyle & WS_EX_LTRREADING)
162 rc +=
" WS_EX_LTRREADING";
163 if (exStyle & WS_EX_MDICHILD)
164 rc +=
" WS_EX_MDICHILD";
165 if (exStyle & WS_EX_NOACTIVATE)
166 rc +=
" WS_EX_NOACTIVATE";
167 if (exStyle & WS_EX_NOPARENTNOTIFY)
168 rc +=
" WS_EX_NOPARENTNOTIFY";
169 if (exStyle & WS_EX_NOREDIRECTIONBITMAP)
170 rc +=
" WS_EX_NOREDIRECTIONBITMAP";
171 if (exStyle & WS_EX_RIGHT)
172 rc +=
" WS_EX_RIGHT";
173 if (exStyle & WS_EX_RIGHTSCROLLBAR)
174 rc +=
" WS_EX_RIGHTSCROLLBAR";
175 if (exStyle & WS_EX_RTLREADING)
176 rc +=
" WS_EX_RTLREADING";
177 if (exStyle & WS_EX_STATICEDGE)
178 rc +=
" WS_EX_STATICEDGE";
179 if (exStyle & WS_EX_TOPMOST)
180 rc +=
" WS_EX_TOPMOST";
181 if (exStyle & WS_EX_TRANSPARENT)
182 rc +=
" WS_EX_TRANSPARENT";
183 if (exStyle & WS_EX_WINDOWEDGE)
184 rc +=
" WS_EX_WINDOWEDGE";
190 QByteArray rc =
"0x";
191 rc += QByteArray::number(flags, 16);
192 if (flags & SWP_FRAMECHANGED)
193 rc +=
" SWP_FRAMECHANGED";
194 if (flags & SWP_HIDEWINDOW)
195 rc +=
" SWP_HIDEWINDOW";
196 if (flags & SWP_NOACTIVATE)
197 rc +=
" SWP_NOACTIVATE";
198 if (flags & SWP_NOCOPYBITS)
199 rc +=
" SWP_NOCOPYBITS";
200 if (flags & SWP_NOMOVE)
202 if (flags & SWP_NOOWNERZORDER)
203 rc +=
" SWP_NOOWNERZORDER";
204 if (flags & SWP_NOREDRAW)
205 rc +=
" SWP_NOREDRAW";
206 if (flags & SWP_NOSENDCHANGING)
207 rc +=
" SWP_NOSENDCHANGING";
208 if (flags & SWP_NOSIZE)
210 if (flags & SWP_NOZORDER)
211 rc +=
" SWP_NOZORDER";
212 if (flags & SWP_SHOWWINDOW)
213 rc +=
" SWP_SHOWWINDOW";
214 if (flags & SWP_ASYNCWINDOWPOS)
215 rc +=
" SWP_ASYNCWINDOWPOS";
216 if (flags & SWP_DEFERERASE)
217 rc +=
" SWP_DEFERERASE";
218 if (flags & SWP_DRAWFRAME)
219 rc +=
" SWP_DRAWFRAME";
220 if (flags & SWP_NOREPOSITION)
221 rc +=
" SWP_NOREPOSITION";
227 QByteArray rc =
"0x";
228 rc += QByteArray::number(flags, 16);
229 if (flags & WPF_SETMINPOSITION)
230 rc +=
" WPF_SETMINPOSITION";
231 if (flags & WPF_RESTORETOMAXIMIZED)
232 rc +=
" WPF_RESTORETOMAXIMIZED";
233 if (flags & WPF_ASYNCWINDOWPLACEMENT)
234 rc +=
" WPF_ASYNCWINDOWPLACEMENT";
241 rc += QByteArray::number(cmd);
244 if (cmd == SW_SHOWNORMAL)
245 rc +=
" SW_SHOWNORMAL";
246 if (cmd == SW_NORMAL)
248 if (cmd == SW_SHOWMINIMIZED)
249 rc +=
" SW_SHOWMINIMIZED";
250 if (cmd == SW_SHOWMAXIMIZED)
251 rc +=
" SW_SHOWMAXIMIZED";
252 if (cmd == SW_MAXIMIZE)
253 rc +=
" SW_MAXIMIZE";
254 if (cmd == SW_SHOWNOACTIVATE)
255 rc +=
" SW_SHOWNOACTIVATE";
258 if (cmd == SW_MINIMIZE)
259 rc +=
" SW_MINIMIZE";
260 if (cmd == SW_SHOWMINNOACTIVE)
261 rc +=
" SW_SHOWMINNOACTIVE";
262 if (cmd == SW_SHOWNA)
264 if (cmd == SW_RESTORE)
266 if (cmd == SW_SHOWDEFAULT)
267 rc +=
" SW_SHOWDEFAULT";
268 if (cmd == SW_FORCEMINIMIZE)
269 rc +=
" SW_FORCEMINIMIZE";
275 return QSize(rect.right -rect.left, rect.bottom - rect.top);
280 return QRect(
QPoint(rect.left, rect.top), qSizeOfRect(rect));
285 const int x = rect.left();
286 const int y = rect.top();
287 RECT result = { x, y, x + rect.width(), y + rect.height() };
291#ifndef QT_NO_DEBUG_STREAM
292QDebug operator<<(QDebug d,
const RECT &r)
294 QDebugStateSaver saver(d);
296 d <<
"RECT(left=" << r.left <<
", top=" << r.top
297 <<
", right=" << r.right <<
", bottom=" << r.bottom
298 <<
" (" << r.right - r.left <<
'x' << r.bottom - r.top <<
"))";
302QDebug operator<<(QDebug d,
const POINT &p)
304 QDebugStateSaver saver(d);
306 d <<
"POINT(x=" << p.x <<
", y=" << p.y <<
')';
310QDebug operator<<(QDebug d,
const WINDOWPOS &wp)
312 QDebugStateSaver saver(d);
315 d <<
"WINDOWPOS(flags=" << debugWinSwpPos(wp.flags) <<
", hwnd="
316 << wp.hwnd <<
", hwndInsertAfter=" << wp.hwndInsertAfter <<
", x=" << wp.x
317 <<
", y=" << wp.y <<
", cx=" << wp.cx <<
", cy=" << wp.cy <<
')';
321QDebug operator<<(QDebug d,
const NCCALCSIZE_PARAMS &p)
323 QDebugStateSaver saver(d);
325 d <<
"NCCALCSIZE_PARAMS(rgrc=[" << p.rgrc[0] <<
", " << p.rgrc[1] <<
", "
326 << p.rgrc[2] <<
"], lppos=" << *p.lppos <<
')';
330QDebug operator<<(QDebug d,
const MINMAXINFO &i)
332 QDebugStateSaver saver(d);
334 d <<
"MINMAXINFO(maxSize=" << i.ptMaxSize <<
", "
335 <<
"maxpos=" << i.ptMaxPosition <<
", "
336 <<
"maxtrack=" << i.ptMaxTrackSize <<
", "
337 <<
"mintrack=" << i.ptMinTrackSize <<
')';
341QDebug operator<<(QDebug d,
const WINDOWPLACEMENT &wp)
343 QDebugStateSaver saver(d);
346 d <<
"WINDOWPLACEMENT(flags=" << debugWindowPlacementFlags(wp.flags) <<
", showCmd="
347 << debugShowWindowCmd(wp.showCmd) <<
", ptMinPosition=" << wp.ptMinPosition
348 <<
", ptMaxPosition=" << wp.ptMaxPosition <<
", rcNormalPosition="
349 << wp.rcNormalPosition <<
')';
353QDebug operator<<(QDebug d,
const GUID &guid)
355 QDebugStateSaver saver(d);
357 d <<
'{' << Qt::hex << Qt::uppercasedigits << qSetPadChar(u'0')
358 << qSetFieldWidth(8) << guid.Data1
359 << qSetFieldWidth(0) <<
'-' << qSetFieldWidth(4)
360 << guid.Data2 << qSetFieldWidth(0) <<
'-' << qSetFieldWidth(4)
361 << guid.Data3 << qSetFieldWidth(0) <<
'-' << qSetFieldWidth(4)
362 << qSetFieldWidth(2) << guid.Data4[0] << guid.Data4[1]
363 << qSetFieldWidth(0) <<
'-' << qSetFieldWidth(2);
364 for (
int i = 2; i < 8; ++i)
366 d << qSetFieldWidth(0) <<
'}';
373 d << r.width() <<
'x' << r.height() << Qt::forcesign << r.x() << r.y() << Qt::noforcesign;
378 d << m.left() <<
", " << m.top() <<
", " << m.right() <<
", " << m.bottom();
385 if (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)
388 const QWindowsScreen *screen = screenManager.screens().size() == 1
389 ? screenManager.screens().constFirst() : screenManager
.screenAtDp(point
);
391 return screen->availableGeometry().topLeft() - screen->geometry().topLeft();
399 RECT rect = { 0, 0, 0, 0 };
401 WINDOWPLACEMENT windowPlacement;
402 windowPlacement.length =
sizeof(WINDOWPLACEMENT);
403 GetWindowPlacement(hwnd, &windowPlacement);
404 if (windowPlacement.showCmd == SW_SHOWMINIMIZED) {
405 const QRect result = qrectFromRECT(windowPlacement.rcNormalPosition);
406 return result.translated(windowPlacementOffset(hwnd, result.topLeft()));
409 GetWindowRect(hwnd, &rect);
410 const HWND parent = GetParent(hwnd);
411 if (parent && !topLevel) {
412 const int width = rect.right - rect.left;
413 const int height = rect.bottom - rect.top;
414 POINT leftTop = { rect.left, rect.top };
415 screenToClient(parent, &leftTop);
416 rect.left = leftTop.x;
417 rect.top = leftTop.y;
418 rect.right = leftTop.x + width;
419 rect.bottom = leftTop.y + height;
421 return qrectFromRECT(rect);
427 if (!IsWindowVisible(hwnd))
428 return QWindow::Hidden;
429 WINDOWPLACEMENT windowPlacement;
430 windowPlacement.length =
sizeof(WINDOWPLACEMENT);
431 if (GetWindowPlacement(hwnd, &windowPlacement)) {
432 switch (windowPlacement.showCmd) {
433 case SW_SHOWMINIMIZED:
435 case SW_FORCEMINIMIZE:
436 return QWindow::Minimized;
437 case SW_SHOWMAXIMIZED:
438 return QWindow::Maximized;
443 return QWindow::Windowed;
448 switch (w->surfaceType()) {
449 case QSurface::OpenGLSurface:
450 case QSurface::VulkanSurface:
451 case QSurface::Direct3DSurface:
460 DWM_BLURBEHIND blurBehind = {0, 0,
nullptr, 0};
462 blurBehind.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
463 blurBehind.fEnable = TRUE;
464 blurBehind.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
466 const bool result = DwmEnableBlurBehindWindow(hwnd, &blurBehind) == S_OK;
468 if (blurBehind.hRgnBlur)
469 DeleteObject(blurBehind.hRgnBlur);
477 if ((flags & Qt::MSWindowsFixedSizeDialogHint) || !(flags & Qt::WindowMaximizeButtonHint))
481 return (flags & Qt::CustomizeWindowHint) ||
482 w->maximumSize() == QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX);
487 const LONG_PTR style = GetWindowLongPtr(hwnd, GWL_STYLE);
488 return (style & WS_CHILD) || (flags & Qt::FramelessWindowHint);
494bool QWindowsWindow::setWindowLayered(HWND hwnd, Qt::WindowFlags flags,
bool hasAlpha, qreal opacity)
496 const LONG_PTR exStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
498 const bool needsLayered = (flags & Qt::WindowTransparentForInput)
499 || (hasAlpha && hasNoNativeFrame(hwnd, flags)) || opacity < 1.0;
500 const bool isLayered = (exStyle & WS_EX_LAYERED);
501 if (needsLayered != isLayered) {
503 SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED);
505 SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED);
511static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags,
bool hasAlpha,
bool accelerated, qreal level)
513 if (QWindowsWindow::setWindowLayered(hwnd, flags, hasAlpha, level)) {
514 const BYTE alpha = BYTE(qRound(255.0 * level));
515 if (hasAlpha && !accelerated && QWindowsWindow::hasNoNativeFrame(hwnd, flags)) {
517 BLENDFUNCTION blend = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA};
518 UpdateLayeredWindow(hwnd,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, 0, &blend, ULW_ALPHA);
520 SetLayeredWindowAttributes(hwnd, 0, alpha, LWA_ALPHA);
522 }
else if (IsWindowVisible(hwnd)) {
523 InvalidateRect(hwnd,
nullptr, TRUE);
532 return GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
533 + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
537
538
539
543 POINT pt = {screenPoint.x(), screenPoint.y()};
544 if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
547 if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY))) {
548 const int gap = getResizeBorderThickness(dpiX);
549 return QMargins(gap, 0, gap, gap);
557 const UINT dpi = GetDpiForWindow(hwnd);
558 const int gap = getResizeBorderThickness(dpi);
559 return QMargins(gap, 0, gap, gap);
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
595 void fromWindow(
const QWindow *w,
const Qt::WindowFlags flags,
unsigned creationFlags = 0);
598 void initialize(
const QWindow *w, HWND h,
bool frameChange, qreal opacityLevel)
const;
615 QDebugStateSaver saver(debug);
618 debug <<
"WindowCreationData: " << d.flags
621 debug <<
" parent=" << d.parentHandle;
622 debug <<
" popup=" << d.popup <<
" dialog=" << d.dialog
623 <<
" embedded=" << d.embedded <<
" tool=" << d.tool
624 <<
"\n style=" << debugWinStyle(d.style);
626 debug <<
"\n exStyle=" << debugWinExStyle(d.exStyle);
634 flags &= ~Qt::WindowFullscreenButtonHint;
639 constexpr Qt::WindowFlags clientAreaHints =
640 Qt::ExpandedClientAreaHint | Qt::NoTitleBarBackgroundHint;
641 switch (flags & ~clientAreaHints) {
643 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint
644 |Qt::WindowMaximizeButtonHint|Qt::WindowCloseButtonHint;
648 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
653 if ((flags & Qt::WindowType_Mask) == Qt::SplashScreen)
654 flags |= Qt::FramelessWindowHint;
659 const auto getDeviceName = [](
const QScreen *screen) -> QString {
660 if (
const auto s =
static_cast<
const QWindowsScreen *>(screen->handle()))
661 return s->data().deviceName;
664 QScreen *winScreen = w ? w->screen() : QGuiApplication::primaryScreen();
665 if (winScreen && getDeviceName(winScreen) != name) {
666 const auto screens = winScreen->virtualSiblings();
667 for (QScreen *screen : screens) {
668 if (getDeviceName(screen) == name)
675static QPoint calcPosition(
const QWindow *w,
const QWindowCreationContextPtr &context,
const QMargins &invMargins)
677 const QPoint orgPos(context->frameX - invMargins.left(), context->frameY - invMargins.top());
679 if (!w || w->type() != Qt::Window)
683 const QScreen *screenForGL = QWindowsWindow::forcedScreenForGLWindow(w);
687 const QPoint posFrame(context->frameX, context->frameY);
688 const QMargins margins = context->margins;
689 const QRect scrGeo = screenForGL->handle()->availableGeometry();
692 if (scrGeo.contains(orgPos))
697 if (scrGeo.contains(posFrame))
701 const auto screens = screenForGL->virtualSiblings();
702 const QScreen *orgScreen =
nullptr;
703 for (QScreen *screen : screens) {
704 if (screen->handle()->availableGeometry().contains(posFrame)) {
709 const QPoint ctPos = QPoint(qMax(scrGeo.left(), scrGeo.center().x()
710 + (margins.right() - margins.left() - context->frameWidth)/2),
711 qMax(scrGeo.top(), scrGeo.center().y()
712 + (margins.bottom() - margins.top() - context->frameHeight)/2));
718 const QRect orgGeo = orgScreen->handle()->availableGeometry();
719 const QRect orgFrame(
QPoint(context->frameX, context->frameY),
720 QSize(context->frameWidth, context->frameHeight));
723 if (orgGeo.center() == (orgFrame - margins).center())
727 const QPoint newPos(scrGeo.left() + ((posFrame.x() - orgGeo.left()) * scrGeo.width()) / orgGeo.width(),
728 scrGeo.top() + ((posFrame.y() - orgGeo.top()) * scrGeo.height()) / orgGeo.height());
729 const QPoint newPosNoMargin(newPos.x() - invMargins.left(), newPos.y() - invMargins.top());
731 return scrGeo.contains(newPosNoMargin) ? newPosNoMargin : newPos;
735 unsigned creationFlags)
742 QVariant prop = w->property(QWindowsWindow::embeddedNativeParentHandleProperty);
743 if (prop.isValid()) {
745 parentHandle =
reinterpret_cast<HWND>(prop.value<WId>());
759 fixTopLevelWindowFlags(flags);
761 type =
static_cast<Qt::WindowType>(
int(flags) & Qt::WindowType_Mask);
777 if ((flags & Qt::MSWindowsFixedSizeDialogHint))
786 if (QGuiApplication::layoutDirection() == Qt::RightToLeft
787 && (QWindowsIntegration::instance()->options() & QWindowsIntegration::RtlEnabled) != 0) {
788 exStyle |= WS_EX_LAYOUTRTL | WS_EX_NOINHERITLAYOUT;
793 flags |= Qt::WindowStaysOnTopHint;
795 if (
const QWindow *parentWindow = topLevel ? w->transientParent() : w->parent())
796 parentHandle = QWindowsWindow::handleOf(parentWindow);
799 if (popup || (type == Qt::ToolTip) || (type == Qt::SplashScreen)) {
802 if (flags & Qt::FramelessWindowHint)
804 else if (flags & Qt::WindowTitleHint)
805 style = WS_OVERLAPPED;
812 style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN ;
814 if (flags & Qt::WindowDoesNotAcceptFocus)
815 exStyle |= WS_EX_NOACTIVATE;
818 if ((type == Qt::Window || dialog || tool)) {
819 if (!(flags & Qt::FramelessWindowHint)) {
821 if (flags & Qt::MSWindowsFixedSizeDialogHint) {
822 style |= WS_DLGFRAME;
824 style |= WS_THICKFRAME;
826 if (flags & Qt::WindowTitleHint)
829 if (flags & Qt::WindowSystemMenuHint)
831 else if (dialog && (flags & Qt::WindowCloseButtonHint) && !(flags & Qt::FramelessWindowHint)) {
832 style |= WS_SYSMENU | WS_BORDER;
833 exStyle |= WS_EX_DLGMODALFRAME;
835 const bool showMinimizeButton = flags & Qt::WindowMinimizeButtonHint;
836 if (showMinimizeButton)
837 style |= WS_MINIMIZEBOX;
838 const bool showMaximizeButton = shouldShowMaximizeButton(w, flags);
839 if (showMaximizeButton)
840 style |= WS_MAXIMIZEBOX;
841 if (showMinimizeButton || showMaximizeButton)
844 exStyle |= WS_EX_TOOLWINDOW;
845 if ((flags & Qt::WindowContextHelpButtonHint) && !showMinimizeButton
846 && !showMaximizeButton)
847 exStyle |= WS_EX_CONTEXTHELP;
849 exStyle |= WS_EX_TOOLWINDOW;
854 if (flagsIn & Qt::WindowTransparentForInput)
855 exStyle |= WS_EX_TRANSPARENT;
858 if (qEnvironmentVariableIntValue(
"QT_QPA_DISABLE_REDIRECTION_SURFACE"))
859 exStyle |= WS_EX_NOREDIRECTIONBITMAP;
865 if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint))
874 auto *dWindow = QWindowPrivate::get(
const_cast<QWindow*>(w));
875 const QPalette windowPal = dWindow->windowPalette();
876 return windowPal.color(QPalette::WindowText).lightness()
877 > windowPal.color(QPalette::Window).lightness();
883 return getResizeBorderThickness(dpi) +
884 ::GetSystemMetricsForDpi(SM_CYCAPTION, dpi);
891 result.flags = flags;
893 const auto appinst =
reinterpret_cast<HINSTANCE>(GetModuleHandle(
nullptr));
898 windowTitlebarDescription.name =
"_q_titlebar"_L1;
899 windowTitlebarDescription.style = CS_VREDRAW | CS_HREDRAW;
903 const QScreen *screen{};
904 const QRect rect = QPlatformWindow::initialGeometry(w, data.geometry,
905 defaultWindowWidth, defaultWindowHeight,
908 if (title.isEmpty() && (result.flags & Qt::WindowTitleHint))
909 title =
topLevel ? qAppName() : w->objectName();
911 const auto *titleUtf16 =
reinterpret_cast<
const wchar_t *>(title.utf16());
912 const auto *classNameUtf16 =
reinterpret_cast<
const wchar_t *>(windowClassName.utf16());
913 const auto *classTitleBarNameUtf16 =
reinterpret_cast<
const wchar_t *>(windowTitlebarName.utf16());
918 rect, data.customMargins,
922 const bool hasFrame = (style & (WS_DLGFRAME | WS_THICKFRAME))
923 && !(result.flags & Qt::FramelessWindowHint);
924 QMargins invMargins = topLevel && hasFrame && QWindowsGeometryHint::positionIncludesFrame(w)
925 ? invisibleMargins(QPoint(context->frameX, context->frameY)) : QMargins();
927 qCDebug(lcQpaWindow).nospace()
928 <<
"CreateWindowEx: " << w <<
" class=" << windowClassName <<
" title=" << title
929 <<
'\n' << *
this <<
"\nrequested: " << rect <<
": "
930 << context->frameWidth <<
'x' << context->frameHeight
931 <<
'+' << context->frameX <<
'+' << context->frameY
932 <<
" custom margins: " << context->customMargins
933 <<
" invisible margins: " << invMargins;
936 QPoint pos = calcPosition(w, context, invMargins);
939 int mirrorParentWidth = 0;
940 if (!w->isTopLevel() && QWindowsBaseWindow::isRtlLayout(parentHandle)) {
942 GetClientRect(parentHandle, &rect);
943 mirrorParentWidth = rect.right;
945 if (mirrorParentWidth != 0 && pos.x() != CW_USEDEFAULT && context->frameWidth != CW_USEDEFAULT)
946 pos.setX(mirrorParentWidth - context->frameWidth - pos.x());
948 result.hwnd = CreateWindowEx(
exStyle, classNameUtf16, titleUtf16,
951 context->frameWidth, context->frameHeight,
952 parentHandle,
nullptr, appinst,
nullptr);
954 const UINT dpi = ::GetDpiForWindow(result.hwnd);
955 const int titleBarHeight = getTitleBarHeight_sys(dpi);
956 result.hwndTitlebar = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOACTIVATE,
957 classTitleBarNameUtf16, classTitleBarNameUtf16,
959 context->frameWidth, titleBarHeight,
960 nullptr,
nullptr, appinst,
nullptr);
962 qCDebug(lcQpaWindow).nospace()
963 <<
"CreateWindowEx: returns " << w <<
' ' << result.hwnd <<
" obtained geometry: "
964 << context->obtainedPos << context->obtainedSize <<
' ' << context->margins;
967 qErrnoWarning(
"%s: CreateWindowEx failed",
__FUNCTION__);
971 if (QWindowsTheme::instance()->colorScheme() == Qt::ColorScheme::Dark && shouldApplyDarkFrame(w))
972 QWindowsWindow::setDarkBorderToWindow(result.hwnd,
true);
974 if (mirrorParentWidth != 0) {
975 context->obtainedPos.setX(mirrorParentWidth - context->obtainedSize.width()
976 - context->obtainedPos.x());
979 QRect obtainedGeometry(context->obtainedPos, context->obtainedSize);
981 result.geometry = obtainedGeometry;
982 result.restoreGeometry = frameGeometry(result.hwnd, topLevel);
983 result.fullFrameMargins = context->margins;
986 result.customMargins = context->customMargins;
994 const LONG_PTR oldStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
995 const LONG_PTR oldExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
997 const LONG_PTR newStyle = style | (oldStyle & (WS_DISABLED|WS_VISIBLE));
998 if (oldStyle != newStyle)
999 SetWindowLongPtr(hwnd, GWL_STYLE, newStyle);
1000 const LONG_PTR newExStyle =
exStyle;
1001 if (newExStyle != oldExStyle)
1002 SetWindowLongPtr(hwnd, GWL_EXSTYLE, newExStyle);
1003 qCDebug(lcQpaWindow).nospace() <<
__FUNCTION__ << hwnd << *
this
1004 <<
"\n Style from " << debugWinStyle(DWORD(oldStyle)) <<
"\n to "
1005 << debugWinStyle(DWORD(newStyle)) <<
"\n ExStyle from "
1006 << debugWinExStyle(DWORD(oldExStyle)) <<
" to "
1007 << debugWinExStyle(DWORD(newExStyle));
1014 UINT swpFlags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER;
1016 swpFlags |= SWP_FRAMECHANGED;
1018 swpFlags |= SWP_NOACTIVATE;
1019 if ((flags & Qt::WindowStaysOnTopHint) || (type == Qt::ToolTip)) {
1020 SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, swpFlags);
1021 if (flags & Qt::WindowStaysOnBottomHint)
1022 qWarning(
"QWidget: Incompatible window flags: the window can't be on top and on bottom at the same time");
1023 }
else if (flags & Qt::WindowStaysOnBottomHint) {
1024 SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, swpFlags);
1025 }
else if (frameChange) {
1026 SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, swpFlags);
1028 if (flags & (Qt::CustomizeWindowHint|Qt::WindowTitleHint)) {
1029 HMENU systemMenu = GetSystemMenu(hwnd, FALSE);
1030 if (flags & Qt::WindowCloseButtonHint)
1031 EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_ENABLED);
1033 EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED);
1035 if (flags & Qt::ExpandedClientAreaHint) {
1036 MARGINS margins = { -1, -1, -1, -1 };
1037 DwmExtendFrameIntoClientArea(hwnd, &margins);
1039 MARGINS margins = { 0, 0, 0, 0 };
1040 DwmExtendFrameIntoClientArea(hwnd, &margins);
1043 SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, swpFlags);
1047 const bool hasAlpha = w->format().hasAlpha();
1048 if (isAccelerated && hasAlpha)
1049 applyBlurBehindWindow(hwnd);
1050 setWindowOpacity(hwnd, flags, hasAlpha, isAccelerated, opacityLevel);
1057 if (QHighDpiScaling::isActive()) {
1058 const qreal factor = QHighDpiScaling::factor(s);
1059 if (!qFuzzyCompare(factor, qreal(1))) {
1060 if (dip.width() > 0 && dip.width() < QWINDOWSIZE_MAX)
1061 dip.setWidth(qRound(qreal(dip.width()) * factor));
1062 if (dip.height() > 0 && dip.height() < QWINDOWSIZE_MAX)
1063 dip.setHeight(qRound(qreal(dip.height()) * factor));
1073 return flags.testFlag(Qt::FramelessWindowHint) && !(style & WS_MAXIMIZE);
1080 DWORD style = hwnd !=
nullptr ? DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)) : 0;
1081 return flags.testFlag(Qt::FramelessWindowHint) && !(style & WS_MAXIMIZE);
1085
1086
1087
1088
1089
1090
1091
1092
1096 if (!w->isTopLevel() || shouldOmitFrameAdjustment(w->flags(), style))
1098 RECT rect = {0,0,0,0};
1099 style &= ~DWORD(WS_OVERLAPPED);
1100 if (AdjustWindowRectEx(&rect, style, FALSE, exStyle) == FALSE)
1101 qErrnoWarning(
"%s: AdjustWindowRectEx failed",
__FUNCTION__);
1102 const QMargins result(qAbs(rect.left), qAbs(rect.top),
1103 qAbs(rect.right), qAbs(rect.bottom));
1104 qCDebug(lcQpaWindow).nospace() <<
__FUNCTION__ <<
" style="
1105 << Qt::showbase << Qt::hex << style <<
" exStyle=" << exStyle << Qt::dec << Qt::noshowbase
1106 <<
' ' << rect <<
' ' << result;
1112 return frameOnPrimaryScreen(w, DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)),
1113 DWORD(GetWindowLongPtr(hwnd, GWL_EXSTYLE)));
1118 if (!w->isTopLevel() || shouldOmitFrameAdjustment(w->flags(), style))
1120 RECT rect = {0,0,0,0};
1121 style &= ~DWORD(WS_OVERLAPPED);
1122 if (AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle,
unsigned(qRound(dpi))) == FALSE) {
1123 qErrnoWarning(
"%s: AdjustWindowRectExForDpi failed",
__FUNCTION__);
1125 const QMargins result(qAbs(rect.left), qAbs(rect.top),
1126 qAbs(rect.right), qAbs(rect.bottom));
1127 qCDebug(lcQpaWindow).nospace() <<
__FUNCTION__ <<
" style="
1128 << Qt::showbase << Qt::hex << style <<
" exStyle=" << exStyle << Qt::dec << Qt::noshowbase
1130 <<
' ' << rect <<
' ' << result;
1136 if (!w->isTopLevel() || shouldOmitFrameAdjustment(w->flags(), style))
1138 if (QWindowsScreenManager::isSingleScreen())
1139 return frameOnPrimaryScreen(w, style, exStyle);
1141 auto screen = screenManager.screenForHwnd(hwnd);
1143 screen = screenManager.screens().value(0);
1144 const auto dpi = screen ? screen->logicalDpi().first : qreal(96);
1145 return frame(w, style, exStyle, dpi);
1150 return frame(w, hwnd, DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)),
1151 DWORD(GetWindowLongPtr(hwnd, GWL_EXSTYLE)));
1156 DWORD style, DWORD exStyle)
1158 if (!w->isTopLevel() || shouldOmitFrameAdjustment(w->flags(), style))
1161 || !QWindowsContext::shouldHaveNonClientDpiScaling(w)) {
1162 return frameOnPrimaryScreen(w, style, exStyle);
1168 screen = screenManager.screens().value(0);
1170 dpi = screen->logicalDpi().first;
1171 return QWindowsGeometryHint::frame(w, style, exStyle, dpi);
1174bool QWindowsGeometryHint::handleCalculateSize(
const QWindow *window,
const QMargins &customMargins,
const MSG &msg, LRESULT *result)
1177 if (msg.wParam && window->flags() & Qt::FramelessWindowHint) {
1181 const QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(window);
1183 const bool clientAreaExpanded = platformWindow !=
nullptr ? platformWindow->isClientAreaExpanded() : window->flags() & Qt::ExpandedClientAreaHint;
1185 if (msg.wParam && clientAreaExpanded) {
1187 const bool maximized = IsZoomed(msg.hwnd) && window->visibility() != QWindow::FullScreen;
1188 auto *ncp =
reinterpret_cast<NCCALCSIZE_PARAMS *>(msg.lParam);
1189 RECT *clientArea = &ncp->rgrc[0];
1190 const int border = getResizeBorderThickness(96);
1192 clientArea->top += border;
1193 clientArea->bottom -= border;
1194 clientArea->left += border;
1195 clientArea->right -= border;
1200 if (!msg.wParam || customMargins.isNull())
1202 *result = DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
1203 auto *ncp =
reinterpret_cast<NCCALCSIZE_PARAMS *>(msg.lParam);
1204 const RECT oldClientArea = ncp->rgrc[0];
1205 ncp->rgrc[0].left += customMargins.left();
1206 ncp->rgrc[0].top += customMargins.top();
1207 ncp->rgrc[0].right -= customMargins.right();
1208 ncp->rgrc[0].bottom -= customMargins.bottom();
1210 qCDebug(lcQpaWindow).nospace() <<
__FUNCTION__ << oldClientArea <<
'+' << customMargins <<
"-->"
1211 << ncp->rgrc[0] <<
' ' << ncp->rgrc[1] <<
' ' << ncp->rgrc[2]
1212 <<
' ' << ncp->lppos->cx <<
',' << ncp->lppos->cy;
1217 const QMargins &margins,
1218 QSize *minimumSize, QSize *maximumSize)
1220 *minimumSize = toNativeSizeConstrained(w->minimumSize(), screen);
1221 *maximumSize = toNativeSizeConstrained(w->maximumSize(), screen);
1223 const int maximumWidth = qMax(maximumSize->width(), minimumSize->width());
1224 const int maximumHeight = qMax(maximumSize->height(), minimumSize->height());
1225 const int frameWidth = margins.left() + margins.right();
1226 const int frameHeight = margins.top() + margins.bottom();
1228 if (minimumSize->width() > 0)
1229 minimumSize->rwidth() += frameWidth;
1230 if (minimumSize->height() > 0)
1231 minimumSize->rheight() += frameHeight;
1232 if (maximumWidth < QWINDOWSIZE_MAX)
1233 maximumSize->setWidth(maximumWidth + frameWidth);
1234 if (maximumHeight < QWINDOWSIZE_MAX)
1235 maximumSize->setHeight(maximumHeight + frameHeight);
1239 const QScreen *screen,
1240 const QMargins &margins,
1245 frameSizeConstraints(w, screen, margins, &minimumSize, &maximumSize);
1246 qCDebug(lcQpaWindow).nospace() <<
'>' <<
__FUNCTION__ <<
'<' <<
" min="
1247 << minimumSize.width() <<
',' << minimumSize.height()
1248 <<
" max=" << maximumSize.width() <<
',' << maximumSize.height()
1249 <<
" margins=" << margins
1252 if (minimumSize.width() > 0)
1253 mmi->ptMinTrackSize.x = minimumSize.width();
1254 if (minimumSize.height() > 0)
1255 mmi->ptMinTrackSize.y = minimumSize.height();
1257 if (maximumSize.width() < QWINDOWSIZE_MAX)
1258 mmi->ptMaxTrackSize.x = maximumSize.width();
1259 if (maximumSize.height() < QWINDOWSIZE_MAX)
1260 mmi->ptMaxTrackSize.y = maximumSize.height();
1261 qCDebug(lcQpaWindow).nospace() <<
'<' <<
__FUNCTION__ <<
" out " << *mmi;
1265 const QMargins &margins,
1268 applyToMinMaxInfo(w, w->screen(), margins, mmi);
1273 return qt_window_private(
const_cast<QWindow *>(w))->positionPolicy
1274 == QWindowPrivate::WindowFrameInclusive;
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1296 return (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) != 0;
1302 if (QPlatformWindow *pw = w->handle())
1303 return static_cast<QWindowsBaseWindow *>(pw);
1311 return bw ? bw->handle() : HWND(
nullptr);
1316 const HWND parent = parentHwnd();
1317 return !parent || parent == GetDesktopWindow();
1322 return frameGeometry(handle(), isTopLevel());
1327 return frameGeometry_sys().marginsRemoved(fullFrameMargins());
1332 return QWindowsGeometryHint::frame(window(), handle(), style(), exStyle());
1338 ULONG touchFlags = 0;
1339 if (IsTouchWindow(handle(), &touchFlags) == FALSE)
1341 TouchWindowTouchTypes result;
1342 if ((touchFlags & TWF_FINETOUCH) != 0)
1343 result.setFlag(TouchWindowTouchType::FineTouch);
1344 if ((touchFlags & TWF_WANTPALM) != 0)
1345 result.setFlag(TouchWindowTouchType::WantPalmTouch);
1351 SetWindowPos(handle(),
nullptr , 0, 0, 0, 0,
1352 SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
1357 qCDebug(lcQpaWindow) <<
__FUNCTION__ <<
this << window();
1358 const Qt::WindowType type = window()->type();
1359 if (type == Qt::Popup
1360 || type == Qt::SubWindow
1361 || !(window()->flags() & Qt::WindowStaysOnBottomHint)) {
1362 SetWindowPos(handle(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1368 qCDebug(lcQpaWindow) <<
__FUNCTION__ <<
this << window();
1369 if (!(window()->flags() & Qt::WindowStaysOnTopHint))
1370 SetWindowPos(handle(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1375 qCDebug(lcQpaWindow) <<
__FUNCTION__ <<
this << window() << title;
1376 SetWindowText(handle(),
reinterpret_cast<
const wchar_t *>(title.utf16()));
1381 return QWindowsGeometryHint::mapToGlobal(handle(), pos);
1386 return QWindowsGeometryHint::mapFromGlobal(handle(), pos);
1412 switch (event->type()) {
1413 case QEvent::ChildWindowAdded:
1414 if (!(GetWindowLongPtr(handle(), GWL_STYLE) & WS_CLIPCHILDREN)) {
1415 auto *childWindowEvent =
static_cast<QChildWindowEvent*>(event);
1416 qWarning() << childWindowEvent->child() <<
"added as child to"
1417 << window() <<
"which does not have WS_CLIPCHILDREN set."
1418 <<
"This will result in drawing artifacts!";
1425 return QPlatformWindow::windowEvent(event);
1429
1430
1431
1432
1433
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1450 , m_topLevelStyle(0)
1452 if (QPlatformWindow::parent())
1453 setParent(QPlatformWindow::parent());
1458 if (QPlatformWindow::parent())
1465 const HWND newParent = newParentWindow ?
reinterpret_cast<HWND>(newParentWindow->winId()) : HWND(
nullptr);
1466 const bool isTopLevel = !newParent;
1467 const DWORD oldStyle =
style();
1469 qCDebug(lcQpaWindow) <<
__FUNCTION__ << window() <<
"newParent="
1470 << newParentWindow << newParent <<
"oldStyle=" << debugWinStyle(oldStyle);
1472 auto updateWindowFlags = [&] {
1474 DWORD newStyle = oldStyle;
1476 newStyle = m_topLevelStyle;
1478 m_topLevelStyle = oldStyle;
1479 newStyle &= ~(WS_OVERLAPPEDWINDOW | WS_POPUPWINDOW);
1480 newStyle |= WS_CHILD;
1482 SetWindowLongPtr(m_hwnd, GWL_STYLE, newStyle);
1485 if (wasTopLevel && !isTopLevel) {
1488 updateWindowFlags();
1491 SetParent(m_hwnd, newParent);
1493 if (!wasTopLevel && isTopLevel) {
1496 updateWindowFlags();
1502 qCDebug(lcQpaWindow) <<
__FUNCTION__ << window() << visible;
1504 ShowWindow(handle(), SW_SHOWNOACTIVATE);
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1530 const QRect &geometryIn,
const QRect &geometry,
1532 DWORD style, DWORD exStyle) :
1535 requestedGeometryIn(geometryIn),
1536 requestedGeometry(geometry),
1537 obtainedPos(geometryIn.topLeft()),
1538 obtainedSize(geometryIn.size()),
1539 margins(QWindowsGeometryHint::frame(w, geometry, style, exStyle))
1546 if (!(w->flags() & Qt::FramelessWindowHint))
1549 if (geometry.isValid()
1550 || !qt_window_private(
const_cast<QWindow *>(w))->resizeAutomatic) {
1551 frameX = geometry.x();
1552 frameY = geometry.y();
1553 const QMargins effectiveMargins = margins + customMargins;
1554 frameWidth = effectiveMargins.left() + geometry.width() + effectiveMargins.right();
1555 frameHeight = effectiveMargins.top() + geometry.height() + effectiveMargins.bottom();
1558 frameHeight += menuHeight;
1560 const bool isDefaultPosition = !frameX && !frameY && w->isTopLevel();
1561 if (!QWindowsGeometryHint::positionIncludesFrame(w) && !isDefaultPosition) {
1562 frameX -= effectiveMargins.left();
1563 frameY -= effectiveMargins.top();
1567 qCDebug(lcQpaWindow).nospace()
1568 <<
__FUNCTION__ <<
' ' << w <<
' ' << geometry
1569 <<
" pos incl. frame=" << QWindowsGeometryHint::positionIncludesFrame(w)
1570 <<
" frame=" << frameWidth <<
'x' << frameHeight <<
'+'
1571 << frameX <<
'+' << frameY
1572 <<
" margins=" << margins <<
" custom margins=" << customMargins;
1577 QWindowsGeometryHint::applyToMinMaxInfo(window, screen, margins + customMargins, mmi);
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1609 m_cursor(
new CursorHandle)
1610#if QT_CONFIG(vulkan)
1611 , m_vkSurface(VK_NULL_HANDLE)
1616 if (aWindow->flags().testFlags(Qt::ExpandedClientAreaHint)) {
1617 SetParent(m_data.hwndTitlebar, m_data.hwnd);
1618 ShowWindow(m_data.hwndTitlebar, SW_SHOW);
1621 if (aWindow->surfaceType() == QWindow::Direct3DSurface)
1623#if QT_CONFIG(opengl)
1624 if (aWindow->surfaceType() == QWindow::OpenGLSurface)
1625 setFlag(OpenGLSurface);
1627#if QT_CONFIG(vulkan)
1628 if (aWindow->surfaceType() == QSurface::VulkanSurface)
1629 setFlag(VulkanSurface);
1631 updateDropSite(window()->isTopLevel());
1635 if (!touchWindowTouchTypes_sys().has_value())
1638 const qreal opacity = qt_window_private(aWindow)->opacity;
1639 if (!qFuzzyCompare(opacity, qreal(1.0)))
1640 setOpacity(opacity);
1642 setMask(QHighDpi::toNativeLocalRegion(window()->mask(), window()));
1644 if (aWindow->isTopLevel())
1645 setWindowIcon(aWindow->icon());
1653 if (m_vsyncServiceCallbackId != 0)
1654 QDxgiVSyncService::instance()->unregisterCallback(m_vsyncServiceCallbackId);
1656 QWindowsThemeCache::clearThemeCache(m_data.hwnd);
1658 UnregisterTouchWindow(m_data.hwnd);
1666 QWindowCreationContextPtr creationContext =
1669 QWindow *w = window();
1670 setWindowState(w->windowStates());
1674 const Qt::WindowState state = w->windowState();
1675 const QRect obtainedGeometry(creationContext->obtainedPos, creationContext->obtainedSize);
1676 QPlatformScreen *obtainedScreen = screenForGeometry(obtainedGeometry);
1677 if (obtainedScreen && screen() != obtainedScreen)
1678 QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(w, obtainedScreen->screen());
1679 if (state != Qt::WindowMaximized && state != Qt::WindowFullScreen
1680 && creationContext->requestedGeometryIn != obtainedGeometry) {
1681 QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(w, obtainedGeometry);
1688 return window()->requestedFormat();
1691void QWindowsWindow::fireExpose(
const QRegion ®ion,
bool force)
1693 if (region.isEmpty() && !force)
1697 QWindowSystemInterface::handleExposeEvent(window(), region);
1702 fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), force);
1707 qCDebug(lcQpaWindow) <<
__FUNCTION__ <<
this << window() << m_data.hwnd;
1711 const auto tlw = QGuiApplication::topLevelWindows();
1712 for (QWindow *w : tlw) {
1713 if (w->transientParent() == window()) {
1714 if (QWindowsWindow *tw = QWindowsWindow::windowsWindowOf(w))
1715 tw->updateTransientParent();
1719 if (context->windowUnderMouse() == window())
1723 setDropSiteEnabled(
false);
1724#if QT_CONFIG(vulkan)
1726 QVulkanInstance *inst = window()->vulkanInstance();
1728 static_cast<QWindowsVulkanInstance *>(inst->handle())->destroySurface(m_vkSurface);
1729 m_vkSurface = VK_NULL_HANDLE;
1736 m_surface =
nullptr;
1739 DestroyWindow(m_data.hwndTitlebar);
1740 DestroyWindow(m_data.hwnd);
1741 context->removeWindow(m_data.hwnd);
1742 m_data.hwndTitlebar =
nullptr;
1743 m_data.hwnd =
nullptr;
1749 bool enabled =
false;
1750 bool parentIsEmbedded =
false;
1755 const QWindow *parent = window()->parent();
1756 if (parent && parent->handle() && parent->handle()->isForeignWindow())
1757 parentIsEmbedded =
true;
1760 if (topLevel || parentIsEmbedded) {
1761 switch (window()->type()) {
1774 setDropSiteEnabled(enabled);
1779 if (isDropSiteEnabled() == dropEnabled)
1781 qCDebug(lcQpaMime) <<
__FUNCTION__ << window() << dropEnabled;
1782#if QT_CONFIG(clipboard) && QT_CONFIG(draganddrop)
1784 Q_ASSERT(m_data.hwnd);
1785 m_dropTarget =
new QWindowsOleDropTarget(window());
1786 RegisterDragDrop(m_data.hwnd, m_dropTarget);
1787 CoLockObjectExternal(m_dropTarget,
true,
true);
1789 CoLockObjectExternal(m_dropTarget,
false,
true);
1790 m_dropTarget->Release();
1791 RevokeDragDrop(m_data.hwnd);
1792 m_dropTarget =
nullptr;
1801 m_screenForGLInitialized =
false;
1806 m_screenForGLInitialized =
false;
1811 static QString forceToScreen;
1812 if (!m_screenForGLInitialized) {
1814 m_screenForGLInitialized =
true;
1816 return forceToScreen.isEmpty() ?
nullptr : screenForDeviceName(w, forceToScreen);
1823 while (QWindow *parent = w->parent())
1826 if (
const QPlatformWindow *handle = w->handle()) {
1827 const auto *ww =
static_cast<
const QWindowsWindow *>(handle);
1828 if (ww->isEmbedded()) {
1829 HWND parentHWND = GetAncestor(ww->handle(), GA_PARENT);
1830 const HWND desktopHwnd = GetDesktopWindow();
1832 while (parentHWND && parentHWND != desktopHwnd) {
1833 if (QWindowsWindow *ancestor = ctx->findPlatformWindow(parentHWND))
1834 return topLevelOf(ancestor->window());
1835 parentHWND = GetAncestor(parentHWND, GA_PARENT);
1845 const QString &title)
1848 creationData.fromWindow(w, parameters.flags);
1851 creationData.initialize(w, result.hwnd, !parameters.customMargins.isNull(), 1);
1857 const QWindow *win = window();
1858 qCDebug(lcQpaWindow) <<
__FUNCTION__ <<
this << win << m_data.hwnd << visible;
1871 if (win->type() == Qt::Popup && !win->parent() && !QGuiApplication::focusWindow())
1872 SetForegroundWindow(m_data.hwnd);
1876 if (window()->flags() & Qt::Popup)
1877 ShowWindow(m_data.hwnd, SW_HIDE);
1887 if (win->isModal()) {
1888 if (QWindow *parent = win->transientParent()) {
1889 if (
auto *pw = QWindowsWindow::windowsWindowOf(parent))
1894 fireExpose(QRegion());
1901 return m_data.hwnd && IsWindowVisible(m_data.hwnd);
1907 if (
const HWND activeHwnd = GetForegroundWindow())
1908 if (m_data.hwnd == activeHwnd || IsChild(activeHwnd, m_data.hwnd))
1915 const auto *childWindow =
static_cast<
const QWindowsWindow *>(child);
1916 return IsChild(m_data.hwnd, childWindow->handle());
1921 return m_data.embedded;
1926 return m_data.hwnd ? QWindowsGeometryHint::mapToGlobal(m_data.hwnd, pos) : pos;
1931 return m_data.hwnd ? QWindowsGeometryHint::mapFromGlobal(m_data.hwnd, pos) : pos;
1941 if (window()->type() == Qt::Popup)
1944 const HWND oldTransientParent = GetWindow(m_data.hwnd, GW_OWNER);
1945 HWND newTransientParent =
nullptr;
1946 if (
const QWindow *tp = window()->transientParent()) {
1947 if (
const QWindowsWindow *tw = QWindowsWindow::windowsWindowOf(tp)) {
1949 newTransientParent = tw->handle();
1952 newTransientParent = tbw->handle();
1958 while (newTransientParent && (GetWindowLongPtr(newTransientParent, GWL_STYLE) & WS_CHILD) != 0)
1959 newTransientParent = GetParent(newTransientParent);
1961 if (newTransientParent != oldTransientParent)
1962 SetWindowLongPtr(m_data.hwnd,
GWL_HWNDPARENT, LONG_PTR(newTransientParent));
1968 const QVariant showWithoutActivating = window->property(
"_q_showWithoutActivating");
1969 return showWithoutActivating.isValid() && showWithoutActivating.toBool();
1974 WINDOWPLACEMENT windowPlacement;
1975 windowPlacement.length =
sizeof(WINDOWPLACEMENT);
1976 if (GetWindowPlacement(hwnd, &windowPlacement)) {
1977 windowPlacement.showCmd = SW_SHOWMINIMIZED;
1978 windowPlacement.rcNormalPosition = RECTfromQRect(r);
1979 SetWindowPlacement(hwnd, &windowPlacement);
1986 WINDOWPLACEMENT windowPlacement;
1987 windowPlacement.length =
sizeof(WINDOWPLACEMENT);
1988 if (GetWindowPlacement(hwnd, &windowPlacement)) {
1990 windowPlacement.flags |= WPF_RESTORETOMAXIMIZED;
1992 windowPlacement.flags &= ~WPF_RESTORETOMAXIMIZED;
1993 SetWindowPlacement(hwnd, &windowPlacement);
2000 int sm = SW_SHOWNORMAL;
2001 bool fakedMaximize =
false;
2002 bool restoreMaximize =
false;
2003 const QWindow *w = window();
2004 const Qt::WindowFlags flags = w->flags();
2005 const Qt::WindowType type = w->type();
2006 if (w->isTopLevel()) {
2007 const Qt::WindowStates state = w->windowStates();
2008 if (state & Qt::WindowMinimized) {
2009 sm = SW_SHOWMINIMIZED;
2011 sm = SW_SHOWMINNOACTIVE;
2012 if (state & Qt::WindowMaximized)
2013 restoreMaximize =
true;
2015 updateTransientParent();
2016 if (state & Qt::WindowMaximized) {
2017 sm = SW_SHOWMAXIMIZED;
2023 if (flags & Qt::WindowTitleHint &&
2024 !(flags & (Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint))) {
2025 fakedMaximize = TRUE;
2026 setStyle(style() | WS_MAXIMIZEBOX);
2031 if (type == Qt::Popup ||
2032 type == Qt::ToolTip ||
2034 (flags & Qt::WindowDoesNotAcceptFocus) ||
2035 testShowWithoutActivating(w))
2036 sm = SW_SHOWNOACTIVATE;
2038 if (w->windowStates() & Qt::WindowMaximized)
2041 ShowWindow(m_data.hwnd, sm);
2045 if (fakedMaximize) {
2046 setStyle(style() & ~WS_MAXIMIZEBOX);
2047 SetWindowPos(m_data.hwnd,
nullptr, 0, 0, 0, 0,
2048 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER
2049 | SWP_FRAMECHANGED);
2051 if (restoreMaximize)
2052 setRestoreMaximizedFlag(m_data.hwnd);
2057 qCDebug(lcQpaWindow) <<
__FUNCTION__ << window() << newParent;
2060 setParent_sys(newParent);
2066 HWND oldParentHWND = parentHwnd();
2067 HWND newParentHWND =
nullptr;
2069 const auto *parentW =
static_cast<
const QWindowsWindow *>(parent);
2070 newParentHWND = parentW->handle();
2075 HWND desktopHwnd = GetDesktopWindow();
2076 if (oldParentHWND == desktopHwnd)
2077 oldParentHWND =
nullptr;
2078 if (newParentHWND == desktopHwnd)
2079 newParentHWND =
nullptr;
2081 if (newParentHWND != oldParentHWND) {
2082 const bool wasTopLevel = oldParentHWND ==
nullptr;
2083 const bool isTopLevel = newParentHWND ==
nullptr;
2086 SetParent(m_data.hwnd, newParentHWND);
2092 if (wasTopLevel != isTopLevel) {
2093 setDropSiteEnabled(
false);
2094 m_data = setWindowFlags_sys(window()->flags(),
unsigned(isTopLevel ? WindowCreationData::ForceTopLevel : WindowCreationData::ForceChild));
2101 m_data.fullFrameMargins = {};
2102 setDarkBorder(QWindowsTheme::instance()->colorScheme() == Qt::ColorScheme::Dark);
2103 updateDropSite(isTopLevel);
2110 fireExpose(QRegion());
2115 const QWindow *w = window();
2117 applyBlurBehindWindow(handle());
2122 return QHighDpiScaling::roundScaleFactor(qreal(dpi) / QWindowsScreen::baseDpi) /
2123 QHighDpiScaling::roundScaleFactor(qreal(savedDpi()) / QWindowsScreen::baseDpi);
2133 const UINT dpi = UINT(wParam);
2134 const qreal scale = dpiRelativeScale(dpi);
2135 const QMargins margins = fullFrameMargins();
2136 if (!(m_data.flags & Qt::FramelessWindowHint)) {
2142 m_data.customMargins *= scale;
2145 const QSize windowSize = (geometry().size() * scale).grownBy((margins * scale) + customMargins());
2146 SIZE *size =
reinterpret_cast<SIZE *>(lParam);
2147 size->cx = windowSize.width();
2148 size->cy = windowSize.height();
2154 const UINT dpi = HIWORD(wParam);
2155 const qreal scale = dpiRelativeScale(dpi);
2158 QWindowsThemeCache::clearThemeCache(hwnd);
2162 if (isTopLevel() && !window()->icon().isNull())
2163 setWindowIcon(window()->icon());
2166 const auto prcNewWindow =
reinterpret_cast<
const RECT *>(lParam);
2167 checkForScreenChanged(QWindowsWindow::FromDpiChange, !m_inSetgeometry ? prcNewWindow :
nullptr);
2169 if (!IsZoomed(hwnd))
2170 m_data.restoreGeometry.setSize(m_data.restoreGeometry.size() * scale);
2188 if (!m_inSetgeometry) {
2192 QWindowsContext::forceNcCalcSize(hwnd);
2193 SetWindowPos(hwnd,
nullptr, prcNewWindow->left, prcNewWindow->top,
2194 prcNewWindow->right - prcNewWindow->left,
2195 prcNewWindow->bottom - prcNewWindow->top, SWP_NOZORDER | SWP_NOACTIVATE);
2199 if (shouldOmitFrameAdjustment(m_data.flags, m_data.hwnd))
2200 handleGeometryChange();
2211 setMask(QHighDpi::toNativeLocalRegion(window()->mask(), window()));
2216 const UINT dpi = GetDpiForWindow(hwnd);
2217 const qreal scale = dpiRelativeScale(dpi);
2220 QWindowsThemeCache::clearThemeCache(hwnd);
2222 checkForScreenChanged(QWindowsWindow::FromDpiChange);
2226 QRect currentGeometry = geometry();
2227 QRect scaledGeometry = QRect(currentGeometry.topLeft() * scale, currentGeometry.size() * scale);
2228 setGeometry(scaledGeometry);
2234 wp.length =
sizeof(WINDOWPLACEMENT);
2235 if (GetWindowPlacement(hwnd, &wp)) {
2236 const QRect result = qrectFromRECT(wp.rcNormalPosition);
2237 return result.translated(windowPlacementOffset(hwnd, result.topLeft()));
2245 const bool fakeFullScreen =
2246 m_savedFrameGeometry.isValid() && (window()->windowStates() & Qt::WindowFullScreen);
2247 const QRect frame = fakeFullScreen ? m_savedFrameGeometry : normalFrameGeometry(m_data.hwnd);
2248 const QMargins margins = fakeFullScreen
2249 ? QWindowsGeometryHint::frame(window(), handle(), m_savedStyle, 0)
2250 : fullFrameMargins();
2251 return frame.isValid() ? frame.marginsRemoved(margins) : frame;
2256 if (m_data.flags.testFlags(Qt::ExpandedClientAreaHint)) {
2257 const int titleBarHeight = getTitleBarHeight_sys(96);
2259 return QMargins(0, titleBarHeight, 0, 0);
2265 const QRect &requestedRect,
2266 const QRect &obtainedRect,
2267 const QMargins &fullMargins,
2268 const QMargins &customMargins)
2271 QDebug debug(&result);
2274 const auto window = platformWindow->window();
2275 debug <<
"Unable to set geometry ";
2276 formatBriefRectangle(debug, requestedRect);
2277 debug <<
" (frame: ";
2278 formatBriefRectangle(debug, requestedRect + fullMargins);
2279 debug <<
") on " << window->metaObject()->className() <<
"/\""
2280 << window->objectName() <<
"\" on \"" << window->screen()->name()
2281 <<
"\". Resulting geometry: ";
2282 formatBriefRectangle(debug, obtainedRect);
2283 debug <<
" (frame: ";
2284 formatBriefRectangle(debug, obtainedRect + fullMargins);
2285 debug <<
") margins: ";
2286 formatBriefMargins(debug, fullMargins);
2287 if (!customMargins.isNull()) {
2288 debug <<
" custom margin: ";
2289 formatBriefMargins(debug, customMargins);
2291 const auto minimumSize = window->minimumSize();
2292 const bool hasMinimumSize = !minimumSize.isEmpty();
2294 debug <<
" minimum size: " << minimumSize.width() <<
'x' << minimumSize.height();
2295 const auto maximumSize = window->maximumSize();
2296 const bool hasMaximumSize = maximumSize.width() != QWINDOWSIZE_MAX || maximumSize.height() != QWINDOWSIZE_MAX;
2298 debug <<
" maximum size: " << maximumSize.width() <<
'x' << maximumSize.height();
2299 if (hasMinimumSize || hasMaximumSize) {
2300 MINMAXINFO minmaxInfo;
2301 memset(&minmaxInfo, 0,
sizeof(minmaxInfo));
2302 platformWindow->getSizeHints(&minmaxInfo);
2303 debug <<
' ' << minmaxInfo;
2311 QScopedValueRollback b(m_inSetgeometry,
true);
2313 QRect rect = rectIn;
2316 if (QWindowsGeometryHint::positionIncludesFrame(window())) {
2317 const QMargins margins = frameMargins();
2318 rect.moveTopLeft(rect.topLeft() +
QPoint(margins.left(), margins.top()));
2320 if (m_windowState & Qt::WindowMinimized)
2321 m_data.geometry = rect;
2327 setGeometry_sys(rect);
2329 if (m_data.geometry != rect && (isVisible() || QLibraryInfo::isDebugBuild())) {
2330 const auto warning =
2331 msgUnableToSetGeometry(
this, rectIn, m_data.geometry,
2332 fullFrameMargins(), customMargins());
2333 qWarning(
"%s: %s",
__FUNCTION__, qPrintable(warning));
2336 QPlatformWindow::setGeometry(rect);
2344 handleGeometryChange();
2350 if ((m_data.flags.testFlag(Qt::FramelessWindowHint)
2351 || (m_data.flags.testFlag(Qt::CustomizeWindowHint) && !m_data.flags.testFlag(Qt::WindowTitleHint)))
2352 && IsZoomed(m_data.hwnd)) {
2353 const int resizedWidth = LOWORD(lParam);
2354 const int resizedHeight = HIWORD(lParam);
2356 const HMONITOR monitor = MonitorFromWindow(m_data.hwnd, MONITOR_DEFAULTTOPRIMARY);
2357 MONITORINFO monitorInfo = {};
2358 monitorInfo.cbSize =
sizeof(MONITORINFO);
2359 GetMonitorInfoW(monitor, &monitorInfo);
2361 int correctLeft = monitorInfo.rcMonitor.left;
2362 int correctTop = monitorInfo.rcMonitor.top;
2363 int correctWidth = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
2364 int correctHeight = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
2366 if (!m_data.flags.testFlag(Qt::FramelessWindowHint)) {
2367 const int borderWidth = invisibleMargins(m_data.hwnd).left();
2368 correctLeft -= borderWidth;
2369 correctTop -= borderWidth;
2370 correctWidth += borderWidth * 2;
2371 correctHeight += borderWidth * 2;
2374 if (resizedWidth != correctWidth || resizedHeight != correctHeight) {
2375 qCDebug(lcQpaWindow) <<
__FUNCTION__ <<
"correcting: " << resizedWidth <<
"x"
2376 << resizedHeight <<
" -> " << correctWidth <<
"x" << correctHeight;
2377 SetWindowPos(m_data.hwnd,
nullptr, correctLeft, correctTop, correctWidth, correctHeight,
2378 SWP_NOZORDER | SWP_NOACTIVATE);
2386 case SIZE_MINIMIZED:
2387 if (!testFlag(WithinSetStyle) && !testFlag(WithinSetGeometry))
2388 handleWindowStateChange(m_windowState | Qt::WindowMinimized);
2390 case SIZE_MAXIMIZED:
2391 handleGeometryChange();
2393 if (!testFlag(WithinSetStyle) && !testFlag(WithinSetGeometry))
2394 handleWindowStateChange(Qt::WindowMaximized | (isFullScreen_sys() ? Qt::WindowFullScreen
2395 : Qt::WindowNoState));
2398 handleGeometryChange();
2400 if (isFullScreen_sys())
2401 handleWindowStateChange(
2402 Qt::WindowFullScreen
2403 | (testFlag(MaximizeToFullScreen) ? Qt::WindowMaximized : Qt::WindowNoState));
2404 else if (m_windowState != Qt::WindowNoState && !testFlag(MaximizeToFullScreen))
2405 handleWindowStateChange(Qt::WindowNoState);
2411static inline bool equalDpi(
const QDpi &d1,
const QDpi &d2)
2413 return qFuzzyCompare(d1.first, d2.first) && qFuzzyCompare(d1.second, d2.second);
2421 QPlatformScreen *currentScreen = screen();
2422 auto topLevel = isTopLevel_sys() ? m_data.hwnd : GetAncestor(m_data.hwnd, GA_ROOT);
2427 if (newScreen ==
nullptr || newScreen == currentScreen)
2431 const bool changingDpi = !equalDpi(QDpi(savedDpi(), savedDpi()), newScreen->logicalDpi());
2435 qCDebug(lcQpaWindow).noquote().nospace() <<
__FUNCTION__
2436 <<
' ' << window() <<
" \"" << (currentScreen ? currentScreen->name() : QString())
2437 <<
"\"->\"" << newScreen->name() <<
'"';
2439 QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(window(), newScreen->screen());
2444 const QRect previousGeometry = m_data.geometry;
2446 m_data.geometry = geometry_sys();
2449 if (m_data.geometry == previousGeometry)
2451 QWindowSystemInterface::handleGeometryChange(window(), m_data.geometry);
2456 && m_data.geometry.size() != previousGeometry.size()
2458 && !(m_data.geometry.width() > previousGeometry.width() || m_data.geometry.height() > previousGeometry.height())) {
2459 fireFullExpose(
true);
2463 checkForScreenChanged();
2465 if (testFlag(SynchronousGeometryChangeEvent))
2466 QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
2473 qCDebug(lcQpaEvents) <<
__FUNCTION__ <<
this << window() << m_data.geometry;
2475 if (m_data.flags & Qt::ExpandedClientAreaHint) {
2476 const int titleBarHeight = getTitleBarHeight_sys(savedDpi());
2477 MoveWindow(m_data.hwndTitlebar, 0, 0, m_data.geometry.width(), titleBarHeight,
true);
2483 const QMargins margins = fullFrameMargins();
2484 const QRect frameGeometry = rect + margins;
2486 qCDebug(lcQpaWindow) <<
'>' <<
__FUNCTION__ << window()
2487 <<
"\n from " << geometry_sys() <<
" frame: "
2488 << margins <<
" to " <<rect
2489 <<
" new frame: " << frameGeometry;
2491 bool result =
false;
2492 const HWND hwnd = handle();
2493 WINDOWPLACEMENT windowPlacement;
2494 windowPlacement.length =
sizeof(WINDOWPLACEMENT);
2495 GetWindowPlacement(hwnd, &windowPlacement);
2498 if ((windowPlacement.showCmd == SW_MAXIMIZE && !IsWindowVisible(hwnd))
2499 || windowPlacement.showCmd == SW_SHOWMINIMIZED) {
2500 windowPlacement.rcNormalPosition =
2501 RECTfromQRect(frameGeometry.translated(-windowPlacementOffset(hwnd, frameGeometry.topLeft())));
2502 windowPlacement.showCmd = windowPlacement.showCmd == SW_SHOWMINIMIZED ? SW_SHOWMINIMIZED : SW_HIDE;
2503 result = SetWindowPlacement(hwnd, &windowPlacement);
2505 int x = frameGeometry.x();
2506 if (!window()->isTopLevel()) {
2507 const HWND parentHandle = GetParent(hwnd);
2508 if (isRtlLayout(parentHandle)) {
2510 GetClientRect(parentHandle, &rect);
2511 x = rect.right - frameGeometry.width() - x;
2514 result = MoveWindow(hwnd, x, frameGeometry.y(),
2515 frameGeometry.width(), frameGeometry.height(),
true);
2517 qCDebug(lcQpaWindow) <<
'<' <<
__FUNCTION__ << window()
2518 <<
"\n resulting " << result << geometry_sys();
2522
2523
2524
2525
2526
2531 m_hdc = GetDC(handle());
2532 if (QGuiApplication::layoutDirection() == Qt::RightToLeft)
2533 SetLayout(m_hdc, 0);
2539
2540
2541
2542
2543
2548 ReleaseDC(handle(), m_hdc);
2555#if QT_CONFIG(dynamicgl)
2556 return QOpenGLStaticContext::opengl32.moduleIsNotOpengl32()
2557 && QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL;
2566 if (message == WM_ERASEBKGND) {
2571 if (!window()->isVisible() && (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED) != 0)
2574 if (!GetUpdateRect(m_data.hwnd, 0, FALSE))
2581 InvalidateRect(hwnd,
nullptr,
false);
2583 BeginPaint(hwnd, &ps);
2588 fireExpose(QRegion(qrectFromRECT(ps.rcPaint)),
true);
2589 if (!QWindowsContext::instance()->asyncExpose())
2590 QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
2592 EndPaint(hwnd, &ps);
2598 m_windowTitle = QWindowsWindow::formatWindowTitle(title);
2599 setWindowTitle_sys(m_windowTitle);
2604 return m_windowTitle;
2609 qCDebug(lcQpaWindow) <<
'>' <<
__FUNCTION__ <<
this << window() <<
"\n from: "
2610 << m_data.flags <<
"\n to: " << flags;
2611 const QRect oldGeometry = geometry();
2612 if (m_data.flags != flags) {
2613 m_data.flags = flags;
2615 m_data = setWindowFlags_sys(flags);
2616 updateDropSite(window()->isTopLevel());
2623 const QRect newGeometry = geometry_sys();
2624 if (oldGeometry != newGeometry)
2625 handleGeometryChange();
2627 qCDebug(lcQpaWindow) <<
'<' <<
__FUNCTION__ <<
"\n returns: "
2628 << m_data.flags <<
" geometry " << oldGeometry <<
"->" << newGeometry;
2632 unsigned flags)
const
2635 creationData.fromWindow(window(), wt, flags);
2636 creationData.applyWindowFlags(m_data.hwnd);
2637 creationData.initialize(window(), m_data.hwnd,
true, m_opacity);
2639 if (creationData.flags.testFlag(Qt::ExpandedClientAreaHint)) {
2640 SetParent(m_data.hwndTitlebar, m_data.hwnd);
2641 ShowWindow(m_data.hwndTitlebar, SW_SHOW);
2643 if (IsWindowVisible(m_data.hwndTitlebar)) {
2644 SetParent(m_data.hwndTitlebar, HWND_MESSAGE);
2645 ShowWindow(m_data.hwndTitlebar, SW_HIDE);
2650 result.flags = creationData.flags;
2652 result.hasFrame = (creationData.style & (WS_DLGFRAME | WS_THICKFRAME))
2653 && !(creationData.flags & Qt::FramelessWindowHint);
2657void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
2659 qCDebug(lcQpaWindow) <<
__FUNCTION__ <<
this << window()
2660 <<
"\n from " << m_windowState <<
" to " << state;
2661 m_windowState = state;
2662 QWindowSystemInterface::handleWindowStateChanged(window(), state);
2663 if (state & Qt::WindowMinimized) {
2665 QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
2668 if (state & Qt::WindowMaximized) {
2669 WINDOWPLACEMENT windowPlacement{};
2670 windowPlacement.length =
sizeof(WINDOWPLACEMENT);
2671 GetWindowPlacement(m_data.hwnd, &windowPlacement);
2672 const RECT geometry = RECTfromQRect(m_data.restoreGeometry);
2673 windowPlacement.rcNormalPosition = geometry;
2674 correctWindowPlacement(windowPlacement);
2680 windowPlacement.showCmd = SW_HIDE;
2681 SetWindowPlacement(m_data.hwnd, &windowPlacement);
2685 QWindow *w = window();
2686 bool exposeEventsSent =
false;
2689 exposeEventsSent =
true;
2691 const QWindowList allWindows = QGuiApplication::allWindows();
2692 for (QWindow *child : allWindows) {
2693 if (child != w && child->isVisible() && child->transientParent() == w) {
2694 QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(child);
2695 if (platformWindow && platformWindow->isLayered()) {
2696 platformWindow->fireFullExpose();
2697 exposeEventsSent =
true;
2701 if (exposeEventsSent && !QWindowsContext::instance()->asyncExpose())
2702 QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
2711 return window()->maximumHeight() != QWINDOWSIZE_MAX;
2716 return window()->maximumWidth() != QWINDOWSIZE_MAX;
2724void QWindowsWindow::correctWindowPlacement(WINDOWPLACEMENT &windowPlacement)
2726 static const auto windows11 = QOperatingSystemVersion::Windows11_21H2;
2727 static const bool isWindows10 = QOperatingSystemVersion::current() < windows11;
2733 const QPoint offset = windowPlacementOffset(m_data.hwnd, m_data.restoreGeometry.topLeft());
2734 windowPlacement.rcNormalPosition = RECTfromQRect(m_data.restoreGeometry.translated(-offset));
2735 qCDebug(lcQpaWindow) <<
"Corrected normal position by" << -offset;
2744 const QMargins margins = frameMargins_sys();
2745 const QPoint topLeft = window()->screen()->geometry().topLeft();
2746 windowPlacement.ptMaxPosition = POINT{ topLeft.x() - margins.left(), topLeft.y() };
2747 qCDebug(lcQpaWindow) <<
"Window has maximum size. Corrected topLeft by"
2753 const int adjust = offset.x() / window()->devicePixelRatio();
2754 window()->setWidth(window()->width() - adjust);
2755 qCDebug(lcQpaWindow) <<
"Width shortened by" << adjust <<
"logical pixels.";
2758 const int adjust = offset.y() / window()->devicePixelRatio();
2759 window()->setHeight(window()->height() - adjust);
2760 qCDebug(lcQpaWindow) <<
"Height shortened by" << adjust <<
"logical pixels.";
2767 m_data.restoreGeometry = normalFrameGeometry(m_data.hwnd);
2773 setWindowState_sys(state);
2774 m_windowState = state;
2780 const QWindow *w = window();
2781 if (!w->isTopLevel())
2783 QRect geometry = geometry_sys();
2785 geometry += QMargins(1, 1, 1, 1);
2786 QPlatformScreen *screen = screenForGeometry(geometry);
2787 return screen && geometry == screen->geometry();
2791
2792
2793
2794
2795
2796
2797
2798
2799
2801void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState)
2803 const Qt::WindowStates oldState = m_windowState;
2804 if (oldState == newState)
2806 qCDebug(lcQpaWindow) <<
'>' <<
__FUNCTION__ <<
this << window()
2807 <<
" from " << oldState <<
" to " << newState;
2810 auto stateChange = oldState ^ newState;
2812 if (stateChange & Qt::WindowFullScreen) {
2813 if (newState & Qt::WindowFullScreen) {
2814 UINT newStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP;
2818 if (!m_savedStyle) {
2819 m_savedStyle =
style();
2820 if ((oldState & Qt::WindowMinimized) || (oldState & Qt::WindowMaximized)) {
2821 const QRect nf = normalFrameGeometry(m_data.hwnd);
2823 m_savedFrameGeometry = nf;
2825 m_savedFrameGeometry = frameGeometry_sys();
2828 if (newState & Qt::WindowMaximized)
2830 if (m_savedStyle & WS_SYSMENU)
2831 newStyle |= WS_SYSMENU;
2833 newStyle |= WS_VISIBLE;
2834 if (testFlag(HasBorderInFullScreen))
2835 newStyle |= WS_BORDER;
2837 const HMONITOR monitor = MonitorFromWindow(m_data.hwnd, MONITOR_DEFAULTTONEAREST);
2838 MONITORINFO monitorInfo = {};
2839 monitorInfo.cbSize =
sizeof(MONITORINFO);
2840 GetMonitorInfoW(monitor, &monitorInfo);
2841 const QRect screenGeometry(monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top,
2842 monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left,
2843 monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top);
2844 if (newState & Qt::WindowMinimized) {
2845 setMinimizedGeometry(m_data.hwnd, screenGeometry);
2846 if (stateChange & Qt::WindowMaximized)
2847 setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized);
2849 const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
2852 SetWindowPos(m_data.hwnd, HWND_TOP, screenGeometry.left(), screenGeometry.top(), screenGeometry.width(), screenGeometry.height(), swpf);
2856 QWindowSystemInterface::handleGeometryChange(window(), screenGeometry);
2857 QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
2861 unsigned newStyle = m_savedStyle ? m_savedStyle :
style();
2863 newStyle |= WS_VISIBLE;
2866 const QScreen *screen = window()->screen();
2868 screen = QGuiApplication::primaryScreen();
2870 if (
const auto platformScreen = screen->handle()) {
2871 if (!platformScreen->geometry().intersects(m_savedFrameGeometry))
2872 m_savedFrameGeometry.moveTo(platformScreen->geometry().topLeft());
2875 if (newState & Qt::WindowMinimized) {
2876 setMinimizedGeometry(m_data.hwnd, m_savedFrameGeometry);
2877 if (stateChange & Qt::WindowMaximized)
2878 setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized);
2880 UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE;
2881 if (!m_savedFrameGeometry.isValid())
2882 swpf |= SWP_NOSIZE | SWP_NOMOVE;
2887 if (windowVisibility_sys(m_data.hwnd) == QWindow::Maximized)
2888 ShowWindow(m_data.hwnd, SW_SHOWNOACTIVATE);
2889 SetWindowPos(m_data.hwnd,
nullptr, m_savedFrameGeometry.x(), m_savedFrameGeometry.y(),
2890 m_savedFrameGeometry.width(), m_savedFrameGeometry.height(), swpf);
2896 ShowWindow(m_data.hwnd,
2897 (newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNA);
2902 m_savedFrameGeometry = QRect();
2904 }
else if ((oldState & Qt::WindowMaximized) != (newState & Qt::WindowMaximized)) {
2905 if (visible && !(newState & Qt::WindowMinimized)) {
2907 if (newState & Qt::WindowFullScreen)
2909 ShowWindow(m_data.hwnd,
2910 (newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
2913 }
else if (visible && (oldState & newState & Qt::WindowMinimized)) {
2915 setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized);
2919 if (stateChange & Qt::WindowMinimized) {
2921 ShowWindow(m_data.hwnd,
2922 (newState & Qt::WindowMinimized) ? SW_MINIMIZE :
2923 (newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNORMAL);
2924 if ((newState & Qt::WindowMinimized) && (stateChange & Qt::WindowMaximized))
2925 setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized);
2928 qCDebug(lcQpaWindow) <<
'<' <<
__FUNCTION__ <<
this << window() << newState;
2933 qCDebug(lcQpaWindow) <<
__FUNCTION__ <<
this << window() << debugWinStyle(s);
2935 SetWindowLongPtr(m_data.hwnd, GWL_STYLE, s);
2941 qCDebug(lcQpaWindow) <<
__FUNCTION__ <<
this << window() << debugWinExStyle(s);
2942 SetWindowLongPtr(m_data.hwnd, GWL_EXSTYLE, s);
2947 switch (event->type()) {
2948 case QEvent::ApplicationPaletteChange:
2949 setDarkBorder(QWindowsTheme::instance()->colorScheme() == Qt::ColorScheme::Dark);
2951 case QEvent::WindowBlocked:
2957 case QEvent::WindowUnblocked:
2965 return QWindowsBaseWindow::windowEvent(event);
2970 qCDebug(lcQpaWindow) <<
__FUNCTION__ <<
this << window();
2975 bool result =
false;
2976 if ((windowPos->flags & SWP_NOSIZE) == 0) {
2978 GetWindowRect(windowPos->hwnd, &rect);
2979 result = rect.right - rect.left != windowPos->cx || rect.bottom - rect.top != windowPos->cy;
2984bool QWindowsWindow::handleGeometryChangingMessage(MSG *message,
const QWindow *qWindow,
const QMargins &margins)
2986 auto *windowPos =
reinterpret_cast<WINDOWPOS *>(message->lParam);
2987 const QRect suggestedFrameGeometry(windowPos->x, windowPos->y,
2988 windowPos->cx, windowPos->cy);
2989 const QRect suggestedGeometry = suggestedFrameGeometry - margins;
2996 if (isResize(windowPos))
2997 windowPos->flags |= SWP_NOCOPYBITS;
2999 if ((windowPos->flags & SWP_NOZORDER) == 0) {
3000 if (
QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(qWindow)) {
3001 QWindow *parentWindow = qWindow->parent();
3002 HWND parentHWND = GetAncestor(windowPos->hwnd, GA_PARENT);
3003 HWND desktopHWND = GetDesktopWindow();
3004 platformWindow->m_data.embedded = !parentWindow && parentHWND && (parentHWND != desktopHWND);
3006 if (qWindow->flags().testFlag(Qt::WindowStaysOnBottomHint))
3007 windowPos->hwndInsertAfter = HWND_BOTTOM;
3009 if (!qWindow->isTopLevel())
3011 if (windowPos->flags & SWP_NOSIZE)
3013 const QRectF correctedGeometryF = QPlatformWindow::closestAcceptableGeometry(qWindow, suggestedGeometry);
3014 if (!correctedGeometryF.isValid())
3016 const QRect correctedFrameGeometry = correctedGeometryF.toRect() + margins;
3017 if (correctedFrameGeometry == suggestedFrameGeometry)
3019 windowPos->x = correctedFrameGeometry.left();
3020 windowPos->y = correctedFrameGeometry.top();
3021 windowPos->cx = correctedFrameGeometry.width();
3022 windowPos->cy = correctedFrameGeometry.height();
3028 const QMargins margins = window()->isTopLevel() ? fullFrameMargins() : QMargins();
3029 return QWindowsWindow::handleGeometryChangingMessage(message, window(), margins);
3034 if (shouldOmitFrameAdjustment(m_data.flags, m_data.hwnd))
3036 if (m_data.fullFrameMargins != newMargins) {
3037 qCDebug(lcQpaWindow) <<
__FUNCTION__ << window() << m_data.fullFrameMargins <<
"->" << newMargins;
3038 m_data.fullFrameMargins = newMargins;
3045 if (GetMenu(m_data.hwnd))
3046 QWindowsContext::forceNcCalcSize(m_data.hwnd);
3048 calculateFullFrameMargins();
3053 if (shouldOmitFrameAdjustment(m_data.flags, m_data.hwnd))
3066 GetWindowRect(handle(), &windowRect);
3067 GetClientRect(handle(), &clientRect);
3073 if (qSizeOfRect(windowRect) == qSizeOfRect(clientRect))
3078 const auto systemMargins = testFlag(DisableNonClientScaling)
3079 ? QWindowsGeometryHint::frameOnPrimaryScreen(window(), m_data.hwnd)
3080 : frameMargins_sys();
3081 const int extendedClientAreaBorder = window()->flags().testFlag(Qt::ExpandedClientAreaHint) ? qRound(QHighDpiScaling::factor(window())) * 2 : 0;
3082 const QMargins actualMargins = systemMargins + customMargins() - extendedClientAreaBorder;
3084 const int yDiff = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top);
3085 const bool typicalFrame = (actualMargins.left() == actualMargins.right())
3086 && (actualMargins.right() == actualMargins.bottom());
3088 const QMargins adjustedMargins = typicalFrame ?
3089 QMargins(actualMargins.left(), (yDiff - actualMargins.bottom()),
3090 actualMargins.right(), actualMargins.bottom())
3093 setFullFrameMargins(adjustedMargins);
3098 QMargins result = fullFrameMargins();
3099 if (isTopLevel() && m_data.hasFrame)
3100 result -= invisibleMargins(m_data.hwnd);
3106 if (shouldOmitFrameAdjustment(m_data.flags, m_data.hwnd))
3108 return m_data.fullFrameMargins;
3113 qCDebug(lcQpaWindow) <<
__FUNCTION__ << level;
3114 if (!qFuzzyCompare(m_opacity, level)) {
3117 setWindowOpacity(m_data.hwnd, m_data.flags,
3125 return CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height());
3130 if (
const HRGN rectRegion = createRectRegion(rect)) {
3131 HRGN result = CreateRectRgn(0, 0, 0, 0);
3132 if (CombineRgn(result, *winRegion, rectRegion, RGN_OR)) {
3133 DeleteObject(*winRegion);
3134 *winRegion = result;
3136 DeleteObject(rectRegion);
3142 auto it = region.begin();
3143 const auto end = region.end();
3146 HRGN hRegion = createRectRegion(*it);
3148 addRectToWinRegion(*it, &hRegion);
3154 if (region.isEmpty()) {
3155 SetWindowRgn(m_data.hwnd,
nullptr,
true);
3158 const HRGN winRegion = qRegionToWinRegion(region);
3161 if (window()->isTopLevel()) {
3162 const QMargins margins = fullFrameMargins();
3163 OffsetRgn(winRegion, margins.left(), margins.top());
3167 if (!SetWindowRgn(m_data.hwnd, winRegion,
true))
3168 DeleteObject(winRegion);
3173 qCDebug(lcQpaWindow) <<
__FUNCTION__ <<
this << window();
3179 if (QGuiApplication::applicationState() == Qt::ApplicationActive
3180 || activationBehavior != QWindowsApplication::AlwaysActivateWindow) {
3181 SetForegroundWindow(m_data.hwnd);
3182 SetFocus(m_data.hwnd);
3191 if (m_data.flags & Qt::WindowStaysOnBottomHint) {
3192 qCWarning(lcQpaWindow) <<
3193 "Windows with Qt::WindowStaysOnBottomHint can't be brought to the foreground.";
3196 if (m_data.flags & Qt::WindowStaysOnTopHint) {
3197 qCWarning(lcQpaWindow) <<
3198 "Windows with Qt::WindowStaysOnTopHint will always be on the foreground.";
3201 if (window()->type() == Qt::ToolTip) {
3202 qCWarning(lcQpaWindow) <<
"ToolTip windows should not be activated.";
3207 if (!IsWindowVisible(m_data.hwnd))
3208 ShowWindow(m_data.hwnd, SW_SHOW);
3210 if (IsIconic(m_data.hwnd)) {
3211 ShowWindow(m_data.hwnd, SW_RESTORE);
3218 const HWND oldForegroundWindow = GetForegroundWindow();
3219 if (!oldForegroundWindow) {
3221 SetActiveWindow(m_data.hwnd);
3223 SetFocus(m_data.hwnd);
3229 if (SendMessageTimeoutW(oldForegroundWindow, WM_NULL, 0, 0,
3230 SMTO_BLOCK | SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG, 1000,
nullptr) == 0) {
3231 qCWarning(lcQpaWindow) <<
"The foreground window hangs, can't activate current window.";
3235 const DWORD windowThreadProcessId = GetWindowThreadProcessId(oldForegroundWindow,
nullptr);
3236 const DWORD currentThreadId = GetCurrentThreadId();
3238 AttachThreadInput(windowThreadProcessId, currentThreadId, TRUE);
3239 const auto cleanup = qScopeGuard([windowThreadProcessId, currentThreadId](){
3240 AttachThreadInput(windowThreadProcessId, currentThreadId, FALSE);
3243 BringWindowToTop(m_data.hwnd);
3247 SetActiveWindow(m_data.hwnd);
3248 SetFocus(m_data.hwnd);
3254 qWarning(
"%s: No handle",
__FUNCTION__);
3257 qCDebug(lcQpaWindow) <<
__FUNCTION__ <<
this << window() << grab;
3261 context->setKeyGrabber(window());
3263 if (context->keyGrabber() == window())
3264 context->setKeyGrabber(
nullptr);
3271 qCDebug(lcQpaWindow) <<
__FUNCTION__ << window() << grab;
3273 qWarning(
"%s: No handle",
__FUNCTION__);
3277 qWarning(
"%s: Not setting mouse grab for invisible window %s/'%s'",
3278 __FUNCTION__, window()->metaObject()->className(),
3279 qPrintable(window()->objectName()));
3286 SetCapture(m_data.hwnd);
3296 if (edges == Qt::LeftEdge)
3298 else if (edges == (Qt::RightEdge))
3300 else if (edges == (Qt::TopEdge))
3302 else if (edges == (Qt::TopEdge | Qt::LeftEdge))
3304 else if (edges == (Qt::TopEdge | Qt::RightEdge))
3306 else if (edges == (Qt::BottomEdge))
3308 else if (edges == (Qt::BottomEdge | Qt::LeftEdge))
3310 else if (edges == (Qt::BottomEdge | Qt::RightEdge))
3318 if (Q_UNLIKELY(window()->flags().testFlag(Qt::MSWindowsFixedSizeDialogHint)))
3322 PostMessage(m_data.hwnd, WM_SYSCOMMAND, edgesToWinOrientation(edges), 0);
3330 PostMessage(m_data.hwnd, WM_SYSCOMMAND, 0xF012 , 0);
3345 QWindowsGeometryHint::applyToMinMaxInfo(window(), fullFrameMargins(), mmi);
3350 if ((m_data.flags & Qt::FramelessWindowHint) && window()->isTopLevel()
3351 && !testFlag(MaximizeToFullScreen)) {
3352 const HMONITOR monitor = MonitorFromWindow(m_data.hwnd, MONITOR_DEFAULTTONEAREST);
3353 MONITORINFO monitorInfo = {};
3354 monitorInfo.cbSize =
sizeof(MONITORINFO);
3355 GetMonitorInfoW(monitor, &monitorInfo);
3356 const RECT &work = monitorInfo.rcWork;
3357 const RECT &screen = monitorInfo.rcMonitor;
3360 mmi->ptMaxPosition.x = work.left - screen.left;
3361 mmi->ptMaxPosition.y = work.top - screen.top;
3362 mmi->ptMaxSize.x = work.right - work.left;
3363 mmi->ptMaxSize.y = work.bottom - work.top;
3365 qCDebug(lcQpaWindow) <<
__FUNCTION__ << window() << *mmi;
3371 const QWindow *w = window();
3372 const QPoint localPos = w->mapFromGlobal(QHighDpi::fromNativePixels(globalPos, w));
3373 const QRect geom = geometry();
3374 static auto oldMouseButtonState = Qt::NoButton;
3376 if (m_data.flags.testFlags(Qt::ExpandedClientAreaHint)) {
3377 bool isDefaultTitleBar = !w->flags().testFlag(Qt::CustomizeWindowHint);
3378 bool isCustomized = w->flags().testFlags(Qt::CustomizeWindowHint) && w->flags().testAnyFlags(Qt::WindowTitleHint|
3379 Qt::WindowMinimizeButtonHint|
3380 Qt::WindowMaximizeButtonHint|
3381 Qt::WindowCloseButtonHint);
3382 const int border = (IsZoomed(m_data.hwnd) || isFullScreen_sys()) ? 0 : getResizeBorderThickness(savedDpi());
3383 const int titleBarHeight = getTitleBarHeight_sys(savedDpi());
3384 const int titleButtonWidth = titleBarHeight * 1.5;
3385 const bool mouseButtonsSwapped = GetSystemMetrics(SM_SWAPBUTTON);
3386 auto mouseButtons = Qt::NoButton;
3387 if (mouseButtonsSwapped)
3388 mouseButtons = GetAsyncKeyState(VK_LBUTTON) != 0 ? Qt::RightButton : (GetAsyncKeyState(VK_RBUTTON) ? Qt::LeftButton : Qt::NoButton);
3390 mouseButtons = GetAsyncKeyState(VK_LBUTTON) != 0 ? Qt::LeftButton : (GetAsyncKeyState(VK_RBUTTON) ? Qt::RightButton : Qt::NoButton);
3393 if (isCustomized || isDefaultTitleBar) {
3396 if (globalPos.y() < geom.top() + titleBarHeight) {
3397 if (m_data.flags.testFlags(Qt::WindowCloseButtonHint) || isDefaultTitleBar) {
3398 if ((globalPos.x() > geom.right() - titleButtonWidth * buttons) && (globalPos.x() <= geom.right())) {
3399 if (mouseButtons == Qt::LeftButton)
3403 }
if (m_data.flags.testFlags(Qt::WindowMaximizeButtonHint) || isDefaultTitleBar) {
3404 if ((globalPos.x() > geom.right() - titleButtonWidth * buttons) && (globalPos.x() <= geom.right() - titleButtonWidth * (buttons-1))){
3405 if (mouseButtons == Qt::LeftButton) {
3406 if (IsZoomed(m_data.hwnd))
3409 *result = HTMAXBUTTON;
3413 }
if (m_data.flags.testFlags(Qt::WindowMinimizeButtonHint) || isDefaultTitleBar) {
3414 if ((globalPos.x() > geom.right() - titleButtonWidth * buttons) && (globalPos.x() <= geom.right() - titleButtonWidth * (buttons-1))){
3415 if (mouseButtons == Qt::LeftButton)
3416 *result = HTMINBUTTON;
3419 }
if ((isCustomized || isDefaultTitleBar) &&
3420 *result == HTCLIENT){
3421 QWindow* wnd = window();
3422 if (mouseButtons != oldMouseButtonState) {
3423 auto mouseEventType = mouseButtons == Qt::NoButton ? QEvent::MouseButtonRelease : QEvent::MouseButtonPress;
3424 auto mouseEventButtons = mouseEventType == QEvent::MouseButtonPress ? mouseButtons : oldMouseButtonState;
3425 bool accepted = QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(wnd, QHighDpi::toNativeLocalPosition(localPos, w), globalPos, mouseEventButtons, mouseEventButtons, mouseEventType);
3426 if (!accepted && mouseButtons == Qt::RightButton)
3427 *result = HTSYSMENU;
3428 else if (!accepted && globalPos.y() < geom.top() + titleBarHeight)
3429 *result = HTCAPTION;
3433 }
else if (w->flags().testFlag(Qt::CustomizeWindowHint)) {
3435 QWindow* wnd = window();
3436 if (mouseButtons != oldMouseButtonState) {
3437 auto mouseEventType = mouseButtons == Qt::NoButton ? QEvent::MouseButtonRelease : QEvent::MouseButtonPress;
3438 auto mouseEventButtons = mouseEventType == QEvent::MouseButtonPress ? mouseButtons : oldMouseButtonState;
3439 bool accepted = QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(wnd, QHighDpi::toNativeLocalPosition(localPos, w), globalPos, mouseEventButtons, mouseEventButtons, mouseEventType);
3440 if (!accepted && mouseButtons == Qt::RightButton)
3441 *result = HTSYSMENU;
3442 else if (!accepted && globalPos.y() < geom.top() + titleBarHeight)
3443 *result = HTCAPTION;
3446 oldMouseButtonState = mouseButtons;
3449 const bool left = (globalPos.x() >= geom.left()) && (globalPos.x() < geom.left() + border);
3450 const bool right = (globalPos.x() > geom.right() - border) && (globalPos.x() <= geom.right());
3451 const bool top = (globalPos.y() >= geom.top()) && (globalPos.y() < geom.top() + border);
3452 const bool bottom = (globalPos.y() > geom.bottom() - border) && (globalPos.y() <= geom.bottom());
3454 if (left || right || top || bottom) {
3456 *result = top ? HTTOPLEFT : (bottom ? HTBOTTOMLEFT : HTLEFT);
3458 *result = top ? HTTOPRIGHT : (bottom ? HTBOTTOMRIGHT : HTRIGHT);
3460 *result = top ? HTTOP : HTBOTTOM;
3466 const_cast<QWindow *>(w)->close();
3469 const_cast<QWindow *>(w)->showMaximized();
3472 const_cast<QWindow *>(w)->showMinimized();
3475 const_cast<QWindow *>(w)->showNormal();
3478 HWND hwnd =
reinterpret_cast<HWND>(w->winId());
3479 HMENU sysMenu = GetSystemMenu(hwnd,
false);
3480 TrackPopupMenu(sysMenu, 0, globalPos.x(), globalPos.y(), 0, hwnd,
nullptr);
3489 if (m_data.flags & Qt::ExpandedClientAreaHint) {
3490 const int border = (IsZoomed(m_data.hwnd) || isFullScreen_sys()) ? 0 : getResizeBorderThickness(savedDpi());
3495 const QRect rect = geom;
3496 const bool left = (globalPos.x() >= rect.left()) && (globalPos.x() < rect.left() + border);
3497 const bool right = (globalPos.x() > rect.right() - border) && (globalPos.x() <= rect.right());
3498 const bool top = (globalPos.y() >= rect.top()) && (globalPos.y() < rect.top() + border);
3499 const bool bottom = (globalPos.y() > rect.bottom() - border) && (globalPos.y() <= rect.bottom());
3502 if (left || right || top || bottom) {
3504 *result = top ? HTTOPLEFT : (bottom ? HTBOTTOMLEFT : HTLEFT);
3506 *result = top ? HTTOPRIGHT : (bottom ? HTBOTTOMRIGHT : HTRIGHT);
3508 *result = top ? HTTOP : HTBOTTOM;
3516 if (!w->isTopLevel()
3517 || (m_windowState != Qt::WindowNoState)
3519 || (m_data.flags & Qt::FramelessWindowHint)) {
3522 const QSize minimumSize = w->minimumSize();
3523 if (minimumSize.isEmpty())
3525 const QSize maximumSize = w->maximumSize();
3526 const bool fixedWidth = minimumSize.width() == maximumSize.width();
3527 const bool fixedHeight = minimumSize.height() == maximumSize.height();
3528 if (!fixedWidth && !fixedHeight)
3530 const QSize size = w->size();
3532 if (localPos.y() >= size.height()) {
3536 if (localPos.y() < 0) {
3537 const int topResizeBarPos = invisibleMargins(m_data.hwnd).left() - frameMargins().top();
3538 if (localPos.y() < topResizeBarPos) {
3539 *result = HTCAPTION;
3544 if (fixedWidth && (localPos.x() < 0 || localPos.x() >= size.width())) {
3556 if (m_data.flags & Qt::FramelessWindowHint) {
3565 HWND hwnd = m_data.hwndTitlebar;
3566 QWindow *wnd = window();
3569 GetWindowRect(hwnd, &windowRect);
3571 const int titleBarHeight = getTitleBarHeight_sys(savedDpi());
3572 const int titleButtonWidth = titleBarHeight * 1.5;
3573 const qreal factor = QHighDpiScaling::factor(wnd);
3574 const int windowWidth = windowRect.right - windowRect.left;
3577 GetCursorPos(&localPos);
3578 MapWindowPoints(HWND_DESKTOP, m_data.hwnd, &localPos, 1);
3580 const bool isDarkmode = QWindowsIntegration::instance()->darkModeHandling().testFlags(QWindowsApplication::DarkModeWindowFrames) &&
3581 qApp->styleHints()->colorScheme() == Qt::ColorScheme::Dark;
3582 const bool isWindows11orAbove = QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows11;
3584 const QBrush closeButtonBrush(QColor(0xC4, 0x2C, 0x1E, 255));
3585 const QBrush minMaxButtonBrush = QBrush(isDarkmode ? QColor(0xFF, 0xFF, 0xFF, 0x40) : QColor(0x00, 0x00, 0x00, 0x20));
3586 const QBrush titleBarBackgroundColor = QBrush(isDarkmode ? QColor(0x1F, 0x1F, 0x1F, 0xFF) : QColor(0xF3, 0xF3, 0xF3, 0xFF));
3587 const QPen textPen = QPen(isDarkmode ? QColor(0xFF, 0xFF, 0xFD, 0xFF) : QColor(0x00, 0x00, 0x00, 0xFF));
3589 QImage image(windowWidth, titleBarHeight, QImage::Format_ARGB32);
3591 p.setCompositionMode(QPainter::CompositionMode_Clear);
3592 p.fillRect(0, 0, windowWidth, titleBarHeight, Qt::transparent);
3594 p.setCompositionMode(QPainter::CompositionMode_SourceOver);
3596 p.setBrush(titleBarBackgroundColor);
3597 p.setPen(Qt::NoPen);
3598 if (!wnd->flags().testFlags(Qt::NoTitleBarBackgroundHint)) {
3600 titleRect.setWidth(windowWidth);
3601 titleRect.setHeight(titleBarHeight);
3602 p.drawRect(titleRect);
3605 if (wnd->flags().testFlags(Qt::WindowTitleHint | Qt::CustomizeWindowHint) || !wnd->flags().testFlag(Qt::CustomizeWindowHint)) {
3609 titleRect.setWidth(windowWidth);
3610 titleRect.setHeight(titleBarHeight);
3612 titleRect.adjust(factor * 4, 0, 0, 0);
3613 QRect iconRect(titleRect.x(), titleRect.y() + factor * 8, factor * 16, factor * 16);
3614 if (wnd->icon().isNull()) {
3615 static QIcon defaultIcon;
3616 if (defaultIcon.isNull()) {
3617 const QImage defaultIconImage = QImage::fromHICON(LoadIcon(0, IDI_APPLICATION));
3618 defaultIcon = QIcon(QPixmap::fromImage(defaultIconImage));
3620 defaultIcon.paint(&p, iconRect);
3622 wnd->icon().paint(&p, iconRect);
3624 titleRect.adjust(factor * 24, 0, 0, 0);
3628 titleFont.setPointSize(factor * 9);
3629 titleFont.setWeight(QFont::Thin);
3630 titleFont.setHintingPreference(QFont::PreferFullHinting);
3631 p.setFont(titleFont);
3632 const QString title = wnd->title().isEmpty() ? qApp->applicationName() : wnd->title();
3633 p.drawText(titleRect, title, QTextOption(Qt::AlignVCenter));
3637 const QString assetFontName = isWindows11orAbove ? QStringLiteral(
"Segoe Fluent Icons") : QStringLiteral(
"Segoe MDL2 Assets");
3638 QFont assetFont = QFont(assetFontName, factor * 7);
3639 assetFont.setWeight(QFont::Thin);
3640 assetFont.setHintingPreference(QFont::PreferFullHinting);
3641 p.setFont(assetFont);
3642 p.setBrush(closeButtonBrush);
3643 p.setPen(Qt::NoPen);
3644 if (wnd->flags().testFlags(Qt::WindowCloseButtonHint | Qt::CustomizeWindowHint) || !wnd->flags().testFlag(Qt::CustomizeWindowHint)) {
3647 rect.setX(windowWidth - titleButtonWidth * buttons);
3648 rect.setWidth(titleButtonWidth);
3649 rect.setHeight(titleBarHeight);
3650 if (localPos.x > (windowWidth - buttons * titleButtonWidth) &&
3651 localPos.x < (windowWidth - (buttons - 1) * titleButtonWidth) &&
3652 localPos.y > rect.y() && localPos.y < rect.y() + rect.height()) {
3654 const QPen closeButtonHoveredPen = QPen(QColor(0xFF, 0xFF, 0xFD, 0xFF));
3655 p.setPen(closeButtonHoveredPen);
3659 p.drawText(rect, QStringLiteral(
"\uE8BB"), QTextOption(Qt::AlignVCenter | Qt::AlignHCenter));
3663 p.setBrush(minMaxButtonBrush);
3664 p.setPen(Qt::NoPen);
3665 if (wnd->flags().testFlags(Qt::WindowMaximizeButtonHint | Qt::CustomizeWindowHint) || !wnd->flags().testFlag(Qt::CustomizeWindowHint)) {
3668 rect.setX(windowWidth - titleButtonWidth * buttons);
3669 rect.setWidth(titleButtonWidth);
3670 rect.setHeight(titleBarHeight);
3671 if (localPos.x > (windowWidth - buttons * titleButtonWidth) &&
3672 localPos.x < (windowWidth - (buttons - 1) * titleButtonWidth) &&
3673 localPos.y > rect.y() && localPos.y < rect.y() + rect.height()) {
3678 const QString maximizeGlyph = IsZoomed(m_data.hwnd) ? QStringLiteral(
"\uE923")
3679 : QStringLiteral(
"\uE922");
3680 p.drawText(rect, maximizeGlyph, QTextOption(Qt::AlignVCenter | Qt::AlignHCenter));
3684 p.setBrush(minMaxButtonBrush);
3685 p.setPen(Qt::NoPen);
3686 if (wnd->flags().testFlags(Qt::WindowMinimizeButtonHint | Qt::CustomizeWindowHint) || !wnd->flags().testFlag(Qt::CustomizeWindowHint)) {
3689 rect.setX(windowWidth - titleButtonWidth * buttons);
3690 rect.setWidth(titleButtonWidth);
3691 rect.setHeight(titleBarHeight);
3692 if (localPos.x > (windowWidth - buttons * titleButtonWidth) &&
3693 localPos.x < (windowWidth - (buttons - 1) * titleButtonWidth) &&
3694 localPos.y > rect.y() && localPos.y < rect.y() + rect.height()) {
3698 p.drawText(rect,QStringLiteral(
"\uE921"), QTextOption(Qt::AlignVCenter | Qt::AlignHCenter));
3704 HBITMAP bmp = image.toHBITMAP();
3706 HDC hdc = GetDC(hwnd);
3708 HDC memdc = CreateCompatibleDC(hdc);
3709 HGDIOBJ original = SelectObject(memdc, bmp);
3712 BLENDFUNCTION blend = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
3713 POINT ptLocation = { 0, 0 };
3714 SIZE szWnd = { windowWidth, titleBarHeight };
3715 POINT ptSrc = { 0, 0 };
3716 UpdateLayeredWindow(hwnd, hdc, &ptLocation, &szWnd, memdc, &ptSrc, 0, &blend, ULW_ALPHA);
3717 SelectObject(hdc, original);
3720 DeleteObject(memdc);
3721 ReleaseDC(hwnd,hdc);
3728 if (QScreen *screen = w->screen())
3729 if (
const QPlatformScreen *platformScreen = screen->handle())
3730 if (QPlatformCursor *cursor = platformScreen->cursor())
3731 return static_cast<QWindowsCursor *>(cursor)->standardWindowCursor(Qt::ArrowCursor);
3732 return CursorHandlePtr(
new CursorHandle(QWindowsCursor::createCursorFromShape(Qt::ArrowCursor)));
3741 if (underMouse == w)
3743 for (
const QWindow *p = underMouse; p ; p = p->parent()) {
3746 const QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(p);
3747 if (platformWindow && !platformWindow->cursor()->isNull())
3755
3756
3757
3758
3768 if (m_cursor->isNull()) {
3769 if (
const QWindow *p = window()->parent()) {
3770 if (
QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(p))
3773 SetCursor(defaultCursor(window())->handle());
3776 SetCursor(m_cursor->handle());
3784 bool changed = c->handle() != m_cursor->handle();
3792 const bool apply = applyNewCursor(window());
3793 qCDebug(lcQpaWindow) << window() <<
__FUNCTION__
3794 << c->handle() <<
" doApply=" << apply;
3817 UINT timeOutMs = GetCaretBlinkTime();
3818 if (!timeOutMs || timeOutMs == INFINITE)
3822 info.cbSize =
sizeof(info);
3823 info.hwnd = m_data.hwnd;
3824 info.dwFlags = FLASHW_TRAY;
3825 info.dwTimeout = timeOutMs;
3826 info.uCount = durationMs == 0 ? 10 : UINT(durationMs) / timeOutMs;
3827 FlashWindowEx(&info);
3833 info.cbSize =
sizeof(info);
3834 info.hwnd = m_data.hwnd;
3835 info.dwFlags = FLASHW_STOP;
3838 FlashWindowEx(&info);
3843 return (style() & WS_DISABLED) == 0;
3848 const unsigned oldStyle =
style();
3849 unsigned newStyle = oldStyle;
3851 newStyle &= ~WS_DISABLED;
3853 newStyle |= WS_DISABLED;
3855 if (newStyle != oldStyle)
3862 const POINT origin{0, 0};
3863 if (
const HMONITOR monitor = MonitorFromPoint(origin, MONITOR_DEFAULTTOPRIMARY)) {
3866 if (SUCCEEDED(GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY)))
3869 return GetDpiForSystem();
3874 if (!icon.isNull()) {
3882 const QSize physicalSize(GetSystemMetricsForDpi(xSizeMetric, dpi),
3883 GetSystemMetricsForDpi(ySizeMetric, dpi));
3884 const QPixmap pm = icon.pixmap(icon.actualSize(physicalSize / dpr), dpr);
3886 return qt_pixmapToWinHICON(pm);
3900 const UINT windowDpi = GetDpiForWindow(m_data.hwnd);
3902 m_iconSmall = createHIcon(icon, titleBarDpi, SM_CXSMICON, SM_CYSMICON);
3909 m_iconBig = createHIcon(icon, primaryScreenDpi(), SM_CXICON, SM_CYICON);
3912 SendMessage(m_data.hwnd, WM_SETICON, 0 , LPARAM(m_iconSmall));
3913 SendMessage(m_data.hwnd, WM_SETICON, 1 , LPARAM(m_iconBig));
3915 SendMessage(m_data.hwnd, WM_SETICON, 0 , LPARAM(m_iconSmall));
3916 SendMessage(m_data.hwnd, WM_SETICON, 1 , LPARAM(m_iconSmall));
3923 return window()->isTopLevel() && !m_data.embedded;
3933 const BOOL darkBorder = d ? TRUE : FALSE;
3938 qCWarning(lcQpaWindow,
"%s: Unable to set %s window border.",
__FUNCTION__, d ?
"dark" :
"light");
3949 d = d && shouldApplyDarkFrame(window());
3951 setDarkBorderToWindow(m_data.hwnd, d);
3956 return m_menuBar.data();
3966 if (m_data.flags & Qt::FramelessWindowHint)
3968 return m_data.customMargins;
3972
3973
3974
3975
3976
3977
3978
3979
3983 if (m_data.flags & Qt::FramelessWindowHint) {
3984 qCWarning(lcQpaWindow) <<
"You should not set custom margins for a frameless window.";
3987 if (newCustomMargins != m_data.customMargins) {
3988 const QMargins oldCustomMargins = m_data.customMargins;
3989 m_data.customMargins = newCustomMargins;
3991 const QRect currentFrameGeometry = frameGeometry_sys();
3992 const QPoint topLeft = currentFrameGeometry.topLeft();
3993 QRect newFrame = currentFrameGeometry.marginsRemoved(oldCustomMargins) + m_data.customMargins;
3994 newFrame.moveTo(topLeft);
3995 qCDebug(lcQpaWindow) <<
__FUNCTION__ << oldCustomMargins <<
"->" << newCustomMargins
3996 << currentFrameGeometry <<
"->" << newFrame;
3997 SetWindowPos(m_data.hwnd,
nullptr, newFrame.x(), newFrame.y(), newFrame.width(), newFrame.height(), SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE);
4003#if QT_CONFIG(vulkan)
4004 Q_UNUSED(nativeConfig);
4006 if (window()->surfaceType() == QSurface::VulkanSurface) {
4008 QVulkanInstance *inst = window()->vulkanInstance();
4010 m_vkSurface =
static_cast<QWindowsVulkanInstance *>(inst->handle())->createSurface(handle());
4012 qWarning(
"Attempted to create Vulkan surface without an instance; was QWindow::setVulkanInstance() called?");
4016 return &m_vkSurface;
4018#elif defined(QT_NO_OPENGL)
4020 Q_UNUSED(nativeConfig);
4037#if QT_CONFIG(vulkan)
4039 QVulkanInstance *inst = window()->vulkanInstance();
4041 static_cast<QWindowsVulkanInstance *>(inst->handle())->destroySurface(m_vkSurface);
4042 m_vkSurface = VK_NULL_HANDLE;
4049 m_surface =
nullptr;
4062 const auto currentTouchTypes = touchWindowTouchTypes_sys();
4063 if (currentTouchTypes.has_value() && currentTouchTypes.value() == touchTypes)
4067 ULONG touchFlags = 0;
4068 if (touchTypes.testFlag(TouchWindowTouchType::FineTouch))
4069 touchFlags |= TWF_FINETOUCH;
4070 if (touchTypes.testFlag(TouchWindowTouchType::WantPalmTouch))
4071 touchFlags |= TWF_WANTPALM;
4072 if (RegisterTouchWindow(m_data.hwnd, touchFlags))
4075 qErrnoWarning(
"RegisterTouchWindow() failed for window '%s'.", qPrintable(window()->objectName()));
4080 if (QPlatformWindow *handle = window->handle())
4081 static_cast<QWindowsWindow *>(handle)->setHasBorderInFullScreen(border);
4088 m_borderInFullScreenDefault = border;
4105 if (m_windowState == Qt::WindowFullScreen) {
4106 LONG_PTR style = GetWindowLongPtr(handle(), GWL_STYLE);
4110 style &= ~WS_BORDER;
4111 SetWindowLongPtr(handle(), GWL_STYLE, style);
4117 return QPlatformWindow::formatWindowTitle(title, QStringLiteral(
" - "));
4127 QWindow *w = window();
4128 QDxgiVSyncService *vs = QDxgiVSyncService::instance();
4129 if (vs->supportsWindow(w)) {
4134 QPlatformWindow::d_ptr->updateTimer.stop();
4135 if (m_vsyncServiceCallbackId == 0) {
4136 m_vsyncServiceCallbackId = vs->registerCallback([
this, w](
const QDxgiVSyncService::CallbackWindowList &windowList, qint64) {
4137 if (windowList.contains(w)) {
4142 if (m_vsyncUpdatePending.testAndSetAcquire(UpdateState::Requested, UpdateState::Posted)) {
4143 QWindowsWindow *oldSelf =
this;
4144 qsizetype oldCallbackId = m_vsyncServiceCallbackId;
4145 QMetaObject::invokeMethod(w, [w, oldSelf, oldCallbackId] {
4147 auto *self =
static_cast<QWindowsWindow *>(w->handle());
4150 if (self && self == oldSelf && self->m_vsyncServiceCallbackId == oldCallbackId) {
4152 self->m_vsyncUpdatePending.storeRelease(UpdateState::Ready);
4153 self->deliverUpdateRequest();
4160 m_vsyncUpdatePending.testAndSetRelease(UpdateState::Ready, UpdateState::Requested);
4162 QPlatformWindow::requestUpdate();
\inmodule QtCore\reentrant
Base class for QWindowsForeignWindow, QWindowsWindow.
QMargins frameMargins_sys() const
bool isTopLevel_sys() const
void setHasBorderInFullScreen(bool border) override
QMargins customMargins() const override
bool windowEvent(QEvent *event) override
Reimplement this method to be able to do any platform specific event handling.
bool hasBorderInFullScreen() const override
bool hasMaximumWidth() const
std::optional< TouchWindowTouchTypes > touchWindowTouchTypes_sys() const
bool hasMaximumHeight() const
QRect frameGeometry_sys() const
QRect geometry_sys() const
void setCustomMargins(const QMargins &margins) override
void setGeometry_sys(const QRect &rect) const
bool hasMaximumSize() const
void setWindowTitle_sys(const QString &title)
Singleton container for all relevant information.
QWindowsScreenManager & screenManager()
void clearWindowUnderMouse()
unsigned systemInfo() const
static QWindowsContext * instance()
Platform cursor implementation.
static bool hasOverrideCursor()
static void enforceOverrideCursor()
Window wrapping a foreign native window.
void setVisible(bool visible) override
Reimplemented in subclasses to show the surface if visible is true, and hide it if visible is false.
static QWindowsStaticOpenGLContext * staticOpenGLContext()
static QWindowsIntegration * instance()
Manages a list of QWindowsScreen.
const QWindowsScreen * screenAtDp(const QPoint &p) const
static bool isSingleScreen()
virtual void * createWindowSurface(void *, void *, int *)
virtual void destroyWindowSurface(void *)
static QWindowsWindowClassRegistry * instance()
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)
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 checkForScreenChanged(ScreenChangeMode mode=FromGeometryChange, const RECT *suggestedRect=nullptr)
void initialize() override
Called as part of QWindow::create(), after constructing the window.
void handleDpiChangedAfterParent(HWND hwnd)
void requestUpdate() override
Requests an QEvent::UpdateRequest event.
bool testFlag(unsigned f) const
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()
void getSizeHints(MINMAXINFO *mmi) const
static void setHasBorderInFullScreenDefault(bool border)
~QWindowsWindow() override
bool handleWmPaint(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result)
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 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
QString windowTitle() const override
Reimplement to return the actual window title used in the underlying windowing system unless the titl...
static void displayChanged()
bool setKeyboardGrabEnabled(bool grab) override
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
void handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
void registerTouchWindow()
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 handleNonClientActivate(LRESULT *result) const
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
QMargins safeAreaMargins() const override
The safe area margins of a window represent the area that is safe to place content within,...
void setSavedDpi(int dpi)
void requestActivateWindow() override
Reimplement to let Qt be able to request activation/focus for a window.
void handleDpiScaledSize(WPARAM wParam, LPARAM lParam, LRESULT *result)
void updateFullFrameMargins()
@ SynchronousGeometryChangeEvent
@ WithinSetParent
Automatic mouse capture on button press.
@ FrameStrutEventsEnabled
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 updateRestoreGeometry()
void setWindowState(Qt::WindowStates state) override
Requests setting the window state of this surface to type.
void setCursor(const CursorHandlePtr &c)
void updateCustomTitlebar()
bool hasBorderInFullScreen() const override
bool hasMouseCapture() const
void * surface(void *nativeConfig, int *err)
void setHasBorderInFullScreen(bool border) override
void handleCompositionSettingsChanged()
void setWindowTitle(const QString &title) override
Reimplement to set the window title to title.
void setDarkBorder(bool d)
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 ®ion) 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...
bool isAlertState() const override
Reimplement this method return whether the window is in an alert state.
Combined button and popup list for selecting options.
static HICON createHIcon(const QIcon &icon, UINT dpi, int xSizeMetric, int ySizeMetric)
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)
static void setMinimizedGeometry(HWND hwnd, const QRect &r)
static bool applyNewCursor(const QWindow *w)
static bool isSoftwareGl()
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)
static void setRestoreMaximizedFlag(HWND hwnd, bool set=true)
static RECT RECTfromQRect(const QRect &rect)
static QMargins invisibleMargins(const HWND hwnd)
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 bool isResize(const WINDOWPOS *windowPos)
static void formatBriefMargins(QDebug &d, const QMargins &m)
static int getTitleBarHeight_sys(const UINT dpi)
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)
static UINT primaryScreenDpi()
static HRGN qRegionToWinRegion(const QRegion ®ion)
static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &context, const QMargins &invMargins)
@ DwmwaUseImmersiveDarkMode
@ DwmwaUseImmersiveDarkModeBefore20h1
static QRect qrectFromRECT(const RECT &rect)
static QWindow::Visibility windowVisibility_sys(HWND hwnd)
static GpuDescription detect()
Active Context for creating windows.
void applyToMinMaxInfo(MINMAXINFO *mmi) const
Stores geometry constraints and provides utility functions.
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)