QtWidgets: Reduce paint events when resizing native widget
This patch reduces paint events by removing code which sets native widgets dirty in QWidgetWindow::handleExposeEvent. Native widgets are also marked dirty in QWidgetPrivate::drawWidget, so it is enough for proper painting. This restores Qt4 behavior when one resize means one repaint for native widgets. Without this patch the native widget is marked as dirty on every expose event, so one repaint is from syncBackingStore and second (or more) is from marking the widget dirty explicitly. This patch improves performance of native widgets and it also reduces locks when paint event is v-synced, e.g. on OpenGL swap buffers or on any other technology like VDPAU, VA-API, etc. Added autotest for checking number of paint events for native widgets. Task-number: QTBUG-50796 Change-Id: I4e1649069e2e73d15b038fd1834d0551915252ee Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
This commit is contained in:
parent
640441882d
commit
bc410cc706
@ -873,14 +873,8 @@ void QWidgetWindow::handleExposeEvent(QExposeEvent *event)
|
|||||||
{
|
{
|
||||||
if (isExposed()) {
|
if (isExposed()) {
|
||||||
m_widget->setAttribute(Qt::WA_Mapped);
|
m_widget->setAttribute(Qt::WA_Mapped);
|
||||||
if (!event->region().isNull()) {
|
if (!event->region().isNull())
|
||||||
// Exposed native widgets need to be marked dirty to get them repainted correctly.
|
|
||||||
if (m_widget->internalWinId() && !m_widget->isWindow() && m_widget->isVisible() && m_widget->updatesEnabled()) {
|
|
||||||
if (QWidgetBackingStore *bs = m_widget->d_func()->maybeBackingStore())
|
|
||||||
bs->markDirty(event->region(), m_widget);
|
|
||||||
}
|
|
||||||
m_widget->d_func()->syncBackingStore(event->region());
|
m_widget->d_func()->syncBackingStore(event->region());
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
m_widget->setAttribute(Qt::WA_Mapped, false);
|
m_widget->setAttribute(Qt::WA_Mapped, false);
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,7 @@ private slots:
|
|||||||
|
|
||||||
void tst_showWithoutActivating();
|
void tst_showWithoutActivating();
|
||||||
void tst_paintEventOnSecondShow();
|
void tst_paintEventOnSecondShow();
|
||||||
|
void tst_paintEventOnResize_QTBUG50796();
|
||||||
|
|
||||||
#ifndef QT_NO_DRAGANDDROP
|
#ifndef QT_NO_DRAGANDDROP
|
||||||
void tst_dnd();
|
void tst_dnd();
|
||||||
@ -369,6 +370,29 @@ void tst_QWidget_window::tst_paintEventOnSecondShow()
|
|||||||
QTRY_VERIFY(w.paintEventCount > 0);
|
QTRY_VERIFY(w.paintEventCount > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QWidget_window::tst_paintEventOnResize_QTBUG50796()
|
||||||
|
{
|
||||||
|
const QRect availableGeo = QGuiApplication::primaryScreen()->availableGeometry();
|
||||||
|
|
||||||
|
QWidget root;
|
||||||
|
root.setGeometry(availableGeo.width()/2 - 100, availableGeo.height()/2 - 100,
|
||||||
|
200, 200);
|
||||||
|
|
||||||
|
PaintTestWidget *native = new PaintTestWidget(&root);
|
||||||
|
native->winId(); // We're testing native widgets
|
||||||
|
native->setGeometry(10, 10, 50, 50);
|
||||||
|
|
||||||
|
root.show();
|
||||||
|
QVERIFY(QTest::qWaitForWindowExposed(&root));
|
||||||
|
QVERIFY(QTest::qWaitForWindowActive(&root));
|
||||||
|
QVERIFY(native->isVisible());
|
||||||
|
|
||||||
|
native->paintEventCount = 0;
|
||||||
|
native->resize(native->width() + 10, native->height() + 10);
|
||||||
|
QTest::qWait(50); // Wait for paint events
|
||||||
|
QTRY_COMPARE(native->paintEventCount, 1); // Only one paint event must occur
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DRAGANDDROP
|
#ifndef QT_NO_DRAGANDDROP
|
||||||
|
|
||||||
/* DnD test for QWidgetWindow (handleDrag*Event() functions).
|
/* DnD test for QWidgetWindow (handleDrag*Event() functions).
|
||||||
|
Loading…
Reference in New Issue
Block a user