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
|
||||
Wayland::Client
|
||||
Wayland::Cursor
|
||||
XCB::XTEST
|
||||
)
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue