summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.cpp38
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.h8
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp27
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp11
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp24
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeimage.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsscaling.cpp79
-rw-r--r--src/plugins/platforms/windows/qwindowsscaling.h114
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp86
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h17
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.cpp10
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp71
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h30
-rw-r--r--src/plugins/platforms/windows/windows.pri6
17 files changed, 420 insertions, 120 deletions
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
index 34a9c1df5f..40d1108f60 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
@@ -43,6 +43,7 @@
#include "qwindowswindow.h"
#include "qwindowsnativeimage.h"
#include "qwindowscontext.h"
+#include "qwindowsscaling.h"
#include <QtGui/QWindow>
#include <QtGui/QPainter>
@@ -75,12 +76,10 @@ QPaintDevice *QWindowsBackingStore::paintDevice()
return &m_image->image();
}
-void QWindowsBackingStore::flush(QWindow *window, const QRegion &region,
- const QPoint &offset)
+void QWindowsBackingStore::flushDp(QWindow *window, const QRect &br, const QPoint &offset)
{
Q_ASSERT(window);
- const QRect br = region.boundingRect();
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaBackingStore) << __FUNCTION__ << this << window << offset << br;
QWindowsWindow *rw = QWindowsWindow::baseWindowOf(window);
@@ -90,8 +89,9 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion &region,
const Qt::WindowFlags flags = window->flags();
if ((flags & Qt::FramelessWindowHint) && QWindowsWindow::setWindowLayered(rw->handle(), flags, hasAlpha, rw->opacity()) && hasAlpha) {
// Windows with alpha: Use blend function to update.
- QRect r = window->frameGeometry();
- QPoint frameOffset(window->frameMargins().left(), window->frameMargins().top());
+ const QMargins marginsDP = rw->frameMarginsDp();
+ const QRect r = rw->geometryDp() + marginsDP;
+ const QPoint frameOffset(marginsDP.left(), marginsDP.top());
QRect dirtyRect = br.translated(offset + frameOffset);
SIZE size = {r.width(), r.height()};
@@ -135,14 +135,15 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion &region,
}
}
-void QWindowsBackingStore::resize(const QSize &size, const QRegion &region)
+void QWindowsBackingStore::resize(const QSize &sizeDip, const QRegion &regionDip)
{
+ const QSize size = sizeDip * QWindowsScaling::factor();
if (m_image.isNull() || m_image->image().size() != size) {
#ifndef QT_NO_DEBUG_OUTPUT
if (QWindowsContext::verbose && lcQpaBackingStore().isDebugEnabled()) {
qCDebug(lcQpaBackingStore)
- << __FUNCTION__ << ' ' << window() << ' ' << size << ' ' << region
- << " from: " << (m_image.isNull() ? QSize() : m_image->image().size());
+ << __FUNCTION__ << ' ' << window() << ' ' << size << ' ' << sizeDip << ' '
+ << regionDip << " from: " << (m_image.isNull() ? QSize() : m_image->image().size());
}
#endif
const QImage::Format format = window()->format().hasAlpha() ?
@@ -151,10 +152,10 @@ void QWindowsBackingStore::resize(const QSize &size, const QRegion &region)
QWindowsNativeImage *oldwni = m_image.data();
QWindowsNativeImage *newwni = new QWindowsNativeImage(size.width(), size.height(), format);
- if (oldwni && !region.isEmpty()) {
+ if (oldwni && !regionDip.isEmpty()) {
const QImage &oldimg(oldwni->image());
QImage &newimg(newwni->image());
- QRegion staticRegion(region);
+ QRegion staticRegion = QWindowsScaling::mapToNative(regionDip);
staticRegion &= QRect(0, 0, oldimg.width(), oldimg.height());
staticRegion &= QRect(0, 0, newimg.width(), newimg.height());
QPainter painter(&newimg);
@@ -163,35 +164,38 @@ void QWindowsBackingStore::resize(const QSize &size, const QRegion &region)
painter.drawImage(rect, oldimg, rect);
}
+ if (QWindowsScaling::isActive())
+ newwni->setDevicePixelRatio(QWindowsScaling::factor());
m_image.reset(newwni);
}
}
Q_GUI_EXPORT void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
-bool QWindowsBackingStore::scroll(const QRegion &area, int dx, int dy)
+bool QWindowsBackingStore::scroll(const QRegion &areaDip, int dxDip, int dyDip)
{
if (m_image.isNull() || m_image->image().isNull())
return false;
- const QVector<QRect> rects = area.rects();
+ const QPoint dp = QPoint(dxDip, dyDip) * QWindowsScaling::factor();
+ const QVector<QRect> rects = areaDip.rects();
for (int i = 0; i < rects.size(); ++i)
- qt_scrollRectInImage(m_image->image(), rects.at(i), QPoint(dx, dy));
+ qt_scrollRectInImage(m_image->image(), QWindowsScaling::mapToNative(rects.at(i)), dp);
return true;
}
-void QWindowsBackingStore::beginPaint(const QRegion &region)
+void QWindowsBackingStore::beginPaint(const QRegion &regionDip)
{
if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaBackingStore) <<__FUNCTION__ << region;
+ qCDebug(lcQpaBackingStore) <<__FUNCTION__ << regionDip;
if (m_image->image().hasAlphaChannel()) {
QPainter p(&m_image->image());
p.setCompositionMode(QPainter::CompositionMode_Source);
const QColor blank = Qt::transparent;
- foreach (const QRect &r, region.rects())
- p.fillRect(r, blank);
+ foreach (const QRect &r, regionDip.rects())
+ p.fillRect(QWindowsScaling::mapToNative(r), blank);
}
}
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.h b/src/plugins/platforms/windows/qwindowsbackingstore.h
index e19b8a4db1..9c9500dabb 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.h
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.h
@@ -43,6 +43,7 @@
#define QWINDOWSBACKINGSTORE_H
#include "qtwindows_additional.h"
+#include "qwindowsscaling.h"
#include <qpa/qplatformbackingstore.h>
#include <QtCore/QScopedPointer>
@@ -60,7 +61,12 @@ public:
~QWindowsBackingStore();
QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
- void flush(QWindow *window, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
+ void flush(QWindow *window, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE
+ {
+ flushDp(window, QWindowsScaling::mapToNative(region.boundingRect()),
+ offset * QWindowsScaling::factor());
+ }
+ void flushDp(QWindow *window, const QRect &boundingRect, const QPoint &offset);
void resize(const QSize &size, const QRegion &r) Q_DECL_OVERRIDE;
bool scroll(const QRegion &area, int dx, int dy) Q_DECL_OVERRIDE;
void beginPaint(const QRegion &) Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index d4c9646b17..b6a9f28aed 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -59,6 +59,7 @@
#endif
#include "qwindowsscreen.h"
#include "qwindowstheme.h"
+#include "qwindowsscaling.h"
#include <QtGui/QWindow>
#include <qpa/qwindowsysteminterface.h>
@@ -1212,7 +1213,9 @@ bool QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg)
}
}
- QWindowSystemInterface::handleContextMenuEvent(window, mouseTriggered, pos, globalPos,
+ QWindowSystemInterface::handleContextMenuEvent(window, mouseTriggered,
+ pos / QWindowsScaling::factor(),
+ globalPos / QWindowsScaling::factor(),
QWindowsKeyMapper::queryKeyboardModifiers());
return true;
}
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index 716d892472..e1b4aca0c4 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -41,6 +41,7 @@
#include "qwindowsdrag.h"
#include "qwindowscontext.h"
+#include "qwindowsscaling.h"
#ifndef QT_NO_CLIPBOARD
# include "qwindowsclipboard.h"
#endif
@@ -50,6 +51,7 @@
#include "qwindowswindow.h"
#include "qwindowsmousehandler.h"
#include "qwindowscursor.h"
+#include "qwindowsscaling.h"
#include <QtGui/QMouseEvent>
#include <QtGui/QPixmap>
@@ -295,12 +297,19 @@ void QWindowsOleDropSource::createCursors()
const QDrag *drag = m_drag->currentDrag();
const QPixmap pixmap = drag->pixmap();
const bool hasPixmap = !pixmap.isNull();
+ const int scaleFactor = QWindowsScaling::factor();
+ const QSize pixmapSizeDp = pixmap.size() * scaleFactor;
+ const bool scalePixmap = hasPixmap
+ && m_mode != TouchDrag // Touch drag: pixmap is shown in a separate QWindow, which will be scaled.
+ && (scaleFactor != 1 && scaleFactor != qRound(pixmap.devicePixelRatio()));
+ const QPixmap drawPixmap = scalePixmap
+ ? pixmap.scaled(pixmapSizeDp, Qt::KeepAspectRatio, Qt::SmoothTransformation) : pixmap;
Qt::DropAction actions[] = { Qt::MoveAction, Qt::CopyAction, Qt::LinkAction, Qt::IgnoreAction };
int actionCount = int(sizeof(actions) / sizeof(actions[0]));
if (!hasPixmap)
--actionCount; // No Qt::IgnoreAction unless pixmap
- const QPoint hotSpot = drag->hotSpot();
+ const QPoint hotSpot = drag->hotSpot() * scaleFactor;
for (int cnum = 0; cnum < actionCount; ++cnum) {
const Qt::DropAction action = actions[cnum];
QPixmap cursorPixmap = drag->dragCursor(action);
@@ -320,15 +329,14 @@ void QWindowsOleDropSource::createCursors()
if (hasPixmap) {
const int x1 = qMin(-hotSpot.x(), 0);
- const int x2 = qMax(pixmap.width() - hotSpot.x(), cursorPixmap.width());
+ const int x2 = qMax(pixmapSizeDp.width() - hotSpot.x(), cursorPixmap.width());
const int y1 = qMin(-hotSpot.y(), 0);
- const int y2 = qMax(pixmap.height() - hotSpot.y(), cursorPixmap.height());
+ const int y2 = qMax(pixmapSizeDp.height() - hotSpot.y(), cursorPixmap.height());
QPixmap newCursor(x2 - x1 + 1, y2 - y1 + 1);
newCursor.fill(Qt::transparent);
QPainter p(&newCursor);
- const QRect srcRect = pixmap.rect();
const QPoint pmDest = QPoint(qMax(0, -hotSpot.x()), qMax(0, -hotSpot.y()));
- p.drawPixmap(pmDest, pixmap, srcRect);
+ p.drawPixmap(pmDest, drawPixmap);
p.drawPixmap(qMax(0, hotSpot.x()),qMax(0, hotSpot.y()), cursorPixmap);
newPixmap = newCursor;
newHotSpot = QPoint(qMax(0, hotSpot.x()), qMax(0, hotSpot.y()));
@@ -454,7 +462,7 @@ QWindowsOleDropSource::GiveFeedback(DWORD dwEffect)
if (!m_touchDragWindow)
m_touchDragWindow = new QWindowsDragCursorWindow;
m_touchDragWindow->setPixmap(e.pixmap);
- m_touchDragWindow->setFramePosition(QWindowsCursor::mousePosition() - e.hotSpot);
+ m_touchDragWindow->setFramePosition((QWindowsCursor::mousePosition() - e.hotSpot) / QWindowsScaling::factor());
if (!m_touchDragWindow->isVisible())
m_touchDragWindow->show();
break;
@@ -530,7 +538,9 @@ void QWindowsOleDropTarget::handleDrag(QWindow *window, DWORD grfKeyState,
QGuiApplicationPrivate::mouse_buttons = QWindowsMouseHandler::keyStateToMouseButtons(grfKeyState);
const QPlatformDragQtResponse response =
- QWindowSystemInterface::handleDrag(window, windowsDrag->dropData(), m_lastPoint, actions);
+ QWindowSystemInterface::handleDrag(window, windowsDrag->dropData(),
+ m_lastPoint / QWindowsScaling::factor(),
+ actions);
m_answerRect = response.answerRect();
const Qt::DropAction action = response.acceptedAction();
@@ -622,7 +632,8 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
QWindowsDrag *windowsDrag = QWindowsDrag::instance();
const QPlatformDropQtResponse response =
- QWindowSystemInterface::handleDrop(m_window, windowsDrag->dropData(), m_lastPoint,
+ QWindowSystemInterface::handleDrop(m_window, windowsDrag->dropData(),
+ m_lastPoint / QWindowsScaling::factor(),
translateToQDragDropActions(*pdwEffect));
if (response.isAccepted()) {
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index f8676c30f7..2284c47ed6 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -44,6 +44,7 @@
#include "qwindowswindow.h"
#include "qwindowsintegration.h"
#include "qwindowsmousehandler.h"
+#include "qwindowsscaling.h"
#include <QtCore/QDebug>
#include <QtCore/QObject>
@@ -214,9 +215,10 @@ void QWindowsInputContext::cursorRectChanged()
if (!m_compositionContext.hwnd)
return;
const QInputMethod *inputMethod = QGuiApplication::inputMethod();
- QRect cursorRectangle = inputMethod->cursorRectangle().toRect();
- if (!cursorRectangle.isValid())
+ const QRect cursorRectangleDip = inputMethod->cursorRectangle().toRect();
+ if (!cursorRectangleDip.isValid())
return;
+ const QRect cursorRectangle = QWindowsScaling::mapToNative(cursorRectangleDip);
qCDebug(lcQpaInputMethods) << __FUNCTION__<< cursorRectangle;
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 7c50ac69c2..7afda853e8 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -41,6 +41,7 @@
****************************************************************************/
#include "qwindowsintegration.h"
+#include "qwindowsscaling.h"
#include "qwindowswindow.h"
#include "qwindowscontext.h"
#include "qwindowsopenglcontext.h"
@@ -229,6 +230,12 @@ QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList &paramL
m_context.setProcessDpiAwareness(dpiAwareness);
dpiAwarenessSet = true;
}
+ // Determine suitable scale factor, don't mix Windows and Qt scaling
+ if (dpiAwareness != QtWindows::ProcessDpiUnaware)
+ QWindowsScaling::setFactor(QWindowsScaling::determineUiScaleFactor());
+ qCDebug(lcQpaWindows)
+ << __FUNCTION__ << "DpiAwareness=" << dpiAwareness <<",Scaling="
+ << QWindowsScaling::factor();
}
QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()
@@ -289,7 +296,7 @@ QWindowsWindowData QWindowsIntegration::createWindowData(QWindow *window) const
{
QWindowsWindowData requested;
requested.flags = window->flags();
- requested.geometry = window->geometry();
+ requested.geometry = QWindowsScaling::mapToNative(window->geometry());
// Apply custom margins (see QWindowsWindow::setCustomMargins())).
const QVariant customMarginsV = window->property("_q_windowsCustomMargins");
if (customMarginsV.isValid())
@@ -310,7 +317,7 @@ QWindowsWindowData QWindowsIntegration::createWindowData(QWindow *window) const
window->setFlags(obtained.flags);
// Trigger geometry change signals of QWindow.
if ((obtained.flags & Qt::Desktop) != Qt::Desktop && requested.geometry != obtained.geometry)
- QWindowSystemInterface::handleGeometryChange(window, obtained.geometry);
+ QWindowSystemInterface::handleGeometryChange(window, QWindowsScaling::mapFromNative(obtained.geometry));
}
#ifndef QT_NO_OPENGL
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index dc1de047fe..540236bda7 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -43,6 +43,7 @@
#include "qwindowscontext.h"
#include "qwindowswindow.h"
#include "qwindowsguieventdispatcher.h"
+#include "qwindowsscaling.h"
#include <QtGui/QWindow>
#include <qpa/qwindowsysteminterface.h>
@@ -767,11 +768,10 @@ static void showSystemMenu(QWindow* w)
#undef enabled
#undef disabled
#endif // !Q_OS_WINCE
+ const QPoint topLeft = topLevel->geometry().topLeft() * QWindowsScaling::factor();
const int ret = TrackPopupMenuEx(menu,
TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
- topLevel->geometry().x(), topLevel->geometry().y(),
- topLevelHwnd,
- 0);
+ topLeft.x(), topLeft.y(), topLevelHwnd, 0);
if (ret)
qWindowsWndProc(topLevelHwnd, WM_SYSCOMMAND, ret, 0);
}
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
index 4633378342..2e677102a5 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
@@ -191,8 +191,10 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
const QPoint globalPosition = winEventPosition;
const QPoint clientPosition = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPosition);
const Qt::MouseButtons buttons = QWindowsMouseHandler::queryMouseButtons();
- QWindowSystemInterface::handleFrameStrutMouseEvent(window, clientPosition,
- globalPosition, buttons,
+ QWindowSystemInterface::handleFrameStrutMouseEvent(window,
+ clientPosition / QWindowsScaling::factor(),
+ globalPosition / QWindowsScaling::factor(),
+ buttons,
QWindowsKeyMapper::queryKeyboardModifiers(),
source);
return false; // Allow further event processing (dragging of windows).
@@ -334,7 +336,10 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
m_windowUnderMouse = currentWindowUnderMouse;
}
- QWindowSystemInterface::handleMouseEvent(window, winEventPosition, globalPosition, buttons,
+ QWindowSystemInterface::handleMouseEvent(window,
+ winEventPosition / QWindowsScaling::factor(),
+ globalPosition / QWindowsScaling::factor(),
+ buttons,
QWindowsKeyMapper::queryKeyboardModifiers(),
source);
m_previousCaptureWindow = hasCapture ? window : 0;
@@ -388,10 +393,11 @@ bool QWindowsMouseHandler::translateMouseWheelEvent(QWindow *window, HWND,
}
if (handleEvent) {
+ const QPoint posDip = QWindowsGeometryHint::mapFromGlobal(receiver, globalPos) / QWindowsScaling::factor();
QWindowSystemInterface::handleWheelEvent(receiver,
- QWindowsGeometryHint::mapFromGlobal(receiver, globalPos),
- globalPos,
- delta, orientation, mods);
+ posDip, globalPos / QWindowsScaling::factor(),
+ delta / QWindowsScaling::factor(),
+ orientation, mods);
}
return true;
@@ -419,6 +425,7 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND,
Q_ASSERT(QWindowsContext::user32dll.getTouchInputInfo);
QWindowsContext::user32dll.getTouchInputInfo((HANDLE) msg.lParam, msg.wParam, winTouchInputs.data(), sizeof(TOUCHINPUT));
+ const qreal screenPosFactor = 0.01 / qreal(QWindowsScaling::factor());
for (int i = 0; i < winTouchPointCount; ++i) {
const TOUCHINPUT &winTouchInput = winTouchInputs[i];
int id = m_touchInputIDToTouchPointID.value(winTouchInput.dwID, -1);
@@ -432,10 +439,9 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND,
if (m_lastTouchPositions.contains(id))
touchPoint.normalPosition = m_lastTouchPositions.value(id);
- QPointF screenPos = QPointF(qreal(winTouchInput.x) / qreal(100.), qreal(winTouchInput.y) / qreal(100.));
+ const QPointF screenPos = QPointF(winTouchInput.x, winTouchInput.y) * screenPosFactor;
if (winTouchInput.dwMask & TOUCHINPUTMASKF_CONTACTAREA)
- touchPoint.area.setSize(QSizeF(qreal(winTouchInput.cxContact) / qreal(100.),
- qreal(winTouchInput.cyContact) / qreal(100.)));
+ touchPoint.area.setSize(QSizeF(winTouchInput.cxContact, winTouchInput.cyContact) * screenPosFactor);
touchPoint.area.moveCenter(screenPos);
QPointF normalPosition = QPointF(screenPos.x() / screenGeometry.width(),
screenPos.y() / screenGeometry.height());
diff --git a/src/plugins/platforms/windows/qwindowsnativeimage.h b/src/plugins/platforms/windows/qwindowsnativeimage.h
index 399bead323..98b7fc9bc5 100644
--- a/src/plugins/platforms/windows/qwindowsnativeimage.h
+++ b/src/plugins/platforms/windows/qwindowsnativeimage.h
@@ -67,6 +67,8 @@ public:
HDC hdc() const { return m_hdc; }
+ void setDevicePixelRatio(qreal scaleFactor) { m_image.setDevicePixelRatio(scaleFactor); }
+
static QImage::Format systemFormat();
private:
diff --git a/src/plugins/platforms/windows/qwindowsscaling.cpp b/src/plugins/platforms/windows/qwindowsscaling.cpp
new file mode 100644
index 0000000000..fcc3440b42
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowsscaling.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwindowsscaling.h"
+#include "qwindowsscreen.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QWindowsScaling
+ \brief Windows scaling utilities
+
+ \internal
+ \ingroup qt-lighthouse-win
+*/
+
+int QWindowsScaling::m_factor = 1;
+
+static const char devicePixelRatioEnvVar[] = "QT_DEVICE_PIXEL_RATIO";
+
+// Suggest a scale factor by checking monitor sizes.
+int QWindowsScaling::determineUiScaleFactor()
+{
+ if (!qEnvironmentVariableIsSet(devicePixelRatioEnvVar))
+ return 1;
+ const QByteArray envDevicePixelRatioEnv = qgetenv(devicePixelRatioEnvVar);
+ // Auto: Suggest a scale factor by checking monitor resolution.
+ if (envDevicePixelRatioEnv == QByteArrayLiteral("auto")) {
+ const int maxResolution = QWindowsScreen::maxMonitorHorizResolution();
+ return maxResolution > 180 ? maxResolution / 96 : 1;
+ }
+ // Get factor from environment
+ bool ok = false;
+ const int envFactor = envDevicePixelRatioEnv.toInt(&ok);
+ return ok && envFactor > 0 ? envFactor : 1;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsscaling.h b/src/plugins/platforms/windows/qwindowsscaling.h
new file mode 100644
index 0000000000..99fec7c810
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowsscaling.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSSCALING_H
+#define QWINDOWSSCALING_H
+
+#include <QtGui/QRegion>
+#include <QtCore/QVector>
+#include <QtCore/QRect>
+
+QT_BEGIN_NAMESPACE
+
+enum
+#if defined(Q_COMPILER_CLASS_ENUM) || defined(Q_CC_MSVC)
+ : int
+#endif
+{ QWINDOWSIZE_MAX = 16777215 };
+
+class QWindowsScaling {
+public:
+ static bool isActive() { return m_factor > 1; }
+ static int factor() { return m_factor; }
+ static void setFactor(int factor) { m_factor = factor; }
+ static int determineUiScaleFactor();
+
+ // Scaling helpers for size constraints.
+ static int mapToNativeConstrained(int qt)
+ { return m_factor != 1 && qt > 0 && qt < QWINDOWSIZE_MAX ? qt * m_factor : qt; }
+
+ static int mapFromNativeConstrained(int dp)
+ { return m_factor != 1 && dp > 0 && dp < QWINDOWSIZE_MAX ? dp / m_factor : dp; }
+
+ static QSize mapToNativeConstrained(const QSize &qt)
+ { return QSize(mapToNativeConstrained(qt.width()), mapToNativeConstrained(qt.height())); }
+
+ static QRect mapToNative(const QRect &qRect)
+ {
+ return QRect(qRect.x() * m_factor, qRect.y() * m_factor, qRect.width() * m_factor, qRect.height() * m_factor);
+ }
+
+ static QRect mapFromNative(const QRect &dp)
+ {
+ return isActive() ?
+ QRect(dp.x() / m_factor, dp.y() / m_factor, (dp.width() + 1) / m_factor, (dp.height() + 1) / m_factor) :
+ dp;
+ }
+
+ static QRegion mapToNative(const QRegion &regionQt)
+ {
+ if (!QWindowsScaling::isActive() || regionQt.isEmpty())
+ return regionQt;
+
+ QRegion result;
+ foreach (const QRect &rectQt, regionQt.rects())
+ result += QWindowsScaling::mapToNative(rectQt);
+ return result;
+ }
+
+ static QRegion mapFromNative(const QRegion &regionDp)
+ {
+ if (!QWindowsScaling::isActive() || regionDp.isEmpty())
+ return regionDp;
+
+ QRegion result;
+ foreach (const QRect &rectDp, regionDp.rects())
+ result += QWindowsScaling::mapFromNative(rectDp);
+ return result;
+ }
+
+private:
+ static int m_factor;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSSCALING_H
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index bcdb8a2352..a5a291a8d8 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -101,21 +101,19 @@ static inline QDpi deviceDPI(const QSize &pixels, const QSizeF &physicalSizeMM)
typedef QList<QWindowsScreenData> WindowsScreenDataList;
-// from QDesktopWidget, taking WindowsScreenDataList as LPARAM
-BOOL QT_WIN_CALLBACK monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM p)
+static bool monitorData(HMONITOR hMonitor, QWindowsScreenData *data)
{
MONITORINFOEX info;
memset(&info, 0, sizeof(MONITORINFOEX));
info.cbSize = sizeof(MONITORINFOEX);
if (GetMonitorInfo(hMonitor, &info) == FALSE)
- return TRUE;
+ return false;
- WindowsScreenDataList *result = reinterpret_cast<WindowsScreenDataList *>(p);
- QWindowsScreenData data;
- data.geometry = QRect(QPoint(info.rcMonitor.left, info.rcMonitor.top), QPoint(info.rcMonitor.right - 1, info.rcMonitor.bottom - 1));
- data.name = QString::fromWCharArray(info.szDevice);
- if (data.name == QLatin1String("WinDisc")) {
- data.flags |= QWindowsScreenData::LockScreen;
+ data->geometry = QRect(QPoint(info.rcMonitor.left, info.rcMonitor.top), QPoint(info.rcMonitor.right - 1, info.rcMonitor.bottom - 1));
+ data->availableGeometry = QRect(QPoint(info.rcWork.left, info.rcWork.top), QPoint(info.rcWork.right - 1, info.rcWork.bottom - 1));
+ data->name = QString::fromWCharArray(info.szDevice);
+ if (data->name == QLatin1String("WinDisc")) {
+ data->flags |= QWindowsScreenData::LockScreen;
} else {
#ifdef Q_OS_WINCE
//Windows CE, just supports one Display and expects to get only DISPLAY,
@@ -127,40 +125,48 @@ BOOL QT_WIN_CALLBACK monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM
if (hdc) {
#ifndef Q_OS_WINCE
const QDpi dpi = monitorDPI(hMonitor);
- data.dpi = dpi.first ? dpi : deviceDPI(hdc);
+ data->dpi = dpi.first ? dpi : deviceDPI(hdc);
#else
- data.dpi = deviceDPI(hdc);
+ data->dpi = deviceDPI(hdc);
#endif
- data.depth = GetDeviceCaps(hdc, BITSPIXEL);
- data.format = data.depth == 16 ? QImage::Format_RGB16 : QImage::Format_RGB32;
- data.physicalSizeMM = QSizeF(GetDeviceCaps(hdc, HORZSIZE), GetDeviceCaps(hdc, VERTSIZE));
+ data->depth = GetDeviceCaps(hdc, BITSPIXEL);
+ data->format = data->depth == 16 ? QImage::Format_RGB16 : QImage::Format_RGB32;
+ data->physicalSizeMM = QSizeF(GetDeviceCaps(hdc, HORZSIZE), GetDeviceCaps(hdc, VERTSIZE));
const int refreshRate = GetDeviceCaps(hdc, VREFRESH);
if (refreshRate > 1) // 0,1 means hardware default.
- data.refreshRateHz = refreshRate;
+ data->refreshRateHz = refreshRate;
DeleteDC(hdc);
} else {
qWarning("%s: Unable to obtain handle for monitor '%s', defaulting to %g DPI.",
__FUNCTION__, qPrintable(QString::fromWCharArray(info.szDevice)),
- data.dpi.first);
+ data->dpi.first);
} // CreateDC() failed
} // not lock screen
- data.geometry = QRect(QPoint(info.rcMonitor.left, info.rcMonitor.top), QPoint(info.rcMonitor.right - 1, info.rcMonitor.bottom - 1));
- data.availableGeometry = QRect(QPoint(info.rcWork.left, info.rcWork.top), QPoint(info.rcWork.right - 1, info.rcWork.bottom - 1));
- data.orientation = data.geometry.height() > data.geometry.width() ?
+ data->orientation = data->geometry.height() > data->geometry.width() ?
Qt::PortraitOrientation : Qt::LandscapeOrientation;
// EnumDisplayMonitors (as opposed to EnumDisplayDevices) enumerates only
// virtual desktop screens.
- data.flags |= QWindowsScreenData::VirtualDesktop;
- if (info.dwFlags & MONITORINFOF_PRIMARY) {
- data.flags |= QWindowsScreenData::PrimaryScreen;
+ data->flags |= QWindowsScreenData::VirtualDesktop;
+ if (info.dwFlags & MONITORINFOF_PRIMARY)
+ data->flags |= QWindowsScreenData::PrimaryScreen;
+ return true;
+}
+
+// from QDesktopWidget, taking WindowsScreenDataList as LPARAM
+BOOL QT_WIN_CALLBACK monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM p)
+{
+ QWindowsScreenData data;
+ if (monitorData(hMonitor, &data)) {
+ WindowsScreenDataList *result = reinterpret_cast<WindowsScreenDataList *>(p);
// QPlatformIntegration::screenAdded() documentation specifies that first
// added screen will be the primary screen, so order accordingly.
// Note that the side effect of this policy is that there is no way to change primary
// screen reported by Qt, unless we want to delete all existing screens and add them
// again whenever primary screen changes.
- result->prepend(data);
- } else {
- result->append(data);
+ if (data.flags & QWindowsScreenData::PrimaryScreen)
+ result->prepend(data);
+ else
+ result->append(data);
}
return TRUE;
}
@@ -217,14 +223,36 @@ QWindowsScreen::QWindowsScreen(const QWindowsScreenData &data) :
{
}
+BOOL QT_WIN_CALLBACK monitorResolutionEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM p)
+{
+ QWindowsScreenData data;
+ if (monitorData(hMonitor, &data)) {
+ int *maxHorizResolution = reinterpret_cast<int *>(p);
+ const int horizResolution = qRound(data.dpi.first);
+ if (horizResolution > *maxHorizResolution)
+ *maxHorizResolution = horizResolution;
+ }
+ return TRUE;
+}
+
+int QWindowsScreen::maxMonitorHorizResolution()
+{
+ int result = 0;
+ EnumDisplayMonitors(0, 0, monitorResolutionEnumCallback, (LPARAM)&result);
+ return result;
+}
+
Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0);
-QPixmap QWindowsScreen::grabWindow(WId window, int x, int y, int width, int height) const
+QPixmap QWindowsScreen::grabWindow(WId window, int qX, int qY, int qWidth, int qHeight) const
{
RECT r;
HWND hwnd = window ? (HWND)window : GetDesktopWindow();
GetClientRect(hwnd, &r);
-
+ const int x = qX * QWindowsScaling::factor();
+ const int y = qY * QWindowsScaling::factor();
+ int width = qWidth * QWindowsScaling::factor();
+ int height = qHeight * QWindowsScaling::factor();
if (width < 0) width = r.right - r.left;
if (height < 0) height = r.bottom - r.top;
@@ -248,6 +276,10 @@ QPixmap QWindowsScreen::grabWindow(WId window, int x, int y, int width, int heig
DeleteObject(bitmap);
ReleaseDC(0, display_dc);
+ if (QWindowsScaling::isActive()) {
+ const qreal factor = 1.0 / qreal(QWindowsScaling::factor());
+ return pixmap.transformed(QTransform::fromScale(factor, factor));
+ }
return pixmap;
}
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index c9d8a5662c..49581db41a 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -43,11 +43,13 @@
#define QWINDOWSSCREEN_H
#include "qwindowscursor.h"
+#include "qwindowsscaling.h"
#ifdef Q_OS_WINCE
# include "qplatformfunctions_wince.h"
#endif
#include <QtCore/QList>
+#include <QtCore/QVector>
#include <QtCore/QPair>
#include <QtCore/QSharedPointer>
#include <qpa/qplatformscreen.h>
@@ -88,24 +90,28 @@ public:
static QWindowsScreen *screenOf(const QWindow *w = 0);
- QRect geometry() const Q_DECL_OVERRIDE { return m_data.geometry; }
- QRect availableGeometry() const Q_DECL_OVERRIDE { return m_data.availableGeometry; }
+ QRect geometryDp() const { return m_data.geometry; }
+ QRect geometry() const Q_DECL_OVERRIDE { return QWindowsScaling::mapFromNative(geometryDp()); }
+ QRect availableGeometryDp() const { return m_data.availableGeometry; }
+ QRect availableGeometry() const Q_DECL_OVERRIDE { return QWindowsScaling::mapFromNative(availableGeometryDp()); }
int depth() const Q_DECL_OVERRIDE { return m_data.depth; }
QImage::Format format() const Q_DECL_OVERRIDE { return m_data.format; }
QSizeF physicalSize() const Q_DECL_OVERRIDE { return m_data.physicalSizeMM; }
- QDpi logicalDpi() const Q_DECL_OVERRIDE { return m_data.dpi; }
+ QDpi logicalDpi() const Q_DECL_OVERRIDE
+ { return QDpi(m_data.dpi.first / QWindowsScaling::factor(), m_data.dpi.second / QWindowsScaling::factor()); }
+ qreal devicePixelRatio() const Q_DECL_OVERRIDE { return QWindowsScaling::factor(); }
qreal refreshRate() const Q_DECL_OVERRIDE { return m_data.refreshRateHz; }
QString name() const Q_DECL_OVERRIDE { return m_data.name; }
Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE { return m_data.orientation; }
QList<QPlatformScreen *> virtualSiblings() const Q_DECL_OVERRIDE;
QWindow *topLevelAt(const QPoint &point) const Q_DECL_OVERRIDE
- { return QWindowsScreen::findTopLevelAt(point, CWP_SKIPINVISIBLE); }
+ { return QWindowsScreen::findTopLevelAt(point * QWindowsScaling::factor() , CWP_SKIPINVISIBLE); }
static QWindow *findTopLevelAt(const QPoint &point, unsigned flags);
static QWindow *windowAt(const QPoint &point, unsigned flags = CWP_SKIPINVISIBLE);
static QWindow *windowUnderMouse(unsigned flags = CWP_SKIPINVISIBLE);
- QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
+ QPixmap grabWindow(WId window, int qX, int qY, int qWidth, int qHeight) const Q_DECL_OVERRIDE;
inline void handleChanges(const QWindowsScreenData &newData);
@@ -117,6 +123,7 @@ public:
#endif // !QT_NO_CURSOR
const QWindowsScreenData &data() const { return m_data; }
+ static int maxMonitorHorizResolution();
private:
QWindowsScreenData m_data;
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
index d1737de907..802fc3605a 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qwindowstabletsupport.h"
+#include "qwindowsscaling.h"
#ifndef QT_NO_TABLETEVENT
@@ -403,7 +404,8 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
// in which case we snap the position to the mouse position.
// It seems there is no way to find out the mode programmatically, the LOGCONTEXT orgX/Y/Ext
// area is always the virtual desktop.
- const QRect virtualDesktopArea = QGuiApplication::primaryScreen()->virtualGeometry();
+ const QRect virtualDesktopArea
+ = QWindowsScaling::mapToNative(QGuiApplication::primaryScreen()->virtualGeometry());
qCDebug(lcQpaTablet) << __FUNCTION__ << "processing " << packetCount
<< "target:" << QGuiApplicationPrivate::tabletPressTarget;
@@ -423,7 +425,7 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
QPoint globalPos = globalPosF.toPoint();
// Get Mouse Position and compare to tablet info
- const QPoint mouseLocation = QWindowsCursor::mousePosition();
+ QPoint mouseLocation = QWindowsCursor::mousePosition();
// Positions should be almost the same if we are in absolute
// mode. If they are not, use the mouse location.
@@ -479,7 +481,9 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
<< tiltY << "tanP:" << tangentialPressure << "rotation:" << rotation;
}
- QWindowSystemInterface::handleTabletEvent(target, QPointF(localPos), globalPosF,
+ const QPointF localPosDip = QPointF(localPos / QWindowsScaling::factor());
+ const QPointF globalPosDip = globalPosF / qreal(QWindowsScaling::factor());
+ QWindowSystemInterface::handleTabletEvent(target, localPosDip, globalPosDip,
currentDevice, currentPointer,
static_cast<Qt::MouseButtons>(packet.pkButtons),
pressureNew, tiltX, tiltY,
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 3b54feabbf..e6b996c685 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -44,6 +44,7 @@
#include "qwindowscontext.h"
#include "qwindowsdrag.h"
#include "qwindowsscreen.h"
+#include "qwindowsscaling.h"
#ifdef QT_NO_CURSOR
# include "qwindowscursor.h"
#endif
@@ -576,7 +577,9 @@ QWindowsWindowData
const QString windowClassName = QWindowsContext::instance()->registerWindowClass(w, isGL);
- QRect rect = QPlatformWindow::initialGeometry(w, data.geometry, defaultWindowWidth, defaultWindowHeight);
+ const QRect geometryDip = QWindowsScaling::mapFromNative(data.geometry);
+ QRect fixedGeometryDip = QPlatformWindow::initialGeometry(w, geometryDip, defaultWindowWidth, defaultWindowHeight);
+ const QRect rect = fixedGeometryDip != geometryDip ? QWindowsScaling::mapToNative(fixedGeometryDip) : data.geometry;
if (title.isEmpty() && (result.flags & Qt::WindowTitleHint))
title = topLevel ? qAppName() : w->objectName();
@@ -683,11 +686,9 @@ void WindowCreationData::initialize(HWND hwnd, bool frameChange, qreal opacityLe
\ingroup qt-lighthouse-win
*/
-#define QWINDOWSIZE_MAX ((1<<24)-1)
-
QWindowsGeometryHint::QWindowsGeometryHint(const QWindow *w, const QMargins &cm) :
- minimumSize(w->minimumSize()),
- maximumSize(w->maximumSize()),
+ minimumSize(QWindowsScaling::mapToNativeConstrained(w->minimumSize())),
+ maximumSize(QWindowsScaling::mapToNativeConstrained(w->maximumSize())),
customMargins(cm)
{
}
@@ -930,7 +931,8 @@ void QWindowsWindow::fireExpose(const QRegion &region, bool force)
clearFlag(Exposed);
else
setFlag(Exposed);
- QWindowSystemInterface::handleExposeEvent(window(), region);
+ QWindowSystemInterface::handleExposeEvent(window(),
+ QWindowsScaling::mapFromNative(region));
}
static inline QWindow *findTransientChild(const QWindow *parent)
@@ -1106,7 +1108,7 @@ bool QWindowsWindow::isEmbedded(const QPlatformWindow *parentWindow) const
return m_data.embedded;
}
-QPoint QWindowsWindow::mapToGlobal(const QPoint &pos) const
+QPoint QWindowsWindow::mapToGlobalDp(const QPoint &pos) const
{
if (m_data.hwnd)
return QWindowsGeometryHint::mapToGlobal(m_data.hwnd, pos);
@@ -1114,7 +1116,7 @@ QPoint QWindowsWindow::mapToGlobal(const QPoint &pos) const
return pos;
}
-QPoint QWindowsWindow::mapFromGlobal(const QPoint &pos) const
+QPoint QWindowsWindow::mapFromGlobalDp(const QPoint &pos) const
{
if (m_data.hwnd)
return QWindowsGeometryHint::mapFromGlobal(m_data.hwnd, pos);
@@ -1286,22 +1288,22 @@ static QRect normalFrameGeometry(HWND hwnd)
return QRect();
}
-QRect QWindowsWindow::normalGeometry() const
+QRect QWindowsWindow::normalGeometryDp() const
{
// Check for fake 'fullscreen' mode.
const bool fakeFullScreen = m_savedFrameGeometry.isValid() && window()->windowState() == 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) : frameMarginsDp();
return frame.isValid() ? frame.marginsRemoved(margins) : frame;
}
-void QWindowsWindow::setGeometry(const QRect &rectIn)
+void QWindowsWindow::setGeometryDp(const QRect &rectIn)
{
QRect rect = rectIn;
// This means it is a call from QWindow::setFramePosition() and
// the coordinates include the frame (size is still the contents rectangle).
if (QWindowsGeometryHint::positionIncludesFrame(window())) {
- const QMargins margins = frameMargins();
+ const QMargins margins = frameMarginsDp();
rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top()));
}
const QSize oldSize = m_data.geometry.size();
@@ -1383,8 +1385,9 @@ void QWindowsWindow::handleGeometryChange()
return;
const QRect previousGeometry = m_data.geometry;
m_data.geometry = geometry_sys();
- QPlatformWindow::setGeometry(m_data.geometry);
- QWindowSystemInterface::handleGeometryChange(window(), m_data.geometry);
+ const QRect geometryDip = QWindowsScaling::mapFromNative(m_data.geometry);
+ QPlatformWindow::setGeometry(geometryDip);
+ QWindowSystemInterface::handleGeometryChange(window(), geometryDip);
// QTBUG-32121: OpenGL/normal windows (with exception of ANGLE) do not receive
// expose events when shrinking, synthesize.
if (!testFlag(OpenGL_ES2) && isExposed()
@@ -1404,7 +1407,7 @@ void QWindowsWindow::handleGeometryChange()
void QWindowsWindow::setGeometry_sys(const QRect &rect) const
{
- const QMargins margins = frameMargins();
+ const QMargins margins = frameMarginsDp();
const QRect frameGeometry = rect + margins;
qCDebug(lcQpaWindows) << '>' << __FUNCTION__ << this << window()
@@ -1441,7 +1444,7 @@ QRect QWindowsWindow::frameGeometry_sys() const
QRect QWindowsWindow::geometry_sys() const
{
- return frameGeometry_sys().marginsRemoved(frameMargins());
+ return frameGeometry_sys().marginsRemoved(frameMarginsDp());
}
/*!
@@ -1514,7 +1517,7 @@ void QWindowsWindow::setWindowFlags(Qt::WindowFlags flags)
qCDebug(lcQpaWindows) << '>' << __FUNCTION__ << this << window() << "\n from: "
<< QWindowsWindow::debugWindowFlags(m_data.flags)
<< "\n to: " << QWindowsWindow::debugWindowFlags(flags);
- const QRect oldGeometry = geometry();
+ const QRect oldGeometry = geometryDp();
if (m_data.flags != flags) {
m_data.flags = flags;
if (m_data.hwnd) {
@@ -1602,7 +1605,8 @@ void QWindowsWindow::setWindowState(Qt::WindowState state)
bool QWindowsWindow::isFullScreen_sys() const
{
- return window()->isTopLevel() && geometry_sys() == window()->screen()->geometry();
+ return window()->isTopLevel()
+ && geometry_sys() == QWindowsScaling::mapToNative(window()->screen()->geometry());
}
/*!
@@ -1683,14 +1687,15 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
// Use geometry of QWindow::screen() within creation or the virtual screen the
// window is in (QTBUG-31166, QTBUG-30724).
const QScreen *screen = window()->screen();
- const QRect r = screen->geometry();
+ const QRect rDip = screen->geometry();
+ const QRect r = QWindowsScaling::mapToNative(rDip);
const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
setFlag(SynchronousGeometryChangeEvent);
SetWindowPos(m_data.hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf);
if (!wasSync)
clearFlag(SynchronousGeometryChangeEvent);
- QWindowSystemInterface::handleGeometryChange(window(), r);
+ QWindowSystemInterface::handleGeometryChange(window(), rDip);
QWindowSystemInterface::flushWindowSystemEvents();
} else if (newState != Qt::WindowMinimized) {
// Restore saved state.
@@ -1778,7 +1783,7 @@ void QWindowsWindow::propagateSizeHints()
qCDebug(lcQpaWindows) << __FUNCTION__ << this << window();
}
-QMargins QWindowsWindow::frameMargins() const
+QMargins QWindowsWindow::frameMarginsDp() const
{
// Frames are invalidated by style changes (window state, flags).
// As they are also required for geometry calculations in resize
@@ -1820,17 +1825,17 @@ static inline void addRectToWinRegion(const QRect &rect, HRGN *winRegion)
}
}
-static HRGN qRegionToWinRegion(const QRegion &region)
+static HRGN qRegionToWinRegion(const QRegion &regionDip)
{
- const QVector<QRect> rects = region.rects();
+ const QVector<QRect> rects = regionDip.rects();
if (rects.isEmpty())
return NULL;
const int rectCount = rects.size();
if (rectCount == 1)
- return createRectRegion(region.boundingRect());
+ return createRectRegion(QWindowsScaling::mapToNative(regionDip.boundingRect()));
HRGN hRegion = createRectRegion(rects.front());
for (int i = 1; i < rectCount; ++i)
- addRectToWinRegion(rects.at(i), &hRegion);
+ addRectToWinRegion(QWindowsScaling::mapToNative(rects.at(i)), &hRegion);
return hRegion;
}
@@ -1844,7 +1849,7 @@ void QWindowsWindow::setMask(const QRegion &region)
// 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 = frameMarginsDp();
OffsetRgn(winRegion, margins.left(), margins.top());
}
@@ -1981,23 +1986,23 @@ bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *re
|| (m_data.flags & Qt::FramelessWindowHint)) {
return false;
}
- const QSize minimumSize = w->minimumSize();
+ const QSize minimumSize = QWindowsScaling::mapToNativeConstrained(w->minimumSize());
if (minimumSize.isEmpty())
return false;
- const QSize maximumSize = w->maximumSize();
+ const QSize maximumSize = QWindowsScaling::mapToNativeConstrained(w->maximumSize());
const bool fixedWidth = minimumSize.width() == maximumSize.width();
const bool fixedHeight = minimumSize.height() == maximumSize.height();
if (!fixedWidth && !fixedHeight)
return false;
- const QPoint localPos = w->mapFromGlobal(globalPos);
- const QSize size = w->size();
+ const QPoint localPos = mapFromGlobalDp(globalPos);
+ const QSize size = w->size() * QWindowsScaling::factor();
if (fixedHeight) {
if (localPos.y() >= size.height()) {
*result = HTBORDER; // Unspecified border, no resize cursor.
return true;
}
if (localPos.y() < 0) {
- const QMargins margins = frameMargins();
+ const QMargins margins = frameMarginsDp();
const int topResizeBarPos = margins.left() - margins.top();
if (localPos.y() < topResizeBarPos) {
*result = HTCAPTION; // Extend caption over top resize bar, let's user move the window.
@@ -2249,6 +2254,10 @@ void QWindowsWindow::setWindowIcon(const QIcon &icon)
The property can be set using QPlatformNativeInterface::setWindowProperty() or,
before platform window creation, by setting a dynamic property
on the QWindow (see QWindowsIntegration::createPlatformWindow()).
+
+ Note: The function uses (unscaled) device pixels since the QWizard also
+ uses AdjustWindowRect() and using device independent pixels would introduce
+ rounding errors.
*/
void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins)
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 19d2236688..cb9da6fe27 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -46,6 +46,7 @@
#ifdef Q_OS_WINCE
# include "qplatformfunctions_wince.h"
#endif
+#include "qwindowsscaling.h"
#include "qwindowscursor.h"
#include "qwindowsopenglcontext.h"
@@ -152,18 +153,28 @@ public:
~QWindowsWindow();
QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; }
- void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
- QRect geometry() const Q_DECL_OVERRIDE { return m_data.geometry; }
- QRect normalGeometry() const Q_DECL_OVERRIDE;
-
+ void setGeometryDp(const QRect &rectIn);
+ void setGeometry(const QRect &rect) Q_DECL_OVERRIDE
+ { setGeometryDp(QWindowsScaling::mapToNative(rect)); }
+ QRect geometryDp() const { return m_data.geometry; }
+ QRect geometry() const Q_DECL_OVERRIDE
+ { return QWindowsScaling::mapFromNative(geometryDp()); }
+ QRect normalGeometryDp() const;
+ QRect normalGeometry() const Q_DECL_OVERRIDE
+ { return QWindowsScaling::mapFromNative(normalGeometryDp()); }
+ qreal devicePixelRatio() const Q_DECL_OVERRIDE
+ { return qreal(QWindowsScaling::factor()); }
void setVisible(bool visible) Q_DECL_OVERRIDE;
bool isVisible() const;
bool isExposed() const Q_DECL_OVERRIDE { return testFlag(Exposed); }
bool isActive() const Q_DECL_OVERRIDE;
bool isEmbedded(const QPlatformWindow *parentWindow) const Q_DECL_OVERRIDE;
- QPoint mapToGlobal(const QPoint &pos) const Q_DECL_OVERRIDE;
- QPoint mapFromGlobal(const QPoint &pos) const Q_DECL_OVERRIDE;
-
+ QPoint mapToGlobalDp(const QPoint &pos) const;
+ QPoint mapToGlobal(const QPoint &pos) const Q_DECL_OVERRIDE
+ { return mapToGlobalDp(pos * QWindowsScaling::factor()) / QWindowsScaling::factor(); }
+ QPoint mapFromGlobalDp(const QPoint &pos) const;
+ QPoint mapFromGlobal(const QPoint &pos) const Q_DECL_OVERRIDE
+ { return mapFromGlobalDp(pos * QWindowsScaling::factor()) / QWindowsScaling::factor(); }
void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE;
void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
@@ -179,7 +190,8 @@ public:
void windowEvent(QEvent *event);
void propagateSizeHints() Q_DECL_OVERRIDE;
- QMargins frameMargins() const Q_DECL_OVERRIDE;
+ QMargins frameMarginsDp() const;
+ QMargins frameMargins() const Q_DECL_OVERRIDE { return frameMarginsDp() / QWindowsScaling::factor(); }
void setOpacity(qreal level) Q_DECL_OVERRIDE;
void setMask(const QRegion &region) Q_DECL_OVERRIDE;
@@ -190,7 +202,7 @@ public:
bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE;
inline bool hasMouseCapture() const { return GetCapture() == m_data.hwnd; }
- bool startSystemResize(const QPoint &pos, Qt::Corner corner) Q_DECL_OVERRIDE;
+ bool startSystemResize(const QPoint &, Qt::Corner corner) Q_DECL_OVERRIDE;
void setFrameStrutEventsEnabled(bool enabled);
bool frameStrutEventsEnabled() const { return testFlag(FrameStrutEventsEnabled); }
diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri
index 104d882fba..8e5f35d293 100644
--- a/src/plugins/platforms/windows/windows.pri
+++ b/src/plugins/platforms/windows/windows.pri
@@ -39,7 +39,8 @@ SOURCES += \
$$PWD/qwindowsdialoghelpers.cpp \
$$PWD/qwindowsservices.cpp \
$$PWD/qwindowsnativeimage.cpp \
- $$PWD/qwindowsnativeinterface.cpp
+ $$PWD/qwindowsnativeinterface.cpp \
+ $$PWD/qwindowsscaling.cpp
HEADERS += \
$$PWD/qwindowswindow.h \
@@ -64,7 +65,8 @@ HEADERS += \
$$PWD/qwindowsservices.h \
$$PWD/qplatformfunctions_wince.h \
$$PWD/qwindowsnativeimage.h \
- $$PWD/qwindowsnativeinterface.h
+ $$PWD/qwindowsnativeinterface.h \
+ $$PWD/qwindowsscaling.h
!wince: HEADERS += $$PWD/qwindowsopengltester.h