summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Alexander Steffens (heftig) <jan.steffens@gmail.com>2019-12-13 22:15:32 +0100
committerJan Alexander Steffens (heftig) <jan.steffens@gmail.com>2019-12-17 12:02:23 +0100
commitce15889614f87b5986f997beffd2826471adfe51 (patch)
tree206f0693a83633558c3f02b440559ef00eb6f512
parent80ed5501cf5dcc4b6ef2a1a126d9d564c1c73851 (diff)
Drive cursor animation with a timer
Using only wl_surface_frame callbacks to update the cursor does so much more often than needed. In addition, at least GNOME and Weston fire the callback for the cursor surface immediately, which ends up updating the cursor at over 3000 Hz here. Use wl_cursor_frame_and_duration to drive a single shot timer. This function is also guaranteed to return 0 for single frame cursors, so we can avoid starting the timer at all. We wait for both the surface frame callback and the timer to fire before updating the cursor for the next frame of animation. This reduces our update rate to the frame rate of the cursor or the rate requested by the compositor, whichever is lower. Change-Id: I10277460ebe9b547ebaf7f73424b9ef17614107f Reviewed-by: Johan Helsing <johan.helsing@qt.io>
-rw-r--r--src/client/qwaylandinputdevice.cpp34
-rw-r--r--src/client/qwaylandinputdevice_p.h5
2 files changed, 36 insertions, 3 deletions
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index 3b26dc427..3f0d61d6a 100644
--- a/src/client/qwaylandinputdevice.cpp
+++ b/src/client/qwaylandinputdevice.cpp
@@ -143,6 +143,12 @@ QWaylandWindow *QWaylandInputDevice::Keyboard::focusWindow() const
QWaylandInputDevice::Pointer::Pointer(QWaylandInputDevice *seat)
: mParent(seat)
{
+#if QT_CONFIG(cursor)
+ mCursor.frameTimer.setSingleShot(true);
+ mCursor.frameTimer.callOnTimeout([&]() {
+ cursorTimerCallback();
+ });
+#endif
}
QWaylandInputDevice::Pointer::~Pointer()
@@ -224,7 +230,7 @@ public:
if (animated) {
m_frameCallback.reset(new WlCallback(frame(), [this](uint32_t time){
Q_UNUSED(time);
- m_pointer->updateCursor();
+ m_pointer->cursorFrameCallback();
}));
}
commit();
@@ -328,7 +334,8 @@ void QWaylandInputDevice::Pointer::updateCursor()
uint time = seat()->mCursor.animationTimer.elapsed();
if (struct ::wl_cursor *waylandCursor = mCursor.theme->cursor(shape)) {
- int frame = wl_cursor_frame(waylandCursor, time);
+ uint duration = 0;
+ int frame = wl_cursor_frame_and_duration(waylandCursor, time, &duration);
::wl_cursor_image *image = waylandCursor->images[frame];
struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
@@ -339,7 +346,12 @@ void QWaylandInputDevice::Pointer::updateCursor()
int bufferScale = mCursor.themeBufferScale;
QPoint hotspot = QPoint(image->hotspot_x, image->hotspot_y) / bufferScale;
QSize size = QSize(image->width, image->height) / bufferScale;
- bool animated = waylandCursor->image_count > 1 && image->delay > 0;
+ bool animated = duration > 0;
+ if (animated) {
+ mCursor.gotFrameCallback = false;
+ mCursor.gotTimerCallback = false;
+ mCursor.frameTimer.start(duration);
+ }
getOrCreateCursorSurface()->update(buffer, hotspot, size, bufferScale, animated);
return;
}
@@ -354,6 +366,22 @@ CursorSurface *QWaylandInputDevice::Pointer::getOrCreateCursorSurface()
return mCursor.surface.get();
}
+void QWaylandInputDevice::Pointer::cursorTimerCallback()
+{
+ mCursor.gotTimerCallback = true;
+ if (mCursor.gotFrameCallback) {
+ updateCursor();
+ }
+}
+
+void QWaylandInputDevice::Pointer::cursorFrameCallback()
+{
+ mCursor.gotFrameCallback = true;
+ if (mCursor.gotTimerCallback) {
+ updateCursor();
+ }
+}
+
#endif // QT_CONFIG(cursor)
QWaylandInputDevice::Touch::Touch(QWaylandInputDevice *p)
diff --git a/src/client/qwaylandinputdevice_p.h b/src/client/qwaylandinputdevice_p.h
index 60d6f2c17..a567c57b4 100644
--- a/src/client/qwaylandinputdevice_p.h
+++ b/src/client/qwaylandinputdevice_p.h
@@ -286,6 +286,8 @@ public:
int idealCursorScale() const;
void updateCursorTheme();
void updateCursor();
+ void cursorTimerCallback();
+ void cursorFrameCallback();
CursorSurface *getOrCreateCursorSurface();
#endif
QWaylandInputDevice *seat() const { return mParent; }
@@ -325,6 +327,9 @@ public:
QWaylandCursorTheme *theme = nullptr;
int themeBufferScale = 0;
QScopedPointer<CursorSurface> surface;
+ QTimer frameTimer;
+ bool gotFrameCallback = false;
+ bool gotTimerCallback = false;
} mCursor;
#endif
QPointF mSurfacePos;