summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@theqtcompany.com>2016-01-08 14:59:22 +0100
committerFriedemann Kleint <Friedemann.Kleint@theqtcompany.com>2016-01-30 16:08:14 +0000
commit14efcaa3921687129d4dca9b7d5794668a329cd6 (patch)
tree701403aae68a312f506b37ec21ed2e7e1aada47b /src/plugins
parent6b285de8ec616ec7110515f503090e5b3a5efe46 (diff)
Windows QPA: Improve handling of windows of type Qt::ForeignWindow.
Extract a base class QWindowsBaseWindow from QWindowsWindow that provides _sys() getters for geometry and margin calculation and implements QPlatformWindow::geometry()/ frameMargins() to be calculated from the HWND. Implement a QWindowsDesktopWindow class directly inheriting QWindowsBaseWindow which does not allow any manipulation. Add a thin QWindowsForeignWindow class that wraps a foreign window id and always returns correct geometry/margin information when queried. Simple reparenting and manipulation of geometry for child windows is also implemented, allowing for embedding foreign windows into Qt. When calling other setters on it, the unimplemented warnings of QPlatformWindow will trigger. Remove the special casing for foreign/desktop window from QWindowsWindow. The existing mechanism to cache the geometry/margin values in QWindowsWindow remains as is. Rename the existing QWindowsWindow::baseWindowOf() and add checks there. Task-number: QTBUG-50206 Task-number: QTBUG-41186 Change-Id: Ib57cb87e3981312d32920fe3e49f0b1c4ad516a3 Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp20
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp9
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp270
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h117
8 files changed, 308 insertions, 132 deletions
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 &region,
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<HWND>(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<HWND>(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)
@@ -849,6 +823,153 @@ bool QWindowsGeometryHint::positionIncludesFrame(const QWindow *w)
}
/*!
+ \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<QWindowsBaseWindow *>(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<const wchar_t *>(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<HWND>(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<const QWindowsWindow *>(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() <<title;
- if (m_data.hwnd) {
- const QString fullTitle = formatWindowTitle(title, QStringLiteral(" - "));
- SetWindowText(m_data.hwnd, (const wchar_t*)fullTitle.utf16());
- }
+ setWindowTitle_sys(QWindowsWindow::formatWindowTitle(title, QStringLiteral(" - ")));
}
void QWindowsWindow::setWindowFlags(Qt::WindowFlags flags)
@@ -1643,8 +1740,8 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowState state)
}
foreach (QWindow *child, QGuiApplication::allWindows()) {
if (child != w && child->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<QWindowsWindow *>(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<QWindowsWindow *>(pw);
+ }
+ }
+ return result;
}
void *QWindowsWindow::userDataOf(HWND hwnd)