[Interest] How to filter redundant paint call for widget with WA_PaintOnScreen

Tor Arne Vestbø Tor.arne.Vestbo at qt.io
Wed Feb 22 11:13:50 CET 2023


Hi,

Your workaround looks safe enough. Ideally we’d want a situation where sendUpdateRequest results in the same callback from the OS as handleExposeEvent, so that the two are coalesced, but the machinery for that Is not in place yet.

Tor Arne

On 22 Feb 2023, at 03:44, sivan nanthiran <nanthiran2005 at gmail.com> wrote:

Hi,

I noticed that when a native widget(Qt::WA_NativeWindow) with WA_PaintOnScreen is added into a vertical splitter, and when the splitter is moved, 2 paint events will be received for one mouse move.

One paint event is scheduled through QWidgetRepaintManager::sendUpdateRequest which is from the code path of processMouseEvent. While another paint event is called straight from NSView::displayLayer -> handleExposeEvent.

The handleExposeEvent will eventually call QWidget::syncBackingStore while the posted event of UpdateRequest will also call QWidget::syncBackingStore. And both of these calls will end up calling PaintOnScreen. Thus 2 paintEvents, for one mouse action.

The problem with this is that since I am handling my own pipeline for native widget rendering, frequent paint calls within a vsync interval is exhausting the rendering resources.

I was wondering if I could do something like this. So far this works well for me. But I would like to know if there is any issue with this approach. Thanks in advance.

 void QWidgetPrivate::syncBackingStore()
 {
+    if (shouldPaintOnScreen())
+    {
+        Q_Q(QWidget);
+        qApp->removePostedEvents(q, QEvent::UpdateRequest);
+    }
+
     if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
         repaintManager->sync();
     }



     if (shouldPaintOnScreen()) {
         paintOnScreen(dirty);
         dirty = QRegion();
     }
 }



 void QWidgetPrivate::syncBackingStore(const QRegion &region)
 {
     if (shouldPaintOnScreen()) {
+        Q_Q(QWidget);
+        qApp->removePostedEvents(q, QEvent::UpdateRequest);
+
         if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
             repaintManager->sync();
         }



-        paintOnScreen(region);
+        paintOnScreen(region + dirty);
+        dirty = QRegion();
     }
     else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
         repaintManager->sync(q_func(), region);
     }
 }

Regards,
Sivan
_______________________________________________
Interest mailing list
Interest at qt-project.org
https://lists.qt-project.org/listinfo/interest

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20230222/4d7f4dd6/attachment.htm>


More information about the Interest mailing list