From f600e2f6f49d3f77ac4b745ab42b2133b714461f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Fri, 27 Feb 2015 17:46:41 +0100 Subject: [PATCH] [wayland] Properly handle Cursor set on focused PointerInterface This replaces getting the Cursor through the X11CursorTracker which is now completely dropped. The Cursor data is now passed through from the Wayland server and forwared to the WaylandBackend. --- input.cpp | 8 +++ wayland_backend.cpp | 149 +++++++++++--------------------------------- wayland_backend.h | 65 +------------------ 3 files changed, 47 insertions(+), 175 deletions(-) diff --git a/input.cpp b/input.cpp index faa4dfc881..8aa4b99996 100644 --- a/input.cpp +++ b/input.cpp @@ -33,6 +33,7 @@ along with this program. If not, see . #include "libinput/connection.h" #endif #if HAVE_WAYLAND +#include "wayland_backend.h" #include "wayland_server.h" #include #endif @@ -267,10 +268,17 @@ void InputRedirection::updatePointerWindow() // disconnect old surface if (oldWindow) { disconnect(oldWindow.data(), &Toplevel::geometryChanged, this, &InputRedirection::updateFocusedPointerPosition); + if (Wayland::WaylandBackend *w = Wayland::WaylandBackend::self()) { + disconnect(seat->focusedPointer()->cursor(), &KWayland::Server::Cursor::changed, w, &Wayland::WaylandBackend::installCursorFromServer); + } } if (t && t->surface()) { seat->setFocusedPointerSurface(t->surface(), t->pos()); connect(t, &Toplevel::geometryChanged, this, &InputRedirection::updateFocusedPointerPosition); + if (Wayland::WaylandBackend *w = Wayland::WaylandBackend::self()) { + w->installCursorFromServer(); + connect(seat->focusedPointer()->cursor(), &KWayland::Server::Cursor::changed, w, &Wayland::WaylandBackend::installCursorFromServer); + } } else { seat->setFocusedPointerSurface(nullptr); t = nullptr; diff --git a/wayland_backend.cpp b/wayland_backend.cpp index 1c36a6a986..2a52aade16 100644 --- a/wayland_backend.cpp +++ b/wayland_backend.cpp @@ -41,15 +41,15 @@ along with this program. If not, see . #include #include #include +#include #include +#include // Qt #include #include #include #include #include -// xcb -#include // Wayland #include #include @@ -61,97 +61,6 @@ namespace Wayland using namespace KWayland::Client; -CursorData::CursorData() - : m_valid(init()) -{ -} - -CursorData::~CursorData() -{ -} - -bool CursorData::init() -{ - QScopedPointer cursor( - xcb_xfixes_get_cursor_image_reply(connection(), - xcb_xfixes_get_cursor_image_unchecked(connection()), - NULL)); - if (cursor.isNull()) { - return false; - } - - QImage cursorImage((uchar *) xcb_xfixes_get_cursor_image_cursor_image(cursor.data()), cursor->width, cursor->height, - QImage::Format_ARGB32_Premultiplied); - if (cursorImage.isNull()) { - return false; - } - // the backend for the cursorImage is destroyed once the xcb cursor goes out of scope - // because of that we create a copy - m_cursor = cursorImage.copy(); - - m_hotSpot = QPoint(cursor->xhot, cursor->yhot); - return true; -} - -X11CursorTracker::X11CursorTracker(WaylandBackend *backend, QObject* parent) - : QObject(parent) - , m_backend(backend) - , m_lastX11Cursor(0) -{ - Cursor::self()->startCursorTracking(); - connect(Cursor::self(), SIGNAL(cursorChanged(uint32_t)), SLOT(cursorChanged(uint32_t))); -} - -X11CursorTracker::~X11CursorTracker() -{ - if (Cursor::self()) { - // Cursor might have been destroyed before Wayland backend gets destroyed - Cursor::self()->stopCursorTracking(); - } -} - -void X11CursorTracker::cursorChanged(uint32_t serial) -{ - if (m_lastX11Cursor == serial) { - // not changed; - return; - } - m_lastX11Cursor = serial; - QHash::iterator it = m_cursors.find(serial); - if (it != m_cursors.end()) { - installCursor(it.value()); - return; - } - ShmPool *pool = m_backend->shmPool(); - if (!pool->isValid()) { - return; - } - CursorData cursor; - if (cursor.isValid()) { - // TODO: discard unused cursors after some time? - m_cursors.insert(serial, cursor); - } - installCursor(cursor); -} - -void X11CursorTracker::installCursor(const CursorData& cursor) -{ - const QImage &cursorImage = cursor.cursor(); - auto buffer = m_backend->shmPool()->createBuffer(cursorImage); - if (!buffer) { - return; - } - emit cursorImageChanged(buffer, cursorImage.size(), cursor.hotSpot()); -} - -void X11CursorTracker::resetCursor() -{ - QHash::iterator it = m_cursors.find(m_lastX11Cursor); - if (it != m_cursors.end()) { - installCursor(it.value()); - } -} - WaylandSeat::WaylandSeat(wl_seat *seat, WaylandBackend *backend) : QObject(NULL) , m_seat(new Seat(this)) @@ -244,14 +153,6 @@ WaylandSeat::WaylandSeat(wl_seat *seat, WaylandBackend *backend) input()->processPointerAxis(toAxis(), delta, time); } ); - connect(m_backend->cursorTracker(), &X11CursorTracker::cursorImageChanged, this, - [this](Buffer::Ptr image, const QSize &size, const QPoint &hotspot) { - if (image.isNull()) { - return; - } - installCursorImage(image.toStrongRef()->buffer(), size, hotspot); - } - ); } else { destroyPointer(); } @@ -317,6 +218,11 @@ void WaylandSeat::installCursorImage(Qt::CursorShape shape) QPoint(image->hotspot_x, image->hotspot_y)); } +void WaylandSeat::installCursorImage(const QImage &image, const QPoint &hotSpot) +{ + installCursorImage(*(m_backend->shmPool()->createBuffer(image).data()), image.size(), hotSpot); +} + void WaylandSeat::setInstallCursor(bool install) { // TODO: remove, add? @@ -381,14 +287,6 @@ WaylandCursor::WaylandCursor(Surface *parentSurface, WaylandBackend *backend) auto surface = backend->compositor()->createSurface(this); m_subSurface = backend->subCompositor()->createSubSurface(QPointer(surface), QPointer(parentSurface), this); - connect(m_backend->cursorTracker(), &X11CursorTracker::cursorImageChanged, this, - [this](Buffer::Ptr image, const QSize &size, const QPoint &hotspot) { - if (image.isNull()) { - return; - } - setCursorImage(image.toStrongRef()->buffer(), size, hotspot); - } - ); connect(Cursor::self(), &Cursor::posChanged, this, [this](const QPoint &pos) { m_subSurface->setPosition(pos - m_hotSpot); @@ -432,6 +330,11 @@ void WaylandCursor::setCursorImage(wl_buffer *image, const QSize &size, const QP parent->commit(Surface::CommitFlag::None); } +void WaylandCursor::setCursorImage(const QImage &image, const QPoint &hotspot) +{ + setCursorImage(*(m_backend->shmPool()->createBuffer(image).data()), image.size(), hotspot); +} + void WaylandCursor::setCursorImage(Qt::CursorShape shape) { wl_cursor_image *image = m_theme->get(shape); @@ -462,7 +365,6 @@ WaylandBackend::WaylandBackend(QObject *parent) , m_shellSurface(NULL) , m_seat() , m_shm(new ShmPool(this)) - , m_cursorTracker() , m_connectionThreadObject(nullptr) , m_connectionThread(nullptr) , m_fullscreenShell(new FullscreenShell(this)) @@ -558,14 +460,12 @@ void WaylandBackend::initConnection() // setup registry m_registry->create(m_display); m_registry->setup(); - m_cursorTracker.reset(new X11CursorTracker(this, this)); }, Qt::QueuedConnection); connect(m_connectionThreadObject, &ConnectionThread::connectionDied, this, [this]() { m_ready = false; emit systemCompositorDied(); - m_cursorTracker.reset(); m_seat.reset(); m_shm->destroy(); destroyOutputs(); @@ -609,6 +509,30 @@ void WaylandBackend::installCursorImage(Qt::CursorShape shape) } } +void WaylandBackend::installCursorFromServer() +{ + if (!waylandServer() || !waylandServer()->seat()->focusedPointer()) { + return; + } + auto c = waylandServer()->seat()->focusedPointer()->cursor(); + if (c) { + auto cursorSurface = c->surface(); + if (!cursorSurface.isNull()) { + auto buffer = cursorSurface.data()->buffer(); + if (buffer) { + // set cursor + if (!m_seat.isNull() && m_seat->isInstallCursor()) { + m_seat->installCursorImage(buffer->data(), c->hotspot()); + } else if (m_cursor) { + m_cursor->setCursorImage(buffer->data(), c->hotspot()); + } + return; + } + } + } + // TODO: unset cursor +} + void WaylandBackend::createSurface() { m_surface = m_compositor->createSurface(this); @@ -642,7 +566,6 @@ void WaylandBackend::createSurface() // map the surface as fullscreen m_shellSurface = m_shell->createSurface(m_surface, this); m_shellSurface->setFullscreen(); - connect(m_shellSurface, &ShellSurface::pinged, m_cursorTracker.data(), &X11CursorTracker::resetCursor); connect(m_shellSurface, &ShellSurface::sizeChanged, this, &WaylandBackend::shellSurfaceSizeChanged); } } diff --git a/wayland_backend.h b/wayland_backend.h index f1a6bbcecd..337a9858fb 100644 --- a/wayland_backend.h +++ b/wayland_backend.h @@ -68,42 +68,6 @@ namespace Wayland class WaylandBackend; class WaylandSeat; -class CursorData -{ -public: - CursorData(); - ~CursorData(); - bool isValid() const; - const QPoint &hotSpot() const; - const QImage &cursor() const; -private: - bool init(); - QImage m_cursor; - QPoint m_hotSpot; - bool m_valid; -}; - -class X11CursorTracker : public QObject -{ - Q_OBJECT -public: - explicit X11CursorTracker(WaylandBackend *backend, QObject* parent = 0); - virtual ~X11CursorTracker(); - void resetCursor(); - -Q_SIGNALS: - void cursorImageChanged(QWeakPointer image, const QSize &size, const QPoint &hotSpot); - -private Q_SLOTS: - void cursorChanged(uint32_t serial); -private: - void installCursor(const CursorData &cursor); - QHash m_cursors; - WaylandBackend *m_backend; - uint32_t m_installedCursor; - uint32_t m_lastX11Cursor; -}; - class WaylandCursorTheme : public QObject { Q_OBJECT @@ -129,6 +93,7 @@ public: void installCursorImage(wl_buffer *image, const QSize &size, const QPoint &hotspot); void installCursorImage(Qt::CursorShape shape); + void installCursorImage(const QImage &image, const QPoint &hotspot); void setInstallCursor(bool install); bool isInstallCursor() const { return m_installCursor; @@ -157,6 +122,7 @@ public: return m_hotSpot; } void setCursorImage(wl_buffer *image, const QSize &size, const QPoint &hotspot); + void setCursorImage(const QImage &image, const QPoint &hotspot); void setCursorImage(Qt::CursorShape shape); Q_SIGNALS: @@ -185,11 +151,11 @@ public: const QList &outputs() const; KWayland::Client::ShmPool *shmPool(); KWayland::Client::SubCompositor *subCompositor(); - X11CursorTracker *cursorTracker(); KWayland::Client::Surface *surface() const; QSize shellSurfaceSize() const; void installCursorImage(Qt::CursorShape shape); + void installCursorFromServer(); protected: void connectNotify(const QMetaMethod &signal) override; @@ -214,7 +180,6 @@ private: KWayland::Client::ShellSurface *m_shellSurface; QScopedPointer m_seat; KWayland::Client::ShmPool *m_shm; - QScopedPointer m_cursorTracker; QList m_outputs; KWayland::Client::ConnectionThread *m_connectionThreadObject; QThread *m_connectionThread; @@ -226,24 +191,6 @@ private: KWIN_SINGLETON(WaylandBackend) }; -inline -bool CursorData::isValid() const -{ - return m_valid; -} - -inline -const QPoint& CursorData::hotSpot() const -{ - return m_hotSpot; -} - -inline -const QImage &CursorData::cursor() const -{ - return m_cursor; -} - inline wl_display *WaylandBackend::display() { @@ -268,12 +215,6 @@ KWayland::Client::ShmPool* WaylandBackend::shmPool() return m_shm; } -inline -X11CursorTracker *WaylandBackend::cursorTracker() -{ - return m_cursorTracker.data(); -} - inline KWayland::Client::Surface *WaylandBackend::surface() const {