core: Make Output::setCursor() take CursorSource

It decouples the contents of the cursor from QImage.
This commit is contained in:
Vlad Zahorodnii 2023-01-03 12:26:56 +02:00
parent d8e6992512
commit 9f100e8292
9 changed files with 69 additions and 47 deletions

View file

@ -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);

View file

@ -14,6 +14,7 @@
#include <QObject>
#include <QPoint>
#include <QPointer>
#include <QSize>
#include <QTimer>
#include <QVector>
@ -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<CursorSource> source;
QPoint position;
} m_cursor;
};

View file

@ -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<WaylandEglBackend *>(Compositor::self()->backend())) {
renderCursorOpengl(backend, image, hotspot);
renderCursorOpengl(backend, source);
} else if (WaylandQPainterBackend *backend = qobject_cast<WaylandQPainterBackend *>(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<OutputLayerBeginFrameInfo> 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<OutputLayerBeginFrameInfo> beginInfo = cursorLayer->beginFrame();
if (!beginInfo) {

View file

@ -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<RenderLoop> m_renderLoop;
std::unique_ptr<KWayland::Client::Surface> m_surface;

View file

@ -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 <config-kwin.h>
#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 <NETWM>
@ -26,9 +29,6 @@
#include <QIcon>
#include <QPainter>
#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<X11WindowedEglBackend *>(Compositor::self()->backend())) {
renderCursorOpengl(backend, image, hotspot);
renderCursorOpengl(backend, source);
} else if (X11WindowedQPainterBackend *backend = qobject_cast<X11WindowedQPainterBackend *>(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<OutputLayerBeginFrameInfo> 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<OutputLayerBeginFrameInfo> beginInfo = cursorLayer->beginFrame();
if (!beginInfo) {

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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<ColorTransformation> &transformation);
virtual bool setCursor(const QImage &image, const QPoint &hotspot);
virtual bool setCursor(CursorSource *source);
virtual bool moveCursor(const QPoint &position);
Q_SIGNALS: