From f9704ff0df17fe887738acb59e0c46280433bf1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Thu, 27 Jun 2013 09:58:04 +0200 Subject: [PATCH] Add support for Wayland Cursor themes WaylandSeat can install a cursor based on Qt::CursorShape using the Wayland cursor theme library. --- CMakeLists.txt | 1 + wayland_backend.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++- wayland_backend.h | 17 ++++++++++++++- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a9f1007f4a..dd633bd0f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -270,6 +270,7 @@ set(kwin_XCB_LIBS set(kwin_WAYLAND_LIBS Wayland::Client + Wayland::Cursor XCB::XTEST ) diff --git a/wayland_backend.cpp b/wayland_backend.cpp index 729dd617dc..1c38c778a5 100644 --- a/wayland_backend.cpp +++ b/wayland_backend.cpp @@ -33,6 +33,7 @@ along with this program. If not, see . #include // Wayland #include +#include // system #include #include @@ -495,10 +496,12 @@ Buffer *ShmPool::getBuffer(const QSize &size, int32_t stride) } WaylandSeat::WaylandSeat(wl_seat *seat, WaylandBackend *backend) - : m_seat(seat) + : QObject(NULL) + , m_seat(seat) , m_pointer(NULL) , m_keyboard(NULL) , m_cursor(NULL) + , m_theme(NULL) , m_enteredSerial(0) , m_cursorTracker() , m_backend(backend) @@ -518,6 +521,7 @@ WaylandSeat::~WaylandSeat() if (m_cursor) { wl_surface_destroy(m_cursor); } + destroyTheme(); } void WaylandSeat::destroyPointer() @@ -580,6 +584,42 @@ void WaylandSeat::installCursorImage(wl_buffer *image, const QSize &size, const wl_surface_commit(m_cursor); } +void WaylandSeat::installCursorImage(Qt::CursorShape shape) +{ + if (!m_theme) { + loadTheme(); + } + wl_cursor *c = wl_cursor_theme_get_cursor(m_theme, Cursor::self()->cursorName(shape).constData()); + if (c->image_count <= 0) { + return; + } + wl_cursor_image *image = c->images[0]; + installCursorImage(wl_cursor_image_get_buffer(image), + QSize(image->width, image->height), + QPoint(image->hotspot_x, image->hotspot_y)); +} + +void WaylandSeat::loadTheme() +{ + Cursor *c = Cursor::self(); + if (!m_theme) { + // so far the theme had not been created, this means we need to start tracking theme changes + connect(c, SIGNAL(themeChanged()), SLOT(loadTheme())); + } else { + destroyTheme(); + } + m_theme = wl_cursor_theme_load(c->themeName().toUtf8().constData(), + c->themeSize(), m_backend->shmPool()->shm()); +} + +void WaylandSeat::destroyTheme() +{ + if (m_theme) { + wl_cursor_theme_destroy(m_theme); + m_theme = NULL; + } +} + WaylandBackend *WaylandBackend::s_self = 0; WaylandBackend *WaylandBackend::create(QObject *parent) { @@ -652,6 +692,14 @@ void WaylandBackend::createSeat(uint32_t name) m_seat.reset(new WaylandSeat(seat, this)); } +void WaylandBackend::installCursorImage(Qt::CursorShape shape) +{ + if (m_seat.isNull()) { + return; + } + m_seat->installCursorImage(shape); +} + void WaylandBackend::createSurface() { m_surface = wl_compositor_create_surface(m_compositor); diff --git a/wayland_backend.h b/wayland_backend.h index fa64166b26..21f9b35bce 100644 --- a/wayland_backend.h +++ b/wayland_backend.h @@ -32,6 +32,7 @@ along with this program. If not, see . class QTemporaryFile; class QImage; +struct wl_cursor_theme; struct wl_buffer; struct wl_shm; @@ -112,6 +113,7 @@ public: wl_buffer *createBuffer(const QSize &size, int32_t stride, const void *src); void *poolAddress() const; Buffer *getBuffer(const QSize &size, int32_t stride); + wl_shm *shm(); Q_SIGNALS: void poolResized(); private: @@ -127,8 +129,9 @@ private: QList m_buffers; }; -class WaylandSeat +class WaylandSeat : public QObject { + Q_OBJECT public: WaylandSeat(wl_seat *seat, WaylandBackend *backend); virtual ~WaylandSeat(); @@ -138,13 +141,18 @@ public: void pointerEntered(uint32_t serial); void resetCursor(); void installCursorImage(wl_buffer *image, const QSize &size, const QPoint &hotspot); + void installCursorImage(Qt::CursorShape shape); +private Q_SLOTS: + void loadTheme(); private: void destroyPointer(); void destroyKeyboard(); + void destroyTheme(); wl_seat *m_seat; wl_pointer *m_pointer; wl_keyboard *m_keyboard; wl_surface *m_cursor; + wl_cursor_theme *m_theme; uint32_t m_enteredSerial; QScopedPointer m_cursorTracker; WaylandBackend *m_backend; @@ -175,6 +183,7 @@ public: wl_surface *surface() const; const QSize &shellSurfaceSize() const; void setShellSurfaceSize(const QSize &size); + void installCursorImage(Qt::CursorShape shape); void dispatchEvents(); Q_SIGNALS: @@ -232,6 +241,12 @@ void* ShmPool::poolAddress() const return m_poolData; } +inline +wl_shm *ShmPool::shm() +{ + return m_shm; +} + inline wl_display *WaylandBackend::display() {