Add support for Wayland Cursor themes

WaylandSeat can install a cursor based on Qt::CursorShape using the
Wayland cursor theme library.
This commit is contained in:
Martin Gräßlin 2013-06-27 09:58:04 +02:00
parent e18bb1006a
commit f9704ff0df
3 changed files with 66 additions and 2 deletions

View file

@ -270,6 +270,7 @@ set(kwin_XCB_LIBS
set(kwin_WAYLAND_LIBS
Wayland::Client
Wayland::Cursor
XCB::XTEST
)

View file

@ -33,6 +33,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <xcb/xfixes.h>
// Wayland
#include <wayland-client-protocol.h>
#include <wayland-cursor.h>
// system
#include <unistd.h>
#include <sys/mman.h>
@ -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);

View file

@ -32,6 +32,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
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<Buffer*> 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<X11CursorTracker> 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()
{