diff options
5 files changed, 64 insertions, 24 deletions
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 2def926409..c5146aac84 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -1401,7 +1401,7 @@ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPAR marginsFromRects(ncCalcSizeFrame, rectFromNcCalcSize(message, wParam, lParam, 0)); if (margins.left() >= 0) { if (platformWindow) { - platformWindow->setFrameMargins(margins); + platformWindow->setFullFrameMargins(margins); } else { const QSharedPointer<QWindowCreationContext> ctx = QWindowsContext::instance()->windowCreationContext(); if (!ctx.isNull()) diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 287b65cd5d..fc85f5199c 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -332,7 +332,7 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons << "\n Requested: " << requested.geometry << " frame incl.=" << QWindowsGeometryHint::positionIncludesFrame(window) << ' ' << requested.flags - << "\n Obtained : " << obtained.geometry << " margins=" << obtained.frame + << "\n Obtained : " << obtained.geometry << " margins=" << obtained.fullFrameMargins << " handle=" << obtained.hwnd << ' ' << obtained.flags << '\n'; if (Q_UNLIKELY(!obtained.hwnd)) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 552c4c0f5c..81af784a75 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -422,6 +422,31 @@ static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::Windo } /*! + Calculates the dimensions of the invisible borders within the + window frames in Windows 10, using an empirical expression that + reproduces the measured values for standard DPI settings. +*/ + +static QMargins invisibleMargins(QPoint screenPoint) +{ + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10) { + POINT pt = {screenPoint.x(), screenPoint.y()}; + if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) { + if (QWindowsContext::shcoredll.isValid()) { + UINT dpiX; + UINT dpiY; + if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, 0, &dpiX, &dpiY))) { + const qreal sc = (dpiX - 96) / 96.0; + const int gap = 7 + qRound(5*sc) - int(sc); + return QMargins(gap, 0, gap, gap); + } + } + } + } + return QMargins(); +} + +/*! \class WindowCreationData \brief Window creation code. @@ -651,16 +676,20 @@ QWindowsWindowData const QWindowCreationContextPtr context(new QWindowCreationContext(w, data.geometry, rect, data.customMargins, style, exStyle)); QWindowsContext::instance()->setWindowCreationContext(context); + QMargins invMargins = topLevel && !(result.flags & Qt::FramelessWindowHint) && QWindowsGeometryHint::positionIncludesFrame(w) + ? invisibleMargins(QPoint(context->frameX, context->frameY)) : QMargins(); + qCDebug(lcQpaWindows).nospace() << "CreateWindowEx: " << w << " class=" << windowClassName << " title=" << title << '\n' << *this << "\nrequested: " << rect << ": " << context->frameWidth << 'x' << context->frameHeight << '+' << context->frameX << '+' << context->frameY - << " custom margins: " << context->customMargins; + << " custom margins: " << context->customMargins + << " invisible margins: " << invMargins; result.hwnd = CreateWindowEx(exStyle, classNameUtf16, titleUtf16, style, - context->frameX, context->frameY, + context->frameX - invMargins.left(), context->frameY - invMargins.top(), context->frameWidth, context->frameHeight, parentHandle, NULL, appinst, NULL); qCDebug(lcQpaWindows).nospace() @@ -673,7 +702,7 @@ QWindowsWindowData } result.geometry = context->obtainedGeometry; - result.frame = context->margins; + result.fullFrameMargins = context->margins; result.embedded = embedded; result.customMargins = context->customMargins; @@ -887,7 +916,7 @@ QRect QWindowsBaseWindow::frameGeometry_sys() const QRect QWindowsBaseWindow::geometry_sys() const { - return frameGeometry_sys().marginsRemoved(frameMargins()); + return frameGeometry_sys().marginsRemoved(fullFrameMargins()); } QMargins QWindowsBaseWindow::frameMargins_sys() const @@ -1560,7 +1589,7 @@ QRect QWindowsWindow::normalGeometry() const const bool fakeFullScreen = m_savedFrameGeometry.isValid() && (window()->windowStates() & Qt::WindowFullScreen); const QRect frame = fakeFullScreen ? m_savedFrameGeometry : normalFrameGeometry(m_data.hwnd); - const QMargins margins = fakeFullScreen ? QWindowsGeometryHint::frame(m_savedStyle, 0) : frameMargins(); + const QMargins margins = fakeFullScreen ? QWindowsGeometryHint::frame(m_savedStyle, 0) : fullFrameMargins(); return frame.isValid() ? frame.marginsRemoved(margins) : frame; } @@ -1592,8 +1621,8 @@ void QWindowsWindow::setGeometry(const QRect &rectIn) window()->metaObject()->className(), qPrintable(window()->objectName()), m_data.geometry.width(), m_data.geometry.height(), m_data.geometry.x(), m_data.geometry.y(), - m_data.frame.left(), m_data.frame.top(), - m_data.frame.right(), m_data.frame.bottom(), + m_data.fullFrameMargins.left(), m_data.fullFrameMargins.top(), + m_data.fullFrameMargins.right(), m_data.fullFrameMargins.bottom(), m_data.customMargins.left(), m_data.customMargins.top(), m_data.customMargins.right(), m_data.customMargins.bottom(), window()->minimumWidth(), window()->minimumHeight(), @@ -1685,7 +1714,7 @@ void QWindowsWindow::handleGeometryChange() void QWindowsBaseWindow::setGeometry_sys(const QRect &rect) const { - const QMargins margins = frameMargins(); + const QMargins margins = fullFrameMargins(); const QRect frameGeometry = rect + margins; qCDebug(lcQpaWindows) << '>' << __FUNCTION__ << window() @@ -2106,21 +2135,29 @@ bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow * bool QWindowsWindow::handleGeometryChanging(MSG *message) const { - const QMargins margins = window()->isTopLevel() ? frameMargins() : QMargins(); + const QMargins margins = window()->isTopLevel() ? fullFrameMargins() : QMargins(); return QWindowsWindow::handleGeometryChangingMessage(message, window(), margins); } -void QWindowsWindow::setFrameMargins(const QMargins &newMargins) +void QWindowsWindow::setFullFrameMargins(const QMargins &newMargins) { - if (m_data.frame != newMargins) { - qCDebug(lcQpaWindows) << __FUNCTION__ << window() << m_data.frame << "->" << newMargins; - m_data.frame = newMargins; + if (m_data.fullFrameMargins != newMargins) { + qCDebug(lcQpaWindows) << __FUNCTION__ << window() << m_data.fullFrameMargins << "->" << newMargins; + m_data.fullFrameMargins = newMargins; } } QMargins QWindowsWindow::frameMargins() const { - return m_data.frame; + QMargins result = fullFrameMargins(); + if (isTopLevel() && !(m_data.flags & Qt::FramelessWindowHint)) + result -= invisibleMargins(geometry().topLeft()); + return result; +} + +QMargins QWindowsWindow::fullFrameMargins() const +{ + return m_data.fullFrameMargins; } void QWindowsWindow::setOpacity(qreal level) @@ -2174,7 +2211,7 @@ void QWindowsWindow::setMask(const QRegion ®ion) // Mask is in client area coordinates, so offset it in case we have a frame if (window()->isTopLevel()) { - const QMargins margins = frameMargins(); + const QMargins margins = fullFrameMargins(); OffsetRgn(winRegion, margins.left(), margins.top()); } diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 68e0617b19..6606f4ee7a 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -108,8 +108,8 @@ struct QWindowsWindowData { Qt::WindowFlags flags; QRect geometry; - QMargins frame; // Do not use directly for windows, see FrameDirty. - QMargins customMargins; // User-defined, additional frame for NCCALCSIZE + QMargins fullFrameMargins; // Do not use directly for windows, see FrameDirty. + QMargins customMargins; // User-defined, additional frame for NCCALCSIZE HWND hwnd = 0; bool embedded = false; @@ -125,9 +125,10 @@ public: WId winId() const override { return WId(handle()); } QRect geometry() const override { return geometry_sys(); } - QMargins frameMargins() const override { return frameMargins_sys(); } + QMargins frameMargins() const override { return fullFrameMargins(); } QPoint mapToGlobal(const QPoint &pos) const override; QPoint mapFromGlobal(const QPoint &pos) const override; + virtual QMargins fullFrameMargins() const { return frameMargins_sys(); } using QPlatformWindow::screenForGeometry; @@ -258,7 +259,8 @@ public: static bool handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &marginsDp); bool handleGeometryChanging(MSG *message) const; QMargins frameMargins() const override; - void setFrameMargins(const QMargins &newMargins); + QMargins fullFrameMargins() const override; + void setFullFrameMargins(const QMargins &newMargins); void setOpacity(qreal level) override; void setMask(const QRegion ®ion) override; diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index ff2d8fd191..3d94c7bcbd 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -3798,9 +3798,10 @@ void tst_QWidget::optimizedResize_topLevel() // a native function call works (it basically has to go through // WM_RESIZE in QApplication). This is a corner case, though. // See task 243708 - const QRect frame = topLevel.frameGeometry(); - MoveWindow(winHandleOf(&topLevel), frame.x(), frame.y(), - frame.width() + 10, frame.height() + 10, + RECT rect; + GetWindowRect(winHandleOf(&topLevel), &rect); + MoveWindow(winHandleOf(&topLevel), rect.left, rect.top, + rect.right - rect.left + 10, rect.bottom - rect.top + 10, true); QTest::qWait(100); #endif |