From c857c03561cbb1c93f4f64b339543c5522e4adfc Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Sat, 23 Jun 2018 23:26:54 +0100 Subject: [PATCH] Load Kwin's internal cursors for the highest resolution of attached monitors Test Plan: Hovered over decoration Looked super crystal clear Same physical size as when I hover over window contents (which had a buffer scale of 1) Reviewers: #kwin, graesslin Reviewed By: #kwin, graesslin Subscribers: graesslin, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D13608 --- pointer_input.cpp | 8 +++++++- screens.cpp | 12 ++++++++++++ screens.h | 14 ++++++++++++++ wayland_cursor_theme.cpp | 4 ++++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/pointer_input.cpp b/pointer_input.cpp index 1a59dbb7f4..46b84b788d 100644 --- a/pointer_input.cpp +++ b/pointer_input.cpp @@ -29,6 +29,7 @@ along with this program. If not, see . #include "wayland_server.h" #include "workspace.h" #include "decorations/decoratedclient.h" +#include "screens.h" // KDecoration #include // KWayland @@ -1217,7 +1218,12 @@ void CursorImage::loadThemeCursor(const T &shape, QHash &cursors, Imag if (!buffer) { return; } - it = decltype(it)(cursors.insert(shape, {buffer->data().copy(), QPoint(cursor->hotspot_x, cursor->hotspot_y)})); + auto scale = screens()->maxScale(); + int hotSpotX = qRound(cursor->hotspot_x / scale); + int hotSpotY = qRound(cursor->hotspot_y / scale); + QImage img = buffer->data().copy(); + img.setDevicePixelRatio(scale); + it = decltype(it)(cursors.insert(shape, {img, QPoint(hotSpotX, hotSpotY)})); } image->hotSpot = it.value().hotSpot; image->image = it.value().image; diff --git a/screens.cpp b/screens.cpp index d28f75ce1a..df119f6490 100644 --- a/screens.cpp +++ b/screens.cpp @@ -56,6 +56,7 @@ Screens::Screens(QObject *parent) , m_currentFollowsMouse(false) , m_changedTimer(new QTimer(this)) , m_orientationSensor(new OrientationSensor(this)) + , m_maxScale(1.0) { connect(this, &Screens::changed, this, [this] { @@ -105,6 +106,11 @@ float Screens::refreshRate(int screen) const return 60.0f; } +qreal Screens::maxScale() const +{ + return m_maxScale; +} + qreal Screens::scale(int screen) const { Q_UNUSED(screen) @@ -124,13 +130,19 @@ void Screens::reconfigure() void Screens::updateSize() { QRect bounding; + qreal maxScale = 1.0; for (int i = 0; i < count(); ++i) { bounding = bounding.united(geometry(i)); + maxScale = qMax(maxScale, scale(i)); } if (m_boundingSize != bounding.size()) { m_boundingSize = bounding.size(); emit sizeChanged(); } + if (!qFuzzyCompare(m_maxScale, maxScale)) { + m_maxScale = maxScale; + emit maxScaleChanged(); + } } void Screens::setCount(int count) diff --git a/screens.h b/screens.h index 4fda86fb9f..e9cdf1c93c 100644 --- a/screens.h +++ b/screens.h @@ -88,6 +88,14 @@ public: **/ virtual QSize size(int screen) const = 0; + /** + * The highest scale() of all connected screens + * for use when deciding what scale to load global assets at + * Similar to QGuiApplication::scale + * @see scale + */ + qreal maxScale() const; + /* * The output scale for this display, for use by high DPI displays */ @@ -171,6 +179,11 @@ Q_SIGNALS: * @see size() **/ void sizeChanged(); + /** + * Emitted when the maximum scale of all attached screens changes + * @see maxScale + */ + void maxScaleChanged(); protected Q_SLOTS: void setCount(int count); @@ -196,6 +209,7 @@ private: KSharedConfig::Ptr m_config; QSize m_boundingSize; OrientationSensor *m_orientationSensor; + qreal m_maxScale; KWIN_SINGLETON(Screens) }; diff --git a/wayland_cursor_theme.cpp b/wayland_cursor_theme.cpp index 7a77533bbe..9444c2f16b 100644 --- a/wayland_cursor_theme.cpp +++ b/wayland_cursor_theme.cpp @@ -20,6 +20,7 @@ along with this program. If not, see . #include "wayland_cursor_theme.h" #include "cursor.h" #include "wayland_server.h" +#include "screens.h" // Qt #include // KWayland @@ -37,6 +38,7 @@ WaylandCursorTheme::WaylandCursorTheme(KWayland::Client::ShmPool *shm, QObject * , m_theme(nullptr) , m_shm(shm) { + connect(screens(), &Screens::maxScaleChanged, this, &WaylandCursorTheme::loadTheme); } WaylandCursorTheme::~WaylandCursorTheme() @@ -56,6 +58,8 @@ void WaylandCursorTheme::loadTheme() size = 24; } + size *= screens()->maxScale(); + auto theme = wl_cursor_theme_load(c->themeName().toUtf8().constData(), size, m_shm->shm()); if (theme) {