diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp index 0f41d01716..b2cd5b124b 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp +++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp @@ -84,7 +84,8 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion ®ion, const QRect br = region.boundingRect(); if (QWindowsContext::verbose > 1) qCDebug(lcQpaBackingStore) << __FUNCTION__ << this << window << offset << br; - QWindowsWindow *rw = QWindowsWindow::baseWindowOf(window); + QWindowsWindow *rw = QWindowsWindow::windowsWindowOf(window); + Q_ASSERT(rw); #ifndef Q_OS_WINCE const bool hasAlpha = rw->format().hasAlpha(); diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 2f133ba705..1f66de23ca 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -1177,8 +1177,11 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, d->m_tabletSupport->notifyActivate(); #endif // !QT_NO_TABLETEVENT if (platformWindow->testFlag(QWindowsWindow::BlockedByModal)) - if (const QWindow *modalWindow = QGuiApplication::modalWindow()) - QWindowsWindow::baseWindowOf(modalWindow)->alertWindow(); + if (const QWindow *modalWindow = QGuiApplication::modalWindow()) { + QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(modalWindow); + Q_ASSERT(platformWindow); + platformWindow->alertWindow(); + } break; case QtWindows::MouseActivateWindowEvent: if (platformWindow->window()->flags() & Qt::WindowDoesNotAcceptFocus) { diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index 13514b47b5..166328cf5e 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -648,17 +648,19 @@ QWindowsCursor::QWindowsCursor(const QPlatformScreen *screen) void QWindowsCursor::changeCursor(QCursor *cursorIn, QWindow *window) { - if (!window) + QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(window); + if (!platformWindow) // Desktop/Foreign window. return; + if (!cursorIn) { - QWindowsWindow::baseWindowOf(window)->setCursor(CursorHandlePtr(new CursorHandle)); + platformWindow->setCursor(CursorHandlePtr(new CursorHandle)); return; } const CursorHandlePtr wcursor = cursorIn->shape() == Qt::BitmapCursor ? pixmapWindowCursor(*cursorIn) : standardWindowCursor(cursorIn->shape()); if (wcursor->handle()) { - QWindowsWindow::baseWindowOf(window)->setCursor(wcursor); + platformWindow->setCursor(wcursor); } else { qWarning("%s: Unable to obtain system cursor for %d", __FUNCTION__, cursorIn->shape()); diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index e223a2ad93..f1addf186d 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -233,12 +233,10 @@ void QWindowsInputContext::updateEnabled() { if (!QGuiApplication::focusObject()) return; - const QWindow *window = QGuiApplication::focusWindow(); - if (window && window->handle()) { - QWindowsWindow *platformWindow = QWindowsWindow::baseWindowOf(window); + if (QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(QGuiApplication::focusWindow())) { const bool accepted = inputMethodAccepted(); if (QWindowsContext::verbose > 1) - qCDebug(lcQpaInputMethods) << __FUNCTION__ << window << "accepted=" << accepted; + qCDebug(lcQpaInputMethods) << __FUNCTION__ << platformWindow->window() << "accepted=" << accepted; QWindowsInputContext::setWindowsImeEnabled(platformWindow, accepted); } } diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index d975460ec7..2904999d96 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -302,6 +302,26 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const { + if (window->type() == Qt::Desktop) { + QWindowsDesktopWindow *result = new QWindowsDesktopWindow(window); + qCDebug(lcQpaWindows) << "Desktop window:" << window + << showbase << hex << result->winId() << noshowbase << dec << result->geometry(); + return result; + } + + if (window->type() == Qt::ForeignWindow) { + QWindowsForeignWindow *result = new QWindowsForeignWindow(window, reinterpret_cast(window->winId())); + const QRect obtainedGeometry = result->geometry(); + QScreen *screen = Q_NULLPTR; + if (const QPlatformScreen *pScreen = result->screenForGeometry(obtainedGeometry)) + screen = pScreen->screen(); + if (screen && screen != window->screen()) + window->setScreen(screen); + qCDebug(lcQpaWindows) << "Foreign window:" << window << showbase << hex + << result->winId() << noshowbase << dec << obtainedGeometry << screen; + return result; + } + QWindowsWindowData requested; requested.flags = window->flags(); requested.geometry = QHighDpi::toNativePixels(window->geometry(), window); diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 2bc9527b1b..c8b18f3b57 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -267,7 +267,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, // Capture is necessary so we don't get WM_MOUSELEAVEs to confuse matters. // This autocapture is released normally when button is released. if (!platformWindow->hasMouseCapture()) { - QWindowsWindow::baseWindowOf(window)->applyCursor(); + platformWindow->applyCursor(); platformWindow->setMouseGrabEnabled(true); platformWindow->setFlag(QWindowsWindow::AutoMouseCapture); qCDebug(lcQpaEvents) << "Automatic mouse capture for missing buttondown event" << window; @@ -355,7 +355,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, m_trackedWindow = 0; // We are not officially in any window, but we need to set some cursor to clear // whatever cursor the left window had, so apply the cursor of the capture window. - QWindowsWindow::baseWindowOf(window)->applyCursor(); + platformWindow->applyCursor(); } } // Enter is needed if: @@ -367,7 +367,8 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, || (m_previousCaptureWindow && window != m_previousCaptureWindow && currentWindowUnderMouse && currentWindowUnderMouse != m_previousCaptureWindow)) { qCDebug(lcQpaEvents) << "Entering " << currentWindowUnderMouse; - QWindowsWindow::baseWindowOf(currentWindowUnderMouse)->applyCursor(); + if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderMouse)) + wumPlatformWindow->applyCursor(); QWindowSystemInterface::handleEnterEvent(currentWindowUnderMouse, currentWindowUnderMouse->mapFromGlobal(globalPosition), globalPosition); @@ -392,7 +393,7 @@ static bool isValidWheelReceiver(QWindow *candidate) { if (candidate) { const QWindow *toplevel = QWindowsWindow::topLevelOf(candidate); - if (const QWindowsWindow *ww = QWindowsWindow::baseWindowOf(toplevel)) + if (const QWindowsWindow *ww = QWindowsWindow::windowsWindowOf(toplevel)) return !ww->testFlag(QWindowsWindow::BlockedByModal); } diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 218de5da85..246ebcb238 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -418,7 +418,7 @@ struct WindowCreationData enum Flags { ForceChild = 0x1, ForceTopLevel = 0x2 }; WindowCreationData() : parentHandle(0), type(Qt::Widget), style(0), exStyle(0), - topLevel(false), popup(false), dialog(false), desktop(false), + topLevel(false), popup(false), dialog(false), tool(false), embedded(false), hasAlpha(false) {} void fromWindow(const QWindow *w, const Qt::WindowFlags flags, unsigned creationFlags = 0); @@ -434,7 +434,6 @@ struct WindowCreationData bool topLevel; bool popup; bool dialog; - bool desktop; bool tool; bool embedded; bool hasAlpha; @@ -449,7 +448,7 @@ QDebug operator<<(QDebug debug, const WindowCreationData &d) << "\n topLevel=" << d.topLevel; if (d.parentHandle) debug << " parent=" << d.parentHandle; - debug << " popup=" << d.popup << " dialog=" << d.dialog << " desktop=" << d.desktop + debug << " popup=" << d.popup << " dialog=" << d.dialog << " embedded=" << d.embedded << " tool=" << d.tool << "\n style=" << debugWinStyle(d.style); if (d.exStyle) @@ -518,9 +517,6 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag case Qt::Popup: popup = true; break; - case Qt::Desktop: - desktop = true; - break; default: break; } @@ -537,7 +533,7 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag if (popup || (type == Qt::ToolTip) || (type == Qt::SplashScreen)) { style = WS_POPUP; - } else if (topLevel && !desktop) { + } else if (topLevel) { if (flags & Qt::FramelessWindowHint) style = WS_POPUP; // no border else if (flags & Qt::WindowTitleHint) @@ -548,7 +544,6 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag style = WS_CHILD; } - if (!desktop) { // if (!testAttribute(Qt::WA_PaintUnclipped)) // ### Commented out for now as it causes some problems, but // this should be correct anyway, so dig some more into this @@ -594,7 +589,6 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag if (flagsIn & Qt::WindowTransparentForInput) exStyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT; #endif - } } } @@ -606,26 +600,6 @@ QWindowsWindowData WindowData result; result.flags = flags; - if (desktop) { // desktop widget. No frame, hopefully? - result.hwnd = GetDesktopWindow(); - result.geometry = frameGeometry(result.hwnd, true); - result.embedded = false; - qCDebug(lcQpaWindows) << "Created desktop window " << w << result.hwnd; - return result; - } - if ((flags & Qt::WindowType_Mask) == Qt::ForeignWindow) { - result.hwnd = reinterpret_cast(w->winId()); - Q_ASSERT(result.hwnd); - const LONG_PTR style = GetWindowLongPtr(result.hwnd, GWL_STYLE); - const LONG_PTR exStyle = GetWindowLongPtr(result.hwnd, GWL_EXSTYLE); - result.embedded = false; - result.frame = QWindowsGeometryHint::frame(style, exStyle); - result.geometry = frameGeometry(result.hwnd, !GetParent(result.hwnd)) - .marginsRemoved(result.frame); - qCDebug(lcQpaWindows) << "Foreign window: " << w << result.hwnd << result.geometry; - return result; - } - const HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0); const QString windowClassName = QWindowsContext::instance()->registerWindowClass(w); @@ -697,7 +671,7 @@ void WindowCreationData::applyWindowFlags(HWND hwnd) const void WindowCreationData::initialize(const QWindow *w, HWND hwnd, bool frameChange, qreal opacityLevel) const { - if (desktop || !hwnd) + if (!hwnd) return; UINT swpFlags = SWP_NOMOVE | SWP_NOSIZE; if (frameChange) @@ -848,6 +822,153 @@ bool QWindowsGeometryHint::positionIncludesFrame(const QWindow *w) == QWindowPrivate::WindowFrameInclusive; } +/*! + \class QWindowsBaseWindow + \brief Base class for QWindowsForeignWindow, QWindowsWindow + + The class provides some _sys() getters for querying window + data from a HWND and some _sys() setters. + + Derived classes wrapping foreign windows may use them directly + to calculate geometry, margins, etc. + + Derived classes representing windows created by Qt may defer + expensive calculations until change notifications are received. + + \since 5.6 + \internal + \ingroup qt-lighthouse-win +*/ + +QWindowsBaseWindow *QWindowsBaseWindow::baseWindowOf(const QWindow *w) +{ + if (w) { + if (QPlatformWindow *pw = w->handle()) + return static_cast(pw); + } + return Q_NULLPTR; +} + +HWND QWindowsBaseWindow::handleOf(const QWindow *w) +{ + const QWindowsBaseWindow *bw = QWindowsBaseWindow::baseWindowOf(w); + return bw ? bw->handle() : HWND(0); +} + +bool QWindowsBaseWindow::isTopLevel_sys() const +{ + const HWND parent = parentHwnd(); + return !parent || parent == GetDesktopWindow(); +} + +QRect QWindowsBaseWindow::frameGeometry_sys() const +{ + return frameGeometry(handle(), isTopLevel()); +} + +QRect QWindowsBaseWindow::geometry_sys() const +{ + return frameGeometry_sys().marginsRemoved(frameMargins()); +} + +QMargins QWindowsBaseWindow::frameMargins_sys() const +{ + return QWindowsGeometryHint::frame(style(), exStyle()); +} + +void QWindowsBaseWindow::hide_sys() // Normal hide, do not activate other windows. +{ + SetWindowPos(handle(),0 , 0, 0, 0, 0, + SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); +} + +void QWindowsBaseWindow::raise_sys() +{ + qCDebug(lcQpaWindows) << __FUNCTION__ << this << window(); + SetWindowPos(handle(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); +} + +void QWindowsBaseWindow::lower_sys() +{ + qCDebug(lcQpaWindows) << __FUNCTION__ << this << window(); + SetWindowPos(handle(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); +} + +void QWindowsBaseWindow::setWindowTitle_sys(const QString &title) +{ + qCDebug(lcQpaWindows) << __FUNCTION__ << this << window() << title; + SetWindowText(handle(), reinterpret_cast(title.utf16())); +} + +QPoint QWindowsBaseWindow::mapToGlobal(const QPoint &pos) const +{ + return QWindowsGeometryHint::mapToGlobal(handle(), pos); +} + +QPoint QWindowsBaseWindow::mapFromGlobal(const QPoint &pos) const +{ + return QWindowsGeometryHint::mapFromGlobal(handle(), pos); +} + +/*! + \class QWindowsDesktopWindow + \brief Window wrapping GetDesktopWindow not allowing any manipulation. + \since 5.6 + \internal + \ingroup qt-lighthouse-win +*/ + +/*! + \class QWindowsForeignWindow + \brief Window wrapping a foreign native window. + + QWindowsForeignWindow stores a native HWND and implements getters for + geometry, margins, etc. reparenting and geometry manipulation for use as a + child window in Qt. + + \since 5.6 + \internal + \ingroup qt-lighthouse-win +*/ + +QWindowsForeignWindow::QWindowsForeignWindow(QWindow *window, HWND hwnd) + : QWindowsBaseWindow(window) + , m_hwnd(hwnd) + , m_topLevelStyle(0) +{ +} + +void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow) +{ + const bool wasTopLevel = isTopLevel_sys(); + const HWND newParent = newParentWindow ? reinterpret_cast(newParentWindow->winId()) : HWND(0); + const bool isTopLevel = !newParent; + const DWORD oldStyle = style(); + qCDebug(lcQpaWindows) << __FUNCTION__ << window() << "newParent=" + << newParentWindow << newParent << "oldStyle=" << debugWinStyle(oldStyle); + SetParent(m_hwnd, newParent); + if (wasTopLevel != isTopLevel) { // Top level window flags need to be set/cleared manually. + DWORD newStyle = oldStyle; + if (isTopLevel) { + newStyle = m_topLevelStyle; + } else { + m_topLevelStyle = oldStyle; + newStyle &= ~(WS_OVERLAPPEDWINDOW | WS_POPUPWINDOW); + newStyle |= WS_CHILD; + } + SetWindowLongPtr(m_hwnd, GWL_STYLE, newStyle); + } +} + +void QWindowsForeignWindow::setVisible(bool visible) +{ + qCDebug(lcQpaWindows) << __FUNCTION__ << window() << visible; + if (visible) + ShowWindow(handle(), SW_SHOWNOACTIVATE); + else + hide_sys(); +} + /*! \class QWindowCreationContext \brief Active Context for creating windows. @@ -928,7 +1049,7 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w, */ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) : - QPlatformWindow(aWindow), + QWindowsBaseWindow(aWindow), m_data(data), m_flags(WithinCreate), m_hdc(0), @@ -1006,7 +1127,7 @@ void QWindowsWindow::destroyWindow() setFlag(WithinDestroy); // Clear any transient child relationships as Windows will otherwise destroy them (QTBUG-35499, QTBUG-36666) if (QWindow *transientChild = findTransientChild(window())) - if (QWindowsWindow *tw = QWindowsWindow::baseWindowOf(transientChild)) + if (QWindowsWindow *tw = QWindowsWindow::windowsWindowOf(transientChild)) tw->updateTransientParent(); QWindowsContext *context = QWindowsContext::instance(); if (context->windowUnderMouse() == window()) @@ -1029,8 +1150,7 @@ void QWindowsWindow::destroyWindow() } } #endif // !Q_OS_WINCE - if (m_data.hwnd != GetDesktopWindow() && window()->type() != Qt::ForeignWindow) - DestroyWindow(m_data.hwnd); + DestroyWindow(m_data.hwnd); context->removeWindow(m_data.hwnd); m_data.hwnd = 0; } @@ -1143,7 +1263,10 @@ void QWindowsWindow::setVisible(bool visible) } else { if (hasMouseCapture()) setMouseGrabEnabled(false); - hide_sys(); + if (window()->flags() & Qt::Popup) // from QWidgetPrivate::hide_sys(), activate other + ShowWindow(m_data.hwnd, SW_HIDE); + else + hide_sys(); fireExpose(QRegion()); } } @@ -1219,7 +1342,7 @@ void QWindowsWindow::updateTransientParent() const const HWND oldTransientParent = transientParentHwnd(m_data.hwnd); HWND newTransientParent = 0; if (const QWindow *tp = window()->transientParent()) - if (const QWindowsWindow *tw = QWindowsWindow::baseWindowOf(tp)) + if (const QWindowsWindow *tw = QWindowsWindow::windowsWindowOf(tp)) if (!tw->testFlag(WithinDestroy)) // Prevent destruction by parent window (QTBUG-35499, QTBUG-36666) newTransientParent = tw->handle(); if (newTransientParent != oldTransientParent) @@ -1283,18 +1406,6 @@ void QWindowsWindow::show_sys() const } } -// partially from QWidgetPrivate::hide_sys() -void QWindowsWindow::hide_sys() const -{ - const Qt::WindowFlags flags = window()->flags(); - if (flags != Qt::Desktop) { - if (flags & Qt::Popup) - ShowWindow(m_data.hwnd, SW_HIDE); - else - SetWindowPos(m_data.hwnd,0, 0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE); - } -} - void QWindowsWindow::setParent(const QPlatformWindow *newParent) { qCDebug(lcQpaWindows) << __FUNCTION__ << window() << newParent; @@ -1306,7 +1417,7 @@ void QWindowsWindow::setParent(const QPlatformWindow *newParent) void QWindowsWindow::setParent_sys(const QPlatformWindow *parent) { // Use GetAncestor instead of GetParent, as GetParent can return owner window for toplevels - HWND oldParentHWND = GetAncestor(m_data.hwnd, GA_PARENT); + HWND oldParentHWND = parentHwnd(); HWND newParentHWND = 0; if (parent) { const QWindowsWindow *parentW = static_cast(parent); @@ -1470,7 +1581,7 @@ void QWindowsWindow::handleGeometryChange() qCDebug(lcQpaEvents) << __FUNCTION__ << this << window() << m_data.geometry; } -void QWindowsWindow::setGeometry_sys(const QRect &rect) const +void QWindowsBaseWindow::setGeometry_sys(const QRect &rect) const { const QMargins margins = frameMargins(); const QRect frameGeometry = rect + margins; @@ -1482,38 +1593,28 @@ void QWindowsWindow::setGeometry_sys(const QRect &rect) const bool result = false; #ifndef Q_OS_WINCE + const HWND hwnd = handle(); WINDOWPLACEMENT windowPlacement; windowPlacement.length = sizeof(WINDOWPLACEMENT); - GetWindowPlacement(m_data.hwnd, &windowPlacement); + GetWindowPlacement(hwnd, &windowPlacement); // If the window is hidden and in maximized state or minimized, instead of moving the // window, set the normal position of the window. - if ((windowPlacement.showCmd == SW_MAXIMIZE && !IsWindowVisible(m_data.hwnd)) + if ((windowPlacement.showCmd == SW_MAXIMIZE && !IsWindowVisible(hwnd)) || windowPlacement.showCmd == SW_SHOWMINIMIZED) { windowPlacement.rcNormalPosition = - RECTfromQRect(frameGeometry.translated(-windowPlacementOffset(m_data.hwnd, frameGeometry.topLeft()))); + RECTfromQRect(frameGeometry.translated(-windowPlacementOffset(hwnd, frameGeometry.topLeft()))); windowPlacement.showCmd = windowPlacement.showCmd == SW_SHOWMINIMIZED ? SW_SHOWMINIMIZED : SW_HIDE; - result = SetWindowPlacement(m_data.hwnd, &windowPlacement); + result = SetWindowPlacement(hwnd, &windowPlacement); } else #endif // !Q_OS_WINCE { - result = MoveWindow(m_data.hwnd, frameGeometry.x(), frameGeometry.y(), + result = MoveWindow(hwnd, frameGeometry.x(), frameGeometry.y(), frameGeometry.width(), frameGeometry.height(), true); } qCDebug(lcQpaWindows) << '<' << __FUNCTION__ << window() << "\n resulting " << result << geometry_sys(); } -QRect QWindowsWindow::frameGeometry_sys() const -{ - bool isRealTopLevel = window()->isTopLevel() && !m_data.embedded; - return frameGeometry(m_data.hwnd, isRealTopLevel); -} - -QRect QWindowsWindow::geometry_sys() const -{ - return frameGeometry_sys().marginsRemoved(frameMargins()); -} - /*! Allocates a HDC for the window or returns the temporary one obtained from WinAPI BeginPaint within a WM_PAINT event. @@ -1572,11 +1673,7 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message, void QWindowsWindow::setWindowTitle(const QString &title) { - qCDebug(lcQpaWindows) << __FUNCTION__ << this << window() <isVisible() && child->transientParent() == w) { - QWindowsWindow *platformWindow = QWindowsWindow::baseWindowOf(child); - if (platformWindow->isLayered()) { + QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(child); + if (platformWindow && platformWindow->isLayered()) { platformWindow->fireExpose(QRegion(0, 0, child->width(), child->height())); exposeEventsSent = true; } @@ -1819,19 +1916,6 @@ void QWindowsWindow::setExStyle(unsigned s) const SetWindowLongPtr(m_data.hwnd, GWL_EXSTYLE, s); } -void QWindowsWindow::raise() -{ - qCDebug(lcQpaWindows) << __FUNCTION__ << this << window(); - SetWindowPos(m_data.hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); -} - -void QWindowsWindow::lower() -{ - qCDebug(lcQpaWindows) << __FUNCTION__ << this << window(); - if (m_data.hwnd) - SetWindowPos(m_data.hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); -} - void QWindowsWindow::windowEvent(QEvent *event) { switch (event->type()) { @@ -2152,7 +2236,8 @@ static inline bool applyNewCursor(const QWindow *w) for (const QWindow *p = underMouse; p ; p = p->parent()) { if (p == w) return true; - if (!QWindowsWindow::baseWindowOf(p)->cursor()->isNull()) + const QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(p); + if (platformWindow && !platformWindow->cursor()->isNull()) return false; } return false; @@ -2170,7 +2255,8 @@ void QWindowsWindow::applyCursor() #ifndef QT_NO_CURSOR if (m_cursor->isNull()) { // Recurse up to parent with non-null cursor. Set default for toplevel. if (const QWindow *p = window()->parent()) { - QWindowsWindow::baseWindowOf(p)->applyCursor(); + if (QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(p)) + platformWindow->applyCursor(); } else { SetCursor(defaultCursor(window())->handle()); } @@ -2281,6 +2367,11 @@ void QWindowsWindow::setWindowIcon(const QIcon &icon) } } +bool QWindowsWindow::isTopLevel() const +{ + return window()->isTopLevel() && !m_data.embedded; +} + /*! \brief Sets custom margins to be added to the default margins determined by the windows style in the handling of the WM_NCCALCSIZE message. @@ -2345,8 +2436,7 @@ void QWindowsWindow::setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWind void QWindowsWindow::registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes) { #ifndef Q_OS_WINCE - if ((QWindowsContext::instance()->systemInfo() & QWindowsContext::SI_SupportsTouch) - && window()->type() != Qt::ForeignWindow) { + if ((QWindowsContext::instance()->systemInfo() & QWindowsContext::SI_SupportsTouch)) { ULONG touchFlags = 0; const bool ret = QWindowsContext::user32dll.isTouchWindow(m_data.hwnd, &touchFlags); // Return if it is not a touch window or the flags are already set by a hook diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 8497931b9a..999761f3c6 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -118,7 +118,78 @@ struct QWindowsWindowData const QString &title); }; -class QWindowsWindow : public QPlatformWindow +class QWindowsBaseWindow : public QPlatformWindow +{ +public: + explicit QWindowsBaseWindow(QWindow *window) : QPlatformWindow(window) {} + + WId winId() const Q_DECL_OVERRIDE { return WId(handle()); } + QRect geometry() const Q_DECL_OVERRIDE { return geometry_sys(); } + QMargins frameMargins() const Q_DECL_OVERRIDE { return frameMargins_sys(); } + QPoint mapToGlobal(const QPoint &pos) const Q_DECL_OVERRIDE; + QPoint mapFromGlobal(const QPoint &pos) const Q_DECL_OVERRIDE; + + using QPlatformWindow::screenForGeometry; + + virtual HWND handle() const = 0; + virtual bool isTopLevel() const { return isTopLevel_sys(); } + + unsigned style() const { return GetWindowLongPtr(handle(), GWL_STYLE); } + unsigned exStyle() const { return GetWindowLongPtr(handle(), GWL_EXSTYLE); } + + static QWindowsBaseWindow *baseWindowOf(const QWindow *w); + static HWND handleOf(const QWindow *w); + +protected: + HWND parentHwnd() const { return GetAncestor(handle(), GA_PARENT); } + bool isTopLevel_sys() const; + QRect frameGeometry_sys() const; + QRect geometry_sys() const; + void setGeometry_sys(const QRect &rect) const; + QMargins frameMargins_sys() const; + void hide_sys(); + void raise_sys(); + void lower_sys(); + void setWindowTitle_sys(const QString &title); +}; + +class QWindowsDesktopWindow : public QWindowsBaseWindow +{ +public: + explicit QWindowsDesktopWindow(QWindow *window) + : QWindowsBaseWindow(window), m_hwnd(GetDesktopWindow()) {} + + QMargins frameMargins() const Q_DECL_OVERRIDE { return QMargins(); } + bool isTopLevel() const Q_DECL_OVERRIDE { return true; } + +protected: + HWND handle() const Q_DECL_OVERRIDE { return m_hwnd; } + +private: + const HWND m_hwnd; +}; + +class QWindowsForeignWindow : public QWindowsBaseWindow +{ +public: + explicit QWindowsForeignWindow(QWindow *window, HWND hwnd); + + void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE; + void setGeometry(const QRect &rect) Q_DECL_OVERRIDE { setGeometry_sys(rect); } + void setVisible(bool visible) Q_DECL_OVERRIDE; + void raise() Q_DECL_OVERRIDE { raise_sys(); } + void lower() Q_DECL_OVERRIDE { lower_sys(); } + void setWindowTitle(const QString &title) Q_DECL_OVERRIDE { setWindowTitle_sys(title); } + +protected: + HWND handle() const Q_DECL_OVERRIDE { return m_hwnd; } + +private: + const HWND m_hwnd; + DWORD m_topLevelStyle; +}; + +class QWindowsWindow : public QWindowsBaseWindow { public: enum Flags @@ -168,14 +239,11 @@ public: void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE; void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE; - HWND handle() const { return m_data.hwnd; } - - WId winId() const Q_DECL_OVERRIDE { return WId(m_data.hwnd); } void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE; void setWindowTitle(const QString &title) Q_DECL_OVERRIDE; - void raise() Q_DECL_OVERRIDE; - void lower() Q_DECL_OVERRIDE; + void raise() Q_DECL_OVERRIDE { raise_sys(); } + void lower() Q_DECL_OVERRIDE { lower_sys(); } void windowEvent(QEvent *event) Q_DECL_OVERRIDE; @@ -198,14 +266,14 @@ public: void setFrameStrutEventsEnabled(bool enabled) Q_DECL_OVERRIDE; bool frameStrutEventsEnabled() const Q_DECL_OVERRIDE { return testFlag(FrameStrutEventsEnabled); } + // QWindowsBaseWindow overrides + HWND handle() const Q_DECL_OVERRIDE { return m_data.hwnd; } + bool isTopLevel() const Q_DECL_OVERRIDE; + QMargins customMargins() const { return m_data.customMargins; } void setCustomMargins(const QMargins &m); - inline unsigned style() const - { return GetWindowLongPtr(m_data.hwnd, GWL_STYLE); } void setStyle(unsigned s) const; - inline unsigned exStyle() const - { return GetWindowLongPtr(m_data.hwnd, GWL_EXSTYLE); } void setExStyle(unsigned s) const; bool handleWmPaint(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); @@ -215,8 +283,7 @@ public: void handleHidden(); void handleCompositionSettingsChanged(); - static inline HWND handleOf(const QWindow *w); - static inline QWindowsWindow *baseWindowOf(const QWindow *w); + static QWindowsWindow *windowsWindowOf(const QWindow *w); static QWindow *topLevelOf(QWindow *w); static inline void *userDataOf(HWND hwnd); static inline void setUserDataOf(HWND hwnd, void *ud); @@ -262,10 +329,6 @@ public: void setHasBorderInFullScreen(bool border); private: inline void show_sys() const; - inline void hide_sys() const; - inline void setGeometry_sys(const QRect &rect) const; - inline QRect frameGeometry_sys() const; - inline QRect geometry_sys() const; inline QWindowsWindowData setWindowFlags_sys(Qt::WindowFlags wt, unsigned flags = 0) const; inline bool isFullScreen_sys() const; inline void setWindowState_sys(Qt::WindowState newState); @@ -334,19 +397,17 @@ QPoint QWindowsGeometryHint::mapFromGlobal(const QWindow *w, const QPoint &p) // ---------- QWindowsBaseWindow inline functions. -QWindowsWindow *QWindowsWindow::baseWindowOf(const QWindow *w) +inline QWindowsWindow *QWindowsWindow::windowsWindowOf(const QWindow *w) { - if (w) - if (QPlatformWindow *pw = w->handle()) - return static_cast(pw); - return 0; -} - -HWND QWindowsWindow::handleOf(const QWindow *w) -{ - if (const QWindowsWindow *bw = QWindowsWindow::baseWindowOf(w)) - return bw->handle(); - return 0; + QWindowsWindow *result = Q_NULLPTR; + if (w) { + const Qt::WindowType type = w->type(); + if (type != Qt::Desktop && type != Qt::ForeignWindow) { + if (QPlatformWindow *pw = w->handle()) + result = static_cast(pw); + } + } + return result; } void *QWindowsWindow::userDataOf(HWND hwnd)