tdf#127687 Qt5 introduce basic HiDPI scaling
For tdf#124292, Qt's own HiDPI scaling was explicitly disabled,
but it turns out, you can't really scale QStyle painting then.
This patch series had a 2nd approach also used by Gtk+ currently,
which relied on the scaling of ths Cairo surface, which works
surprisingly good, but has to lie about the real DPI value, so
nothing is scaled twice. Also all icons are then scaled instead
of rendered with the proper resolution.
When HiDPI support in Qt is enabled, and the application is
started using QT_SCALE_FACTOR=1.25, Qt simply lowers the reported
resolution, keeps the logical DPI value of 96 and changes the
devicePixelRatio to the specified value. But LO still expects
the real DPI values and sizes, so we have to multiply a lot of
rectangles, sizes and positions.
The current result is far from perfect, which you can see with
the various graphics glitches, but it at least doesn't crash
anymore in the ControlType::Editbox sizing code.
The main problem is all the up and downscaling in the
getNativeControlRegion code, so LO knows the size of the widgets
for the correct layouting, since there seem to be no API to
get the scaled values from Qt / QStyle.
Change-Id: I687b1df6ef27724ce68326d256e9addccd72e759
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86239
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
diff --git a/vcl/inc/qt5/Qt5Frame.hxx b/vcl/inc/qt5/Qt5Frame.hxx
index 5a88221..0caf1bc 100644
--- a/vcl/inc/qt5/Qt5Frame.hxx
+++ b/vcl/inc/qt5/Qt5Frame.hxx
@@ -141,6 +141,7 @@ public:
QWidget* GetQWidget() const { return m_pQWidget; }
Qt5MainWindow* GetTopLevelWindow() const { return m_pTopLevel; }
QWidget* asChild() const;
qreal devicePixelRatioF() const;
void Damage(sal_Int32 nExtentsX, sal_Int32 nExtentsY, sal_Int32 nExtentsWidth,
sal_Int32 nExtentsHeight) const;
diff --git a/vcl/inc/qt5/Qt5Graphics.hxx b/vcl/inc/qt5/Qt5Graphics.hxx
index c36d222..0a66271 100644
--- a/vcl/inc/qt5/Qt5Graphics.hxx
+++ b/vcl/inc/qt5/Qt5Graphics.hxx
@@ -27,6 +27,8 @@
#include <QtGui/QPainterPath>
#include <QtGui/QRegion>
#include "Qt5GraphicsBase.hxx"
class PhysicalFontCollection;
class QImage;
class QPushButton;
@@ -35,7 +37,7 @@ class Qt5FontFace;
class Qt5Frame;
class Qt5Painter;
class Qt5Graphics final : public SalGraphics
class Qt5Graphics final : public SalGraphics, public Qt5GraphicsBase
{
friend class Qt5Bitmap;
friend class Qt5Painter;
diff --git a/vcl/inc/qt5/Qt5GraphicsBase.hxx b/vcl/inc/qt5/Qt5GraphicsBase.hxx
new file mode 100644
index 0000000..ef79551
--- /dev/null
+++ b/vcl/inc/qt5/Qt5GraphicsBase.hxx
@@ -0,0 +1,30 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <QtWidgets/QApplication>
class Qt5GraphicsBase
{
qreal m_fDPR;
protected:
Qt5GraphicsBase()
: m_fDPR(qApp ? qApp->devicePixelRatio() : 1.0)
{
}
void setDevicePixelRatioF(qreal fDPR) { m_fDPR = fDPR; }
public:
qreal devicePixelRatioF() const { return m_fDPR; }
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/qt5/Qt5Graphics_Controls.hxx b/vcl/inc/qt5/Qt5Graphics_Controls.hxx
index f70804c..04503c7 100644
--- a/vcl/inc/qt5/Qt5Graphics_Controls.hxx
+++ b/vcl/inc/qt5/Qt5Graphics_Controls.hxx
@@ -31,13 +31,16 @@
#include <QtWidgets/QStyle>
#include <QtWidgets/QStyleOption>
class Qt5GraphicsBase;
class Qt5Graphics_Controls final : public vcl::WidgetDrawInterface
{
std::unique_ptr<QImage> m_image;
QRect m_lastPopupRect;
Qt5GraphicsBase const& m_rGraphics;
public:
Qt5Graphics_Controls();
Qt5Graphics_Controls(const Qt5GraphicsBase& rGraphics);
QImage* getImage() { return m_image.get(); }
@@ -60,19 +63,34 @@ private:
const QSize& contentsSize);
static QRect subControlRect(QStyle::ComplexControl control, const QStyleOptionComplex* option,
QStyle::SubControl subControl);
static QRect subElementRect(QStyle::SubElement element, const QStyleOption* option);
static void draw(QStyle::ControlElement element, QStyleOption* option, QImage* image,
QStyle::State const state = QStyle::State_None, QRect rect = QRect());
static void draw(QStyle::PrimitiveElement element, QStyleOption* option, QImage* image,
QStyle::State const state = QStyle::State_None, QRect rect = QRect());
static void draw(QStyle::ComplexControl element, QStyleOptionComplex* option, QImage* image,
QStyle::State const state = QStyle::State_None);
static void drawFrame(QStyle::PrimitiveElement element, QImage* image,
QStyle::State const& state, bool bClip = true,
QStyle::PixelMetric eLineMetric = QStyle::PM_DefaultFrameWidth);
void draw(QStyle::ControlElement element, QStyleOption* option, QImage* image,
QStyle::State const state = QStyle::State_None, QRect rect = QRect());
void draw(QStyle::PrimitiveElement element, QStyleOption* option, QImage* image,
QStyle::State const state = QStyle::State_None, QRect rect = QRect());
void draw(QStyle::ComplexControl element, QStyleOptionComplex* option, QImage* image,
QStyle::State const state = QStyle::State_None);
void drawFrame(QStyle::PrimitiveElement element, QImage* image, QStyle::State const& state,
bool bClip = true,
QStyle::PixelMetric eLineMetric = QStyle::PM_DefaultFrameWidth);
static void fillQStyleOptionTab(const ImplControlValue& value, QStyleOptionTab& sot);
static void fullQStyleOptionTabWidgetFrame(QStyleOptionTabWidgetFrame& option);
void fullQStyleOptionTabWidgetFrame(QStyleOptionTabWidgetFrame& option, bool bDownscale);
enum class Round
{
Floor,
Ceil,
};
int downscale(int value, Round eRound);
int upscale(int value, Round eRound);
QRect downscale(const QRect& rect);
QRect upscale(const QRect& rect);
QSize downscale(const QSize& size, Round eRound);
QSize upscale(const QSize& size, Round eRound);
QPoint upscale(const QPoint& point, Round eRound);
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/qt5/Qt5Painter.hxx b/vcl/inc/qt5/Qt5Painter.hxx
index 3434d80..51ddc3d 100644
--- a/vcl/inc/qt5/Qt5Painter.hxx
+++ b/vcl/inc/qt5/Qt5Painter.hxx
@@ -42,16 +42,20 @@ public:
void update(int nx, int ny, int nw, int nh)
{
if (m_rGraphics.m_pFrame)
m_aRegion += QRect(nx, ny, nw, nh);
m_aRegion += scaledQRect({ nx, ny, nw, nh }, 1 / m_rGraphics.devicePixelRatioF());
}
void update(const QRect& rRect)
{
if (m_rGraphics.m_pFrame)
m_aRegion += rRect;
m_aRegion += scaledQRect(rRect, 1 / m_rGraphics.devicePixelRatioF());
}
void update(const QRectF& rRectF) { update(rRectF.toAlignedRect()); }
void update(const QRectF& rRectF)
{
if (m_rGraphics.m_pFrame)
update(scaledQRect(rRectF.toAlignedRect(), 1 / m_rGraphics.devicePixelRatioF()));
}
void update()
{
diff --git a/vcl/inc/qt5/Qt5SvpGraphics.hxx b/vcl/inc/qt5/Qt5SvpGraphics.hxx
index 8950230..2ea5e6a 100644
--- a/vcl/inc/qt5/Qt5SvpGraphics.hxx
+++ b/vcl/inc/qt5/Qt5SvpGraphics.hxx
@@ -22,9 +22,11 @@
#include <vclpluginapi.h>
#include <headless/svpgdi.hxx>
#include "Qt5GraphicsBase.hxx"
class Qt5Frame;
class VCLPLUG_QT5_PUBLIC Qt5SvpGraphics : public SvpSalGraphics
class VCLPLUG_QT5_PUBLIC Qt5SvpGraphics : public SvpSalGraphics, public Qt5GraphicsBase
{
Qt5Frame* const m_pFrame;
diff --git a/vcl/inc/qt5/Qt5Tools.hxx b/vcl/inc/qt5/Qt5Tools.hxx
index 47f37d8..88a85f8 100644
--- a/vcl/inc/qt5/Qt5Tools.hxx
+++ b/vcl/inc/qt5/Qt5Tools.hxx
@@ -54,6 +54,18 @@ inline QRect toQRect(const tools::Rectangle& rRect)
return QRect(rRect.Left(), rRect.Top(), rRect.GetWidth(), rRect.GetHeight());
}
inline QRect toQRect(const tools::Rectangle& rRect, const qreal fScale)
{
return QRect(floor(rRect.Left() * fScale), floor(rRect.Top() * fScale),
ceil(rRect.GetWidth() * fScale), ceil(rRect.GetHeight() * fScale));
}
inline QRect scaledQRect(const QRect& rRect, const qreal fScale)
{
return QRect(floor(rRect.x() * fScale), floor(rRect.y() * fScale), ceil(rRect.width() * fScale),
ceil(rRect.height() * fScale));
}
inline tools::Rectangle toRectangle(const QRect& rRect)
{
return tools::Rectangle(rRect.left(), rRect.top(), rRect.right(), rRect.bottom());
diff --git a/vcl/qt5/Qt5Frame.cxx b/vcl/qt5/Qt5Frame.cxx
index 722dca9..2d780c7 100644
--- a/vcl/qt5/Qt5Frame.cxx
+++ b/vcl/qt5/Qt5Frame.cxx
@@ -284,7 +284,8 @@ Qt5Frame::~Qt5Frame()
void Qt5Frame::Damage(sal_Int32 nExtentsX, sal_Int32 nExtentsY, sal_Int32 nExtentsWidth,
sal_Int32 nExtentsHeight) const
{
m_pQWidget->update(nExtentsX, nExtentsY, nExtentsWidth, nExtentsHeight);
m_pQWidget->update(scaledQRect(QRect(nExtentsX, nExtentsY, nExtentsWidth, nExtentsHeight),
1 / devicePixelRatioF()));
}
void Qt5Frame::InitQt5SvpGraphics(Qt5SvpGraphics* pQt5SvpGraphics)
@@ -320,7 +321,8 @@ SalGraphics* Qt5Frame::AcquireGraphics()
if (!m_pQt5Graphics.get() || m_bGraphicsInvalid)
{
m_pQt5Graphics.reset(new Qt5Graphics(this));
m_pQImage.reset(new QImage(m_pQWidget->size(), Qt5_DefaultFormat32));
m_pQImage.reset(
new QImage(m_pQWidget->size() * devicePixelRatioF(), Qt5_DefaultFormat32));
m_pQImage->fill(Qt::transparent);
m_pQt5Graphics->ChangeQImage(m_pQImage.get());
m_bGraphicsInvalid = false;
@@ -348,6 +350,8 @@ bool Qt5Frame::PostEvent(std::unique_ptr<ImplSVEvent> pData)
QWidget* Qt5Frame::asChild() const { return m_pTopLevel ? m_pTopLevel : m_pQWidget; }
qreal Qt5Frame::devicePixelRatioF() const { return asChild()->devicePixelRatioF(); }
bool Qt5Frame::isWindow() const { return asChild()->isWindow(); }
QWindow* Qt5Frame::windowHandle() const
@@ -429,13 +433,19 @@ void Qt5Frame::Show(bool bVisible, bool /*bNoActivate*/)
void Qt5Frame::SetMinClientSize(long nWidth, long nHeight)
{
if (!isChild())
asChild()->setMinimumSize(nWidth, nHeight);
{
const qreal fRatio = devicePixelRatioF();
asChild()->setMinimumSize(round(nWidth / fRatio), round(nHeight / fRatio));
}
}
void Qt5Frame::SetMaxClientSize(long nWidth, long nHeight)
{
if (!isChild())
asChild()->setMaximumSize(nWidth, nHeight);
{
const qreal fRatio = devicePixelRatioF();
asChild()->setMaximumSize(round(nWidth / fRatio), round(nHeight / fRatio));
}
}
void Qt5Frame::SetDefaultPos()
@@ -446,10 +456,12 @@ void Qt5Frame::SetDefaultPos()
// center on parent
if (m_pParent)
{
const qreal fRatio = devicePixelRatioF();
QWidget* const pWindow = m_pParent->GetQWidget()->window();
QWidget* const pWidget = asChild();
QPoint aPos = pWindow->rect().center() - pWidget->rect().center();
SetPosSize(aPos.x(), aPos.y(), 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y);
SetPosSize(round(aPos.x() * fRatio), round(aPos.y() * fRatio), 0, 0,
SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y);
assert(!m_bDefaultPos);
}
else
@@ -518,10 +530,12 @@ void Qt5Frame::SetPosSize(long nX, long nY, long nWidth, long nHeight, sal_uInt1
if (nWidth > 0 && nHeight > 0)
{
m_bDefaultSize = false;
const int nNewWidth = round(nWidth / devicePixelRatioF());
const int nNewHeight = round(nHeight / devicePixelRatioF());
if (m_nStyle & SalFrameStyleFlags::SIZEABLE)
asChild()->resize(nWidth, nHeight);
asChild()->resize(nNewWidth, nNewHeight);
else
asChild()->setFixedSize(nWidth, nHeight);
asChild()->setFixedSize(nNewWidth, nNewHeight);
}
// assume the resize happened
@@ -546,7 +560,7 @@ void Qt5Frame::SetPosSize(long nX, long nY, long nWidth, long nHeight, sal_uInt1
Qt5MainWindow* pTopLevel = m_pParent->GetTopLevelWindow();
if (pTopLevel && pTopLevel->menuBar() && pTopLevel->menuBar()->isVisible())
nY += pTopLevel->menuBar()->geometry().height();
nY += round(pTopLevel->menuBar()->geometry().height() * devicePixelRatioF());
}
if (!(nFlags & SAL_FRAME_POSSIZE_X))
@@ -560,14 +574,14 @@ void Qt5Frame::SetPosSize(long nX, long nY, long nWidth, long nHeight, sal_uInt1
maGeometry.nY = nY;
m_bDefaultPos = false;
asChild()->move(nX, nY);
asChild()->move(round(nX / devicePixelRatioF()), round(nY / devicePixelRatioF()));
}
}
void Qt5Frame::GetClientSize(long& rWidth, long& rHeight)
{
rWidth = m_pQWidget->width();
rHeight = m_pQWidget->height();
rWidth = round(m_pQWidget->width() * devicePixelRatioF());
rHeight = round(m_pQWidget->height() * devicePixelRatioF());
}
void Qt5Frame::GetWorkArea(tools::Rectangle& rRect)
@@ -578,7 +592,7 @@ void Qt5Frame::GetWorkArea(tools::Rectangle& rRect)
if (!pScreen)
return;
QSize aSize = pScreen->availableVirtualSize();
QSize aSize = pScreen->availableVirtualSize() * devicePixelRatioF();
rRect = tools::Rectangle(0, 0, aSize.width(), aSize.height());
}
@@ -622,9 +636,10 @@ void Qt5Frame::SetWindowState(const SalFrameState* pState)
if ((pState->mnMask & WindowStateMask::State) && (pState->mnState & WindowStateState::Maximized)
&& !isMaximized() && (pState->mnMask & nMaxGeometryMask) == nMaxGeometryMask)
{
const qreal fRatio = devicePixelRatioF();
QWidget* const pChild = asChild();
pChild->resize(pState->mnWidth, pState->mnHeight);
pChild->move(pState->mnX, pState->mnY);
pChild->resize(ceil(pState->mnWidth / fRatio), ceil(pState->mnHeight / fRatio));
pChild->move(ceil(pState->mnX / fRatio), ceil(pState->mnY / fRatio));
SetWindowStateImpl(Qt::WindowMaximized);
}
else if (pState->mnMask
@@ -666,7 +681,7 @@ bool Qt5Frame::GetWindowState(SalFrameState* pState)
else
{
// geometry() is the drawable area, which is wanted here
QRect rect = asChild()->geometry();
QRect rect = scaledQRect(asChild()->geometry(), devicePixelRatioF());
pState->mnX = rect.x();
pState->mnY = rect.y();
pState->mnWidth = rect.width();
@@ -1132,7 +1147,7 @@ void Qt5Frame::Beep() { QApplication::beep(); }
SalFrame::SalPointerState Qt5Frame::GetPointerState()
{
SalPointerState aState;
aState.maPos = toPoint(QCursor::pos());
aState.maPos = toPoint(QCursor::pos() * devicePixelRatioF());
aState.maPos.Move(-maGeometry.nX, -maGeometry.nY);
aState.mnState = GetMouseModCode(QGuiApplication::mouseButtons())
| GetKeyModCode(QGuiApplication::keyboardModifiers());
@@ -1163,7 +1178,8 @@ void Qt5Frame::BeginSetClipRegion(sal_uInt32)
void Qt5Frame::UnionClipRegion(long nX, long nY, long nWidth, long nHeight)
{
m_aRegion = m_aRegion.united(QRegion(nX, nY, nWidth, nHeight));
m_aRegion
= m_aRegion.united(scaledQRect(QRect(nX, nY, nWidth, nHeight), 1 / devicePixelRatioF()));
}
void Qt5Frame::EndSetClipRegion() { m_bNullRegion = false; }
@@ -1330,12 +1346,13 @@ void Qt5Frame::handleDragMove(QDragMoveEvent* pEvent)
const sal_Int8 nSourceActions = toVclDropActions(pEvent->possibleActions());
const QMimeData* pMimeData = pEvent->mimeData();
const sal_Int8 nUserDropAction = lcl_getUserDropAction(pEvent, nSourceActions, pMimeData);
const Point aPos = toPoint(pEvent->pos() * devicePixelRatioF());
css::datatransfer::dnd::DropTargetDragEnterEvent aEvent;
aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(m_pDropTarget);
aEvent.Context = static_cast<css::datatransfer::dnd::XDropTargetDragContext*>(m_pDropTarget);
aEvent.LocationX = pEvent->pos().x();
aEvent.LocationY = pEvent->pos().y();
aEvent.LocationX = aPos.X();
aEvent.LocationY = aPos.Y();
aEvent.DropAction = nUserDropAction;
aEvent.SourceActions = nSourceActions;
@@ -1367,12 +1384,13 @@ void Qt5Frame::handleDrop(QDropEvent* pEvent)
const sal_Int8 nSourceActions = toVclDropActions(pEvent->possibleActions());
const sal_Int8 nUserDropAction
= lcl_getUserDropAction(pEvent, nSourceActions, pEvent->mimeData());
const Point aPos = toPoint(pEvent->pos() * devicePixelRatioF());
css::datatransfer::dnd::DropTargetDropEvent aEvent;
aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(m_pDropTarget);
aEvent.Context = static_cast<css::datatransfer::dnd::XDropTargetDropContext*>(m_pDropTarget);
aEvent.LocationX = pEvent->pos().x();
aEvent.LocationY = pEvent->pos().y();
aEvent.LocationX = aPos.X();
aEvent.LocationY = aPos.Y();
aEvent.SourceActions = nSourceActions;
aEvent.DropAction = nUserDropAction;
aEvent.Transferable = lcl_getXTransferable(pEvent->mimeData());
diff --git a/vcl/qt5/Qt5Graphics.cxx b/vcl/qt5/Qt5Graphics.cxx
index e9d57d2..34f6108 100644
--- a/vcl/qt5/Qt5Graphics.cxx
+++ b/vcl/qt5/Qt5Graphics.cxx
@@ -45,8 +45,10 @@ Qt5Graphics::Qt5Graphics( Qt5Frame *pFrame, QImage *pQImage )
if (!initWidgetDrawBackends(false))
{
if (!Qt5Data::noNativeControls())
m_pWidgetDraw.reset(new Qt5Graphics_Controls());
m_pWidgetDraw.reset(new Qt5Graphics_Controls(*this));
}
if (m_pFrame)
setDevicePixelRatioF(m_pFrame->devicePixelRatioF());
}
Qt5Graphics::~Qt5Graphics() { ReleaseFonts(); }
@@ -116,8 +118,10 @@ void Qt5Graphics::handleDamage(const tools::Rectangle& rDamagedRegion)
assert(!rDamagedRegion.IsEmpty());
QImage* pImage = static_cast<Qt5Graphics_Controls*>(m_pWidgetDraw.get())->getImage();
QImage blit(*pImage);
blit.setDevicePixelRatio(1);
Qt5Painter aPainter(*this);
aPainter.drawImage(QPoint(rDamagedRegion.getX(), rDamagedRegion.getY()), *pImage);
aPainter.drawImage(QPoint(rDamagedRegion.getX(), rDamagedRegion.getY()), blit);
aPainter.update(toQRect(rDamagedRegion));
}
diff --git a/vcl/qt5/Qt5Graphics_Controls.cxx b/vcl/qt5/Qt5Graphics_Controls.cxx
index a6d8e6f..ee7b43d 100644
--- a/vcl/qt5/Qt5Graphics_Controls.cxx
+++ b/vcl/qt5/Qt5Graphics_Controls.cxx
@@ -25,6 +25,7 @@
#include <QtWidgets/QLabel>
#include <qt5/Qt5Tools.hxx>
#include <qt5/Qt5GraphicsBase.hxx>
#include <vcl/decoview.hxx>
/**
@@ -62,7 +63,10 @@ static QStyle::State vclStateValue2StateFlag(ControlState nControlState,
return nState;
}
Qt5Graphics_Controls::Qt5Graphics_Controls() {}
Qt5Graphics_Controls::Qt5Graphics_Controls(const Qt5GraphicsBase& rGraphics)
: m_rGraphics(rGraphics)
{
}
bool Qt5Graphics_Controls::isNativeControlSupported(ControlType type, ControlPart part)
{
@@ -133,11 +137,19 @@ inline QRect Qt5Graphics_Controls::subControlRect(QStyle::ComplexControl control
return QApplication::style()->subControlRect(control, option, subControl);
}
inline QRect Qt5Graphics_Controls::subElementRect(QStyle::SubElement element,
const QStyleOption* option)
{
return QApplication::style()->subElementRect(element, option);
}
void Qt5Graphics_Controls::draw(QStyle::ControlElement element, QStyleOption* option, QImage* image,
QStyle::State const state, QRect rect)
{
const QRect& targetRect = !rect.isNull() ? rect : image->rect();
option->state |= state;
option->rect = !rect.isNull() ? rect : image->rect();
option->rect = downscale(targetRect);
QPainter painter(image);
QApplication::style()->drawControl(element, option, &painter);
@@ -146,8 +158,10 @@ void Qt5Graphics_Controls::draw(QStyle::ControlElement element, QStyleOption* op
void Qt5Graphics_Controls::draw(QStyle::PrimitiveElement element, QStyleOption* option,
QImage* image, QStyle::State const state, QRect rect)
{
const QRect& targetRect = !rect.isNull() ? rect : image->rect();
option->state |= state;
option->rect = !rect.isNull() ? rect : image->rect();
option->rect = downscale(targetRect);
QPainter painter(image);
QApplication::style()->drawPrimitive(element, option, &painter);
@@ -156,8 +170,10 @@ void Qt5Graphics_Controls::draw(QStyle::PrimitiveElement element, QStyleOption*
void Qt5Graphics_Controls::draw(QStyle::ComplexControl element, QStyleOptionComplex* option,
QImage* image, QStyle::State const state)
{
const QRect& targetRect = image->rect();
option->state |= state;
option->rect = image->rect();
option->rect = downscale(targetRect);
QPainter painter(image);
QApplication::style()->drawComplexControl(element, option, &painter);
@@ -173,7 +189,7 @@ void Qt5Graphics_Controls::drawFrame(QStyle::PrimitiveElement element, QImage* i
option.state = QStyle::State_Sunken | state;
option.lineWidth = fw;
QRect aRect(image->rect());
QRect aRect = downscale(image->rect());
option.rect = aRect;
QPainter painter(image);
@@ -193,12 +209,14 @@ void Qt5Graphics_Controls::fillQStyleOptionTab(const ImplControlValue& value, QS
sot.position = QStyleOptionTab::Middle;
}
void Qt5Graphics_Controls::fullQStyleOptionTabWidgetFrame(QStyleOptionTabWidgetFrame& option)
void Qt5Graphics_Controls::fullQStyleOptionTabWidgetFrame(QStyleOptionTabWidgetFrame& option,
bool bDownscale)
{
option.state = QStyle::State_Enabled;
option.rightCornerWidgetSize = QSize(0, 0);
option.leftCornerWidgetSize = QSize(0, 0);
option.lineWidth = pixelMetric(QStyle::PM_DefaultFrameWidth);
int nLineWidth = pixelMetric(QStyle::PM_DefaultFrameWidth);
option.lineWidth = bDownscale ? std::max(1, downscale(nLineWidth, Round::Ceil)) : nLineWidth;
option.midLineWidth = 0;
option.shape = QTabBar::RoundedNorth;
}
@@ -228,6 +246,7 @@ bool Qt5Graphics_Controls::drawNativeControl(ControlType type, ControlPart part,
{
m_image.reset(new QImage(widgetRect.width(), widgetRect.height(),
QImage::Format_ARGB32_Premultiplied));
m_image->setDevicePixelRatio(m_rGraphics.devicePixelRatioF());
}
// Default image color - just once
@@ -643,13 +662,13 @@ bool Qt5Graphics_Controls::drawNativeControl(ControlType type, ControlPart part,
TabPaneValue::m_nOverlap = pixelMetric(QStyle::PM_TabBarBaseOverlap, &tabOverlap);
QStyleOptionTabWidgetFrame option;
fullQStyleOptionTabWidgetFrame(option);
fullQStyleOptionTabWidgetFrame(option, false);
option.tabBarRect = toQRect(rValue.m_aTabHeaderRect);
option.selectedTabRect
= rValue.m_aSelectedTabRect.IsEmpty() ? QRect() : toQRect(rValue.m_aSelectedTabRect);
option.tabBarSize = toQSize(rValue.m_aTabHeaderRect.GetSize());
option.rect = m_image->rect();
QRect aRect = QApplication::style()->subElementRect(QStyle::SE_TabWidgetTabPane, &option);
QRect aRect = subElementRect(QStyle::SE_TabWidgetTabPane, &option);
draw(QStyle::PE_FrameTabWidget, &option, m_image.get(),
vclStateValue2StateFlag(nControlState, value), aRect);
}
@@ -684,7 +703,8 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart
if (controlState & ControlState::DEFAULT)
{
int size = pixelMetric(QStyle::PM_ButtonDefaultIndicator, &styleOption);
int size = upscale(pixelMetric(QStyle::PM_ButtonDefaultIndicator, &styleOption),
Round::Ceil);
boundingRect.adjust(-size, -size, size, size);
retVal = true;
}
@@ -693,23 +713,24 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart
case ControlType::Editbox:
case ControlType::MultilineEditbox:
{
// we have to get stable borders, otherwise layout loops.
// so we simply only scale the detected borders.
QStyleOptionFrame fo;
fo.frameShape = QFrame::StyledPanel;
fo.state = QStyle::State_Sunken;
fo.lineWidth = pixelMetric(QStyle::PM_DefaultFrameWidth);
QSize aMinSize = sizeFromContents(QStyle::CT_LineEdit, &fo, contentRect.size());
if (aMinSize.height() > boundingRect.height())
{
int nHeight = (aMinSize.height() - boundingRect.height()) / 2;
assert(0 == (aMinSize.height() - boundingRect.height()) % 2);
boundingRect.adjust(0, -nHeight, 0, nHeight);
}
if (aMinSize.width() > boundingRect.width())
{
int nWidth = (aMinSize.width() - boundingRect.width()) / 2;
assert(0 == (aMinSize.width() - boundingRect.width()) % 2);
boundingRect.adjust(-nWidth, 0, nWidth, 0);
}
fo.rect = downscale(contentRect);
fo.rect.setSize(sizeFromContents(QStyle::CT_LineEdit, &fo, fo.rect.size()));
QRect aSubRect = subElementRect(QStyle::SE_LineEditContents, &fo);
// VCL tests borders with small defaults before layout, where Qt returns no sub-rect,
// so this gets us at least some frame.
int nLine = upscale(fo.lineWidth, Round::Ceil);
int nLeft = qMin(-nLine, upscale(fo.rect.left() - aSubRect.left(), Round::Floor));
int nTop = qMin(-nLine, upscale(fo.rect.top() - aSubRect.top(), Round::Floor));
int nRight = qMax(nLine, upscale(fo.rect.right() - aSubRect.right(), Round::Ceil));
int nBottom = qMax(nLine, upscale(fo.rect.bottom() - aSubRect.bottom(), Round::Ceil));
boundingRect.adjust(nLeft, nTop, nRight, nBottom);
retVal = true;
break;
}
@@ -720,11 +741,12 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart
int nWidth = pixelMetric(QStyle::PM_IndicatorWidth, &styleOption);
int nHeight = pixelMetric(QStyle::PM_IndicatorHeight, &styleOption);
contentRect.setSize({ nWidth, nHeight });
contentRect.setSize(upscale(QSize(nWidth, nHeight), Round::Ceil));
int nHMargin = pixelMetric(QStyle::PM_FocusFrameHMargin, &styleOption);
int nVMargin = pixelMetric(QStyle::PM_FocusFrameVMargin, &styleOption);
contentRect.adjust(0, 0, 2 * nHMargin, 2 * nVMargin);
contentRect.adjust(0, 0, 2 * upscale(nHMargin, Round::Ceil),
2 * upscale(nVMargin, Round::Ceil));
boundingRect = contentRect;
retVal = true;
@@ -735,7 +757,7 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart
{
QStyleOptionComboBox cbo;
cbo.rect = QRect(0, 0, contentRect.width(), contentRect.height());
cbo.rect = downscale(QRect(0, 0, contentRect.width(), contentRect.height()));
cbo.state = vclStateValue2StateFlag(controlState, val);
switch (part)
@@ -744,25 +766,28 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart
{
// find out the minimum size that should be used
// assume contents is a text line
int nHeight = QApplication::fontMetrics().height();
QSize aContentSize(contentRect.width(), nHeight);
QSize aMinSize = sizeFromContents(QStyle::CT_ComboBox, &cbo, aContentSize);
QSize aContentSize = downscale(contentRect.size(), Round::Ceil);
aContentSize.setHeight(QApplication::fontMetrics().height());
QSize aMinSize = upscale(
sizeFromContents(QStyle::CT_ComboBox, &cbo, aContentSize), Round::Ceil);
if (aMinSize.height() > contentRect.height())
contentRect.adjust(0, 0, 0, aMinSize.height() - contentRect.height());
contentRect.setHeight(aMinSize.height());
boundingRect = contentRect;
retVal = true;
break;
}
case ControlPart::ButtonDown:
contentRect
= subControlRect(QStyle::CC_ComboBox, &cbo, QStyle::SC_ComboBoxArrow);
{
contentRect = upscale(
subControlRect(QStyle::CC_ComboBox, &cbo, QStyle::SC_ComboBoxArrow));
contentRect.translate(boundingRect.left(), boundingRect.top());
retVal = true;
break;
}
case ControlPart::SubEdit:
{
contentRect
= subControlRect(QStyle::CC_ComboBox, &cbo, QStyle::SC_ComboBoxEditField);
contentRect = upscale(
subControlRect(QStyle::CC_ComboBox, &cbo, QStyle::SC_ComboBoxEditField));
contentRect.translate(boundingRect.left(), boundingRect.top());
retVal = true;
break;
@@ -777,41 +802,40 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart
QStyleOptionSpinBox sbo;
sbo.frame = true;
sbo.rect = QRect(0, 0, contentRect.width(), contentRect.height());
sbo.rect = downscale(QRect(0, 0, contentRect.width(), contentRect.height()));
sbo.state = vclStateValue2StateFlag(controlState, val);
switch (part)
{
case ControlPart::Entire:
{
int nHeight = QApplication::fontMetrics().height();
QSize aContentSize(contentRect.width(), nHeight);
QSize aMinSize = sizeFromContents(QStyle::CT_SpinBox, &sbo, aContentSize);
QSize aContentSize = downscale(contentRect.size(), Round::Ceil);
aContentSize.setHeight(QApplication::fontMetrics().height());
QSize aMinSize = upscale(
sizeFromContents(QStyle::CT_SpinBox, &sbo, aContentSize), Round::Ceil);
if (aMinSize.height() > contentRect.height())
contentRect.adjust(0, 0, 0, aMinSize.height() - contentRect.height());
contentRect.setHeight(aMinSize.height());
boundingRect = contentRect;
retVal = true;
break;
}
case ControlPart::ButtonUp:
contentRect = subControlRect(QStyle::CC_SpinBox, &sbo, QStyle::SC_SpinBoxUp);
contentRect.translate(boundingRect.left(), boundingRect.top());
retVal = true;
boundingRect = QRect();
break;
case ControlPart::ButtonDown:
contentRect = subControlRect(QStyle::CC_SpinBox, &sbo, QStyle::SC_SpinBoxDown);
retVal = true;
contentRect.translate(boundingRect.left(), boundingRect.top());
boundingRect = QRect();
break;
case ControlPart::SubEdit:
contentRect
= subControlRect(QStyle::CC_SpinBox, &sbo, QStyle::SC_SpinBoxEditField);
retVal = true;
= upscale(subControlRect(QStyle::CC_SpinBox, &sbo, QStyle::SC_SpinBoxUp));
contentRect.translate(boundingRect.left(), boundingRect.top());
retVal = true;
break;
case ControlPart::ButtonDown:
contentRect
= upscale(subControlRect(QStyle::CC_SpinBox, &sbo, QStyle::SC_SpinBoxDown));
contentRect.translate(boundingRect.left(), boundingRect.top());
retVal = true;
break;
case ControlPart::SubEdit:
contentRect = upscale(
subControlRect(QStyle::CC_SpinBox, &sbo, QStyle::SC_SpinBoxEditField));
contentRect.translate(boundingRect.left(), boundingRect.top());
retVal = true;
break;
default:
break;
@@ -824,13 +848,13 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart
switch (part)
{
case ControlPart::MenuItemCheckMark:
h = pixelMetric(QStyle::PM_IndicatorHeight);
w = pixelMetric(QStyle::PM_IndicatorWidth);
h = upscale(pixelMetric(QStyle::PM_IndicatorHeight), Round::Floor);
w = upscale(pixelMetric(QStyle::PM_IndicatorWidth), Round::Floor);
retVal = true;
break;
case ControlPart::MenuItemRadioMark:
h = pixelMetric(QStyle::PM_ExclusiveIndicatorHeight);
w = pixelMetric(QStyle::PM_ExclusiveIndicatorWidth);
h = upscale(pixelMetric(QStyle::PM_ExclusiveIndicatorHeight), Round::Floor);
w = upscale(pixelMetric(QStyle::PM_ExclusiveIndicatorWidth), Round::Floor);
retVal = true;
break;
default:
@@ -850,7 +874,8 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart
auto nStyle = static_cast<DrawFrameFlags>(val.getNumericVal() & 0xFFF0);
if (nStyle & DrawFrameFlags::NoDraw)
{
const int nFrameWidth = pixelMetric(QStyle::PM_DefaultFrameWidth);
int nFrameWidth
= upscale(pixelMetric(QStyle::PM_DefaultFrameWidth), Round::Ceil);
contentRect.adjust(nFrameWidth, nFrameWidth, -nFrameWidth, -nFrameWidth);
}
retVal = true;
@@ -859,12 +884,14 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart
}
case ControlType::Radiobutton:
{
const int h = pixelMetric(QStyle::PM_ExclusiveIndicatorHeight);
const int w = pixelMetric(QStyle::PM_ExclusiveIndicatorWidth);
const int h = upscale(pixelMetric(QStyle::PM_ExclusiveIndicatorHeight), Round::Ceil);
const int w = upscale(pixelMetric(QStyle::PM_ExclusiveIndicatorWidth), Round::Ceil);
contentRect = QRect(boundingRect.left(), boundingRect.top(), w, h);
contentRect.adjust(0, 0, 2 * pixelMetric(QStyle::PM_FocusFrameHMargin, &styleOption),
2 * pixelMetric(QStyle::PM_FocusFrameVMargin, &styleOption));
int nHMargin = pixelMetric(QStyle::PM_FocusFrameHMargin, &styleOption);
int nVMargin = pixelMetric(QStyle::PM_FocusFrameVMargin, &styleOption);
contentRect.adjust(0, 0, upscale(2 * nHMargin, Round::Ceil),
upscale(2 * nVMargin, Round::Ceil));
boundingRect = contentRect;
retVal = true;
@@ -872,7 +899,7 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart
}
case ControlType::Slider:
{
const int w = pixelMetric(QStyle::PM_SliderLength);
const int w = upscale(pixelMetric(QStyle::PM_SliderLength), Round::Ceil);
if (part == ControlPart::ThumbHorz)
{
contentRect
@@ -891,7 +918,7 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart
}
case ControlType::Toolbar:
{
const int nWorH = pixelMetric(QStyle::PM_ToolBarHandleExtent);
const int nWorH = upscale(pixelMetric(QStyle::PM_ToolBarHandleExtent), Round::Ceil);
if (part == ControlPart::ThumbHorz)
{
contentRect
@@ -906,6 +933,13 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart
boundingRect = contentRect;
retVal = true;
}
else if (part == ControlPart::Button)
{
contentRect = QRect(boundingRect.left(), boundingRect.top(),
upscale(25, Round::Ceil), upscale(25, Round::Ceil));
boundingRect = contentRect;
retVal = true;
}
break;
}
case ControlType::Scrollbar:
@@ -930,11 +964,12 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart
// widget and screen coordinates the same. QStyle functions should use screen
// coordinates but at least QPlastiqueStyle::subControlRect() is buggy
// and sometimes uses widget coordinates.
option.rect = QRect({ 0, 0 }, contentRect.size());
contentRect
= subControlRect(QStyle::CC_ScrollBar, &option, QStyle::SC_ScrollBarGroove);
contentRect.translate(contentRect.topLeft()); // reverse the workaround above
option.rect = downscale(QRect({ 0, 0 }, contentRect.size()));
contentRect = upscale(
subControlRect(QStyle::CC_ScrollBar, &option, QStyle::SC_ScrollBarGroove));
contentRect.translate(boundingRect.left()
- (contentRect.width() - boundingRect.width()),
boundingRect.top());
boundingRect = contentRect;
retVal = true;
}
@@ -944,7 +979,9 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart
{
QStyleOptionTab sot;
fillQStyleOptionTab(val, sot);
QSize aMinSize = sizeFromContents(QStyle::CT_TabBarTab, &sot, contentRect.size());
QSize aMinSize = upscale(sizeFromContents(QStyle::CT_TabBarTab, &sot,
downscale(contentRect.size(), Round::Ceil)),
Round::Ceil);
contentRect.setSize(aMinSize);
boundingRect = contentRect;
retVal = true;
@@ -954,11 +991,13 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart
{
const TabPaneValue& rValue = static_cast<const TabPaneValue&>(val);
QStyleOptionTabWidgetFrame sotwf;
fullQStyleOptionTabWidgetFrame(sotwf);
QSize aMinSize = sizeFromContents(
QStyle::CT_TabWidget, &sotwf,
QSize(std::max(rValue.m_aTabHeaderRect.GetWidth(), controlRegion.GetWidth()),
rValue.m_aTabHeaderRect.GetHeight() + controlRegion.GetHeight()));
fullQStyleOptionTabWidgetFrame(sotwf, true);
QSize contentSize(
std::max(rValue.m_aTabHeaderRect.GetWidth(), controlRegion.GetWidth()),
rValue.m_aTabHeaderRect.GetHeight() + controlRegion.GetHeight());
QSize aMinSize = upscale(
sizeFromContents(QStyle::CT_TabWidget, &sotwf, downscale(contentSize, Round::Ceil)),
Round::Ceil);
contentRect.setSize(aMinSize);
boundingRect = contentRect;
retVal = true;
@@ -1025,4 +1064,43 @@ bool Qt5Graphics_Controls::hitTestNativeControl(ControlType nType, ControlPart n
return false;
}
inline int Qt5Graphics_Controls::downscale(int size, Round eRound)
{
return static_cast<int>(eRound == Round::Ceil ? ceil(size / m_rGraphics.devicePixelRatioF())
: floor(size / m_rGraphics.devicePixelRatioF()));
}
inline int Qt5Graphics_Controls::upscale(int size, Round eRound)
{
return static_cast<int>(eRound == Round::Ceil ? ceil(size * m_rGraphics.devicePixelRatioF())
: floor(size * m_rGraphics.devicePixelRatioF()));
}
inline QRect Qt5Graphics_Controls::downscale(const QRect& rect)
{
return QRect(downscale(rect.x(), Round::Floor), downscale(rect.y(), Round::Floor),
downscale(rect.width(), Round::Ceil), downscale(rect.height(), Round::Ceil));
}
inline QRect Qt5Graphics_Controls::upscale(const QRect& rect)
{
return QRect(upscale(rect.x(), Round::Floor), upscale(rect.y(), Round::Floor),
upscale(rect.width(), Round::Ceil), upscale(rect.height(), Round::Ceil));
}
inline QSize Qt5Graphics_Controls::downscale(const QSize& size, Round eRound)
{
return QSize(downscale(size.width(), eRound), downscale(size.height(), eRound));
}
inline QSize Qt5Graphics_Controls::upscale(const QSize& size, Round eRound)
{
return QSize(upscale(size.width(), eRound), upscale(size.height(), eRound));
}
inline QPoint Qt5Graphics_Controls::upscale(const QPoint& point, Round eRound)
{
return QPoint(upscale(point.x(), eRound), upscale(point.y(), eRound));
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/Qt5Instance.cxx b/vcl/qt5/Qt5Instance.cxx
index 855f32d..06b959b 100644
--- a/vcl/qt5/Qt5Instance.cxx
+++ b/vcl/qt5/Qt5Instance.cxx
@@ -603,7 +603,9 @@ void Qt5Instance::MoveFakeCmdlineArgs(std::unique_ptr<char* []>& rFakeArgv,
std::unique_ptr<QApplication> Qt5Instance::CreateQApplication(int& nArgc, char** pArgv)
{
QApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
// for scaled icons in the native menus
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
FreeableCStr session_manager;
if (getenv("SESSION_MANAGER") != nullptr)
diff --git a/vcl/qt5/Qt5MainWindow.cxx b/vcl/qt5/Qt5MainWindow.cxx
index a2a0d6c..45d726b 100644
--- a/vcl/qt5/Qt5MainWindow.cxx
+++ b/vcl/qt5/Qt5MainWindow.cxx
@@ -38,7 +38,8 @@ void Qt5MainWindow::closeEvent(QCloseEvent* pEvent)
void Qt5MainWindow::moveEvent(QMoveEvent* pEvent)
{
m_rFrame.maGeometry.nX = pEvent->pos().x();
m_rFrame.maGeometry.nY = pEvent->pos().y();
const qreal fRatio = m_rFrame.devicePixelRatioF();
m_rFrame.maGeometry.nX = round(pEvent->pos().x() * fRatio);
m_rFrame.maGeometry.nY = round(pEvent->pos().y() * fRatio);
m_rFrame.CallCallback(SalEvent::Move, nullptr);
}
diff --git a/vcl/qt5/Qt5SvpGraphics.cxx b/vcl/qt5/Qt5SvpGraphics.cxx
index 364cbb1..8885b9c 100644
--- a/vcl/qt5/Qt5SvpGraphics.cxx
+++ b/vcl/qt5/Qt5SvpGraphics.cxx
@@ -29,7 +29,9 @@ Qt5SvpGraphics::Qt5SvpGraphics(Qt5Frame* pFrame)
, m_pFrame(pFrame)
{
if (!Qt5Data::noNativeControls())
m_pWidgetDraw.reset(new Qt5Graphics_Controls());
m_pWidgetDraw.reset(new Qt5Graphics_Controls(*this));
if (m_pFrame)
setDevicePixelRatioF(m_pFrame->devicePixelRatioF());
}
Qt5SvpGraphics::~Qt5SvpGraphics() {}
diff --git a/vcl/qt5/Qt5System.cxx b/vcl/qt5/Qt5System.cxx
index 4e00a0d..d769f71 100644
--- a/vcl/qt5/Qt5System.cxx
+++ b/vcl/qt5/Qt5System.cxx
@@ -27,7 +27,7 @@ tools::Rectangle Qt5System::GetDisplayScreenPosSizePixel(unsigned int nScreen)
SAL_WNODEPRECATED_DECLARATIONS_PUSH
QRect qRect = QApplication::desktop()->screenGeometry(nScreen);
SAL_WNODEPRECATED_DECLARATIONS_POP
return toRectangle(qRect);
return toRectangle(scaledQRect(qRect, qApp->devicePixelRatio()));
}
int Qt5System::ShowNativeDialog(const OUString&, const OUString&, const std::vector<OUString>&)
diff --git a/vcl/qt5/Qt5Widget.cxx b/vcl/qt5/Qt5Widget.cxx
index 02039c0..1c7a130 100644
--- a/vcl/qt5/Qt5Widget.cxx
+++ b/vcl/qt5/Qt5Widget.cxx
@@ -60,23 +60,30 @@ void Qt5Widget::paintEvent(QPaintEvent* pEvent)
if (!m_rFrame.m_bNullRegion)
p.setClipRegion(m_rFrame.m_aRegion);
QImage aImage;
if (m_rFrame.m_bUseCairo)
{
cairo_surface_t* pSurface = m_rFrame.m_pSurface.get();
cairo_surface_flush(pSurface);
QImage aImage(cairo_image_surface_get_data(pSurface), size().width(), size().height(),
Qt5_DefaultFormat32);
p.drawImage(pEvent->rect().topLeft(), aImage, pEvent->rect());
aImage = QImage(cairo_image_surface_get_data(pSurface),
cairo_image_surface_get_width(pSurface),
cairo_image_surface_get_height(pSurface), Qt5_DefaultFormat32);
}
else
p.drawImage(pEvent->rect().topLeft(), *m_rFrame.m_pQImage, pEvent->rect());
aImage = *m_rFrame.m_pQImage;
const qreal fRatio = m_rFrame.devicePixelRatioF();
aImage.setDevicePixelRatio(fRatio);
QRectF source(pEvent->rect().topLeft() * fRatio, pEvent->rect().size() * fRatio);
p.drawImage(pEvent->rect(), aImage, source);
}
void Qt5Widget::resizeEvent(QResizeEvent* pEvent)
{
const int nWidth = pEvent->size().width();
const int nHeight = pEvent->size().height();
const qreal fRatio = m_rFrame.devicePixelRatioF();
const int nWidth = ceil(pEvent->size().width() * fRatio);
const int nHeight = ceil(pEvent->size().height() * fRatio);
m_rFrame.maGeometry.nWidth = nWidth;
m_rFrame.maGeometry.nHeight = nHeight;
@@ -93,8 +100,8 @@ void Qt5Widget::resizeEvent(QResizeEvent* pEvent)
UniqueCairoSurface old_surface(m_rFrame.m_pSurface.release());
m_rFrame.m_pSurface.reset(pSurface);
int min_width = qMin(pEvent->oldSize().width(), nWidth);
int min_height = qMin(pEvent->oldSize().height(), nHeight);
int min_width = qMin(cairo_image_surface_get_width(old_surface.get()), nWidth);
int min_height = qMin(cairo_image_surface_get_height(old_surface.get()), nHeight);
SalTwoRect rect(0, 0, min_width, min_height, 0, 0, min_width, min_height);
@@ -139,11 +146,14 @@ void Qt5Widget::handleMouseButtonEvent(const Qt5Frame& rFrame, const QMouseEvent
return;
}
const qreal fRatio = rFrame.devicePixelRatioF();
const Point aPos = toPoint(pEvent->pos() * fRatio);
aEvent.mnX = QGuiApplication::isLeftToRight()
? aPos.X()
: round(rFrame.GetQWidget()->width() * fRatio) - aPos.X();
aEvent.mnY = aPos.Y();
aEvent.mnTime = pEvent->timestamp();
aEvent.mnX = static_cast<long>(QGuiApplication::isLeftToRight()
? pEvent->pos().x()
: rFrame.GetQWidget()->width() - pEvent->pos().x());
aEvent.mnY = static_cast<long>(pEvent->pos().y());
aEvent.mnCode = GetKeyModCode(pEvent->modifiers()) | GetMouseModCode(pEvent->buttons());
SalEvent nEventType;
@@ -163,12 +173,13 @@ void Qt5Widget::mouseReleaseEvent(QMouseEvent* pEvent)
void Qt5Widget::mouseMoveEvent(QMouseEvent* pEvent)
{
QPoint point = pEvent->pos();
const qreal fRatio = m_rFrame.devicePixelRatioF();
const Point aPos = toPoint(pEvent->pos() * fRatio);
SalMouseEvent aEvent;
aEvent.mnX = QGuiApplication::isLeftToRight() ? aPos.X() : round(width() * fRatio) - aPos.X();
aEvent.mnY = aPos.Y();
aEvent.mnTime = pEvent->timestamp();
aEvent.mnX = QGuiApplication::isLeftToRight() ? point.x() : width() - point.x();
aEvent.mnY = point.y();
aEvent.mnCode = GetKeyModCode(pEvent->modifiers()) | GetMouseModCode(pEvent->buttons());
aEvent.mnButton = 0;
@@ -178,11 +189,12 @@ void Qt5Widget::mouseMoveEvent(QMouseEvent* pEvent)
void Qt5Widget::wheelEvent(QWheelEvent* pEvent)
{
SalWheelMouseEvent aEvent;
const Point aPos = toPoint(pEvent->pos() * m_rFrame.devicePixelRatioF());
SalWheelMouseEvent aEvent;
aEvent.mnX = aPos.X();
aEvent.mnY = aPos.Y();
aEvent.mnTime = pEvent->timestamp();
aEvent.mnX = pEvent->pos().x();
aEvent.mnY = pEvent->pos().y();
aEvent.mnCode = GetKeyModCode(pEvent->modifiers()) | GetMouseModCode(pEvent->buttons());
// mouse wheel ticks are 120, which we map to 3 lines.
@@ -235,14 +247,15 @@ void Qt5Widget::moveEvent(QMoveEvent* pEvent)
if (m_rFrame.m_pTopLevel)
return;
m_rFrame.maGeometry.nX = pEvent->pos().x();
m_rFrame.maGeometry.nY = pEvent->pos().y();
const Point aPos = toPoint(pEvent->pos() * m_rFrame.devicePixelRatioF());
m_rFrame.maGeometry.nX = aPos.X();
m_rFrame.maGeometry.nY = aPos.Y();
m_rFrame.CallCallback(SalEvent::Move, nullptr);
}
void Qt5Widget::showEvent(QShowEvent*)
{
QSize aSize(m_rFrame.GetQWidget()->size());
QSize aSize(m_rFrame.GetQWidget()->size() * m_rFrame.devicePixelRatioF());
// forcing an immediate update somehow interferes with the hide + show
// sequence from Qt5Frame::SetModal, if the frame was already set visible,
// resulting in a hidden / unmapped window