widgets: Mark widgets as needing flush during painting

Except for the case of syncing in response to an expose event,
where the platform asked us to flush a specific region, we
should strive to only flush parts that have been repainted.

And we should flush those parts to their nearest native child,
instead of unconditionally flushing the root/top level widget
as well.

By allowing drawWidget to schedule the flush we automatically
flush the minimal region, to the right widgets.

(manually cherry-picked from commit 79bf1b7e348d186934b14c417859a48bf9b3a06c)

Task-number: QTBUG-77447
Change-Id: I1a8fa703c0b7172655271e2a8f5eca694cb14129
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
This commit is contained in:
Tor Arne Vestbø 2019-08-26 22:08:59 +02:00
parent 9a322dfdea
commit 1e310b5a45
2 changed files with 4 additions and 12 deletions

View File

@ -5520,9 +5520,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
}
sourced->context = 0;
// Native widgets need to be marked dirty on screen so painting will be done in correct context
// Same check as in the no effects case below.
if (backingStore && !onScreen && !asRoot && (q->internalWinId() || !q->nativeParentWidget()->isWindow()))
if (backingStore)
backingStore->markDirtyOnScreen(rgn, q, offset);
return;
@ -5641,8 +5639,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
sendPaintEvent(toBePainted);
}
// Native widgets need to be marked dirty on screen so painting will be done in correct context
if (backingStore && !onScreen && !asRoot && (q->internalWinId() || (q->nativeParentWidget() && !q->nativeParentWidget()->isWindow())))
if (backingStore)
backingStore->markDirtyOnScreen(toBePainted, q, offset);
//restore

View File

@ -333,9 +333,6 @@ void QWidgetBackingStore::beginPaint(QRegion &toClean, QWidget *widget, QBacking
Q_UNUSED(widget);
Q_UNUSED(toCleanIsInTopLevelCoordinates);
// Always flush repainted areas.
dirtyOnScreen += toClean;
#ifdef QT_NO_PAINT_DEBUG
backingStore->beginPaint(toClean);
#else
@ -714,7 +711,6 @@ void QWidgetBackingStore::markDirtyOnScreen(const QRegion &region, QWidget *widg
// Top-level.
if (widget == tlw) {
if (!widget->testAttribute(Qt::WA_WState_InPaintEvent))
dirtyOnScreen += region;
return;
}
@ -723,7 +719,6 @@ void QWidgetBackingStore::markDirtyOnScreen(const QRegion &region, QWidget *widg
if (!hasPlatformWindow(widget) && !widget->isWindow()) {
QWidget *nativeParent = widget->nativeParentWidget(); // Alien widgets with the top-level as the native parent (common case).
if (nativeParent == tlw) {
if (!widget->testAttribute(Qt::WA_WState_InPaintEvent))
dirtyOnScreen += region.translated(topLevelOffset);
return;
}