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};
557 style &= ~(WS_OVERLAPPED); // Not permitted, see docs.
559 if (!AdjustWindowRectEx(&rect, style, FALSE, exStyle))
560 qErrnoWarning("%s: AdjustWindowRectEx failed", __FUNCTION__);
561 const QMargins result(qAbs(rect.left), qAbs(rect.top),
562 qAbs(rect.right), qAbs(rect.bottom));
563 if (QWindowsContext::verboseWindows)
564 qDebug().nospace() << __FUNCTION__ << " style= 0x"
565 << QString::number(style, 16)
566 << " exStyle=0x" << QString::number(exStyle, 16) << ' ' << rect << ' ' << result;
572 void QWindowsGeometryHint::applyToMinMaxInfo(HWND hwnd, MINMAXINFO *mmi) const
574 return applyToMinMaxInfo(GetWindowLong(hwnd, GWL_STYLE),
575 GetWindowLong(hwnd, GWL_EXSTYLE), mmi);
578 void QWindowsGeometryHint::applyToMinMaxInfo(DWORD style, DWORD exStyle, MINMAXINFO *mmi) const
580 if (QWindowsContext::verboseWindows)
581 qDebug().nospace() << '>' << __FUNCTION__ << '<' << " min="
582 << minimumSize.width() << ',' << minimumSize.height()
583 << " max=" << maximumSize.width() << ',' << maximumSize.height()
586 const QMargins margins = QWindowsGeometryHint::frame(style, exStyle);
587 const int frameWidth = margins.left() + margins.right();
588 const int frameHeight = margins.top() + margins.bottom();
589 if (minimumSize.width() > 0)
590 mmi->ptMinTrackSize.x = minimumSize.width() + frameWidth;
591 if (minimumSize.height() > 0)
592 mmi->ptMinTrackSize.y = minimumSize.height() + frameHeight;
594 const int maximumWidth = qMax(maximumSize.width(), minimumSize.width());
595 const int maximumHeight = qMax(maximumSize.height(), minimumSize.height());
596 if (maximumWidth < QWINDOWSIZE_MAX)
597 mmi->ptMaxTrackSize.x = maximumWidth + frameWidth;
598 // windows with title bar have an implicit size limit of 112 pixels
599 if (maximumHeight < QWINDOWSIZE_MAX)
600 mmi->ptMaxTrackSize.y = qMax(maximumHeight + frameHeight, 112);
601 if (QWindowsContext::verboseWindows)
602 qDebug().nospace() << '<' << __FUNCTION__
603 << " frame=" << margins << ' ' << frameWidth << ',' << frameHeight
606 #endif // !Q_OS_WINCE
608 bool QWindowsGeometryHint::positionIncludesFrame(const QWindow *w)
610 return qt_window_private(const_cast<QWindow *>(w))->positionPolicy
611 == QWindowPrivate::WindowFrameInclusive;
615 \class QWindowCreationContext
616 \brief Active Context for creating windows.
618 There is a phase in window creation (WindowCreationData::create())
619 in which events are sent before the system API CreateWindowEx() returns
620 the handle. These cannot be handled by the platform window as the association
621 of the unknown handle value to the window does not exist yet and as not
622 to trigger recursive handle creation, etc.
624 In that phase, an instance of QWindowCreationContext is set on
627 QWindowCreationContext stores the information to answer the initial
628 WM_GETMINMAXINFO and obtains the corrected size/position.
630 \sa WindowCreationData, QWindowsContext
632 \ingroup qt-lighthouse-win
635 QWindowCreationContext::QWindowCreationContext(const QWindow *w,
636 const QRect &geometry,
637 DWORD style_, DWORD exStyle_) :
638 geometryHint(w), style(style_), exStyle(exStyle_),
639 requestedGeometry(geometry), obtainedGeometry(geometry),
640 margins(QWindowsGeometryHint::frame(style, exStyle)),
641 frameX(CW_USEDEFAULT), frameY(CW_USEDEFAULT),
642 frameWidth(CW_USEDEFAULT), frameHeight(CW_USEDEFAULT)
644 // Geometry of toplevels does not consider window frames.
645 // TODO: No concept of WA_wasMoved yet that would indicate a
646 // CW_USEDEFAULT unless set. For now, assume that 0,0 means 'default'
648 if (geometry.isValid()) {
649 frameX = geometry.x();
650 frameY = geometry.y();
651 frameWidth = margins.left() + geometry.width() + margins.right();
652 frameHeight = margins.top() + geometry.height() + margins.bottom();
653 const bool isDefaultPosition = !frameX && !frameY && w->isTopLevel();
654 if (!QWindowsGeometryHint::positionIncludesFrame(w) && !isDefaultPosition) {
655 frameX -= margins.left();
656 frameY -= margins.top();
659 if (QWindowsContext::verboseWindows)
661 << __FUNCTION__ << ' ' << w << geometry
662 << " pos incl. frame" << QWindowsGeometryHint::positionIncludesFrame(w)
663 << " frame: " << frameWidth << 'x' << frameHeight << '+'
664 << frameX << '+' << frameY
665 << " min" << geometryHint.minimumSize
666 << " max" << geometryHint.maximumSize;
670 \class QWindowsWindow
671 \brief Raster or OpenGL Window.
674 \li Raster type: handleWmPaint() is implemented to
675 to bitblt the image. The DC can be accessed
676 via getDC/Relase DC, which has a special handling
677 when within a paint event (in that case, the DC obtained
678 from BeginPaint() is returned).
680 \li Open GL: The first time QWindowsGLContext accesses
681 the handle, it sets up the pixelformat on the DC
682 which in turn sets it on the window (see flag
683 PixelFormatInitialized).
684 handleWmPaint() is empty (although required).
688 \ingroup qt-lighthouse-win
691 QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) :
692 QPlatformWindow(aWindow),
696 m_windowState(Qt::WindowNoState),
699 m_cursor(QWindowsScreen::screenOf(aWindow)->windowsCursor()->standardWindowCursor()),
702 m_format(aWindow->format())
703 #ifdef QT_OPENGL_ES_2
707 , m_previouslyHidden(false)
710 if (aWindow->surfaceType() == QWindow::OpenGLSurface)
711 setFlag(OpenGLSurface);
712 QWindowsContext::instance()->addWindow(m_data.hwnd, this);
713 if (aWindow->isTopLevel()) {
714 switch (aWindow->windowType()) {
727 setWindowState(aWindow->windowState());
730 QWindowsWindow::~QWindowsWindow()
735 void QWindowsWindow::destroyWindow()
737 if (QWindowsContext::verboseIntegration || QWindowsContext::verboseWindows)
738 qDebug() << __FUNCTION__ << this << window() << m_data.hwnd;
739 if (m_data.hwnd) { // Stop event dispatching before Window is destroyed.
740 unregisterDropSite();
741 QWindowsContext::instance()->removeWindow(m_data.hwnd);
742 #ifdef QT_OPENGL_ES_2
744 if (QWindowsContext::verboseGL)
745 qDebug("%s: Freeing EGL surface %p, this = %p",
746 __FUNCTION__, m_eglSurface, this);
747 eglDestroySurface(m_staticEglContext->display(), m_eglSurface);
752 if ((m_windowState & Qt::WindowFullScreen) && !m_previouslyHidden) {
753 HWND handle = FindWindow(L"HHTaskBar", L"");
755 ShowWindow(handle, SW_SHOW);
759 if (m_data.hwnd != GetDesktopWindow())
760 DestroyWindow(m_data.hwnd);
765 void QWindowsWindow::registerDropSite()
767 if (m_data.hwnd && !m_dropTarget) {
768 m_dropTarget = new QWindowsOleDropTarget(window());
769 RegisterDragDrop(m_data.hwnd, m_dropTarget);
770 CoLockObjectExternal(m_dropTarget, true, true);
774 void QWindowsWindow::unregisterDropSite()
776 if (m_data.hwnd && m_dropTarget) {
777 m_dropTarget->Release();
778 CoLockObjectExternal(m_dropTarget, false, true);
779 RevokeDragDrop(m_data.hwnd);
784 QWindow *QWindowsWindow::topLevelOf(QWindow *w)
786 while (QWindow *parent = w->parent())
791 QWindowsWindow::WindowData
792 QWindowsWindow::WindowData::create(const QWindow *w,
793 const WindowData ¶meters,
794 const QString &title)
796 WindowCreationData creationData;
797 creationData.fromWindow(w, parameters.flags);
798 WindowData result = creationData.create(w, parameters.geometry, title);
799 creationData.initialize(result.hwnd, false, 1);
803 void QWindowsWindow::setVisible(bool visible)
805 if (QWindowsContext::verboseWindows)
806 qDebug() << __FUNCTION__ << this << window() << m_data.hwnd << visible;
810 QWindowSystemInterface::handleExposeEvent(window(),
811 QRect(QPoint(), geometry().size()));
814 QWindowSystemInterface::handleExposeEvent(window(), QRegion());
819 bool QWindowsWindow::isVisible() const
821 return m_data.hwnd && IsWindowVisible(m_data.hwnd);
824 bool QWindowsWindow::isActive() const
826 // Check for native windows or children of the active native window.
827 if (const HWND activeHwnd = GetActiveWindow())
828 if (m_data.hwnd == activeHwnd || IsChild(activeHwnd, m_data.hwnd))
833 // partially from QWidgetPrivate::show_sys()
834 void QWindowsWindow::show_sys() const
836 int sm = SW_SHOWNORMAL;
837 bool fakedMaximize = false;
838 const QWindow *w = window();
839 const Qt::WindowFlags flags = w->windowFlags();
840 const Qt::WindowType type = w->windowType();
841 if (w->isTopLevel()) {
842 const Qt::WindowState state = w->windowState();
843 if (state & Qt::WindowMinimized) {
844 sm = SW_SHOWMINIMIZED;
846 sm = SW_SHOWMINNOACTIVE;
847 } else if (state & Qt::WindowMaximized) {
848 sm = SW_SHOWMAXIMIZED;
849 // Windows will not behave correctly when we try to maximize a window which does not
850 // have minimize nor maximize buttons in the window frame. Windows would then ignore
851 // non-available geometry, and rather maximize the widget to the full screen, minus the
852 // window frame (caption). So, we do a trick here, by adding a maximize button before
853 // maximizing the widget, and then remove the maximize button afterwards.
854 if (flags & Qt::WindowTitleHint &&
855 !(flags & (Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint))) {
856 fakedMaximize = TRUE;
857 setStyle(style() | WS_MAXIMIZEBOX);
861 if (type == Qt::Popup || type == Qt::ToolTip || type == Qt::Tool)
862 sm = SW_SHOWNOACTIVATE;
864 ShowWindow(m_data.hwnd, sm);
867 setStyle(style() & ~WS_MAXIMIZEBOX);
868 SetWindowPos(m_data.hwnd, 0, 0, 0, 0, 0,
869 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER
874 // partially from QWidgetPrivate::hide_sys()
875 void QWindowsWindow::hide_sys() const
877 const Qt::WindowFlags flags = window()->windowFlags();
878 if (flags != Qt::Desktop) {
879 if (flags & Qt::Popup)
880 ShowWindow(m_data.hwnd, SW_HIDE);
882 SetWindowPos(m_data.hwnd,0, 0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
886 void QWindowsWindow::setParent(const QPlatformWindow *newParent)
888 if (QWindowsContext::verboseWindows)
889 qDebug() << __FUNCTION__ << window() << newParent;
892 setParent_sys(newParent);
895 void QWindowsWindow::setParent_sys(const QPlatformWindow *parent) const
897 // Use GetAncestor instead of GetParent, as GetParent can return owner window for toplevels
898 HWND oldParentHWND = GetAncestor(m_data.hwnd, GA_PARENT);
899 HWND newParentHWND = 0;
901 const QWindowsWindow *parentW = static_cast<const QWindowsWindow *>(parent);
902 newParentHWND = parentW->handle();
906 if (newParentHWND != oldParentHWND) {
907 const bool wasTopLevel = window()->isTopLevel();
908 const bool isTopLevel = newParentHWND == 0;
910 setFlag(WithinSetParent);
911 SetParent(m_data.hwnd, newParentHWND);
912 clearFlag(WithinSetParent);
914 // WS_CHILD/WS_POPUP must be manually set/cleared in addition
915 // to dialog frames, etc (see SetParent() ) if the top level state changes.
916 if (wasTopLevel != isTopLevel) {
917 const unsigned flags = isTopLevel ? unsigned(0) : unsigned(WindowCreationData::ForceChild);
918 setWindowFlags_sys(window()->windowFlags(), flags);
923 void QWindowsWindow::handleShown()
925 QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size()));
928 void QWindowsWindow::handleHidden()
930 QWindowSystemInterface::handleExposeEvent(window(), QRegion());
933 void QWindowsWindow::setGeometry(const QRect &rectIn)
936 // This means it is a call from QWindow::setFramePos() and
937 // the coordinates include the frame (size is still the contents rectangle).
938 if (QWindowsGeometryHint::positionIncludesFrame(window())) {
939 const QMargins margins = frameMargins();
940 rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top()));
942 const QSize oldSize = m_data.geometry.size();
943 m_data.geometry = rect;
944 const QSize newSize = rect.size();
946 if (newSize != oldSize) {
947 const QWindowsGeometryHint hint(window());
948 if (!hint.validSize(newSize)) {
949 qWarning("%s: Attempt to set a size (%dx%d) violating the constraints"
950 "(%dx%d - %dx%d) on window '%s'.", __FUNCTION__,
951 newSize.width(), newSize.height(),
952 hint.minimumSize.width(), hint.minimumSize.height(),
953 hint.maximumSize.width(), hint.maximumSize.height(),
954 qPrintable(window()->objectName()));
958 // A ResizeEvent with resulting geometry will be sent. If we cannot
959 // achieve that size (for example, window title minimal constraint),
961 setGeometry_sys(rect);
962 if (m_data.geometry != rect) {
963 qWarning("%s: Unable to set geometry %dx%d+%d+%d on '%s'."
964 " Resulting geometry: %dx%d+%d+%d "
965 "(frame: %d, %d, %d, %d).",
967 rect.width(), rect.height(), rect.x(), rect.y(),
968 qPrintable(window()->objectName()),
969 m_data.geometry.width(), m_data.geometry.height(),
970 m_data.geometry.x(), m_data.geometry.y(),
971 m_data.frame.left(), m_data.frame.top(),
972 m_data.frame.right(), m_data.frame.bottom());
975 QPlatformWindow::setGeometry(rect);
979 void QWindowsWindow::handleMoved()
981 // Minimize/Set parent can send nonsensical move events.
982 if (!IsIconic(m_data.hwnd) && !testFlag(WithinSetParent))
983 handleGeometryChange();
986 void QWindowsWindow::handleResized(int wParam)
989 case SIZE_MAXHIDE: // Some other window affected.
993 handleWindowStateChange(Qt::WindowMinimized);
996 handleWindowStateChange(Qt::WindowMaximized);
997 handleGeometryChange();
1000 bool fullScreen = isFullScreen_sys();
1001 if ((m_windowState != Qt::WindowNoState) || fullScreen)
1002 handleWindowStateChange(fullScreen ? Qt::WindowFullScreen : Qt::WindowNoState);
1003 handleGeometryChange();
1008 void QWindowsWindow::handleGeometryChange()
1010 //Prevent recursive resizes for Windows CE
1011 if (testFlag(WithinSetStyle))
1013 m_data.geometry = geometry_sys();
1014 QPlatformWindow::setGeometry(m_data.geometry);
1015 if (testFlag(SynchronousGeometryChangeEvent))
1016 QWindowSystemInterface::handleSynchronousGeometryChange(window(), m_data.geometry);
1018 QWindowSystemInterface::handleGeometryChange(window(), m_data.geometry);
1020 if (QWindowsContext::verboseEvents || QWindowsContext::verboseWindows)
1021 qDebug() << __FUNCTION__ << this << window() << m_data.geometry;
1024 void QWindowsWindow::setGeometry_sys(const QRect &rect) const
1026 const QMargins margins = frameMargins();
1027 const QRect frameGeometry = rect + margins;
1029 if (QWindowsContext::verboseWindows)
1030 qDebug() << '>' << __FUNCTION__ << this << window()
1031 << " \n from " << geometry_sys() << " frame: "
1032 << margins << " to " <<rect
1033 << " new frame: " << frameGeometry;
1035 const bool rc = MoveWindow(m_data.hwnd, frameGeometry.x(), frameGeometry.y(),
1036 frameGeometry.width(), frameGeometry.height(), true);
1037 if (QWindowsContext::verboseWindows)
1038 qDebug() << '<' << __FUNCTION__ << this << window()
1039 << " \n resulting " << rc << geometry_sys();
1042 QRect QWindowsWindow::frameGeometry_sys() const
1044 // Warning: Returns bogus values when minimized.
1045 bool isRealTopLevel = window()->isTopLevel() && !m_data.embedded;
1046 return frameGeometry(m_data.hwnd, isRealTopLevel);
1049 QRect QWindowsWindow::geometry_sys() const
1051 return frameGeometry_sys() - frameMargins();
1055 Allocates a HDC for the window or returns the temporary one
1056 obtained from WinAPI BeginPaint within a WM_PAINT event.
1061 HDC QWindowsWindow::getDC()
1064 m_hdc = GetDC(handle());
1069 Relases the HDC for the window or does nothing in
1070 case it was obtained from WinAPI BeginPaint within a WM_PAINT event.
1075 void QWindowsWindow::releaseDC()
1077 if (m_hdc && !testFlag(DCFromBeginPaint)) {
1078 ReleaseDC(handle(), m_hdc);
1083 bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message,
1086 // Ignore invalid update bounding rectangles
1087 if (!GetUpdateRect(m_data.hwnd, 0, FALSE))
1089 if (message == WM_ERASEBKGND) // Backing store - ignored.
1092 if (testFlag(OpenGLSurface)) {
1093 // Observed painting problems with Aero style disabled (QTBUG-7865).
1094 if (testFlag(OpenGLDoubleBuffered))
1095 InvalidateRect(hwnd, 0, false);
1096 BeginPaint(hwnd, &ps);
1097 QWindowSystemInterface::handleSynchronousExposeEvent(window(),
1098 QRegion(qrectFromRECT(ps.rcPaint)));
1099 EndPaint(hwnd, &ps);
1101 const HDC dc = BeginPaint(hwnd, &ps);
1102 const QRect updateRect = qrectFromRECT(ps.rcPaint);
1103 if (updateRect.size() == m_data.geometry.size()) {
1104 // Store DC for access by the backing store if it has the full size.
1106 setFlag(DCFromBeginPaint);
1109 if (QWindowsContext::verboseIntegration)
1110 qDebug() << __FUNCTION__ << this << window() << updateRect;
1112 QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRegion(updateRect));
1113 if (testFlag(DCFromBeginPaint)) {
1114 clearFlag(DCFromBeginPaint);
1117 EndPaint(hwnd, &ps);
1122 void QWindowsWindow::setWindowTitle(const QString &title)
1124 if (QWindowsContext::verboseWindows)
1125 qDebug() << __FUNCTION__ << this << window() <<title;
1127 SetWindowText(m_data.hwnd, (const wchar_t*)title.utf16());
1130 Qt::WindowFlags QWindowsWindow::setWindowFlags(Qt::WindowFlags flags)
1132 if (QWindowsContext::verboseWindows)
1133 qDebug() << '>' << __FUNCTION__ << this << window() << "\n from: "
1134 << QWindowsWindow::debugWindowFlags(m_data.flags)
1135 << "\n to: " << QWindowsWindow::debugWindowFlags(flags);
1136 const QRect oldGeometry = geometry();
1137 if (m_data.flags != flags) {
1138 m_data.flags = flags;
1140 m_data = setWindowFlags_sys(flags);
1142 // When switching to a frameless window, geometry
1143 // may change without a WM_MOVE. Report change manually.
1144 // Do not send synchronously as not to clobber the widget
1145 // geometry in a sequence of setting flags and geometry.
1146 const QRect newGeometry = geometry_sys();
1147 if (oldGeometry != newGeometry)
1148 handleGeometryChange();
1150 if (QWindowsContext::verboseWindows)
1151 qDebug() << '<' << __FUNCTION__ << "\n returns: "
1152 << QWindowsWindow::debugWindowFlags(m_data.flags)
1153 << " geometry " << oldGeometry << "->" << newGeometry;
1154 return m_data.flags;
1157 QWindowsWindow::WindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt,
1158 unsigned flags) const
1160 WindowCreationData creationData;
1161 creationData.fromWindow(window(), wt, flags);
1162 creationData.applyWindowFlags(m_data.hwnd);
1163 creationData.initialize(m_data.hwnd, true, m_opacity);
1165 WindowData result = m_data;
1166 result.flags = creationData.flags;
1167 result.embedded = creationData.embedded;
1168 setFlag(FrameDirty);
1172 void QWindowsWindow::handleWindowStateChange(Qt::WindowState state)
1174 if (QWindowsContext::verboseWindows)
1175 qDebug() << __FUNCTION__ << this << window()
1176 << "\n from " << debugWindowStates(m_windowState)
1177 << " to " << debugWindowStates(state);
1178 setFlag(FrameDirty);
1179 m_windowState = state;
1180 QWindowSystemInterface::handleWindowStateChanged(window(), state);
1183 Qt::WindowState QWindowsWindow::setWindowState(Qt::WindowState state)
1186 setWindowState_sys(state);
1187 m_windowState = state;
1192 bool QWindowsWindow::isFullScreen_sys() const
1194 return geometry_sys() == window()->screen()->geometry();
1198 \brief Change the window state.
1200 \note Window frames change when maximized;
1201 the top margin shrinks somewhat but that cannot be obtained using
1202 AdjustWindowRectEx().
1204 \note Some calls to SetWindowLong require a subsequent call
1208 void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
1210 const Qt::WindowState oldState = m_windowState;
1211 if (oldState == newState)
1213 if (QWindowsContext::verboseWindows)
1214 qDebug() << '>' << __FUNCTION__ << this << window()
1215 << " from " << debugWindowStates(oldState)
1216 << " to " << debugWindowStates(newState);
1218 const bool visible = isVisible();
1220 setFlag(FrameDirty);
1222 if ((oldState == Qt::WindowMaximized) != (newState == Qt::WindowMaximized)) {
1223 if (visible && !(newState == Qt::WindowMinimized))
1224 ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
1227 if ((oldState == Qt::WindowFullScreen) != (newState == Qt::WindowFullScreen)) {
1229 HWND handle = FindWindow(L"HHTaskBar", L"");
1231 if (newState == Qt::WindowFullScreen) {
1232 BOOL hidden = ShowWindow(handle, SW_HIDE);
1234 m_previouslyHidden = true;
1235 } else if (!m_previouslyHidden){
1236 ShowWindow(handle, SW_SHOW);
1240 if (newState == Qt::WindowFullScreen) {
1241 #ifndef Q_FLATTEN_EXPOSE
1242 UINT newStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP;
1244 UINT newStyle = WS_POPUP;
1246 // Save geometry and style to be restored when fullscreen
1247 // is turned off again, since on Windows, it is not a real
1248 // Window state but emulated by changing geometry and style.
1249 if (!m_savedStyle) {
1250 m_savedStyle = style();
1252 if (oldState == Qt::WindowMinimized) {
1254 wp.length = sizeof(WINDOWPLACEMENT);
1255 if (GetWindowPlacement(m_data.hwnd, &wp))
1256 m_savedFrameGeometry = qrectFromRECT(wp.rcNormalPosition);
1259 m_savedFrameGeometry = frameGeometry_sys();
1264 if (m_savedStyle & WS_SYSMENU)
1265 newStyle |= WS_SYSMENU;
1267 newStyle |= WS_VISIBLE;
1270 const QRect r = window()->screen()->geometry();
1271 const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
1272 const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
1273 setFlag(SynchronousGeometryChangeEvent);
1274 SetWindowPos(m_data.hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf);
1276 clearFlag(SynchronousGeometryChangeEvent);
1277 QWindowSystemInterface::handleSynchronousGeometryChange(window(), r);
1278 } else if (newState != Qt::WindowMinimized) {
1279 // Restore saved state.
1280 unsigned newStyle = m_savedStyle ? m_savedStyle : style();
1282 newStyle |= WS_VISIBLE;
1285 UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE;
1286 if (!m_savedFrameGeometry.isValid())
1287 swpf |= SWP_NOSIZE | SWP_NOMOVE;
1288 const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
1289 setFlag(SynchronousGeometryChangeEvent);
1290 SetWindowPos(m_data.hwnd, 0, m_savedFrameGeometry.x(), m_savedFrameGeometry.y(),
1291 m_savedFrameGeometry.width(), m_savedFrameGeometry.height(), swpf);
1293 clearFlag(SynchronousGeometryChangeEvent);
1294 // preserve maximized state
1296 ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
1298 m_savedFrameGeometry = QRect();
1302 if ((oldState == Qt::WindowMinimized) != (newState == Qt::WindowMinimized)) {
1304 ShowWindow(m_data.hwnd, (newState == Qt::WindowMinimized) ? SW_MINIMIZE :
1305 (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
1307 if (QWindowsContext::verboseWindows)
1308 qDebug() << '<' << __FUNCTION__ << this << window()
1309 << debugWindowStates(newState);
1312 void QWindowsWindow::setStyle(unsigned s) const
1314 if (QWindowsContext::verboseWindows)
1315 qDebug() << __FUNCTION__ << this << window() << debugWinStyle(s);
1316 setFlag(WithinSetStyle);
1317 setFlag(FrameDirty);
1318 SetWindowLongPtr(m_data.hwnd, GWL_STYLE, s);
1319 clearFlag(WithinSetStyle);
1322 void QWindowsWindow::setExStyle(unsigned s) const
1324 if (QWindowsContext::verboseWindows)
1325 qDebug().nospace() << __FUNCTION__ << ' ' << this << ' ' << window()
1326 << " 0x" << QByteArray::number(s, 16);
1327 setFlag(FrameDirty);
1328 SetWindowLongPtr(m_data.hwnd, GWL_EXSTYLE, s);
1331 void QWindowsWindow::raise()
1333 if (QWindowsContext::verboseWindows)
1334 qDebug() << __FUNCTION__ << this << window();
1335 SetWindowPos(m_data.hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1338 void QWindowsWindow::lower()
1340 if (QWindowsContext::verboseWindows)
1341 qDebug() << __FUNCTION__ << this << window();
1343 SetWindowPos(m_data.hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1346 void QWindowsWindow::windowEvent(QEvent *event)
1348 switch (event->type()) {
1349 case QEvent::WindowBlocked: // Blocked by another modal window.
1351 setFlag(BlockedByModal);
1353 case QEvent::WindowUnblocked:
1355 clearFlag(BlockedByModal);
1362 void QWindowsWindow::propagateSizeHints()
1364 if (QWindowsContext::verboseWindows)
1365 qDebug() << __FUNCTION__ << this << window();
1368 QMargins QWindowsWindow::frameMargins() const
1370 // Frames are invalidated by style changes (window state, flags).
1371 // As they are also required for geometry calculations in resize
1372 // event sequences, introduce a dirty flag mechanism to be able
1373 // to cache results.
1374 if (testFlag(FrameDirty)) {
1375 m_data.frame = QWindowsGeometryHint::frame(style(), exStyle());
1376 clearFlag(FrameDirty);
1378 return m_data.frame;
1381 void QWindowsWindow::setOpacity(qreal level)
1383 if (QWindowsContext::verboseWindows)
1384 qDebug() << __FUNCTION__ << level;
1385 if (m_opacity != level) {
1388 setWindowOpacity(m_data.hwnd, m_data.flags, level);
1392 static inline HRGN createRectRegion(const QRect &r)
1394 return CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height());
1397 static inline void addRectToWinRegion(const QRect &rect, HRGN *winRegion)
1399 if (const HRGN rectRegion = createRectRegion(rect)) {
1400 HRGN result = CreateRectRgn(0, 0, 0, 0);
1401 if (CombineRgn(result, *winRegion, rectRegion, RGN_OR)) {
1402 DeleteObject(winRegion);
1403 *winRegion = result;
1405 DeleteObject(rectRegion);
1409 static HRGN qRegionToWinRegion(const QRegion ®ion)
1411 const QVector<QRect> rects = region.rects();
1412 if (rects.isEmpty())
1414 const int rectCount = rects.size();
1416 return createRectRegion(region.boundingRect());
1417 HRGN hRegion = createRectRegion(rects.front());
1418 for (int i = 1; i < rectCount; ++i)
1419 addRectToWinRegion(rects.at(i), &hRegion);
1423 void QWindowsWindow::setMask(const QRegion ®ion)
1425 if (region.isEmpty()) {
1426 SetWindowRgn(m_data.hwnd, 0, true);
1429 const HRGN winRegion = qRegionToWinRegion(region);
1431 // Mask is in client area coordinates, so offset it in case we have a frame
1432 if (window()->isTopLevel()) {
1433 const QMargins margins = frameMargins();
1434 OffsetRgn(winRegion, margins.left(), margins.top());
1437 // SetWindowRgn takes ownership.
1438 if (!SetWindowRgn(m_data.hwnd, winRegion, true))
1439 DeleteObject(winRegion);
1442 void QWindowsWindow::requestActivateWindow()
1444 if (QWindowsContext::verboseWindows)
1445 qDebug() << __FUNCTION__ << this << window();
1446 // 'Active' state handling is based in focus since it needs to work for
1447 // child windows as well.
1449 SetForegroundWindow(m_data.hwnd);
1450 SetFocus(m_data.hwnd);
1454 bool QWindowsWindow::setKeyboardGrabEnabled(bool grab)
1457 qWarning("%s: No handle", __FUNCTION__);
1460 if (QWindowsContext::verboseWindows)
1461 qDebug() << __FUNCTION__ << this << window() << grab;
1463 QWindowsContext *context = QWindowsContext::instance();
1465 context->setKeyGrabber(window());
1467 if (context->keyGrabber() == window())
1468 context->setKeyGrabber(0);
1473 bool QWindowsWindow::setMouseGrabEnabled(bool grab)
1475 bool result = false;
1477 qWarning("%s: No handle", __FUNCTION__);
1480 if (QWindowsContext::verboseWindows)
1481 qDebug() << __FUNCTION__ << window() << grab;
1483 if (m_mouseGrab != grab) {
1486 setMouseGrabEnabled_sys(grab);
1491 void QWindowsWindow::setMouseGrabEnabled_sys(bool grab)
1494 SetCapture(m_data.hwnd);
1500 static inline DWORD cornerToWinOrientation(Qt::Corner corner)
1503 case Qt::TopLeftCorner:
1504 return 0xf004; // SZ_SIZETOPLEFT;
1505 case Qt::TopRightCorner:
1506 return 0xf005; // SZ_SIZETOPRIGHT
1507 case Qt::BottomLeftCorner:
1508 return 0xf007; // SZ_SIZEBOTTOMLEFT
1509 case Qt::BottomRightCorner:
1510 return 0xf008; // SZ_SIZEBOTTOMRIGHT
1515 bool QWindowsWindow::startSystemResize(const QPoint &, Qt::Corner corner)
1517 if (!GetSystemMenu(m_data.hwnd, FALSE))
1521 PostMessage(m_data.hwnd, WM_SYSCOMMAND, cornerToWinOrientation(corner), 0);
1522 setFlag(SizeGripOperation);
1526 void QWindowsWindow::setFrameStrutEventsEnabled(bool enabled)
1529 setFlag(FrameStrutEventsEnabled);
1531 clearFlag(FrameStrutEventsEnabled);
1535 #ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO
1536 void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
1538 const QWindowsGeometryHint hint(window());
1539 hint.applyToMinMaxInfo(m_data.hwnd, mmi);
1540 if (QWindowsContext::verboseWindows)
1541 qDebug() << __FUNCTION__ << window() << *mmi;
1543 #endif // !Q_OS_WINCE
1546 \brief Applies to cursor property set on the window to the global cursor.
1551 void QWindowsWindow::applyCursor()
1553 SetCursor(m_cursor.handle());
1556 void QWindowsWindow::setCursor(const QWindowsWindowCursor &c)
1558 if (c.handle() != m_cursor.handle()) {
1559 const bool underMouse = QWindowsContext::instance()->windowUnderMouse() == window();
1560 if (QWindowsContext::verboseWindows)
1561 qDebug() << window() << __FUNCTION__ << "Shape=" << c.cursor().shape()
1562 << " isWUM=" << underMouse;
1570 \brief Find a child window using flags from ChildWindowFromPointEx.
1573 QWindowsWindow *QWindowsWindow::childAtScreenPoint(const QPoint &screenPoint,
1574 unsigned cwexflags) const
1577 return QWindowsContext::instance()->findPlatformWindowAt(m_data.hwnd, screenPoint, cwexflags);
1581 QWindowsWindow *QWindowsWindow::childAt(const QPoint &clientPoint, unsigned cwexflags) const
1584 return childAtScreenPoint(QWindowsGeometryHint::mapToGlobal(m_data.hwnd, clientPoint),
1590 void QWindowsWindow::alertWindow(int durationMs)
1592 DWORD timeOutMs = GetCaretBlinkTime();
1593 if (!timeOutMs || timeOutMs == INFINITE)
1597 info.cbSize = sizeof(info);
1598 info.hwnd = m_data.hwnd;
1599 info.dwFlags = FLASHW_TRAY;
1600 info.dwTimeout = timeOutMs;
1601 info.uCount = durationMs == 0 ? 10 : durationMs / timeOutMs;
1602 FlashWindowEx(&info);
1605 void QWindowsWindow::stopAlertWindow()
1608 info.cbSize = sizeof(info);
1609 info.hwnd = m_data.hwnd;
1610 info.dwFlags = FLASHW_STOP;
1613 FlashWindowEx(&info);
1615 #endif // !Q_OS_WINCE
1617 bool QWindowsWindow::isEnabled() const
1619 return (style() & WS_DISABLED) == 0;
1622 void QWindowsWindow::setEnabled(bool enabled)
1624 const unsigned oldStyle = style();
1625 unsigned newStyle = oldStyle;
1627 newStyle &= ~WS_DISABLED;
1629 newStyle |= WS_DISABLED;
1631 if (newStyle != oldStyle)
1635 #ifdef QT_OPENGL_ES_2
1636 EGLSurface QWindowsWindow::ensureEglSurfaceHandle(const QWindowsWindow::QWindowsEGLStaticContextPtr &staticContext, EGLConfig config)
1638 if (!m_eglSurface) {
1639 m_staticEglContext = staticContext;
1640 m_eglSurface = eglCreateWindowSurface(staticContext->display(), config, (EGLNativeWindowType)m_data.hwnd, NULL);
1641 if (m_eglSurface == EGL_NO_SURFACE)
1642 qWarning("%s: Could not create the egl surface (eglCreateWindowSurface failed): error = 0x%x\n",
1643 Q_FUNC_INFO, eglGetError());
1644 if (QWindowsContext::verboseGL)
1645 qDebug("%s: Created EGL surface %p, this = %p",
1646 __FUNCTION__, m_eglSurface, this);
1648 return m_eglSurface;
1650 #endif // QT_OPENGL_ES_2
1652 QByteArray QWindowsWindow::debugWindowFlags(Qt::WindowFlags wf)
1654 const int iwf = int(wf);
1655 QByteArray rc = "0x";
1656 rc += QByteArray::number(iwf, 16);
1659 switch ((iwf & Qt::WindowType_Mask)) {
1681 case Qt::SplashScreen:
1682 rc += " SplashScreen";
1691 if (iwf & Qt::MSWindowsFixedSizeDialogHint) rc += " MSWindowsFixedSizeDialogHint";
1692 if (iwf & Qt::MSWindowsOwnDC) rc += " MSWindowsOwnDC";
1693 if (iwf & Qt::FramelessWindowHint) rc += " FramelessWindowHint";
1694 if (iwf & Qt::WindowTitleHint) rc += " WindowTitleHint";
1695 if (iwf & Qt::WindowSystemMenuHint) rc += " WindowSystemMenuHint";
1696 if (iwf & Qt::WindowMinimizeButtonHint) rc += " WindowMinimizeButtonHint";
1697 if (iwf & Qt::WindowMaximizeButtonHint) rc += " WindowMaximizeButtonHint";
1698 if (iwf & Qt::WindowContextHelpButtonHint) rc += " WindowContextHelpButtonHint";
1699 if (iwf & Qt::WindowShadeButtonHint) rc += " WindowShadeButtonHint";
1700 if (iwf & Qt::WindowStaysOnTopHint) rc += " WindowStaysOnTopHint";
1701 if (iwf & Qt::CustomizeWindowHint) rc += " CustomizeWindowHint";
1702 if (iwf & Qt::WindowStaysOnBottomHint) rc += " WindowStaysOnBottomHint";
1703 if (iwf & Qt::WindowCloseButtonHint) rc += " WindowCloseButtonHint";