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