summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2022-03-31 16:59:50 +0200
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2022-04-01 15:12:24 +0000
commit919f514f29f33d653e492b0dbf9fc95d7cd93287 (patch)
tree44c6a8acf13f21e2bb83fab590cb03ce3c146f9a /src/plugins/platforms/cocoa
parent1032cc54ea55cefd69530a9fe34658f23ff91f9c (diff)
macOS: Don't scroll individual rects of a region when inline scrolling
The QPlatformBackingStore::scroll() API takes a QRegion as input, and we kept this data type in the implementation of QCALayerBackingStore::scroll for the logic of figuring out whether we could use the existing back buffer as source of the scroll or if we needed to pull data from the front buffer. We then iterated the rects of the resulting in-line region, and called qt_scrollRectInImage for each of them. This will unfortunately not work whenever the scroll of one of these rects ends up overwriting parts of the back buffer that later rects of the region use as their source rect. This could be reproduced by moving the cursor within a text document, which would dirty a small area around the cursor, making the subsequent scroll of the viewport result in garbled text. This issue exists in the other platform backingstore implementations too, but since the QWidgetRepaintManager never calls scroll() with anything but a single rect they would not have any issues. The problem could potentially be solved by sorting the rects before blitting them, but now this quick fix solves the regression on macOS. Fixes: QTBUG-102181 Pick-to: 6.2 6.3 6.3.0 Change-Id: I80f6d26117321e3c09e068cdb03eb320e244a5de Reviewed-by: Eike Ziller <eike.ziller@qt.io> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Diffstat (limited to 'src/plugins/platforms/cocoa')
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm18
1 files changed, 10 insertions, 8 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index 8f3e3036ad..a8e6791e84 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -271,20 +271,22 @@ bool QCALayerBackingStore::scroll(const QRegion &region, int dx, int dy)
m_buffers.back()->lock(QPlatformGraphicsBuffer::SWWriteAccess);
if (!inPlaceRegion.isEmpty()) {
- qCDebug(lcQpaBackingStore) << "Scrolling" << inPlaceRegion << "in place";
+ // We have to scroll everything in one go, instead of scrolling the
+ // individual rects of the region, as otherwise we may end up reading
+ // already overwritten (scrolled) pixels.
+ const QRect inPlaceBoundingRect = inPlaceRegion.boundingRect();
+
+ qCDebug(lcQpaBackingStore) << "Scrolling" << inPlaceBoundingRect << "in place";
QImage *backBufferImage = m_buffers.back()->asImage();
const qreal devicePixelRatio = backBufferImage->devicePixelRatio();
const QPoint devicePixelDelta = scrollDelta * devicePixelRatio;
extern void qt_scrollRectInImage(QImage &, const QRect &, const QPoint &);
- for (const QRect &rect : inPlaceRegion) {
- qt_scrollRectInImage(*backBufferImage,
- QRect(rect.topLeft() * devicePixelRatio,
- rect.size() * devicePixelRatio),
- devicePixelDelta);
- }
-
+ qt_scrollRectInImage(*backBufferImage,
+ QRect(inPlaceBoundingRect.topLeft() * devicePixelRatio,
+ inPlaceBoundingRect.size() * devicePixelRatio),
+ devicePixelDelta);
}
if (!frontBufferRegion.isEmpty()) {