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 if (aWindow->surfaceType() == QWindow::OpenGLSurface)
708 setFlag(OpenGLSurface);
709 QWindowsContext::instance()->addWindow(m_data.hwnd, this);
710 if (aWindow->isTopLevel()) {
711 switch (aWindow->windowType()) {
724 setWindowState(aWindow->windowState());
727 QWindowsWindow::~QWindowsWindow()
732 void QWindowsWindow::destroyWindow()
734 if (QWindowsContext::verboseIntegration || QWindowsContext::verboseWindows)
735 qDebug() << __FUNCTION__ << this << window() << m_data.hwnd;
736 if (m_data.hwnd) { // Stop event dispatching before Window is destroyed.
737 unregisterDropSite();
738 QWindowsContext::instance()->removeWindow(m_data.hwnd);
739 #ifdef QT_OPENGL_ES_2
741 if (QWindowsContext::verboseGL)
742 qDebug("%s: Freeing EGL surface %p, this = %p",
743 __FUNCTION__, m_eglSurface, this);
744 eglDestroySurface(m_staticEglContext->display(), m_eglSurface);
748 if (m_data.hwnd != GetDesktopWindow())
749 DestroyWindow(m_data.hwnd);
754 void QWindowsWindow::registerDropSite()
756 if (m_data.hwnd && !m_dropTarget) {
757 m_dropTarget = new QWindowsOleDropTarget(window());
758 RegisterDragDrop(m_data.hwnd, m_dropTarget);
759 CoLockObjectExternal(m_dropTarget, true, true);
763 void QWindowsWindow::unregisterDropSite()
765 if (m_data.hwnd && m_dropTarget) {
766 m_dropTarget->Release();
767 CoLockObjectExternal(m_dropTarget, false, true);
768 RevokeDragDrop(m_data.hwnd);
773 QWindow *QWindowsWindow::topLevelOf(QWindow *w)
775 while (QWindow *parent = w->parent())
780 QWindowsWindow::WindowData
781 QWindowsWindow::WindowData::create(const QWindow *w,
782 const WindowData ¶meters,
783 const QString &title)
785 WindowCreationData creationData;
786 creationData.fromWindow(w, parameters.flags);
787 WindowData result = creationData.create(w, parameters.geometry, title);
788 creationData.initialize(result.hwnd, false, 1);
792 void QWindowsWindow::setVisible(bool visible)
794 if (QWindowsContext::verboseWindows)
795 qDebug() << __FUNCTION__ << this << window() << m_data.hwnd << visible;
799 QWindowSystemInterface::handleExposeEvent(window(),
800 QRect(QPoint(), geometry().size()));
803 QWindowSystemInterface::handleExposeEvent(window(), QRegion());
808 bool QWindowsWindow::isVisible() const
810 return m_data.hwnd && IsWindowVisible(m_data.hwnd);
813 bool QWindowsWindow::isActive() const
815 // Check for native windows or children of the active native window.
816 if (const HWND activeHwnd = GetActiveWindow())
817 if (m_data.hwnd == activeHwnd || IsChild(activeHwnd, m_data.hwnd))
822 // partially from QWidgetPrivate::show_sys()
823 void QWindowsWindow::show_sys() const
825 int sm = SW_SHOWNORMAL;
826 bool fakedMaximize = false;
827 const QWindow *w = window();
828 const Qt::WindowFlags flags = w->windowFlags();
829 const Qt::WindowType type = w->windowType();
830 if (w->isTopLevel()) {
831 const Qt::WindowState state = w->windowState();
832 if (state & Qt::WindowMinimized) {
833 sm = SW_SHOWMINIMIZED;
835 sm = SW_SHOWMINNOACTIVE;
836 } else if (state & Qt::WindowMaximized) {
837 sm = SW_SHOWMAXIMIZED;
838 // Windows will not behave correctly when we try to maximize a window which does not
839 // have minimize nor maximize buttons in the window frame. Windows would then ignore
840 // non-available geometry, and rather maximize the widget to the full screen, minus the
841 // window frame (caption). So, we do a trick here, by adding a maximize button before
842 // maximizing the widget, and then remove the maximize button afterwards.
843 if (flags & Qt::WindowTitleHint &&
844 !(flags & (Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint))) {
845 fakedMaximize = TRUE;
846 setStyle(style() | WS_MAXIMIZEBOX);
850 if (type == Qt::Popup || type == Qt::ToolTip || type == Qt::Tool)
851 sm = SW_SHOWNOACTIVATE;
853 ShowWindow(m_data.hwnd, sm);
856 setStyle(style() & ~WS_MAXIMIZEBOX);
857 SetWindowPos(m_data.hwnd, 0, 0, 0, 0, 0,
858 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER
863 // partially from QWidgetPrivate::hide_sys()
864 void QWindowsWindow::hide_sys() const
866 const Qt::WindowFlags flags = window()->windowFlags();
867 if (flags != Qt::Desktop) {
868 if (flags & Qt::Popup)
869 ShowWindow(m_data.hwnd, SW_HIDE);
871 SetWindowPos(m_data.hwnd,0, 0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
875 void QWindowsWindow::setParent(const QPlatformWindow *newParent)
877 if (QWindowsContext::verboseWindows)
878 qDebug() << __FUNCTION__ << window() << newParent;
880 if (newParent != parent() && m_data.hwnd)
881 setParent_sys(newParent);
884 void QWindowsWindow::setParent_sys(const QPlatformWindow *parent) const
888 const QWindowsWindow *parentW = static_cast<const QWindowsWindow *>(parent);
889 parentHWND = parentW->handle();
893 const bool wasTopLevel = window()->isTopLevel();
894 const bool isTopLevel = parentHWND == 0;
896 setFlag(WithinSetParent);
897 SetParent(m_data.hwnd, parentHWND);
898 clearFlag(WithinSetParent);
900 // WS_CHILD/WS_POPUP must be manually set/cleared in addition
901 // to dialog frames, etc (see SetParent() ) if the top level state changes.
902 if (wasTopLevel != isTopLevel) {
903 const unsigned flags = isTopLevel ? unsigned(0) : unsigned(WindowCreationData::ForceChild);
904 setWindowFlags_sys(window()->windowFlags(), flags);
908 void QWindowsWindow::handleShown()
910 QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size()));
913 void QWindowsWindow::handleHidden()
915 QWindowSystemInterface::handleExposeEvent(window(), QRegion());
918 void QWindowsWindow::setGeometry(const QRect &rectIn)
921 // This means it is a call from QWindow::setFramePos() and
922 // the coordinates include the frame (size is still the contents rectangle).
923 if (QWindowsGeometryHint::positionIncludesFrame(window())) {
924 const QMargins margins = frameMargins();
925 rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top()));
927 const QSize oldSize = m_data.geometry.size();
928 m_data.geometry = rect;
929 const QSize newSize = rect.size();
931 if (newSize != oldSize) {
932 const QWindowsGeometryHint hint(window());
933 if (!hint.validSize(newSize)) {
934 qWarning("%s: Attempt to set a size (%dx%d) violating the constraints"
935 "(%dx%d - %dx%d) on window '%s'.", __FUNCTION__,
936 newSize.width(), newSize.height(),
937 hint.minimumSize.width(), hint.minimumSize.height(),
938 hint.maximumSize.width(), hint.maximumSize.height(),
939 qPrintable(window()->objectName()));
943 // A ResizeEvent with resulting geometry will be sent. If we cannot
944 // achieve that size (for example, window title minimal constraint),
946 setGeometry_sys(rect);
947 if (m_data.geometry != rect) {
948 qWarning("%s: Unable to set geometry %dx%d+%d+%d on '%s'."
949 " Resulting geometry: %dx%d+%d+%d "
950 "(frame: %d, %d, %d, %d).",
952 rect.width(), rect.height(), rect.x(), rect.y(),
953 qPrintable(window()->objectName()),
954 m_data.geometry.width(), m_data.geometry.height(),
955 m_data.geometry.x(), m_data.geometry.y(),
956 m_data.frame.left(), m_data.frame.top(),
957 m_data.frame.right(), m_data.frame.bottom());
960 QPlatformWindow::setGeometry(rect);
964 void QWindowsWindow::handleMoved()
966 // Minimize/Set parent can send nonsensical move events.
967 if (!IsIconic(m_data.hwnd) && !testFlag(WithinSetParent))
968 handleGeometryChange();
971 void QWindowsWindow::handleResized(int wParam)
974 case SIZE_MAXHIDE: // Some other window affected.
978 handleWindowStateChange(Qt::WindowMinimized);
981 handleWindowStateChange(Qt::WindowMaximized);
982 handleGeometryChange();
985 bool fullScreen = isFullScreen_sys();
986 if ((m_windowState != Qt::WindowNoState) || fullScreen)
987 handleWindowStateChange(fullScreen ? Qt::WindowFullScreen : Qt::WindowNoState);
988 handleGeometryChange();
993 void QWindowsWindow::handleGeometryChange()
995 //Prevent recursive resizes for Windows CE
996 if (testFlag(WithinSetStyle))
998 m_data.geometry = geometry_sys();
999 QPlatformWindow::setGeometry(m_data.geometry);
1000 if (testFlag(SynchronousGeometryChangeEvent))
1001 QWindowSystemInterface::handleSynchronousGeometryChange(window(), m_data.geometry);
1003 QWindowSystemInterface::handleGeometryChange(window(), m_data.geometry);
1005 if (QWindowsContext::verboseEvents || QWindowsContext::verboseWindows)
1006 qDebug() << __FUNCTION__ << this << window() << m_data.geometry;
1009 void QWindowsWindow::setGeometry_sys(const QRect &rect) const
1011 const QMargins margins = frameMargins();
1012 const QRect frameGeometry = rect + margins;
1014 if (QWindowsContext::verboseWindows)
1015 qDebug() << '>' << __FUNCTION__ << this << window()
1016 << " \n from " << geometry_sys() << " frame: "
1017 << margins << " to " <<rect
1018 << " new frame: " << frameGeometry;
1020 const bool rc = MoveWindow(m_data.hwnd, frameGeometry.x(), frameGeometry.y(),
1021 frameGeometry.width(), frameGeometry.height(), true);
1022 if (QWindowsContext::verboseWindows)
1023 qDebug() << '<' << __FUNCTION__ << this << window()
1024 << " \n resulting " << rc << geometry_sys();
1027 QRect QWindowsWindow::frameGeometry_sys() const
1029 // Warning: Returns bogus values when minimized.
1030 bool isRealTopLevel = window()->isTopLevel() && !m_data.embedded;
1031 return frameGeometry(m_data.hwnd, isRealTopLevel);
1034 QRect QWindowsWindow::geometry_sys() const
1036 return frameGeometry_sys() - frameMargins();
1040 Allocates a HDC for the window or returns the temporary one
1041 obtained from WinAPI BeginPaint within a WM_PAINT event.
1046 HDC QWindowsWindow::getDC()
1049 m_hdc = GetDC(handle());
1054 Relases the HDC for the window or does nothing in
1055 case it was obtained from WinAPI BeginPaint within a WM_PAINT event.
1060 void QWindowsWindow::releaseDC()
1062 if (m_hdc && !testFlag(DCFromBeginPaint)) {
1063 ReleaseDC(handle(), m_hdc);
1068 bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message,
1071 // Ignore invalid update bounding rectangles
1072 if (!GetUpdateRect(m_data.hwnd, 0, FALSE))
1074 if (message == WM_ERASEBKGND) // Backing store - ignored.
1077 if (testFlag(OpenGLSurface)) {
1078 // Observed painting problems with Aero style disabled (QTBUG-7865).
1079 if (testFlag(OpenGLDoubleBuffered))
1080 InvalidateRect(hwnd, 0, false);
1081 BeginPaint(hwnd, &ps);
1082 QWindowSystemInterface::handleSynchronousExposeEvent(window(),
1083 QRegion(qrectFromRECT(ps.rcPaint)));
1084 EndPaint(hwnd, &ps);
1086 const HDC dc = BeginPaint(hwnd, &ps);
1087 const QRect updateRect = qrectFromRECT(ps.rcPaint);
1088 if (updateRect.size() == m_data.geometry.size()) {
1089 // Store DC for access by the backing store if it has the full size.
1091 setFlag(DCFromBeginPaint);
1094 if (QWindowsContext::verboseIntegration)
1095 qDebug() << __FUNCTION__ << this << window() << updateRect;
1097 QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRegion(updateRect));
1098 if (testFlag(DCFromBeginPaint)) {
1099 clearFlag(DCFromBeginPaint);
1102 EndPaint(hwnd, &ps);
1107 void QWindowsWindow::setWindowTitle(const QString &title)
1109 if (QWindowsContext::verboseWindows)
1110 qDebug() << __FUNCTION__ << this << window() <<title;
1112 SetWindowText(m_data.hwnd, (const wchar_t*)title.utf16());
1115 Qt::WindowFlags QWindowsWindow::setWindowFlags(Qt::WindowFlags flags)
1117 if (QWindowsContext::verboseWindows)
1118 qDebug() << '>' << __FUNCTION__ << this << window() << "\n from: "
1119 << QWindowsWindow::debugWindowFlags(m_data.flags)
1120 << "\n to: " << QWindowsWindow::debugWindowFlags(flags);
1121 const QRect oldGeometry = geometry();
1122 if (m_data.flags != flags) {
1123 m_data.flags = flags;
1125 m_data = setWindowFlags_sys(flags);
1127 // When switching to a frameless window, geometry
1128 // may change without a WM_MOVE. Report change manually.
1129 // Do not send synchronously as not to clobber the widget
1130 // geometry in a sequence of setting flags and geometry.
1131 const QRect newGeometry = geometry_sys();
1132 if (oldGeometry != newGeometry)
1133 handleGeometryChange();
1135 if (QWindowsContext::verboseWindows)
1136 qDebug() << '<' << __FUNCTION__ << "\n returns: "
1137 << QWindowsWindow::debugWindowFlags(m_data.flags)
1138 << " geometry " << oldGeometry << "->" << newGeometry;
1139 return m_data.flags;
1142 QWindowsWindow::WindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt,
1143 unsigned flags) const
1145 WindowCreationData creationData;
1146 creationData.fromWindow(window(), wt, flags);
1147 creationData.applyWindowFlags(m_data.hwnd);
1148 creationData.initialize(m_data.hwnd, true, m_opacity);
1150 WindowData result = m_data;
1151 result.flags = creationData.flags;
1152 result.embedded = creationData.embedded;
1153 setFlag(FrameDirty);
1157 void QWindowsWindow::handleWindowStateChange(Qt::WindowState state)
1159 if (QWindowsContext::verboseWindows)
1160 qDebug() << __FUNCTION__ << this << window()
1161 << "\n from " << debugWindowStates(m_windowState)
1162 << " to " << debugWindowStates(state);
1163 setFlag(FrameDirty);
1164 m_windowState = state;
1165 QWindowSystemInterface::handleWindowStateChanged(window(), state);
1168 Qt::WindowState QWindowsWindow::setWindowState(Qt::WindowState state)
1171 setWindowState_sys(state);
1172 m_windowState = state;
1177 bool QWindowsWindow::isFullScreen_sys() const
1179 return geometry_sys() == window()->screen()->geometry();
1183 \brief Change the window state.
1185 \note Window frames change when maximized;
1186 the top margin shrinks somewhat but that cannot be obtained using
1187 AdjustWindowRectEx().
1189 \note Some calls to SetWindowLong require a subsequent call
1193 void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
1195 const Qt::WindowState &oldState = m_windowState;
1196 if (oldState == newState)
1198 if (QWindowsContext::verboseWindows)
1199 qDebug() << '>' << __FUNCTION__ << this << window()
1200 << " from " << debugWindowStates(oldState)
1201 << " to " << debugWindowStates(newState);
1203 const bool visible = isVisible();
1205 setFlag(FrameDirty);
1207 if ((oldState == Qt::WindowMaximized) != (newState == Qt::WindowMaximized)) {
1208 if (visible && !(newState == Qt::WindowMinimized))
1209 ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
1212 if ((oldState == Qt::WindowFullScreen) != (newState == Qt::WindowFullScreen)) {
1213 if (newState == Qt::WindowFullScreen) {
1214 #ifndef Q_FLATTEN_EXPOSE
1215 UINT newStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP;
1217 UINT newStyle = WS_POPUP;
1219 // Save geometry and style to be restored when fullscreen
1220 // is turned off again, since on Windows, it is not a real
1221 // Window state but emulated by changing geometry and style.
1222 if (!m_savedStyle) {
1223 m_savedStyle = style();
1225 if (oldState == Qt::WindowMinimized) {
1227 wp.length = sizeof(WINDOWPLACEMENT);
1228 if (GetWindowPlacement(m_data.hwnd, &wp))
1229 m_savedFrameGeometry = qrectFromRECT(wp.rcNormalPosition);
1232 m_savedFrameGeometry = frameGeometry_sys();
1237 if (m_savedStyle & WS_SYSMENU)
1238 newStyle |= WS_SYSMENU;
1240 newStyle |= WS_VISIBLE;
1243 const QRect r = window()->screen()->geometry();
1244 const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
1245 const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
1246 setFlag(SynchronousGeometryChangeEvent);
1247 SetWindowPos(m_data.hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf);
1249 clearFlag(SynchronousGeometryChangeEvent);
1250 QWindowSystemInterface::handleSynchronousGeometryChange(window(), r);
1251 } else if (newState != Qt::WindowMinimized) {
1252 // Restore saved state.
1253 unsigned newStyle = m_savedStyle ? m_savedStyle : style();
1255 newStyle |= WS_VISIBLE;
1258 UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE;
1259 if (!m_savedFrameGeometry.isValid())
1260 swpf |= SWP_NOSIZE | SWP_NOMOVE;
1261 const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
1262 setFlag(SynchronousGeometryChangeEvent);
1263 SetWindowPos(m_data.hwnd, 0, m_savedFrameGeometry.x(), m_savedFrameGeometry.y(),
1264 m_savedFrameGeometry.width(), m_savedFrameGeometry.height(), swpf);
1266 clearFlag(SynchronousGeometryChangeEvent);
1267 // preserve maximized state
1269 ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
1271 m_savedFrameGeometry = QRect();
1275 if ((oldState == Qt::WindowMinimized) != (newState == Qt::WindowMinimized)) {
1277 ShowWindow(m_data.hwnd, (newState == Qt::WindowMinimized) ? SW_MINIMIZE :
1278 (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
1280 if (QWindowsContext::verboseWindows)
1281 qDebug() << '<' << __FUNCTION__ << this << window()
1282 << debugWindowStates(newState);
1285 void QWindowsWindow::setStyle(unsigned s) const
1287 if (QWindowsContext::verboseWindows)
1288 qDebug() << __FUNCTION__ << this << window() << debugWinStyle(s);
1289 setFlag(WithinSetStyle);
1290 setFlag(FrameDirty);
1291 SetWindowLongPtr(m_data.hwnd, GWL_STYLE, s);
1292 clearFlag(WithinSetStyle);
1295 void QWindowsWindow::setExStyle(unsigned s) const
1297 if (QWindowsContext::verboseWindows)
1298 qDebug().nospace() << __FUNCTION__ << ' ' << this << ' ' << window()
1299 << " 0x" << QByteArray::number(s, 16);
1300 setFlag(FrameDirty);
1301 SetWindowLongPtr(m_data.hwnd, GWL_EXSTYLE, s);
1304 void QWindowsWindow::raise()
1306 if (QWindowsContext::verboseWindows)
1307 qDebug() << __FUNCTION__ << this << window();
1308 SetWindowPos(m_data.hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1311 void QWindowsWindow::lower()
1313 if (QWindowsContext::verboseWindows)
1314 qDebug() << __FUNCTION__ << this << window();
1316 SetWindowPos(m_data.hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1319 void QWindowsWindow::windowEvent(QEvent *event)
1321 switch (event->type()) {
1322 case QEvent::WindowBlocked: // Blocked by another modal window.
1324 setFlag(BlockedByModal);
1326 case QEvent::WindowUnblocked:
1328 clearFlag(BlockedByModal);
1335 void QWindowsWindow::propagateSizeHints()
1337 if (QWindowsContext::verboseWindows)
1338 qDebug() << __FUNCTION__ << this << window();
1341 QMargins QWindowsWindow::frameMargins() const
1343 // Frames are invalidated by style changes (window state, flags).
1344 // As they are also required for geometry calculations in resize
1345 // event sequences, introduce a dirty flag mechanism to be able
1346 // to cache results.
1347 if (testFlag(FrameDirty)) {
1348 m_data.frame = QWindowsGeometryHint::frame(style(), exStyle());
1349 clearFlag(FrameDirty);
1351 return m_data.frame;
1354 void QWindowsWindow::setOpacity(qreal level)
1356 if (QWindowsContext::verboseWindows)
1357 qDebug() << __FUNCTION__ << level;
1358 if (m_opacity != level) {
1361 setWindowOpacity(m_data.hwnd, m_data.flags, level);
1365 static inline HRGN createRectRegion(const QRect &r)
1367 return CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height());
1370 static inline void addRectToWinRegion(const QRect &rect, HRGN *winRegion)
1372 if (const HRGN rectRegion = createRectRegion(rect)) {
1373 HRGN result = CreateRectRgn(0, 0, 0, 0);
1374 if (CombineRgn(result, *winRegion, rectRegion, RGN_OR)) {
1375 DeleteObject(winRegion);
1376 *winRegion = result;
1378 DeleteObject(rectRegion);
1382 static HRGN qRegionToWinRegion(const QRegion ®ion)
1384 const QVector<QRect> rects = region.rects();
1385 if (rects.isEmpty())
1387 const int rectCount = rects.size();
1389 return createRectRegion(region.boundingRect());
1390 HRGN hRegion = createRectRegion(rects.front());
1391 for (int i = 1; i < rectCount; ++i)
1392 addRectToWinRegion(rects.at(i), &hRegion);
1396 void QWindowsWindow::setMask(const QRegion ®ion)
1398 if (region.isEmpty()) {
1399 SetWindowRgn(m_data.hwnd, 0, true);
1402 const HRGN winRegion = qRegionToWinRegion(region);
1404 // Mask is in client area coordinates, so offset it in case we have a frame
1405 if (window()->isTopLevel()) {
1406 const QMargins margins = frameMargins();
1407 OffsetRgn(winRegion, margins.left(), margins.top());
1410 // SetWindowRgn takes ownership.
1411 if (!SetWindowRgn(m_data.hwnd, winRegion, true))
1412 DeleteObject(winRegion);
1415 void QWindowsWindow::requestActivateWindow()
1417 if (QWindowsContext::verboseWindows)
1418 qDebug() << __FUNCTION__ << this << window();
1419 // 'Active' state handling is based in focus since it needs to work for
1420 // child windows as well.
1422 SetForegroundWindow(m_data.hwnd);
1423 SetFocus(m_data.hwnd);
1427 bool QWindowsWindow::setKeyboardGrabEnabled(bool grab)
1430 qWarning("%s: No handle", __FUNCTION__);
1433 if (QWindowsContext::verboseWindows)
1434 qDebug() << __FUNCTION__ << this << window() << grab;
1436 QWindowsContext *context = QWindowsContext::instance();
1438 context->setKeyGrabber(window());
1440 if (context->keyGrabber() == window())
1441 context->setKeyGrabber(0);
1446 bool QWindowsWindow::setMouseGrabEnabled(bool grab)
1448 bool result = false;
1450 qWarning("%s: No handle", __FUNCTION__);
1453 if (QWindowsContext::verboseWindows)
1454 qDebug() << __FUNCTION__ << window() << grab;
1456 if (m_mouseGrab != grab) {
1459 setMouseGrabEnabled_sys(grab);
1464 void QWindowsWindow::setMouseGrabEnabled_sys(bool grab)
1467 SetCapture(m_data.hwnd);
1473 static inline DWORD cornerToWinOrientation(Qt::Corner corner)
1476 case Qt::TopLeftCorner:
1477 return 0xf004; // SZ_SIZETOPLEFT;
1478 case Qt::TopRightCorner:
1479 return 0xf005; // SZ_SIZETOPRIGHT
1480 case Qt::BottomLeftCorner:
1481 return 0xf007; // SZ_SIZEBOTTOMLEFT
1482 case Qt::BottomRightCorner:
1483 return 0xf008; // SZ_SIZEBOTTOMRIGHT
1488 bool QWindowsWindow::startSystemResize(const QPoint &, Qt::Corner corner)
1490 if (!GetSystemMenu(m_data.hwnd, FALSE))
1494 PostMessage(m_data.hwnd, WM_SYSCOMMAND, cornerToWinOrientation(corner), 0);
1495 setFlag(SizeGripOperation);
1499 void QWindowsWindow::setFrameStrutEventsEnabled(bool enabled)
1502 setFlag(FrameStrutEventsEnabled);
1504 clearFlag(FrameStrutEventsEnabled);
1508 #ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO
1509 void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
1511 const QWindowsGeometryHint hint(window());
1512 hint.applyToMinMaxInfo(m_data.hwnd, mmi);
1513 if (QWindowsContext::verboseWindows)
1514 qDebug() << __FUNCTION__ << window() << *mmi;
1516 #endif // !Q_OS_WINCE
1519 \brief Applies to cursor property set on the window to the global cursor.
1524 void QWindowsWindow::applyCursor()
1526 SetCursor(m_cursor.handle());
1529 void QWindowsWindow::setCursor(const QWindowsWindowCursor &c)
1531 if (c.handle() != m_cursor.handle()) {
1532 const bool underMouse = QWindowsContext::instance()->windowUnderMouse() == window();
1533 if (QWindowsContext::verboseWindows)
1534 qDebug() << window() << __FUNCTION__ << "Shape=" << c.cursor().shape()
1535 << " isWUM=" << underMouse;
1543 \brief Find a child window using flags from ChildWindowFromPointEx.
1546 QWindowsWindow *QWindowsWindow::childAtScreenPoint(const QPoint &screenPoint,
1547 unsigned cwexflags) const
1550 return QWindowsContext::instance()->findPlatformWindowAt(m_data.hwnd, screenPoint, cwexflags);
1554 QWindowsWindow *QWindowsWindow::childAt(const QPoint &clientPoint, unsigned cwexflags) const
1557 return childAtScreenPoint(QWindowsGeometryHint::mapToGlobal(m_data.hwnd, clientPoint),
1563 void QWindowsWindow::alertWindow(int durationMs)
1565 DWORD timeOutMs = GetCaretBlinkTime();
1566 if (!timeOutMs || timeOutMs == INFINITE)
1570 info.cbSize = sizeof(info);
1571 info.hwnd = m_data.hwnd;
1572 info.dwFlags = FLASHW_TRAY;
1573 info.dwTimeout = timeOutMs;
1574 info.uCount = durationMs == 0 ? 10 : durationMs / timeOutMs;
1575 FlashWindowEx(&info);
1578 void QWindowsWindow::stopAlertWindow()
1581 info.cbSize = sizeof(info);
1582 info.hwnd = m_data.hwnd;
1583 info.dwFlags = FLASHW_STOP;
1586 FlashWindowEx(&info);
1588 #endif // !Q_OS_WINCE
1590 bool QWindowsWindow::isEnabled() const
1592 return (style() & WS_DISABLED) == 0;
1595 void QWindowsWindow::setEnabled(bool enabled)
1597 const unsigned oldStyle = style();
1598 unsigned newStyle = oldStyle;
1600 newStyle &= ~WS_DISABLED;
1602 newStyle |= WS_DISABLED;
1604 if (newStyle != oldStyle)
1608 #ifdef QT_OPENGL_ES_2
1609 EGLSurface QWindowsWindow::ensureEglSurfaceHandle(const QWindowsWindow::QWindowsEGLStaticContextPtr &staticContext, EGLConfig config)
1611 if (!m_eglSurface) {
1612 m_staticEglContext = staticContext;
1613 m_eglSurface = eglCreateWindowSurface(staticContext->display(), config, (EGLNativeWindowType)m_data.hwnd, NULL);
1614 if (m_eglSurface == EGL_NO_SURFACE)
1615 qWarning("%s: Could not create the egl surface (eglCreateWindowSurface failed): error = 0x%x\n",
1616 Q_FUNC_INFO, eglGetError());
1617 if (QWindowsContext::verboseGL)
1618 qDebug("%s: Created EGL surface %p, this = %p",
1619 __FUNCTION__, m_eglSurface, this);
1621 return m_eglSurface;
1623 #endif // QT_OPENGL_ES_2
1625 QByteArray QWindowsWindow::debugWindowFlags(Qt::WindowFlags wf)
1627 const int iwf = int(wf);
1628 QByteArray rc = "0x";
1629 rc += QByteArray::number(iwf, 16);
1632 switch ((iwf & Qt::WindowType_Mask)) {
1654 case Qt::SplashScreen:
1655 rc += " SplashScreen";
1664 if (iwf & Qt::MSWindowsFixedSizeDialogHint) rc += " MSWindowsFixedSizeDialogHint";
1665 if (iwf & Qt::MSWindowsOwnDC) rc += " MSWindowsOwnDC";
1666 if (iwf & Qt::FramelessWindowHint) rc += " FramelessWindowHint";
1667 if (iwf & Qt::WindowTitleHint) rc += " WindowTitleHint";
1668 if (iwf & Qt::WindowSystemMenuHint) rc += " WindowSystemMenuHint";
1669 if (iwf & Qt::WindowMinimizeButtonHint) rc += " WindowMinimizeButtonHint";
1670 if (iwf & Qt::WindowMaximizeButtonHint) rc += " WindowMaximizeButtonHint";
1671 if (iwf & Qt::WindowContextHelpButtonHint) rc += " WindowContextHelpButtonHint";
1672 if (iwf & Qt::WindowShadeButtonHint) rc += " WindowShadeButtonHint";
1673 if (iwf & Qt::WindowStaysOnTopHint) rc += " WindowStaysOnTopHint";
1674 if (iwf & Qt::CustomizeWindowHint) rc += " CustomizeWindowHint";
1675 if (iwf & Qt::WindowStaysOnBottomHint) rc += " WindowStaysOnBottomHint";
1676 if (iwf & Qt::WindowCloseButtonHint) rc += " WindowCloseButtonHint";