diff options
author | Johan Klokkhammer Helsing <johan.helsing@qt.io> | 2019-02-06 09:32:22 +0100 |
---|---|---|
committer | Johan Helsing <johan.helsing@qt.io> | 2019-05-02 11:07:43 +0000 |
commit | 20314e67f66f9bee74438a00cde17922bd2da18a (patch) | |
tree | 4832852b2ff5c0d008a9273a33672a661bb7aae3 /src/client | |
parent | 3eea45e31ef796ab6f1363f8fd2882c151becc20 (diff) |
Client: Add support for animated cursors
[ChangeLog][QPA plugin] Added support for animated cursors.
Previously we would just show the first frame of the animation.
Fixes: QTBUG-48181
Change-Id: Ie06bff8950678b5ff7b7e2e50915c85905a1200b
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
Diffstat (limited to 'src/client')
-rw-r--r-- | src/client/qwaylandcursor.cpp | 7 | ||||
-rw-r--r-- | src/client/qwaylandcursor_p.h | 2 | ||||
-rw-r--r-- | src/client/qwaylandinputdevice.cpp | 38 | ||||
-rw-r--r-- | src/client/qwaylandinputdevice_p.h | 4 |
4 files changed, 43 insertions, 8 deletions
diff --git a/src/client/qwaylandcursor.cpp b/src/client/qwaylandcursor.cpp index 8b2ed036d..165df7762 100644 --- a/src/client/qwaylandcursor.cpp +++ b/src/client/qwaylandcursor.cpp @@ -209,7 +209,7 @@ wl_cursor *QWaylandCursorTheme::requestCursor(WaylandCursor shape) return nullptr; } -struct wl_cursor_image *QWaylandCursorTheme::cursorImage(Qt::CursorShape shape) +::wl_cursor_image *QWaylandCursorTheme::cursorImage(Qt::CursorShape shape, uint millisecondsIntoAnimation) { struct wl_cursor *waylandCursor = nullptr; @@ -227,8 +227,9 @@ struct wl_cursor_image *QWaylandCursorTheme::cursorImage(Qt::CursorShape shape) return nullptr; } - struct wl_cursor_image *image = waylandCursor->images[0]; - struct wl_buffer *buffer = wl_cursor_image_get_buffer(image); + int frame = wl_cursor_frame(waylandCursor, millisecondsIntoAnimation); + ::wl_cursor_image *image = waylandCursor->images[frame]; + ::wl_buffer *buffer = wl_cursor_image_get_buffer(image); if (!buffer) { qCWarning(lcQpaWayland) << "Could not find buffer for cursor"; return nullptr; diff --git a/src/client/qwaylandcursor_p.h b/src/client/qwaylandcursor_p.h index 6c48fb628..a4605f3d2 100644 --- a/src/client/qwaylandcursor_p.h +++ b/src/client/qwaylandcursor_p.h @@ -75,7 +75,7 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandCursorTheme public: static QWaylandCursorTheme *create(QWaylandShm *shm, int size, const QString &themeName); ~QWaylandCursorTheme(); - struct wl_cursor_image *cursorImage(Qt::CursorShape shape); + ::wl_cursor_image *cursorImage(Qt::CursorShape shape, uint millisecondsIntoAnimation = 0); private: enum WaylandCursor { diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp index 8231dd9c3..04aefa166 100644 --- a/src/client/qwaylandinputdevice.cpp +++ b/src/client/qwaylandinputdevice.cpp @@ -191,6 +191,27 @@ QWaylandInputDevice::Pointer::~Pointer() #if QT_CONFIG(cursor) +class WlCallback : public QtWayland::wl_callback { +public: + explicit WlCallback(::wl_callback *callback, std::function<void(uint32_t)> fn, bool autoDelete = false) + : QtWayland::wl_callback(callback) + , m_fn(fn) + , m_autoDelete(autoDelete) + {} + ~WlCallback() override { wl_callback_destroy(object()); } + bool done() const { return m_done; } + void callback_done(uint32_t callback_data) override { + m_done = true; + m_fn(callback_data); + if (m_autoDelete) + delete this; + } +private: + bool m_done = false; + std::function<void(uint32_t)> m_fn; + bool m_autoDelete = false; +}; + class CursorSurface : public QWaylandSurface { public: @@ -213,7 +234,7 @@ public: } // Size and hotspot are in surface coordinates - void update(wl_buffer *buffer, const QPoint &hotspot, const QSize &size, int bufferScale) + void update(wl_buffer *buffer, const QPoint &hotspot, const QSize &size, int bufferScale, bool animated = false) { // Calling code needs to ensure buffer scale is supported if != 1 Q_ASSERT(bufferScale == 1 || m_version >= 3); @@ -230,6 +251,13 @@ public: attach(buffer, 0, 0); damage(0, 0, size.width(), size.height()); + m_frameCallback.reset(); + if (animated) { + m_frameCallback.reset(new WlCallback(frame(), [this](uint32_t time){ + Q_UNUSED(time); + m_pointer->updateCursor(); + })); + } commit(); } @@ -242,6 +270,7 @@ public: } private: + QScopedPointer<WlCallback> m_frameCallback; QWaylandInputDevice::Pointer *m_pointer = nullptr; uint m_version = 0; uint m_setSerial = 0; @@ -320,12 +349,14 @@ void QWaylandInputDevice::Pointer::updateCursor() updateCursorTheme(); // Set from shape using theme - if (struct ::wl_cursor_image *image = mCursor.theme->cursorImage(shape)) { + uint time = seat()->mCursor.animationTimer.elapsed(); + if (struct ::wl_cursor_image *image = mCursor.theme->cursorImage(shape, time)) { struct wl_buffer *buffer = wl_cursor_image_get_buffer(image); int bufferScale = mCursor.themeBufferScale; QPoint hotspot = QPoint(image->hotspot_x, image->hotspot_y) / bufferScale; QSize size = QSize(image->width, image->height) / bufferScale; - getOrCreateCursorSurface()->update(buffer, hotspot, size, bufferScale); + bool animated = image->delay > 0; + getOrCreateCursorSurface()->update(buffer, hotspot, size, bufferScale, animated); return; } @@ -515,6 +546,7 @@ void QWaylandInputDevice::setCursor(const QCursor *cursor, const QSharedPointer< mCursor.shape = cursor ? cursor->shape() : Qt::ArrowCursor; mCursor.hotspot = cursor ? cursor->hotSpot() : QPoint(); mCursor.fallbackOutputScale = fallbackOutputScale; + mCursor.animationTimer.start(); if (mCursor.shape == Qt::BitmapCursor) { mCursor.bitmapBuffer = cachedBuffer ? cachedBuffer : QWaylandCursor::cursorBitmapBuffer(mQDisplay, cursor); diff --git a/src/client/qwaylandinputdevice_p.h b/src/client/qwaylandinputdevice_p.h index e87de6ae7..f9fa43c92 100644 --- a/src/client/qwaylandinputdevice_p.h +++ b/src/client/qwaylandinputdevice_p.h @@ -69,7 +69,8 @@ #endif #include <QtCore/QDebug> -#include <QPointer> +#include <QtCore/QElapsedTimer> +#include <QtCore/QPointer> #if QT_CONFIG(cursor) struct wl_cursor_image; @@ -153,6 +154,7 @@ private: Qt::CursorShape shape = Qt::ArrowCursor; int fallbackOutputScale = 1; QPoint hotspot; + QElapsedTimer animationTimer; } mCursor; #endif |