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:
parent
e18bb1006a
commit
f9704ff0df
3 changed files with 66 additions and 2 deletions
|
@ -270,6 +270,7 @@ set(kwin_XCB_LIBS
|
||||||
|
|
||||||
set(kwin_WAYLAND_LIBS
|
set(kwin_WAYLAND_LIBS
|
||||||
Wayland::Client
|
Wayland::Client
|
||||||
|
Wayland::Cursor
|
||||||
XCB::XTEST
|
XCB::XTEST
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include <xcb/xfixes.h>
|
#include <xcb/xfixes.h>
|
||||||
// Wayland
|
// Wayland
|
||||||
#include <wayland-client-protocol.h>
|
#include <wayland-client-protocol.h>
|
||||||
|
#include <wayland-cursor.h>
|
||||||
// system
|
// system
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/mman.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)
|
WaylandSeat::WaylandSeat(wl_seat *seat, WaylandBackend *backend)
|
||||||
: m_seat(seat)
|
: QObject(NULL)
|
||||||
|
, m_seat(seat)
|
||||||
, m_pointer(NULL)
|
, m_pointer(NULL)
|
||||||
, m_keyboard(NULL)
|
, m_keyboard(NULL)
|
||||||
, m_cursor(NULL)
|
, m_cursor(NULL)
|
||||||
|
, m_theme(NULL)
|
||||||
, m_enteredSerial(0)
|
, m_enteredSerial(0)
|
||||||
, m_cursorTracker()
|
, m_cursorTracker()
|
||||||
, m_backend(backend)
|
, m_backend(backend)
|
||||||
|
@ -518,6 +521,7 @@ WaylandSeat::~WaylandSeat()
|
||||||
if (m_cursor) {
|
if (m_cursor) {
|
||||||
wl_surface_destroy(m_cursor);
|
wl_surface_destroy(m_cursor);
|
||||||
}
|
}
|
||||||
|
destroyTheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaylandSeat::destroyPointer()
|
void WaylandSeat::destroyPointer()
|
||||||
|
@ -580,6 +584,42 @@ void WaylandSeat::installCursorImage(wl_buffer *image, const QSize &size, const
|
||||||
wl_surface_commit(m_cursor);
|
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::s_self = 0;
|
||||||
WaylandBackend *WaylandBackend::create(QObject *parent)
|
WaylandBackend *WaylandBackend::create(QObject *parent)
|
||||||
{
|
{
|
||||||
|
@ -652,6 +692,14 @@ void WaylandBackend::createSeat(uint32_t name)
|
||||||
m_seat.reset(new WaylandSeat(seat, this));
|
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()
|
void WaylandBackend::createSurface()
|
||||||
{
|
{
|
||||||
m_surface = wl_compositor_create_surface(m_compositor);
|
m_surface = wl_compositor_create_surface(m_compositor);
|
||||||
|
|
|
@ -32,6 +32,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
class QTemporaryFile;
|
class QTemporaryFile;
|
||||||
class QImage;
|
class QImage;
|
||||||
|
struct wl_cursor_theme;
|
||||||
struct wl_buffer;
|
struct wl_buffer;
|
||||||
struct wl_shm;
|
struct wl_shm;
|
||||||
|
|
||||||
|
@ -112,6 +113,7 @@ public:
|
||||||
wl_buffer *createBuffer(const QSize &size, int32_t stride, const void *src);
|
wl_buffer *createBuffer(const QSize &size, int32_t stride, const void *src);
|
||||||
void *poolAddress() const;
|
void *poolAddress() const;
|
||||||
Buffer *getBuffer(const QSize &size, int32_t stride);
|
Buffer *getBuffer(const QSize &size, int32_t stride);
|
||||||
|
wl_shm *shm();
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void poolResized();
|
void poolResized();
|
||||||
private:
|
private:
|
||||||
|
@ -127,8 +129,9 @@ private:
|
||||||
QList<Buffer*> m_buffers;
|
QList<Buffer*> m_buffers;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WaylandSeat
|
class WaylandSeat : public QObject
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
WaylandSeat(wl_seat *seat, WaylandBackend *backend);
|
WaylandSeat(wl_seat *seat, WaylandBackend *backend);
|
||||||
virtual ~WaylandSeat();
|
virtual ~WaylandSeat();
|
||||||
|
@ -138,13 +141,18 @@ public:
|
||||||
void pointerEntered(uint32_t serial);
|
void pointerEntered(uint32_t serial);
|
||||||
void resetCursor();
|
void resetCursor();
|
||||||
void installCursorImage(wl_buffer *image, const QSize &size, const QPoint &hotspot);
|
void installCursorImage(wl_buffer *image, const QSize &size, const QPoint &hotspot);
|
||||||
|
void installCursorImage(Qt::CursorShape shape);
|
||||||
|
private Q_SLOTS:
|
||||||
|
void loadTheme();
|
||||||
private:
|
private:
|
||||||
void destroyPointer();
|
void destroyPointer();
|
||||||
void destroyKeyboard();
|
void destroyKeyboard();
|
||||||
|
void destroyTheme();
|
||||||
wl_seat *m_seat;
|
wl_seat *m_seat;
|
||||||
wl_pointer *m_pointer;
|
wl_pointer *m_pointer;
|
||||||
wl_keyboard *m_keyboard;
|
wl_keyboard *m_keyboard;
|
||||||
wl_surface *m_cursor;
|
wl_surface *m_cursor;
|
||||||
|
wl_cursor_theme *m_theme;
|
||||||
uint32_t m_enteredSerial;
|
uint32_t m_enteredSerial;
|
||||||
QScopedPointer<X11CursorTracker> m_cursorTracker;
|
QScopedPointer<X11CursorTracker> m_cursorTracker;
|
||||||
WaylandBackend *m_backend;
|
WaylandBackend *m_backend;
|
||||||
|
@ -175,6 +183,7 @@ public:
|
||||||
wl_surface *surface() const;
|
wl_surface *surface() const;
|
||||||
const QSize &shellSurfaceSize() const;
|
const QSize &shellSurfaceSize() const;
|
||||||
void setShellSurfaceSize(const QSize &size);
|
void setShellSurfaceSize(const QSize &size);
|
||||||
|
void installCursorImage(Qt::CursorShape shape);
|
||||||
|
|
||||||
void dispatchEvents();
|
void dispatchEvents();
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
@ -232,6 +241,12 @@ void* ShmPool::poolAddress() const
|
||||||
return m_poolData;
|
return m_poolData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
wl_shm *ShmPool::shm()
|
||||||
|
{
|
||||||
|
return m_shm;
|
||||||
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
wl_display *WaylandBackend::display()
|
wl_display *WaylandBackend::display()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue