1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the plugins of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qwindowswindow.h"
43 #include "qwindowsnativeimage.h"
44 #include "qwindowscontext.h"
45 #include "qwindowsdrag.h"
46 #include "qwindowsscreen.h"
47 #include "qwindowscursor.h"
50 # include "qwindowseglcontext.h"
53 #include <QtGui/QGuiApplication>
54 #include <QtGui/QScreen>
55 #include <QtGui/QWindow>
56 #include <QtGui/QRegion>
57 #include <private/qwindow_p.h>
58 #include <qpa/qwindowsysteminterface.h>
60 #include <QtCore/QDebug>
64 static QByteArray debugWinStyle(DWORD style)
67 rc += QByteArray::number(qulonglong(style), 16);
72 if (style & WS_OVERLAPPED)
73 rc += " WS_OVERLAPPED";
74 if (style & WS_CLIPSIBLINGS)
75 rc += " WS_CLIPSIBLINGS";
76 if (style & WS_CLIPCHILDREN)
77 rc += " WS_CLIPCHILDREN";
78 if (style & WS_THICKFRAME)
79 rc += " WS_THICKFRAME";
80 if (style & WS_DLGFRAME)
82 if (style & WS_SYSMENU)
84 if (style & WS_MINIMIZEBOX)
85 rc += " WS_MINIMIZEBOX";
86 if (style & WS_MAXIMIZEBOX)
87 rc += " WS_MAXIMIZEBOX";
91 static QByteArray debugWinExStyle(DWORD exStyle)
94 rc += QByteArray::number(qulonglong(exStyle), 16);
95 if (exStyle & WS_EX_TOOLWINDOW)
96 rc += " WS_EX_TOOLWINDOW";
97 if (exStyle & WS_EX_CONTEXTHELP)
98 rc += " WS_EX_CONTEXTHELP";
99 if (exStyle & WS_EX_LAYERED)
100 rc += " WS_EX_LAYERED";
104 static QByteArray debugWindowStates(Qt::WindowStates s)
107 QByteArray rc = "0x";
108 rc += QByteArray::number(int(s), 16);
109 if (s & Qt::WindowMinimized)
110 rc += " WindowMinimized";
111 if (s & Qt::WindowMaximized)
112 rc += " WindowMaximized";
113 if (s & Qt::WindowFullScreen)
114 rc += " WindowFullScreen";
115 if (s & Qt::WindowActive)
116 rc += " WindowActive";
120 #ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO
121 QDebug operator<<(QDebug d, const MINMAXINFO &i)
123 d.nospace() << "MINMAXINFO maxSize=" << i.ptMaxSize.x << ','
124 << i.ptMaxSize.y << " maxpos=" << i.ptMaxPosition.x
125 << ',' << i.ptMaxPosition.y << " mintrack="
126 << i.ptMinTrackSize.x << ',' << i.ptMinTrackSize.y
127 << " maxtrack=" << i.ptMaxTrackSize.x << ','
128 << i.ptMaxTrackSize.y;
131 #endif // !Q_OS_WINCE
133 static inline QSize qSizeOfRect(const RECT &rect)
135 return QSize(rect.right -rect.left, rect.bottom - rect.top);
138 static inline QRect qrectFromRECT(const RECT &rect)
140 return QRect(QPoint(rect.left, rect.top), qSizeOfRect(rect));
143 static inline RECT RECTfromQRect(const QRect &rect)
145 const int x = rect.left();
146 const int y = rect.top();
147 RECT result = { x, y, x + rect.width(), y + rect.height() };
151 QDebug operator<<(QDebug d, const RECT &r)
153 d.nospace() << "RECT: left/top=" << r.left << ',' << r.top
154 << " right/bottom=" << r.right << ',' << r.bottom;
158 #ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_NCCALCSIZE
159 QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p)
161 qDebug().nospace() << "NCCALCSIZE_PARAMS "
162 << qrectFromRECT(p.rgrc[0])
163 << ' ' << qrectFromRECT(p.rgrc[1]) << ' '
164 << qrectFromRECT(p.rgrc[2]);
167 #endif // !Q_OS_WINCE
169 // Return the frame geometry relative to the parent
171 static inline QRect frameGeometry(HWND hwnd, bool topLevel)
173 RECT rect = { 0, 0, 0, 0 };
174 GetWindowRect(hwnd, &rect); // Screen coordinates.
175 const HWND parent = GetParent(hwnd);
176 if (parent && !topLevel) {
177 const int width = rect.right - rect.left;
178 const int height = rect.bottom - rect.top;
179 POINT leftTop = { rect.left, rect.top };
180 ScreenToClient(parent, &leftTop);
181 rect.left = leftTop.x;
182 rect.top = leftTop.y;
183 rect.right = leftTop.x + width;
184 rect.bottom = leftTop.y + height;
186 return qrectFromRECT(rect);
189 static inline QSize clientSize(HWND hwnd)
191 RECT rect = { 0, 0, 0, 0 };
192 GetClientRect(hwnd, &rect); // Always returns point 0,0, thus unusable for geometry.
193 return qSizeOfRect(rect);
196 // from qwidget_win.cpp/maximum layout size check removed.
197 static bool shouldShowMaximizeButton(Qt::WindowFlags flags)
199 if (flags & Qt::MSWindowsFixedSizeDialogHint)
201 // if the user explicitly asked for the maximize button, we try to add
202 // it even if the window has fixed size.
203 if (flags & Qt::CustomizeWindowHint &&
204 flags & Qt::WindowMaximizeButtonHint)
206 return flags & Qt::WindowMaximizeButtonHint;
209 static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, qreal level)
211 #ifdef Q_OS_WINCE // maybe needs revisit WS_EX_LAYERED
216 const long wl = GetWindowLong(hwnd, GWL_EXSTYLE);
217 const bool isOpaque = level == 1.0 && !(flags & Qt::WindowTransparentForInput);
220 if (wl & WS_EX_LAYERED)
221 SetWindowLong(hwnd, GWL_EXSTYLE, wl & ~WS_EX_LAYERED);
223 if ((wl & WS_EX_LAYERED) == 0)
224 SetWindowLong(hwnd, GWL_EXSTYLE, wl | WS_EX_LAYERED);
225 if (flags & Qt::FramelessWindowHint) {
226 BLENDFUNCTION blend = {AC_SRC_OVER, 0, (int)(255.0 * level), AC_SRC_ALPHA};
227 QWindowsContext::user32dll.updateLayeredWindow(hwnd, NULL, NULL, NULL, NULL, NULL, 0, &blend, ULW_ALPHA);
229 QWindowsContext::user32dll.setLayeredWindowAttributes(hwnd, 0, (int)(level * 255), LWA_ALPHA);
232 #endif // !Q_OS_WINCE
236 \class WindowCreationData
237 \brief Window creation code.
239 This struct gathers all information required to create a window.
240 Window creation is split in 3 steps:
243 \li fromWindow() Gather all required information
244 \li create() Create the system handle.
245 \li initialize() Post creation initialization steps.
248 The reason for this split is to also enable changing the QWindowFlags
252 \li fromWindow() Gather information and determine new system styles
253 \li applyWindowFlags() to apply the new window system styles.
254 \li initialize() Post creation initialization steps.
257 Contains the window creation code formerly in qwidget_win.cpp.
259 \sa QWindowCreationContext
261 \ingroup qt-lighthouse-win
264 struct WindowCreationData
266 typedef QWindowsWindow::WindowData WindowData;
267 enum Flags { ForceChild = 0x1 };
269 WindowCreationData() : parentHandle(0), type(Qt::Widget), style(0), exStyle(0),
270 topLevel(false), popup(false), dialog(false), desktop(false),
271 tool(false), embedded(false) {}
273 void fromWindow(const QWindow *w, const Qt::WindowFlags flags, unsigned creationFlags = 0);
274 inline WindowData create(const QWindow *w, const QRect &geometry, QString title) const;
275 inline void applyWindowFlags(HWND hwnd) const;
276 void initialize(HWND h, bool frameChange, qreal opacityLevel) const;
278 Qt::WindowFlags flags;
292 QDebug operator<<(QDebug debug, const WindowCreationData &d)
294 debug.nospace() << QWindowsWindow::debugWindowFlags(d.flags)
295 << " GL=" << d.isGL << " topLevel=" << d.topLevel << " popup="
296 << d.popup << " dialog=" << d.dialog << " desktop=" << d.desktop
297 << " embedded=" << d.embedded
298 << " tool=" << d.tool << " style=" << debugWinStyle(d.style)
299 << " exStyle=" << debugWinExStyle(d.exStyle)
300 << " parent=" << d.parentHandle;
304 void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flagsIn,
305 unsigned creationFlags)
307 isGL = w->surfaceType() == QWindow::OpenGLSurface;
310 // Sometimes QWindow doesn't have a QWindow parent but does have a native parent window,
311 // e.g. in case of embedded ActiveQt servers. They should not be considered a top-level
312 // windows in such cases.
313 QVariant prop = w->property("_q_embedded_native_parent_handle");
314 if (prop.isValid()) {
316 parentHandle = (HWND)prop.value<WId>();
319 topLevel = ((creationFlags & ForceChild) || embedded) ? false : w->isTopLevel();
321 if (topLevel && flags == 1) {
322 qWarning("Remove me: fixing toplevel window flags");
323 flags |= Qt::WindowTitleHint|Qt::WindowSystemMenuHint|Qt::WindowMinimizeButtonHint
324 |Qt::WindowMaximizeButtonHint|Qt::WindowCloseButtonHint;
327 type = static_cast<Qt::WindowType>(int(flags) & Qt::WindowType_Mask);
346 if ((flags & Qt::MSWindowsFixedSizeDialogHint))
349 // Parent: Use transient parent for top levels.
351 flags |= Qt::WindowStaysOnTopHint; // a popup stays on top, no parent.
352 } else if (!embedded) {
353 if (const QWindow *parentWindow = topLevel ? w->transientParent() : w->parent())
354 parentHandle = QWindowsWindow::handleOf(parentWindow);
357 if (popup || (type == Qt::ToolTip) || (type == Qt::SplashScreen)) {
359 } else if (topLevel && !desktop) {
360 if (flags & Qt::FramelessWindowHint)
361 style = WS_POPUP; // no border
362 else if (flags & Qt::WindowTitleHint)
363 style = WS_OVERLAPPED;
371 // if (!testAttribute(Qt::WA_PaintUnclipped))
372 // ### Commented out for now as it causes some problems, but
373 // this should be correct anyway, so dig some more into this
374 #ifdef Q_FLATTEN_EXPOSE
376 style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN; // see SetPixelFormat
378 style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN ;
381 if ((type == Qt::Window || dialog || tool)) {
382 if (!(flags & Qt::FramelessWindowHint)) {
384 if (flags & Qt::MSWindowsFixedSizeDialogHint) {
385 style |= WS_DLGFRAME;
387 style |= WS_THICKFRAME;
389 if (flags & Qt::WindowTitleHint)
390 style |= WS_CAPTION; // Contains WS_DLGFRAME
392 if (flags & Qt::WindowSystemMenuHint)
394 if (flags & Qt::WindowMinimizeButtonHint)
395 style |= WS_MINIMIZEBOX;
396 if (shouldShowMaximizeButton(flags))
397 style |= WS_MAXIMIZEBOX;
399 exStyle |= WS_EX_TOOLWINDOW;
400 if (flags & Qt::WindowContextHelpButtonHint)
401 exStyle |= WS_EX_CONTEXTHELP;
403 exStyle |= WS_EX_TOOLWINDOW;
407 // make mouse events fall through this window
408 // NOTE: WS_EX_TRANSPARENT flag can make mouse inputs fall through a layered window
409 if (flagsIn & Qt::WindowTransparentForInput)
410 exStyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT;
416 QWindowsWindow::WindowData
417 WindowCreationData::create(const QWindow *w, const QRect &geometry, QString title) const
419 typedef QSharedPointer<QWindowCreationContext> QWindowCreationContextPtr;
422 result.flags = flags;
424 if (desktop) { // desktop widget. No frame, hopefully?
425 result.hwnd = GetDesktopWindow();
426 result.geometry = frameGeometry(result.hwnd, true);
427 if (QWindowsContext::verboseWindows)
428 qDebug().nospace() << "Created desktop window " << w << result.hwnd;
432 const HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0);
434 const QString windowClassName = QWindowsContext::instance()->registerWindowClass(w, isGL);
436 if (title.isEmpty() && (result.flags & Qt::WindowTitleHint))
437 title = topLevel ? qAppName() : w->objectName();
439 const wchar_t *titleUtf16 = reinterpret_cast<const wchar_t *>(title.utf16());
440 const wchar_t *classNameUtf16 = reinterpret_cast<const wchar_t *>(windowClassName.utf16());
442 // Capture events before CreateWindowEx() returns.
443 const QWindowCreationContextPtr context(new QWindowCreationContext(w, geometry, style, exStyle));
444 QWindowsContext::instance()->setWindowCreationContext(context);
446 if (QWindowsContext::verboseWindows)
448 << "CreateWindowEx: " << w << *this
449 << " class=" <<windowClassName << " title=" << title
450 << "\nrequested: " << geometry << ": "
451 << context->frameWidth << 'x' << context->frameHeight
452 << '+' << context->frameX << '+' << context->frameY;
454 result.hwnd = CreateWindowEx(exStyle, classNameUtf16, titleUtf16,
456 context->frameX, context->frameY,
457 context->frameWidth, context->frameHeight,
458 parentHandle, NULL, appinst, NULL);
459 QWindowsContext::instance()->setWindowCreationContext(QWindowCreationContextPtr());
460 if (QWindowsContext::verboseWindows)
462 << "CreateWindowEx: returns " << w << ' ' << result.hwnd << " obtained geometry: "
463 << context->obtainedGeometry << context->margins;
466 qErrnoWarning("%s: CreateWindowEx failed", __FUNCTION__);
470 result.geometry = context->obtainedGeometry;
471 result.frame = context->margins;
472 result.embedded = embedded;
476 void WindowCreationData::applyWindowFlags(HWND hwnd) const
478 // Keep enabled and visible from the current style.
479 const LONG_PTR oldStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
480 const LONG_PTR oldExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
482 const LONG_PTR newStyle = style | (oldStyle & (WS_DISABLED|WS_VISIBLE));
483 if (oldStyle != newStyle)
484 SetWindowLongPtr(hwnd, GWL_STYLE, newStyle);
485 const LONG_PTR newExStyle = exStyle;
486 if (newExStyle != oldExStyle)
487 SetWindowLongPtr(hwnd, GWL_EXSTYLE, newExStyle);
488 if (QWindowsContext::verboseWindows)
489 qDebug().nospace() << __FUNCTION__ << hwnd << *this
490 << "\n Style from " << debugWinStyle(oldStyle) << "\n to "
491 << debugWinStyle(newStyle) << "\n ExStyle from "
492 << debugWinExStyle(oldExStyle) << " to "
493 << debugWinExStyle(newExStyle);
496 void WindowCreationData::initialize(HWND hwnd, bool frameChange, qreal opacityLevel) const
498 if (desktop || !hwnd)
500 UINT swpFlags = SWP_NOMOVE | SWP_NOSIZE;
502 swpFlags |= SWP_FRAMECHANGED;
504 swpFlags |= SWP_NOACTIVATE;
505 if ((flags & Qt::WindowStaysOnTopHint) || (type == Qt::ToolTip)) {
506 SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, swpFlags);
507 if (flags & Qt::WindowStaysOnBottomHint)
508 qWarning() << "QWidget: Incompatible window flags: the window can't be on top and on bottom at the same time";
509 } else if (flags & Qt::WindowStaysOnBottomHint) {
510 SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, swpFlags);
512 if (flags & (Qt::CustomizeWindowHint|Qt::WindowTitleHint)) {
513 HMENU systemMenu = GetSystemMenu(hwnd, FALSE);
514 if (flags & Qt::WindowCloseButtonHint)
515 EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_ENABLED);
517 EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED);
520 setWindowOpacity(hwnd, flags, opacityLevel);
522 SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, swpFlags);
527 \class QWindowsGeometryHint
528 \brief Stores geometry constraints and provides utility functions.
530 Geometry constraints ready to apply to a MINMAXINFO taking frame
534 \ingroup qt-lighthouse-win
537 #define QWINDOWSIZE_MAX ((1<<24)-1)
539 QWindowsGeometryHint::QWindowsGeometryHint(const QWindow *w) :
540 minimumSize(w->minimumSize()),
541 maximumSize(w->maximumSize())
545 bool QWindowsGeometryHint::validSize(const QSize &s) const
547 const int width = s.width();
548 const int height = s.height();
549 return width >= minimumSize.width() && width <= maximumSize.width()
550 && height >= minimumSize.height() && height <= maximumSize.height();
553 QMargins QWindowsGeometryHint::frame(DWORD style, DWORD exStyle)
555 RECT rect = {0,0,0,0};
556 style &= ~(WS_OVERLAPPED); // Not permitted, see docs.
557 if (!AdjustWindowRectEx(&rect, style, FALSE, exStyle))
558 qErrnoWarning("%s: AdjustWindowRectEx failed", __FUNCTION__);
559 const QMargins result(qAbs(rect.left), qAbs(rect.top),
560 qAbs(rect.right), qAbs(rect.bottom));
561 if (QWindowsContext::verboseWindows)
562 qDebug().nospace() << __FUNCTION__ << " style= 0x"
563 << QString::number(style, 16)
564 << " exStyle=0x" << QString::number(exStyle, 16) << ' ' << rect << ' ' << result;
570 void QWindowsGeometryHint::applyToMinMaxInfo(HWND hwnd, MINMAXINFO *mmi) const
572 return applyToMinMaxInfo(GetWindowLong(hwnd, GWL_STYLE),
573 GetWindowLong(hwnd, GWL_EXSTYLE), mmi);
576 void QWindowsGeometryHint::applyToMinMaxInfo(DWORD style, DWORD exStyle, MINMAXINFO *mmi) const
578 if (QWindowsContext::verboseWindows)
579 qDebug().nospace() << '>' << __FUNCTION__ << '<' << " min="
580 << minimumSize.width() << ',' << minimumSize.height()
581 << " max=" << maximumSize.width() << ',' << maximumSize.height()
584 const QMargins margins = QWindowsGeometryHint::frame(style, exStyle);
585 const int frameWidth = margins.left() + margins.right();
586 const int frameHeight = margins.top() + margins.bottom();
587 if (minimumSize.width() > 0)
588 mmi->ptMinTrackSize.x = minimumSize.width() + frameWidth;
589 if (minimumSize.height() > 0)
590 mmi->ptMinTrackSize.y = minimumSize.height() + frameHeight;
592 const int maximumWidth = qMax(maximumSize.width(), minimumSize.width());
593 const int maximumHeight = qMax(maximumSize.height(), minimumSize.height());
594 if (maximumWidth < QWINDOWSIZE_MAX)
595 mmi->ptMaxTrackSize.x = maximumWidth + frameWidth;
596 // windows with title bar have an implicit size limit of 112 pixels
597 if (maximumHeight < QWINDOWSIZE_MAX)
598 mmi->ptMaxTrackSize.y = qMax(maximumHeight + frameHeight, 112);
599 if (QWindowsContext::verboseWindows)
600 qDebug().nospace() << '<' << __FUNCTION__
601 << " frame=" << margins << ' ' << frameWidth << ',' << frameHeight
604 #endif // !Q_OS_WINCE
606 bool QWindowsGeometryHint::positionIncludesFrame(const QWindow *w)
608 return qt_window_private(const_cast<QWindow *>(w))->positionPolicy
609 == QWindowPrivate::WindowFrameInclusive;
613 \class QWindowCreationContext
614 \brief Active Context for creating windows.
616 There is a phase in window creation (WindowCreationData::create())
617 in which events are sent before the system API CreateWindowEx() returns
618 the handle. These cannot be handled by the platform window as the association
619 of the unknown handle value to the window does not exist yet and as not
620 to trigger recursive handle creation, etc.
622 In that phase, an instance of QWindowCreationContext is set on
625 QWindowCreationContext stores the information to answer the initial
626 WM_GETMINMAXINFO and obtains the corrected size/position.
628 \sa WindowCreationData, QWindowsContext
630 \ingroup qt-lighthouse-win
633 QWindowCreationContext::QWindowCreationContext(const QWindow *w,
634 const QRect &geometry,
635 DWORD style_, DWORD exStyle_) :
636 geometryHint(w), style(style_), exStyle(exStyle_),
637 requestedGeometry(geometry), obtainedGeometry(geometry),
638 margins(QWindowsGeometryHint::frame(style, exStyle)),
639 frameX(CW_USEDEFAULT), frameY(CW_USEDEFAULT),
640 frameWidth(CW_USEDEFAULT), frameHeight(CW_USEDEFAULT)
642 // Geometry of toplevels does not consider window frames.
643 // TODO: No concept of WA_wasMoved yet that would indicate a
644 // CW_USEDEFAULT unless set. For now, assume that 0,0 means 'default'
646 if (geometry.isValid()) {
647 frameX = geometry.x();
648 frameY = geometry.y();
649 frameWidth = margins.left() + geometry.width() + margins.right();
650 frameHeight = margins.top() + geometry.height() + margins.bottom();
651 const bool isDefaultPosition = !frameX && !frameY && w->isTopLevel();
652 if (!QWindowsGeometryHint::positionIncludesFrame(w) && !isDefaultPosition) {
653 frameX -= margins.left();
654 frameY -= margins.top();
657 if (QWindowsContext::verboseWindows)
659 << __FUNCTION__ << ' ' << w << geometry
660 << " pos incl. frame" << QWindowsGeometryHint::positionIncludesFrame(w)
661 << " frame: " << frameWidth << 'x' << frameHeight << '+'
662 << frameX << '+' << frameY
663 << " min" << geometryHint.minimumSize
664 << " max" << geometryHint.maximumSize;
668 \class QWindowsWindow
669 \brief Raster or OpenGL Window.
672 \li Raster type: handleWmPaint() is implemented to
673 to bitblt the image. The DC can be accessed
674 via getDC/Relase DC, which has a special handling
675 when within a paint event (in that case, the DC obtained
676 from BeginPaint() is returned).
678 \li Open GL: The first time QWindowsGLContext accesses
679 the handle, it sets up the pixelformat on the DC
680 which in turn sets it on the window (see flag
681 PixelFormatInitialized).
682 handleWmPaint() is empty (although required).
686 \ingroup qt-lighthouse-win
689 QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) :
690 QPlatformWindow(aWindow),
694 m_windowState(aWindow->windowState()),
697 m_cursor(QWindowsScreen::screenOf(aWindow)->windowsCursor()->standardWindowCursor()),
700 m_format(aWindow->format())
701 #ifdef QT_OPENGL_ES_2
705 if (aWindow->surfaceType() == QWindow::OpenGLSurface)
706 setFlag(OpenGLSurface);
707 QWindowsContext::instance()->addWindow(m_data.hwnd, this);
708 if (aWindow->isTopLevel()) {
709 switch (aWindow->windowType()) {
724 QWindowsWindow::~QWindowsWindow()
729 void QWindowsWindow::destroyWindow()
731 if (QWindowsContext::verboseIntegration || QWindowsContext::verboseWindows)
732 qDebug() << __FUNCTION__ << this << window() << m_data.hwnd;
733 if (m_data.hwnd) { // Stop event dispatching before Window is destroyed.
734 unregisterDropSite();
735 QWindowsContext::instance()->removeWindow(m_data.hwnd);
736 #ifdef QT_OPENGL_ES_2
738 if (QWindowsContext::verboseGL)
739 qDebug("%s: Freeing EGL surface %p, this = %p",
740 __FUNCTION__, m_eglSurface, this);
741 eglDestroySurface(m_staticEglContext->display(), m_eglSurface);
745 if (m_data.hwnd != GetDesktopWindow())
746 DestroyWindow(m_data.hwnd);
751 void QWindowsWindow::registerDropSite()
753 if (m_data.hwnd && !m_dropTarget) {
754 m_dropTarget = new QWindowsOleDropTarget(window());
755 RegisterDragDrop(m_data.hwnd, m_dropTarget);
756 CoLockObjectExternal(m_dropTarget, true, true);
760 void QWindowsWindow::unregisterDropSite()
762 if (m_data.hwnd && m_dropTarget) {
763 m_dropTarget->Release();
764 CoLockObjectExternal(m_dropTarget, false, true);
765 RevokeDragDrop(m_data.hwnd);
770 QWindow *QWindowsWindow::topLevelOf(QWindow *w)
772 while (QWindow *parent = w->parent())
777 QWindowsWindow::WindowData
778 QWindowsWindow::WindowData::create(const QWindow *w,
779 const WindowData ¶meters,
780 const QString &title)
782 WindowCreationData creationData;
783 creationData.fromWindow(w, parameters.flags);
784 WindowData result = creationData.create(w, parameters.geometry, title);
785 creationData.initialize(result.hwnd, false, 1);
789 void QWindowsWindow::setVisible(bool visible)
791 if (QWindowsContext::verboseWindows)
792 qDebug() << __FUNCTION__ << this << window() << m_data.hwnd << visible;
796 QWindowSystemInterface::handleSynchronousExposeEvent(window(),
797 QRect(QPoint(), geometry().size()));
800 QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRegion());
805 bool QWindowsWindow::isVisible() const
807 return m_data.hwnd && IsWindowVisible(m_data.hwnd);
810 bool QWindowsWindow::isActive() const
812 // Check for native windows or children of the active native window.
813 if (const HWND activeHwnd = GetActiveWindow())
814 if (m_data.hwnd == activeHwnd || IsChild(activeHwnd, m_data.hwnd))
819 // partially from QWidgetPrivate::show_sys()
820 void QWindowsWindow::show_sys() const
822 int sm = SW_SHOWNORMAL;
823 bool fakedMaximize = false;
824 const QWindow *w = window();
825 const Qt::WindowFlags flags = w->windowFlags();
826 const Qt::WindowType type = w->windowType();
827 if (w->isTopLevel()) {
828 const Qt::WindowState state = w->windowState();
829 if (state & Qt::WindowMinimized) {
830 sm = SW_SHOWMINIMIZED;
832 sm = SW_SHOWMINNOACTIVE;
833 } else if (state & Qt::WindowMaximized) {
834 sm = SW_SHOWMAXIMIZED;
835 // Windows will not behave correctly when we try to maximize a window which does not
836 // have minimize nor maximize buttons in the window frame. Windows would then ignore
837 // non-available geometry, and rather maximize the widget to the full screen, minus the
838 // window frame (caption). So, we do a trick here, by adding a maximize button before
839 // maximizing the widget, and then remove the maximize button afterwards.
840 if (flags & Qt::WindowTitleHint &&
841 !(flags & (Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint))) {
842 fakedMaximize = TRUE;
843 setStyle(style() | WS_MAXIMIZEBOX);
847 if (type == Qt::Popup || type == Qt::ToolTip || type == Qt::Tool)
848 sm = SW_SHOWNOACTIVATE;
850 ShowWindow(m_data.hwnd, sm);
853 setStyle(style() & ~WS_MAXIMIZEBOX);
854 SetWindowPos(m_data.hwnd, 0, 0, 0, 0, 0,
855 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER
860 // partially from QWidgetPrivate::hide_sys()
861 void QWindowsWindow::hide_sys() const
863 const Qt::WindowFlags flags = window()->windowFlags();
864 if (flags != Qt::Desktop) {
865 if (flags & Qt::Popup)
866 ShowWindow(m_data.hwnd, SW_HIDE);
868 SetWindowPos(m_data.hwnd,0, 0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
872 void QWindowsWindow::setParent(const QPlatformWindow *newParent)
874 if (QWindowsContext::verboseWindows)
875 qDebug() << __FUNCTION__ << window() << newParent;
877 if (newParent != parent() && m_data.hwnd)
878 setParent_sys(newParent);
881 void QWindowsWindow::setParent_sys(const QPlatformWindow *parent) const
885 const QWindowsWindow *parentW = static_cast<const QWindowsWindow *>(parent);
886 parentHWND = parentW->handle();
890 const bool wasTopLevel = window()->isTopLevel();
891 const bool isTopLevel = parentHWND == 0;
893 setFlag(WithinSetParent);
894 SetParent(m_data.hwnd, parentHWND);
895 clearFlag(WithinSetParent);
897 // WS_CHILD/WS_POPUP must be manually set/cleared in addition
898 // to dialog frames, etc (see SetParent() ) if the top level state changes.
899 if (wasTopLevel != isTopLevel) {
900 const unsigned flags = isTopLevel ? unsigned(0) : unsigned(WindowCreationData::ForceChild);
901 setWindowFlags_sys(window()->windowFlags(), flags);
905 void QWindowsWindow::handleShown()
907 QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size()));
910 void QWindowsWindow::handleHidden()
912 QWindowSystemInterface::handleExposeEvent(window(), QRegion());
915 void QWindowsWindow::setGeometry(const QRect &rectIn)
918 // This means it is a call from QWindow::setFramePos() and
919 // the coordinates include the frame (size is still the contents rectangle).
920 if (QWindowsGeometryHint::positionIncludesFrame(window())) {
921 const QMargins margins = frameMargins();
922 rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top()));
924 const QSize oldSize = m_data.geometry.size();
925 m_data.geometry = rect;
926 const QSize newSize = rect.size();
928 if (newSize != oldSize) {
929 const QWindowsGeometryHint hint(window());
930 if (!hint.validSize(newSize)) {
931 qWarning("%s: Attempt to set a size (%dx%d) violating the constraints"
932 "(%dx%d - %dx%d) on window '%s'.", __FUNCTION__,
933 newSize.width(), newSize.height(),
934 hint.minimumSize.width(), hint.minimumSize.height(),
935 hint.maximumSize.width(), hint.maximumSize.height(),
936 qPrintable(window()->objectName()));
940 // A ResizeEvent with resulting geometry will be sent. If we cannot
941 // achieve that size (for example, window title minimal constraint),
943 setGeometry_sys(rect);
944 if (m_data.geometry != rect) {
945 qWarning("%s: Unable to set geometry %dx%d+%d+%d on '%s'."
946 " Resulting geometry: %dx%d+%d+%d "
947 "(frame: %d, %d, %d, %d).",
949 rect.width(), rect.height(), rect.x(), rect.y(),
950 qPrintable(window()->objectName()),
951 m_data.geometry.width(), m_data.geometry.height(),
952 m_data.geometry.x(), m_data.geometry.y(),
953 m_data.frame.left(), m_data.frame.top(),
954 m_data.frame.right(), m_data.frame.bottom());
957 QPlatformWindow::setGeometry(rect);
961 void QWindowsWindow::handleMoved()
963 // Minimize/Set parent can send nonsensical move events.
964 if (!IsIconic(m_data.hwnd) && !testFlag(WithinSetParent))
965 handleGeometryChange();
968 void QWindowsWindow::handleResized(int wParam)
971 case SIZE_MAXHIDE: // Some other window affected.
975 handleWindowStateChange(Qt::WindowMinimized);
978 handleWindowStateChange(Qt::WindowMaximized);
979 handleGeometryChange();
982 if (m_windowState != Qt::WindowNoState)
983 handleWindowStateChange(isFullScreen_sys() ? Qt::WindowFullScreen : Qt::WindowNoState);
984 handleGeometryChange();
989 void QWindowsWindow::handleGeometryChange()
991 m_data.geometry = geometry_sys();
992 QPlatformWindow::setGeometry(m_data.geometry);
993 QWindowSystemInterface::handleGeometryChange(window(), m_data.geometry);
995 if (QWindowsContext::verboseEvents || QWindowsContext::verboseWindows)
996 qDebug() << __FUNCTION__ << this << window() << m_data.geometry;
999 void QWindowsWindow::setGeometry_sys(const QRect &rect) const
1001 const QMargins margins = frameMargins();
1002 const QRect frameGeometry = rect + margins;
1004 if (QWindowsContext::verboseWindows)
1005 qDebug() << '>' << __FUNCTION__ << this << window()
1006 << " \n from " << geometry_sys() << " frame: "
1007 << margins << " to " <<rect
1008 << " new frame: " << frameGeometry;
1010 const bool rc = MoveWindow(m_data.hwnd, frameGeometry.x(), frameGeometry.y(),
1011 frameGeometry.width(), frameGeometry.height(), true);
1012 if (QWindowsContext::verboseWindows)
1013 qDebug() << '<' << __FUNCTION__ << this << window()
1014 << " \n resulting " << rc << geometry_sys();
1017 QRect QWindowsWindow::frameGeometry_sys() const
1019 // Warning: Returns bogus values when minimized.
1020 bool isRealTopLevel = window()->isTopLevel() && !m_data.embedded;
1021 return frameGeometry(m_data.hwnd, isRealTopLevel);
1024 QRect QWindowsWindow::geometry_sys() const
1026 return frameGeometry_sys() - frameMargins();
1030 Allocates a HDC for the window or returns the temporary one
1031 obtained from WinAPI BeginPaint within a WM_PAINT event.
1036 HDC QWindowsWindow::getDC()
1039 m_hdc = GetDC(handle());
1044 Relases the HDC for the window or does nothing in
1045 case it was obtained from WinAPI BeginPaint within a WM_PAINT event.
1050 void QWindowsWindow::releaseDC()
1052 if (m_hdc && !testFlag(DCFromBeginPaint)) {
1053 ReleaseDC(handle(), m_hdc);
1058 bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message,
1061 // Ignore invalid update bounding rectangles
1062 if (!GetUpdateRect(m_data.hwnd, 0, FALSE))
1064 if (message == WM_ERASEBKGND) // Backing store - ignored.
1067 if (testFlag(OpenGLSurface)) {
1068 // Observed painting problems with Aero style disabled (QTBUG-7865).
1069 if (testFlag(OpenGLDoubleBuffered))
1070 InvalidateRect(hwnd, 0, false);
1071 BeginPaint(hwnd, &ps);
1072 QWindowSystemInterface::handleSynchronousExposeEvent(window(),
1073 QRegion(qrectFromRECT(ps.rcPaint)));
1074 EndPaint(hwnd, &ps);
1076 const HDC dc = BeginPaint(hwnd, &ps);
1077 const QRect updateRect = qrectFromRECT(ps.rcPaint);
1078 if (updateRect.size() == m_data.geometry.size()) {
1079 // Store DC for access by the backing store if it has the full size.
1081 setFlag(DCFromBeginPaint);
1084 if (QWindowsContext::verboseIntegration)
1085 qDebug() << __FUNCTION__ << this << window() << updateRect;
1087 QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRegion(updateRect));
1088 if (testFlag(DCFromBeginPaint)) {
1089 clearFlag(DCFromBeginPaint);
1092 EndPaint(hwnd, &ps);
1097 void QWindowsWindow::setWindowTitle(const QString &title)
1099 if (QWindowsContext::verboseWindows)
1100 qDebug() << __FUNCTION__ << this << window() <<title;
1102 SetWindowText(m_data.hwnd, (const wchar_t*)title.utf16());
1105 Qt::WindowFlags QWindowsWindow::setWindowFlags(Qt::WindowFlags flags)
1107 if (QWindowsContext::verboseWindows)
1108 qDebug() << '>' << __FUNCTION__ << this << window() << "\n from: "
1109 << QWindowsWindow::debugWindowFlags(m_data.flags)
1110 << "\n to: " << QWindowsWindow::debugWindowFlags(flags);
1111 const QRect oldGeometry = geometry();
1112 if (m_data.flags != flags) {
1113 m_data.flags = flags;
1115 m_data = setWindowFlags_sys(flags);
1117 // When switching to a frameless window, geometry
1118 // may change without a WM_MOVE. Report change manually.
1119 // Do not send synchronously as not to clobber the widget
1120 // geometry in a sequence of setting flags and geometry.
1121 const QRect newGeometry = geometry_sys();
1122 if (oldGeometry != newGeometry)
1123 handleGeometryChange();
1125 if (QWindowsContext::verboseWindows)
1126 qDebug() << '<' << __FUNCTION__ << "\n returns: "
1127 << QWindowsWindow::debugWindowFlags(m_data.flags)
1128 << " geometry " << oldGeometry << "->" << newGeometry;
1129 return m_data.flags;
1132 QWindowsWindow::WindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt,
1133 unsigned flags) const
1135 WindowCreationData creationData;
1136 creationData.fromWindow(window(), wt, flags);
1137 creationData.applyWindowFlags(m_data.hwnd);
1138 creationData.initialize(m_data.hwnd, true, m_opacity);
1140 WindowData result = m_data;
1141 result.flags = creationData.flags;
1142 result.embedded = creationData.embedded;
1143 setFlag(FrameDirty);
1147 void QWindowsWindow::handleWindowStateChange(Qt::WindowState state)
1149 if (QWindowsContext::verboseWindows)
1150 qDebug() << __FUNCTION__ << this << window()
1151 << "\n from " << debugWindowStates(m_windowState)
1152 << " to " << debugWindowStates(state);
1153 setFlag(FrameDirty);
1154 m_windowState = state;
1155 QWindowSystemInterface::handleWindowStateChanged(window(), state);
1158 Qt::WindowState QWindowsWindow::setWindowState(Qt::WindowState state)
1161 setWindowState_sys(state);
1162 m_windowState = state;
1167 Qt::WindowState QWindowsWindow::windowState_sys() const
1169 if (IsIconic(m_data.hwnd))
1170 return Qt::WindowMinimized;
1171 if (IsZoomed(m_data.hwnd))
1172 return Qt::WindowMaximized;
1173 if (isFullScreen_sys())
1174 return Qt::WindowFullScreen;
1175 return Qt::WindowNoState;
1178 Qt::WindowStates QWindowsWindow::windowStates_sys() const
1180 Qt::WindowStates result = windowState_sys();
1181 if (GetActiveWindow() == m_data.hwnd)
1182 result |= Qt::WindowActive;
1186 bool QWindowsWindow::isFullScreen_sys() const
1188 return geometry_sys() == window()->screen()->geometry();
1192 \brief Change the window state.
1194 \note Window frames change when maximized;
1195 the top margin shrinks somewhat but that cannot be obtained using
1196 AdjustWindowRectEx().
1198 \note Some calls to SetWindowLong require a subsequent call
1202 void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
1204 const Qt::WindowStates oldStates = windowStates_sys();
1205 // Maintain the active flag as the platform window API does not
1207 Qt::WindowStates newStates = newState;
1208 if (oldStates & Qt::WindowActive)
1209 newStates |= Qt::WindowActive;
1210 if (oldStates == newStates)
1212 if (QWindowsContext::verboseWindows)
1213 qDebug() << '>' << __FUNCTION__ << this << window()
1214 << " from " << debugWindowStates(oldStates)
1215 << " to " << debugWindowStates(newStates);
1217 const bool isActive = newStates & Qt::WindowActive;
1218 const int max = isActive ? SW_SHOWMAXIMIZED : SW_MAXIMIZE;
1219 const int normal = isActive ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE;
1220 const int min = isActive ? SW_SHOWMINIMIZED : SW_MINIMIZE;
1221 const bool visible = isVisible();
1223 setFlag(FrameDirty);
1225 if ((oldStates & Qt::WindowMaximized) != (newStates & Qt::WindowMaximized)) {
1226 if (visible && !(newStates & Qt::WindowMinimized))
1227 ShowWindow(m_data.hwnd, (newStates & Qt::WindowMaximized) ? max : normal);
1230 if ((oldStates & Qt::WindowFullScreen) != (newStates & Qt::WindowFullScreen)) {
1231 if (newStates & Qt::WindowFullScreen) {
1232 #ifndef Q_FLATTEN_EXPOSE
1233 UINT newStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP;
1235 UINT newStyle = WS_POPUP;
1237 // Save geometry and style to be restored when fullscreen
1238 // is turned off again, since on Windows, it is not a real
1239 // Window state but emulated by changing geometry and style.
1240 m_savedStyle = style();
1241 m_savedFrameGeometry = frameGeometry_sys();
1242 if (m_savedStyle & WS_SYSMENU)
1243 newStyle |= WS_SYSMENU;
1245 newStyle |= WS_VISIBLE;
1248 const QRect r = window()->screen()->geometry();
1249 UINT swpf = SWP_FRAMECHANGED;
1250 if (newStates & Qt::WindowActive)
1251 swpf |= SWP_NOACTIVATE;
1252 SetWindowPos(m_data.hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf);
1253 QWindowSystemInterface::handleSynchronousGeometryChange(window(), r);
1255 // Restore saved state.
1256 unsigned newStyle = m_savedStyle ? m_savedStyle : style();
1258 newStyle |= WS_VISIBLE;
1261 UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER;
1262 if (newStates & Qt::WindowActive)
1263 swpf |= SWP_NOACTIVATE;
1264 if (!m_savedFrameGeometry.isValid())
1265 swpf |= SWP_NOSIZE | SWP_NOMOVE;
1266 SetWindowPos(m_data.hwnd, 0, m_savedFrameGeometry.x(), m_savedFrameGeometry.y(),
1267 m_savedFrameGeometry.width(), m_savedFrameGeometry.height(), swpf);
1268 // preserve maximized state
1270 ShowWindow(m_data.hwnd, (newStates & Qt::WindowMaximized) ? max : normal);
1272 m_savedFrameGeometry = QRect();
1276 if ((oldStates & Qt::WindowMinimized) != (newStates & Qt::WindowMinimized)) {
1278 ShowWindow(m_data.hwnd, (newStates & Qt::WindowMinimized) ? min :
1279 (newStates & Qt::WindowMaximized) ? max : normal);
1281 if (QWindowsContext::verboseWindows)
1282 qDebug() << '<' << __FUNCTION__ << this << window()
1283 << debugWindowStates(newStates);
1286 void QWindowsWindow::setStyle(unsigned s) const
1288 if (QWindowsContext::verboseWindows)
1289 qDebug() << __FUNCTION__ << this << window() << debugWinStyle(s);
1290 setFlag(FrameDirty);
1291 SetWindowLongPtr(m_data.hwnd, GWL_STYLE, s);
1294 void QWindowsWindow::setExStyle(unsigned s) const
1296 if (QWindowsContext::verboseWindows)
1297 qDebug().nospace() << __FUNCTION__ << ' ' << this << ' ' << window()
1298 << " 0x" << QByteArray::number(s, 16);
1299 setFlag(FrameDirty);
1300 SetWindowLongPtr(m_data.hwnd, GWL_EXSTYLE, s);
1303 void QWindowsWindow::raise()
1305 if (QWindowsContext::verboseWindows)
1306 qDebug() << __FUNCTION__ << this << window();
1307 SetWindowPos(m_data.hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1310 void QWindowsWindow::lower()
1312 if (QWindowsContext::verboseWindows)
1313 qDebug() << __FUNCTION__ << this << window();
1315 SetWindowPos(m_data.hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1318 void QWindowsWindow::windowEvent(QEvent *event)
1320 switch (event->type()) {
1321 case QEvent::WindowBlocked: // Blocked by another modal window.
1323 setFlag(BlockedByModal);
1325 case QEvent::WindowUnblocked:
1327 clearFlag(BlockedByModal);
1334 void QWindowsWindow::propagateSizeHints()
1336 if (QWindowsContext::verboseWindows)
1337 qDebug() << __FUNCTION__ << this << window();
1340 QMargins QWindowsWindow::frameMargins() const
1342 // Frames are invalidated by style changes (window state, flags).
1343 // As they are also required for geometry calculations in resize
1344 // event sequences, introduce a dirty flag mechanism to be able
1345 // to cache results.
1346 if (testFlag(FrameDirty)) {
1347 m_data.frame = QWindowsGeometryHint::frame(style(), exStyle());
1348 clearFlag(FrameDirty);
1350 return m_data.frame;
1353 void QWindowsWindow::setOpacity(qreal level)
1355 if (QWindowsContext::verboseWindows)
1356 qDebug() << __FUNCTION__ << level;
1357 if (m_opacity != level) {
1360 setWindowOpacity(m_data.hwnd, m_data.flags, level);
1364 static inline HRGN createRectRegion(const QRect &r)
1366 return CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height());
1369 static inline void addRectToWinRegion(const QRect &rect, HRGN *winRegion)
1371 if (const HRGN rectRegion = createRectRegion(rect)) {
1372 HRGN result = CreateRectRgn(0, 0, 0, 0);
1373 if (CombineRgn(result, *winRegion, rectRegion, RGN_OR)) {
1374 DeleteObject(winRegion);
1375 *winRegion = result;
1377 DeleteObject(rectRegion);
1381 static HRGN qRegionToWinRegion(const QRegion ®ion)
1383 const QVector<QRect> rects = region.rects();
1384 if (rects.isEmpty())
1386 const int rectCount = rects.size();
1388 return createRectRegion(region.boundingRect());
1389 HRGN hRegion = createRectRegion(rects.front());
1390 for (int i = 1; i < rectCount; ++i)
1391 addRectToWinRegion(rects.at(i), &hRegion);
1395 void QWindowsWindow::setMask(const QRegion ®ion)
1397 if (region.isEmpty()) {
1398 SetWindowRgn(m_data.hwnd, 0, true);
1401 const HRGN winRegion = qRegionToWinRegion(region);
1403 // Mask is in client area coordinates, so offset it in case we have a frame
1404 if (window()->isTopLevel()) {
1405 const QMargins margins = frameMargins();
1406 OffsetRgn(winRegion, margins.left(), margins.top());
1409 // SetWindowRgn takes ownership.
1410 if (!SetWindowRgn(m_data.hwnd, winRegion, true))
1411 DeleteObject(winRegion);
1414 void QWindowsWindow::requestActivateWindow()
1416 if (QWindowsContext::verboseWindows)
1417 qDebug() << __FUNCTION__ << this << window();
1418 // 'Active' state handling is based in focus since it needs to work for
1419 // child windows as well.
1421 SetForegroundWindow(m_data.hwnd);
1422 SetFocus(m_data.hwnd);
1426 bool QWindowsWindow::setKeyboardGrabEnabled(bool grab)
1429 qWarning("%s: No handle", __FUNCTION__);
1432 if (QWindowsContext::verboseWindows)
1433 qDebug() << __FUNCTION__ << this << window() << grab;
1435 QWindowsContext *context = QWindowsContext::instance();
1437 context->setKeyGrabber(window());
1439 if (context->keyGrabber() == window())
1440 context->setKeyGrabber(0);
1445 bool QWindowsWindow::setMouseGrabEnabled(bool grab)
1447 bool result = false;
1449 qWarning("%s: No handle", __FUNCTION__);
1452 if (QWindowsContext::verboseWindows)
1453 qDebug() << __FUNCTION__ << window() << grab;
1455 if (m_mouseGrab != grab) {
1458 setMouseGrabEnabled_sys(grab);
1463 void QWindowsWindow::setMouseGrabEnabled_sys(bool grab)
1466 SetCapture(m_data.hwnd);
1472 static inline DWORD cornerToWinOrientation(Qt::Corner corner)
1475 case Qt::TopLeftCorner:
1476 return 0xf004; // SZ_SIZETOPLEFT;
1477 case Qt::TopRightCorner:
1478 return 0xf005; // SZ_SIZETOPRIGHT
1479 case Qt::BottomLeftCorner:
1480 return 0xf007; // SZ_SIZEBOTTOMLEFT
1481 case Qt::BottomRightCorner:
1482 return 0xf008; // SZ_SIZEBOTTOMRIGHT
1487 bool QWindowsWindow::startSystemResize(const QPoint &, Qt::Corner corner)
1489 if (!GetSystemMenu(m_data.hwnd, FALSE))
1493 PostMessage(m_data.hwnd, WM_SYSCOMMAND, cornerToWinOrientation(corner), 0);
1494 setFlag(SizeGripOperation);
1498 void QWindowsWindow::setFrameStrutEventsEnabled(bool enabled)
1501 setFlag(FrameStrutEventsEnabled);
1503 clearFlag(FrameStrutEventsEnabled);
1507 #ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO
1508 void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
1510 const QWindowsGeometryHint hint(window());
1511 hint.applyToMinMaxInfo(m_data.hwnd, mmi);
1512 if (QWindowsContext::verboseWindows)
1513 qDebug() << __FUNCTION__ << window() << *mmi;
1515 #endif // !Q_OS_WINCE
1518 \brief Applies to cursor property set on the window to the global cursor.
1523 void QWindowsWindow::applyCursor()
1525 SetCursor(m_cursor.handle());
1528 void QWindowsWindow::setCursor(const QWindowsWindowCursor &c)
1530 if (c.handle() != m_cursor.handle()) {
1531 const bool underMouse = QWindowsContext::instance()->windowUnderMouse() == window();
1532 if (QWindowsContext::verboseWindows)
1533 qDebug() << window() << __FUNCTION__ << "Shape=" << c.cursor().shape()
1534 << " isWUM=" << underMouse;
1542 \brief Find a child window using flags from ChildWindowFromPointEx.
1545 QWindowsWindow *QWindowsWindow::childAtScreenPoint(const QPoint &screenPoint,
1546 unsigned cwexflags) const
1549 return QWindowsContext::instance()->findPlatformWindowAt(m_data.hwnd, screenPoint, cwexflags);
1553 QWindowsWindow *QWindowsWindow::childAt(const QPoint &clientPoint, unsigned cwexflags) const
1556 return childAtScreenPoint(QWindowsGeometryHint::mapToGlobal(m_data.hwnd, clientPoint),
1562 void QWindowsWindow::alertWindow(int durationMs)
1564 DWORD timeOutMs = GetCaretBlinkTime();
1565 if (!timeOutMs || timeOutMs == INFINITE)
1569 info.cbSize = sizeof(info);
1570 info.hwnd = m_data.hwnd;
1571 info.dwFlags = FLASHW_TRAY;
1572 info.dwTimeout = timeOutMs;
1573 info.uCount = durationMs == 0 ? 10 : durationMs / timeOutMs;
1574 FlashWindowEx(&info);
1577 void QWindowsWindow::stopAlertWindow()
1580 info.cbSize = sizeof(info);
1581 info.hwnd = m_data.hwnd;
1582 info.dwFlags = FLASHW_STOP;
1585 FlashWindowEx(&info);
1587 #endif // !Q_OS_WINCE
1589 bool QWindowsWindow::isEnabled() const
1591 return (style() & WS_DISABLED) == 0;
1594 void QWindowsWindow::setEnabled(bool enabled)
1596 const unsigned oldStyle = style();
1597 unsigned newStyle = oldStyle;
1599 newStyle &= ~WS_DISABLED;
1601 newStyle |= WS_DISABLED;
1603 if (newStyle != oldStyle)
1607 #ifdef QT_OPENGL_ES_2
1608 EGLSurface QWindowsWindow::ensureEglSurfaceHandle(const QWindowsWindow::QWindowsEGLStaticContextPtr &staticContext, EGLConfig config)
1610 if (!m_eglSurface) {
1611 m_staticEglContext = staticContext;
1612 m_eglSurface = eglCreateWindowSurface(staticContext->display(), config, (EGLNativeWindowType)m_data.hwnd, NULL);
1613 if (m_eglSurface == EGL_NO_SURFACE)
1614 qWarning("%s: Could not create the egl surface (eglCreateWindowSurface failed): error = 0x%x\n",
1615 Q_FUNC_INFO, eglGetError());
1616 if (QWindowsContext::verboseGL)
1617 qDebug("%s: Created EGL surface %p, this = %p",
1618 __FUNCTION__, m_eglSurface, this);
1620 return m_eglSurface;
1622 #endif // QT_OPENGL_ES_2
1624 QByteArray QWindowsWindow::debugWindowFlags(Qt::WindowFlags wf)
1626 const int iwf = int(wf);
1627 QByteArray rc = "0x";
1628 rc += QByteArray::number(iwf, 16);
1631 switch ((iwf & Qt::WindowType_Mask)) {
1653 case Qt::SplashScreen:
1654 rc += " SplashScreen";
1663 if (iwf & Qt::MSWindowsFixedSizeDialogHint) rc += " MSWindowsFixedSizeDialogHint";
1664 if (iwf & Qt::MSWindowsOwnDC) rc += " MSWindowsOwnDC";
1665 if (iwf & Qt::FramelessWindowHint) rc += " FramelessWindowHint";
1666 if (iwf & Qt::WindowTitleHint) rc += " WindowTitleHint";
1667 if (iwf & Qt::WindowSystemMenuHint) rc += " WindowSystemMenuHint";
1668 if (iwf & Qt::WindowMinimizeButtonHint) rc += " WindowMinimizeButtonHint";
1669 if (iwf & Qt::WindowMaximizeButtonHint) rc += " WindowMaximizeButtonHint";
1670 if (iwf & Qt::WindowContextHelpButtonHint) rc += " WindowContextHelpButtonHint";
1671 if (iwf & Qt::WindowShadeButtonHint) rc += " WindowShadeButtonHint";
1672 if (iwf & Qt::WindowStaysOnTopHint) rc += " WindowStaysOnTopHint";
1673 if (iwf & Qt::CustomizeWindowHint) rc += " CustomizeWindowHint";
1674 if (iwf & Qt::WindowStaysOnBottomHint) rc += " WindowStaysOnBottomHint";
1675 if (iwf & Qt::WindowCloseButtonHint) rc += " WindowCloseButtonHint";