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.

Change-Id: I73c143761d4a0da6991433b41dea0a0bc83a448a
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
bb10
Tor Arne Vestbø 2019-08-26 22:08:59 +02:00
parent 984df39c79
commit 79bf1b7e34
2 changed files with 4 additions and 15 deletions

View File

@ -5313,9 +5313,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 (repaintManager && !asRoot && (q->internalWinId() || !q->nativeParentWidget()->isWindow()))
if (repaintManager)
repaintManager->markNeedsFlush(q, rgn, offset);
return;
@ -5422,8 +5420,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 (repaintManager && !asRoot && (q->internalWinId() || (q->nativeParentWidget() && !q->nativeParentWidget()->isWindow())))
if (repaintManager)
repaintManager->markNeedsFlush(q, toBePainted, offset);
//restore

View File

@ -979,12 +979,6 @@ void QWidgetRepaintManager::paintAndFlush()
}
#endif
// Always flush repainted areas. FIXME: We should mark individual widgets,
// not the top level widget unconditionally, as this results in always
// flushing the top level widget, even if the painted region is entirely
// within a native child.
markNeedsFlush(tlw, toClean, QPoint());
store->beginPaint(toClean);
// Must do this before sending any paint events because
@ -1041,8 +1035,7 @@ void QWidgetRepaintManager::markNeedsFlush(QWidget *widget, const QRegion &regio
// Top-level (native)
qCInfo(lcWidgetPainting) << "Marking" << region << "of top level"
<< widget << "as needing flush";
if (!widget->testAttribute(Qt::WA_WState_InPaintEvent))
topLevelNeedsFlush += region;
topLevelNeedsFlush += region;
} else if (!hasPlatformWindow(widget) && !widget->isWindow()) {
QWidget *nativeParent = widget->nativeParentWidget();
qCInfo(lcWidgetPainting) << "Marking" << region << "of"
@ -1050,8 +1043,7 @@ void QWidgetRepaintManager::markNeedsFlush(QWidget *widget, const QRegion &regio
<< "at offset" << topLevelOffset;
if (nativeParent == tlw) {
// Alien widgets with the top-level as the native parent (common case)
if (!widget->testAttribute(Qt::WA_WState_InPaintEvent))
topLevelNeedsFlush += region.translated(topLevelOffset);
topLevelNeedsFlush += region.translated(topLevelOffset);
} else {
// Alien widgets with native parent != tlw
const QPoint nativeParentOffset = widget->mapTo(nativeParent, QPoint());