diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp index a0265bdc338..a993817654c 100644 --- a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp +++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp @@ -45,6 +45,8 @@ QT_BEGIN_NAMESPACE +extern void qt_scrollRectInImage(QImage &, const QRect &, const QPoint &); + namespace QtWaylandClient { QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display, @@ -210,6 +212,40 @@ void QWaylandShmBackingStore::endPaint() flush(window(), mPendingRegion, QPoint()); } +// Inspired by QCALayerBackingStore. +bool QWaylandShmBackingStore::scroll(const QRegion ®ion, int dx, int dy) +{ + if (!mBackBuffer) + return false; + + QImage *backBufferImage = mBackBuffer->image(); + const qreal devicePixelRatio = backBufferImage->devicePixelRatio(); + + // On Wayland, the window can have a device pixel ratio different from + // the window/screen, therefore we cannot rely on QHighDpi here, cf. QBackingStore::scroll. + // With fractional scaling we cannot easily scroll the existing pixels. + if (!qFuzzyIsNull(devicePixelRatio - static_cast(devicePixelRatio))) + return false; + + const QPoint scrollDelta(dx, dy); + const QMargins margins = windowDecorationMargins(); + const QRegion adjustedRegion = region.translated(margins.left(), margins.top()); + + const QRect boundingRect = adjustedRegion.boundingRect(); + const QPoint devicePixelDelta = scrollDelta * devicePixelRatio; + + qt_scrollRectInImage(*backBufferImage, + QRect(boundingRect.topLeft() * devicePixelRatio, + boundingRect.size() * devicePixelRatio), + devicePixelDelta); + + // We do not mark the source region as dirty, even though it technically has "moved". + // This matches the behavior of other backingstore implementations using qt_scrollRectInImage. + updateDirtyStates(adjustedRegion.translated(scrollDelta)); + + return true; +} + void QWaylandShmBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) { Q_UNUSED(offset) diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h b/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h index 0f38ba11e23..1cd6135f250 100644 --- a/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h +++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h @@ -66,6 +66,7 @@ public: void resize(const QSize &size, const QRegion &staticContents) override; void beginPaint(const QRegion ®ion) override; void endPaint() override; + bool scroll(const QRegion ®ion, int dx, int dy) override; QWaylandAbstractDecoration *windowDecoration() const;