diff --git a/src/backends/wayland/wayland_backend.cpp b/src/backends/wayland/wayland_backend.cpp index efd08332bd..c6dfca7e66 100644 --- a/src/backends/wayland/wayland_backend.cpp +++ b/src/backends/wayland/wayland_backend.cpp @@ -21,7 +21,6 @@ #include "cursor.h" #include "dpmsinputeventfilter.h" #include "input.h" -#include "pointer_input.h" #include #include @@ -32,8 +31,6 @@ #include #include #include -#include -#include #include #include @@ -58,127 +55,59 @@ using namespace KWayland::Client; WaylandCursor::WaylandCursor(WaylandBackend *backend) : m_backend(backend) + , m_surface(backend->display()->compositor()->createSurface()) { - resetSurface(); } WaylandCursor::~WaylandCursor() = default; -void WaylandCursor::resetSurface() +void WaylandCursor::enable() { - m_surface.reset(backend()->display()->compositor()->createSurface()); + Q_ASSERT(m_disableCount > 0); + --m_disableCount; + if (m_disableCount == 0) { + install(); + } } -void WaylandCursor::init() +void WaylandCursor::disable() { - installImage(); + ++m_disableCount; + if (m_disableCount == 1) { + uninstall(); + } } -void WaylandCursor::installImage() +void WaylandCursor::install() { const QImage image = Cursors::self()->currentCursor()->image(); - if (image.isNull() || image.size().isEmpty()) { - doInstallImage(nullptr, QSize(), 1); + if (m_disableCount || image.isNull() || image.size().isEmpty()) { + uninstall(); + return; + } + + auto *pointer = m_backend->seat()->pointerDevice()->nativePointer(); + if (!pointer || !pointer->isValid()) { return; } auto buffer = m_backend->display()->shmPool()->createBuffer(image).toStrongRef(); wl_buffer *imageBuffer = *buffer.data(); - doInstallImage(imageBuffer, image.size(), image.devicePixelRatio()); + + pointer->setCursor(m_surface.get(), imageBuffer ? Cursors::self()->currentCursor()->hotspot() : QPoint()); + m_surface->attachBuffer(imageBuffer); + m_surface->setScale(std::ceil(image.devicePixelRatio())); + m_surface->damageBuffer(image.rect()); + m_surface->commit(KWayland::Client::Surface::CommitFlag::None); } -void WaylandCursor::doInstallImage(wl_buffer *image, const QSize &size, qreal scale) +void WaylandCursor::uninstall() { auto *pointer = m_backend->seat()->pointerDevice()->nativePointer(); if (!pointer || !pointer->isValid()) { return; } - pointer->setCursor(m_surface.get(), image ? Cursors::self()->currentCursor()->hotspot() : QPoint()); - drawSurface(image, size, scale); -} - -void WaylandCursor::drawSurface(wl_buffer *image, const QSize &size, qreal scale) -{ - m_surface->attachBuffer(image); - m_surface->setScale(std::ceil(scale)); - m_surface->damageBuffer(QRect(QPoint(0, 0), size)); - m_surface->commit(KWayland::Client::Surface::CommitFlag::None); -} - -WaylandSubSurfaceCursor::WaylandSubSurfaceCursor(WaylandBackend *backend) - : WaylandCursor(backend) -{ -} - -WaylandSubSurfaceCursor::~WaylandSubSurfaceCursor() = default; - -void WaylandSubSurfaceCursor::init() -{ - if (auto *pointer = backend()->seat()->pointerDevice()->nativePointer()) { - pointer->hideCursor(); - } -} - -void WaylandSubSurfaceCursor::changeOutput(WaylandOutput *output) -{ - m_subSurface.reset(); - m_output = output; - if (!output) { - return; - } - createSubSurface(); - surface()->commit(); -} - -void WaylandSubSurfaceCursor::createSubSurface() -{ - if (m_subSurface) { - return; - } - if (!m_output) { - return; - } - resetSurface(); - m_subSurface.reset(backend()->display()->subCompositor()->createSubSurface(surface(), m_output->surface())); - m_subSurface->setMode(SubSurface::Mode::Desynchronized); -} - -void WaylandSubSurfaceCursor::doInstallImage(wl_buffer *image, const QSize &size, qreal scale) -{ - if (!image) { - m_subSurface.reset(); - return; - } - createSubSurface(); - // cursor position might have changed due to different cursor hot spot - move(input()->pointer()->pos()); - drawSurface(image, size, scale); -} - -QPointF WaylandSubSurfaceCursor::absoluteToRelativePosition(const QPointF &position) -{ - return position - m_output->geometry().topLeft() - Cursors::self()->currentCursor()->hotspot(); -} - -void WaylandSubSurfaceCursor::move(const QPointF &globalPosition) -{ - auto *output = backend()->getOutputAt(globalPosition.toPoint()); - if (!m_output || (output && m_output != output)) { - changeOutput(output); - if (!m_output) { - // cursor might be off the grid - return; - } - installImage(); - return; - } - if (!m_subSurface) { - return; - } - // place the sub-surface relative to the output it is on and factor in the hotspot - const auto relativePosition = globalPosition.toPoint() - Cursors::self()->currentCursor()->hotspot() - m_output->geometry().topLeft(); - m_subSurface->setPosition(relativePosition); - m_output->renderLoop()->scheduleRepaint(); + pointer->hideCursor(); } WaylandInputDevice::WaylandInputDevice(KWayland::Client::Keyboard *keyboard, WaylandSeat *seat) @@ -577,26 +506,16 @@ bool WaylandBackend::initialize() QObject::connect(dispatcher, &QAbstractEventDispatcher::awake, m_display.get(), &WaylandDisplay::flush); connect(Cursors::self(), &Cursors::currentCursorChanged, this, [this]() { - if (!m_seat || !m_waylandCursor) { - return; - } - m_waylandCursor->installImage(); - }); - connect(Cursors::self(), &Cursors::positionChanged, this, [this](Cursor *cursor, const QPoint &position) { - if (m_waylandCursor) { - m_waylandCursor->move(position); - } + m_waylandCursor->install(); }); connect(this, &WaylandBackend::pointerLockChanged, this, [this](bool locked) { if (locked) { - m_waylandCursor = std::make_unique(this); - m_waylandCursor->move(input()->pointer()->pos()); + m_waylandCursor->disable(); m_seat->createRelativePointer(); } else { m_seat->destroyRelativePointer(); - m_waylandCursor = std::make_unique(this); + m_waylandCursor->enable(); } - m_waylandCursor->init(); }); return true; diff --git a/src/backends/wayland/wayland_backend.h b/src/backends/wayland/wayland_backend.h index 9f24f18fab..01c73af149 100644 --- a/src/backends/wayland/wayland_backend.h +++ b/src/backends/wayland/wayland_backend.h @@ -38,7 +38,6 @@ class PointerSwipeGesture; class PointerPinchGesture; class RelativePointer; class Seat; -class SubSurface; class Surface; class Touch; } @@ -61,52 +60,18 @@ class WaylandCursor { public: explicit WaylandCursor(WaylandBackend *backend); - virtual ~WaylandCursor(); + ~WaylandCursor(); - virtual void init(); - virtual void move(const QPointF &globalPosition) - { - } + void enable(); + void disable(); - void installImage(); - -protected: - void resetSurface(); - virtual void doInstallImage(wl_buffer *image, const QSize &size, qreal scale); - void drawSurface(wl_buffer *image, const QSize &size, qreal scale); - - KWayland::Client::Surface *surface() const - { - return m_surface.get(); - } - WaylandBackend *backend() const - { - return m_backend; - } + void install(); + void uninstall(); private: WaylandBackend *const m_backend; std::unique_ptr m_surface; -}; - -class WaylandSubSurfaceCursor : public WaylandCursor -{ -public: - explicit WaylandSubSurfaceCursor(WaylandBackend *backend); - ~WaylandSubSurfaceCursor() override; - - void init() override; - - void move(const QPointF &globalPosition) override; - -private: - void changeOutput(WaylandOutput *output); - void doInstallImage(wl_buffer *image, const QSize &size, qreal scale) override; - void createSubSurface(); - - QPointF absoluteToRelativePosition(const QPointF &position); - WaylandOutput *m_output = nullptr; - std::unique_ptr m_subSurface; + int m_disableCount = 0; }; class WaylandInputDevice : public InputDevice diff --git a/src/backends/wayland/wayland_display.cpp b/src/backends/wayland/wayland_display.cpp index 3f483e6424..72f3b9ce1d 100644 --- a/src/backends/wayland/wayland_display.cpp +++ b/src/backends/wayland/wayland_display.cpp @@ -162,7 +162,6 @@ WaylandDisplay::~WaylandDisplay() m_seat.reset(); m_xdgDecorationManager.reset(); m_shmPool.reset(); - m_subCompositor.reset(); m_xdgShell.reset(); if (m_registry) { @@ -230,11 +229,6 @@ KWayland::Client::ShmPool *WaylandDisplay::shmPool() const return m_shmPool.get(); } -KWayland::Client::SubCompositor *WaylandDisplay::subCompositor() const -{ - return m_subCompositor.get(); -} - KWayland::Client::Seat *WaylandDisplay::seat() const { return m_seat.get(); @@ -260,9 +254,6 @@ void WaylandDisplay::registry_global(void *data, wl_registry *registry, uint32_t } display->m_compositor = std::make_unique(); display->m_compositor->setup(static_cast(wl_registry_bind(registry, name, &wl_compositor_interface, std::min(version, 4u)))); - } else if (strcmp(interface, wl_subcompositor_interface.name) == 0) { - display->m_subCompositor = std::make_unique(); - display->m_subCompositor->setup(static_cast(wl_registry_bind(registry, name, &wl_subcompositor_interface, std::min(version, 1u)))); } else if (strcmp(interface, wl_shm_interface.name) == 0) { display->m_shmPool = std::make_unique(); display->m_shmPool->setup(static_cast(wl_registry_bind(registry, name, &wl_shm_interface, std::min(version, 1u)))); diff --git a/src/backends/wayland/wayland_display.h b/src/backends/wayland/wayland_display.h index 0975321ce4..e8dd286fec 100644 --- a/src/backends/wayland/wayland_display.h +++ b/src/backends/wayland/wayland_display.h @@ -23,7 +23,6 @@ class PointerGestures; class RelativePointerManager; class Seat; class ShmPool; -class SubCompositor; class XdgDecorationManager; class XdgShell; } @@ -54,7 +53,6 @@ public: KWayland::Client::Seat *seat() const; KWayland::Client::XdgDecorationManager *xdgDecorationManager() const; KWayland::Client::ShmPool *shmPool() const; - KWayland::Client::SubCompositor *subCompositor() const; KWayland::Client::XdgShell *xdgShell() const; public Q_SLOTS: @@ -74,7 +72,6 @@ private: std::unique_ptr m_seat; std::unique_ptr m_xdgDecorationManager; std::unique_ptr m_shmPool; - std::unique_ptr m_subCompositor; std::unique_ptr m_xdgShell; }; diff --git a/src/backends/wayland/wayland_output.cpp b/src/backends/wayland/wayland_output.cpp index 5625093f52..b4ca9638e9 100644 --- a/src/backends/wayland/wayland_output.cpp +++ b/src/backends/wayland/wayland_output.cpp @@ -86,6 +86,11 @@ RenderLoop *WaylandOutput::renderLoop() const return m_renderLoop.get(); } +bool WaylandOutput::usesSoftwareCursor() const +{ + return m_hasPointerLock; +} + void WaylandOutput::init(const QSize &pixelSize, qreal scale) { m_renderLoop->setRefreshRate(s_refreshRate); diff --git a/src/backends/wayland/wayland_output.h b/src/backends/wayland/wayland_output.h index 46635efecf..b1d05538af 100644 --- a/src/backends/wayland/wayland_output.h +++ b/src/backends/wayland/wayland_output.h @@ -40,6 +40,7 @@ public: ~WaylandOutput() override; RenderLoop *renderLoop() const override; + bool usesSoftwareCursor() const override; void init(const QSize &pixelSize, qreal scale);