Highdpi changes for Windows
Adapt the Windows plugin to work with the new cross-platform high-DPI scaling. Task-number: QTBUG-38993 Task-number: QTBUG-46615 Change-Id: I108d319255925a290b75611e95ef006d4aaf7ace Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>bb10
parent
a705b4ec1f
commit
fd6821740f
|
|
@ -38,6 +38,7 @@
|
|||
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QPainter>
|
||||
#include <private/qhighdpiscaling_p.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
|
|
@ -82,8 +83,8 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion ®ion,
|
|||
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());
|
||||
QRect r = QHighDpi::toNativePixels(window->frameGeometry(), window);
|
||||
QPoint frameOffset(QHighDpi::toNativePixels(QPoint(window->frameMargins().left(), window->frameMargins().top()), window));
|
||||
QRect dirtyRect = br.translated(offset + frameOffset);
|
||||
|
||||
SIZE size = {r.width(), r.height()};
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "qwindowsdrag.h"
|
||||
#include "qwindowscontext.h"
|
||||
#include "qwindowsscreen.h"
|
||||
#ifndef QT_NO_CLIPBOARD
|
||||
# include "qwindowsclipboard.h"
|
||||
#endif
|
||||
|
|
@ -50,6 +51,7 @@
|
|||
#include <QtGui/QGuiApplication>
|
||||
#include <qpa/qwindowsysteminterface_p.h>
|
||||
#include <QtGui/private/qguiapplication_p.h>
|
||||
#include <QtGui/private/qhighdpiscaling_p.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QBuffer>
|
||||
|
|
@ -278,6 +280,13 @@ QDebug operator<<(QDebug d, const QWindowsOleDropSource::CursorEntry &e)
|
|||
}
|
||||
#endif // !QT_NO_DEBUG_OUTPUT
|
||||
|
||||
static qreal dragScaleFactor()
|
||||
{
|
||||
const QWindowsScreenManager &screenManager = QWindowsContext::instance()->screenManager();
|
||||
const QWindowsScreen *screen = screenManager.screenAtDp(QWindowsCursor::mousePosition());
|
||||
return screen ? QHighDpiScaling::factor(screen) : qreal(1);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Blend custom pixmap with cursors.
|
||||
*/
|
||||
|
|
@ -288,11 +297,21 @@ void QWindowsOleDropSource::createCursors()
|
|||
const QPixmap pixmap = drag->pixmap();
|
||||
const bool hasPixmap = !pixmap.isNull();
|
||||
|
||||
const qreal scaleFactor = dragScaleFactor();
|
||||
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 scaledPixmap = scalePixmap
|
||||
? pixmap.scaled((QSizeF(pixmap.size()) * scaleFactor).toSize(),
|
||||
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 = scalePixmap
|
||||
? (QPointF(drag->hotSpot()) * scaleFactor).toPoint()
|
||||
: drag->hotSpot();
|
||||
for (int cnum = 0; cnum < actionCount; ++cnum) {
|
||||
const Qt::DropAction action = actions[cnum];
|
||||
QPixmap cursorPixmap = drag->dragCursor(action);
|
||||
|
|
@ -312,15 +331,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(scaledPixmap.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(scaledPixmap.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, scaledPixmap);
|
||||
p.drawPixmap(qMax(0, hotSpot.x()),qMax(0, hotSpot.y()), cursorPixmap);
|
||||
newPixmap = newCursor;
|
||||
newHotSpot = QPoint(qMax(0, hotSpot.x()), qMax(0, hotSpot.y()));
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@
|
|||
# include "qwindowssessionmanager.h"
|
||||
#endif
|
||||
#include <QtGui/private/qguiapplication_p.h>
|
||||
#include <QtGui/private/qhighdpiscaling_p.h>
|
||||
#include <QtGui/qpa/qplatforminputcontextfactory_p.h>
|
||||
|
||||
#include <QtCore/private/qeventdispatcher_win_p.h>
|
||||
|
|
@ -302,7 +303,7 @@ QWindowsWindowData QWindowsIntegration::createWindowData(QWindow *window) const
|
|||
{
|
||||
QWindowsWindowData requested;
|
||||
requested.flags = window->flags();
|
||||
requested.geometry = window->geometry();
|
||||
requested.geometry = QHighDpi::toNativePixels(window->geometry(), window);
|
||||
// Apply custom margins (see QWindowsWindow::setCustomMargins())).
|
||||
const QVariant customMarginsV = window->property("_q_windowsCustomMargins");
|
||||
if (customMarginsV.isValid())
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include <QtGui/QWindow>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
#include <private/qguiapplication_p.h>
|
||||
#include <private/qhighdpiscaling_p.h>
|
||||
#include <QtGui/QKeyEvent>
|
||||
|
||||
#if defined(WM_APPCOMMAND)
|
||||
|
|
@ -791,9 +792,10 @@ static void showSystemMenu(QWindow* w)
|
|||
#undef enabled
|
||||
#undef disabled
|
||||
#endif // !Q_OS_WINCE
|
||||
const QPoint pos = QHighDpi::toNativePixels(topLevel->geometry().topLeft(), topLevel);
|
||||
const int ret = TrackPopupMenuEx(menu,
|
||||
TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
|
||||
topLevel->geometry().x(), topLevel->geometry().y(),
|
||||
pos.x(), pos.y(),
|
||||
topLevelHwnd,
|
||||
0);
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#include <QtGui/QPixmap>
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
#include <private/qhighdpiscaling_p.h>
|
||||
#include <QtGui/QScreen>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
|
@ -287,6 +288,12 @@ QWindowsScreen *QWindowsScreen::screenOf(const QWindow *w)
|
|||
return 0;
|
||||
}
|
||||
|
||||
qreal QWindowsScreen::pixelDensity() const
|
||||
{
|
||||
const qreal physicalDpi = m_data.geometry.width() / m_data.physicalSizeMM.width() * qreal(25.4);
|
||||
return qRound(physicalDpi / 96);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Determine siblings in a virtual desktop system.
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ public:
|
|||
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; }
|
||||
qreal pixelDensity() const Q_DECL_OVERRIDE;
|
||||
qreal devicePixelRatio() const Q_DECL_OVERRIDE { return 1.0; }
|
||||
qreal refreshRate() const Q_DECL_OVERRIDE { return m_data.refreshRateHz; }
|
||||
QString name() const Q_DECL_OVERRIDE { return m_data.name; }
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@
|
|||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QPixmapCache>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
#include <private/qhighdpiscaling_p.h>
|
||||
#include <private/qsystemlibrary_p.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
|
@ -494,7 +495,8 @@ static QPixmap loadIconFromShell32(int resourceId, QSizeF size)
|
|||
|
||||
QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
|
||||
{
|
||||
const int scaleFactor = 1; // HIGDPI Fixme: ?
|
||||
const QScreen *primaryScreen = QGuiApplication::primaryScreen();
|
||||
const int scaleFactor = primaryScreen ? qRound(QHighDpiScaling::factor(primaryScreen)) : 1;
|
||||
const QSizeF pixmapSize = size * scaleFactor;
|
||||
int resourceId = -1;
|
||||
LPCTSTR iconName = 0;
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
#include <private/qsystemlibrary_p.h>
|
||||
#include <private/qwindow_p.h> // QWINDOWSIZE_MAX
|
||||
#include <private/qguiapplication_p.h>
|
||||
#include <private/qhighdpiscaling_p.h>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
|
@ -703,6 +704,20 @@ void WindowCreationData::initialize(const QWindow *w, HWND hwnd, bool frameChang
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Scaling helpers for size constraints.
|
||||
static QSize toNativeSizeConstrained(QSize dip, const QWindow *w)
|
||||
{
|
||||
if (QHighDpiScaling::isActive()) {
|
||||
const qreal factor = QHighDpiScaling::factor(w);
|
||||
if (dip.width() > 0 && dip.width() < QWINDOWSIZE_MAX)
|
||||
dip.rwidth() *= factor;
|
||||
if (dip.height() > 0 && dip.height() < QWINDOWSIZE_MAX)
|
||||
dip.rheight() *= factor;
|
||||
}
|
||||
return dip;
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QWindowsGeometryHint
|
||||
\brief Stores geometry constraints and provides utility functions.
|
||||
|
|
@ -715,8 +730,8 @@ void WindowCreationData::initialize(const QWindow *w, HWND hwnd, bool frameChang
|
|||
*/
|
||||
|
||||
QWindowsGeometryHint::QWindowsGeometryHint(const QWindow *w, const QMargins &cm) :
|
||||
minimumSize(w->minimumSize()),
|
||||
maximumSize(w->maximumSize()),
|
||||
minimumSize(toNativeSizeConstrained(w->minimumSize(), w)),
|
||||
maximumSize(toNativeSizeConstrained(w->maximumSize(), w)),
|
||||
customMargins(cm)
|
||||
{
|
||||
}
|
||||
|
|
@ -1621,7 +1636,9 @@ void QWindowsWindow::setWindowState(Qt::WindowState state)
|
|||
|
||||
bool QWindowsWindow::isFullScreen_sys() const
|
||||
{
|
||||
return window()->isTopLevel() && geometry_sys() == window()->screen()->geometry();
|
||||
const QWindow *w = window();
|
||||
return w->isTopLevel()
|
||||
&& geometry_sys() == QHighDpi::toNativePixels(w->screen()->geometry(), w);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -1691,7 +1708,7 @@ 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 r = QHighDpi::toNativePixels(screen->geometry(), window());
|
||||
const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
|
||||
const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
|
||||
setFlag(SynchronousGeometryChangeEvent);
|
||||
|
|
@ -1808,8 +1825,7 @@ bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow *
|
|||
const QRect suggestedFrameGeometry(windowPos->x, windowPos->y,
|
||||
windowPos->cx, windowPos->cy);
|
||||
const QRect suggestedGeometry = suggestedFrameGeometry - margins;
|
||||
const QRectF correctedGeometryF =
|
||||
qt_window_private(const_cast<QWindow *>(qWindow))->closestAcceptableGeometry(suggestedGeometry);
|
||||
const QRectF correctedGeometryF = qWindow->handle()->windowClosestAcceptableGeometry(suggestedGeometry);
|
||||
if (!correctedGeometryF.isValid())
|
||||
return false;
|
||||
const QRect correctedFrameGeometry = correctedGeometryF.toRect() + margins;
|
||||
|
|
@ -2048,7 +2064,7 @@ bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *re
|
|||
const bool fixedHeight = minimumSize.height() == maximumSize.height();
|
||||
if (!fixedWidth && !fixedHeight)
|
||||
return false;
|
||||
const QPoint localPos = w->mapFromGlobal(globalPos);
|
||||
const QPoint localPos = w->mapFromGlobal(QHighDpi::fromNativePixels(globalPos, w));
|
||||
const QSize size = w->size();
|
||||
if (fixedHeight) {
|
||||
if (localPos.y() >= size.height()) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue