diff --git a/src/backends/drm/drm_output.cpp b/src/backends/drm/drm_output.cpp index 2ba07aef9a..1a824ce383 100644 --- a/src/backends/drm/drm_output.cpp +++ b/src/backends/drm/drm_output.cpp @@ -36,6 +36,7 @@ #include "composite.h" #include "core/renderlayer.h" +#include "cursorsource.h" #include "scene/cursorscene.h" namespace KWin @@ -134,7 +135,7 @@ DrmLease *DrmOutput::lease() const return m_lease; } -bool DrmOutput::setCursor(const QImage &image, const QPoint &hotspot) +bool DrmOutput::setCursor(CursorSource *source) { static bool valid; static const bool forceSoftwareCursor = qEnvironmentVariableIntValue("KWIN_FORCE_SW_CURSOR", &valid) == 1 && valid; @@ -147,9 +148,8 @@ bool DrmOutput::setCursor(const QImage &image, const QPoint &hotspot) if (!m_pipeline->crtc() || !layer) { return false; } - m_cursor.image = image; - m_cursor.hotspot = hotspot; - if (m_cursor.image.isNull()) { + m_cursor.source = source; + if (!m_cursor.source || m_cursor.source->size().isEmpty()) { if (layer->isVisible()) { layer->setVisible(false); m_pipeline->setCursor(); @@ -158,7 +158,7 @@ bool DrmOutput::setCursor(const QImage &image, const QPoint &hotspot) } bool rendered = false; const QMatrix4x4 monitorMatrix = logicalToNativeMatrix(rect(), scale(), transform()); - const QSize cursorSize = m_cursor.image.size() / m_cursor.image.devicePixelRatio(); + const QSize cursorSize = m_cursor.source->size(); const QRect cursorRect = QRect(m_cursor.position, cursorSize); const QRect nativeCursorRect = monitorMatrix.mapRect(cursorRect); if (nativeCursorRect.width() <= m_gpu->cursorSize().width() && nativeCursorRect.height() <= m_gpu->cursorSize().height()) { @@ -189,7 +189,7 @@ bool DrmOutput::setCursor(const QImage &image, const QPoint &hotspot) const QRect layerRect = monitorMatrix.mapRect(QRect(m_cursor.position, layerSize)); layer->setVisible(cursorRect.intersects(rect())); if (layer->isVisible()) { - m_setCursorSuccessful = m_pipeline->setCursor(logicalToNativeMatrix(QRect(QPoint(), layerRect.size()), scale(), transform()).map(m_cursor.hotspot)); + m_setCursorSuccessful = m_pipeline->setCursor(logicalToNativeMatrix(QRect(QPoint(), layerRect.size()), scale(), transform()).map(m_cursor.source->hotspot())); layer->setVisible(m_setCursorSuccessful); } return m_setCursorSuccessful; @@ -202,10 +202,10 @@ bool DrmOutput::moveCursor(const QPoint &position) } m_cursor.position = position; - const QSize cursorSize = m_cursor.image.size() / m_cursor.image.devicePixelRatio(); + const QSize cursorSize = m_cursor.source ? m_cursor.source->size() : QSize(0, 0); const QRect cursorRect = QRect(m_cursor.position, cursorSize); - if (m_cursor.image.isNull() || !cursorRect.intersects(rect())) { + if (!cursorRect.intersects(rect())) { const auto layer = m_pipeline->cursorLayer(); if (layer->isVisible()) { layer->setVisible(false); diff --git a/src/backends/drm/drm_output.h b/src/backends/drm/drm_output.h index 9946ab544e..2e47c1a081 100644 --- a/src/backends/drm/drm_output.h +++ b/src/backends/drm/drm_output.h @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -48,7 +49,7 @@ public: void updateModes(); void updateDpmsMode(DpmsMode dpmsMode); - bool setCursor(const QImage &image, const QPoint &hotspot) override; + bool setCursor(CursorSource *source) override; bool moveCursor(const QPoint &position) override; DrmLease *lease() const; @@ -73,8 +74,7 @@ private: DrmLease *m_lease = nullptr; struct { - QImage image; - QPoint hotspot; + QPointer source; QPoint position; } m_cursor; }; diff --git a/src/backends/wayland/wayland_output.cpp b/src/backends/wayland/wayland_output.cpp index 9d7babffcb..317046da9e 100644 --- a/src/backends/wayland/wayland_output.cpp +++ b/src/backends/wayland/wayland_output.cpp @@ -7,8 +7,9 @@ SPDX-License-Identifier: GPL-2.0-or-later */ #include "wayland_output.h" -#include "core/renderloop_p.h" #include "composite.h" +#include "core/renderloop_p.h" +#include "cursorsource.h" #include "wayland_backend.h" #include "wayland_display.h" #include "wayland_egl_backend.h" @@ -180,16 +181,16 @@ RenderLoop *WaylandOutput::renderLoop() const return m_renderLoop.get(); } -bool WaylandOutput::setCursor(const QImage &image, const QPoint &hotspot) +bool WaylandOutput::setCursor(CursorSource *source) { if (m_hasPointerLock) { return false; } if (WaylandEglBackend *backend = qobject_cast(Compositor::self()->backend())) { - renderCursorOpengl(backend, image, hotspot); + renderCursorOpengl(backend, source); } else if (WaylandQPainterBackend *backend = qobject_cast(Compositor::self()->backend())) { - renderCursorQPainter(backend, image, hotspot); + renderCursorQPainter(backend, source); } return true; @@ -201,12 +202,17 @@ bool WaylandOutput::moveCursor(const QPoint &position) return !m_hasPointerLock; } -void WaylandOutput::renderCursorOpengl(WaylandEglBackend *backend, const QImage &image, const QPoint &hotspot) +void WaylandOutput::renderCursorOpengl(WaylandEglBackend *backend, CursorSource *source) { WaylandEglCursorLayer *cursorLayer = backend->cursorLayer(this); - cursorLayer->setSize(image.size()); - cursorLayer->setScale(image.devicePixelRatio()); - cursorLayer->setHotspot(hotspot); + if (source) { + cursorLayer->setSize(source->size()); + cursorLayer->setScale(scale()); + cursorLayer->setHotspot(source->hotspot()); + } else { + cursorLayer->setSize(QSize()); + cursorLayer->setHotspot(QPoint()); + } std::optional beginInfo = cursorLayer->beginFrame(); if (!beginInfo) { @@ -226,12 +232,17 @@ void WaylandOutput::renderCursorOpengl(WaylandEglBackend *backend, const QImage cursorLayer->endFrame(infiniteRegion(), infiniteRegion()); } -void WaylandOutput::renderCursorQPainter(WaylandQPainterBackend *backend, const QImage &image, const QPoint &hotspot) +void WaylandOutput::renderCursorQPainter(WaylandQPainterBackend *backend, CursorSource *source) { WaylandQPainterCursorLayer *cursorLayer = backend->cursorLayer(this); - cursorLayer->setSize(image.size()); - cursorLayer->setScale(image.devicePixelRatio()); - cursorLayer->setHotspot(hotspot); + if (source) { + cursorLayer->setSize(source->size()); + cursorLayer->setScale(scale()); + cursorLayer->setHotspot(source->hotspot()); + } else { + cursorLayer->setSize(QSize()); + cursorLayer->setHotspot(QPoint()); + } std::optional beginInfo = cursorLayer->beginFrame(); if (!beginInfo) { diff --git a/src/backends/wayland/wayland_output.h b/src/backends/wayland/wayland_output.h index 4970b38cc5..e6af4883e9 100644 --- a/src/backends/wayland/wayland_output.h +++ b/src/backends/wayland/wayland_output.h @@ -68,7 +68,7 @@ public: ~WaylandOutput() override; RenderLoop *renderLoop() const override; - bool setCursor(const QImage &image, const QPoint &hotspot) override; + bool setCursor(CursorSource *source) override; bool moveCursor(const QPoint &position) override; void init(const QSize &pixelSize, qreal scale); @@ -87,8 +87,8 @@ public: private: void handleConfigure(const QSize &size, KWayland::Client::XdgShellSurface::States states, quint32 serial); void updateWindowTitle(); - void renderCursorOpengl(WaylandEglBackend *backend, const QImage &image, const QPoint &hotspot); - void renderCursorQPainter(WaylandQPainterBackend *backend, const QImage &image, const QPoint &hotspot); + void renderCursorOpengl(WaylandEglBackend *backend, CursorSource *source); + void renderCursorQPainter(WaylandQPainterBackend *backend, CursorSource *source); std::unique_ptr m_renderLoop; std::unique_ptr m_surface; diff --git a/src/backends/x11/windowed/x11_windowed_output.cpp b/src/backends/x11/windowed/x11_windowed_output.cpp index 60699fc7fe..42c9a60a86 100644 --- a/src/backends/x11/windowed/x11_windowed_output.cpp +++ b/src/backends/x11/windowed/x11_windowed_output.cpp @@ -8,14 +8,17 @@ */ #include "x11_windowed_output.h" #include "../common/kwinxrenderutils.h" +#include "x11_windowed_backend.h" #include "x11_windowed_egl_backend.h" #include "x11_windowed_qpainter_backend.h" #include -#include "core/renderloop_p.h" #include "composite.h" -#include "x11_windowed_backend.h" +#include "core/renderlayer.h" +#include "core/renderloop_p.h" +#include "cursorsource.h" +#include "scene/cursorscene.h" #include @@ -26,9 +29,6 @@ #include #include -#include "core/renderlayer.h" -#include "scene/cursorscene.h" - namespace KWin { @@ -285,12 +285,12 @@ QPointF X11WindowedOutput::mapFromGlobal(const QPointF &pos) const return (pos - hostPosition() + internalPosition()) / scale(); } -bool X11WindowedOutput::setCursor(const QImage &image, const QPoint &hotspot) +bool X11WindowedOutput::setCursor(CursorSource *source) { if (X11WindowedEglBackend *backend = qobject_cast(Compositor::self()->backend())) { - renderCursorOpengl(backend, image, hotspot); + renderCursorOpengl(backend, source); } else if (X11WindowedQPainterBackend *backend = qobject_cast(Compositor::self()->backend())) { - renderCursorQPainter(backend, image, hotspot); + renderCursorQPainter(backend, source); } return true; @@ -302,11 +302,16 @@ bool X11WindowedOutput::moveCursor(const QPoint &position) return true; } -void X11WindowedOutput::renderCursorOpengl(X11WindowedEglBackend *backend, const QImage &image, const QPoint &hotspot) +void X11WindowedOutput::renderCursorOpengl(X11WindowedEglBackend *backend, CursorSource *source) { X11WindowedEglCursorLayer *cursorLayer = backend->cursorLayer(this); - cursorLayer->setHotspot(hotspot); - cursorLayer->setSize(image.size()); + if (source) { + cursorLayer->setSize(source->size()); + cursorLayer->setHotspot(source->hotspot()); + } else { + cursorLayer->setSize(QSize()); + cursorLayer->setHotspot(QPoint()); + } std::optional beginInfo = cursorLayer->beginFrame(); if (!beginInfo) { @@ -326,11 +331,16 @@ void X11WindowedOutput::renderCursorOpengl(X11WindowedEglBackend *backend, const cursorLayer->endFrame(infiniteRegion(), infiniteRegion()); } -void X11WindowedOutput::renderCursorQPainter(X11WindowedQPainterBackend *backend, const QImage &image, const QPoint &hotspot) +void X11WindowedOutput::renderCursorQPainter(X11WindowedQPainterBackend *backend, CursorSource *source) { X11WindowedQPainterCursorLayer *cursorLayer = backend->cursorLayer(this); - cursorLayer->setHotspot(hotspot); - cursorLayer->setSize(image.size()); + if (source) { + cursorLayer->setSize(source->size()); + cursorLayer->setHotspot(source->hotspot()); + } else { + cursorLayer->setSize(QSize()); + cursorLayer->setHotspot(QPoint()); + } std::optional beginInfo = cursorLayer->beginFrame(); if (!beginInfo) { diff --git a/src/backends/x11/windowed/x11_windowed_output.h b/src/backends/x11/windowed/x11_windowed_output.h index 27a6cc65ce..2d99d9b639 100644 --- a/src/backends/x11/windowed/x11_windowed_output.h +++ b/src/backends/x11/windowed/x11_windowed_output.h @@ -72,7 +72,7 @@ public: */ QPointF mapFromGlobal(const QPointF &pos) const; - bool setCursor(const QImage &image, const QPoint &hotspot) override; + bool setCursor(CursorSource *source) override; bool moveCursor(const QPoint &position) override; QRegion exposedArea() const; @@ -85,8 +85,8 @@ public: private: void initXInputForWindow(); - void renderCursorOpengl(X11WindowedEglBackend *backend, const QImage &image, const QPoint &hotspot); - void renderCursorQPainter(X11WindowedQPainterBackend *backend, const QImage &image, const QPoint &hotspot); + void renderCursorOpengl(X11WindowedEglBackend *backend, CursorSource *source); + void renderCursorQPainter(X11WindowedQPainterBackend *backend, CursorSource *source); xcb_window_t m_window = XCB_WINDOW_NONE; xcb_present_event_t m_presentEvent = XCB_NONE; diff --git a/src/composite.cpp b/src/composite.cpp index 2e3c16a8a5..7ed869afff 100644 --- a/src/composite.cpp +++ b/src/composite.cpp @@ -452,9 +452,9 @@ void Compositor::addOutput(Output *output) const QRect layerRect = output->mapFromGlobal(cursor->geometry()); bool usesHardwareCursor = false; if (!Cursors::self()->isCursorHidden()) { - usesHardwareCursor = output->setCursor(cursor->image(), cursor->hotspot()) && output->moveCursor(layerRect.topLeft()); + usesHardwareCursor = output->setCursor(cursor->source()) && output->moveCursor(layerRect.topLeft()); } else { - usesHardwareCursor = output->setCursor(QImage(), QPoint()); + usesHardwareCursor = output->setCursor(nullptr); } cursorLayer->setVisible(cursor->isOnOutput(output) && !usesHardwareCursor); cursorLayer->setGeometry(layerRect); diff --git a/src/core/output.cpp b/src/core/output.cpp index 37958429de..11f147315d 100644 --- a/src/core/output.cpp +++ b/src/core/output.cpp @@ -416,7 +416,7 @@ Output::Transform Output::panelOrientation() const return m_information.panelOrientation; } -bool Output::setCursor(const QImage &image, const QPoint &hotspot) +bool Output::setCursor(CursorSource *source) { return false; } diff --git a/src/core/output.h b/src/core/output.h index bd484a356a..ac30104855 100644 --- a/src/core/output.h +++ b/src/core/output.h @@ -23,6 +23,7 @@ namespace KWin { +class CursorSource; class EffectScreenImpl; class RenderLoop; class OutputConfiguration; @@ -259,7 +260,7 @@ public: virtual void setColorTransformation(const std::shared_ptr &transformation); - virtual bool setCursor(const QImage &image, const QPoint &hotspot); + virtual bool setCursor(CursorSource *source); virtual bool moveCursor(const QPoint &position); Q_SIGNALS: