Upgraded to 4.8.5, now have GL redraw issues
-
Hi,
I'm using Qt 4.8.5 on a big project. I just upgraded from 4.7.2.
Since upgrading I have a problem, on OSX only. I have two dockable windows in a layout. Window A has a vertical scrollbar, and window B is a QGLWidget.
In 4.7.2, if I scrolled the scrollbar in A, only A received paintEvents as you would expect.
However, since upgrading to 4.8.5, both A and B get paintEvents. This causes the GLWidget to paint incompletely at time. I have to click on the GLWidget (forcing a new paintEvent) to get window B to redraw properly.
If I cause paint events in window B, they are not occurring in window A. Only from A to B.
Debugging paint events is hard. Can anyone give me any help?
Thanks
-
Hi,
This might be a regression, did you check the "bug report system":http://bugreports.qt-project.org/issues to see if it's something known ?
If not, can you create a minimal compilable application that allows to reproduce the problem and create a new report with it ?
-
I did check, yes. I found one but its for 5.1!
https://bugreports.qt-project.org/browse/QTBUG-30655
The workaround they describe does not work in my case.
I've not been able to produce a simple repro case yet.
I forgot to say that the problem is solved if I dock the two windows together then move back to original position.
-
Then the best way is to start with your current software and remove piece by piece everything until you have the minimal case
-
So does this sound like a Qt bug? I found a fix for my problem.
Initially I found a runtime fix. I have the two widgets, A (containing a QScrollArea) and B (a QGLWidget). They both have a common QSplitter as ancestor.
If the scroll area in A was bigger than the containing widget, the paint events 'spilled' out. Paint events from A made B draw badly, until B got a paint event to correct the mess.
If I docked the two widgets, then restored position, the problem was fixed. So why was this?
When a QWidget calls setGeometry, setWSGeometry is called. This calculates the dirty rect and tries to inform the 'native parent' using QWidget::nativeParentWidget::update(QRect).
A native parent is not the same as a parent. Its the closest ancestor with a system ID. See:
http://qt-project.org/doc/qt-4.8/qwidget.html#nativeParentWidget
Note this does not need to be the MainWindow.
Since the upgrade to Qt 4.8, the initial state of nativeWidgets in my app is different.
Dirty rects from widget A's QScrollArea are sent directly to the QSplitter, 'spilling' into widget B. They should be clipped by the parent, widget A itself. But widget A is not a nativeWidget!
The act of moving either A or B to make them siblings changes this. Now widget A has become a nativeWidget. Only by making them siblings does this occur.
My theory is that widget B, being a QGLWidget, is a native widget. Qt doesn't ordinarily seem to allow native and non-native siblings, so by making widgets A and B siblings, widget A is converted to a nativeWidget.
The fix is to set the Qt::WA_NativeWindow attribute on widget A at initialisation.
But why?
-
IIRC, there was a switch to "alien widgets for Qt 4.8 on mac":http://blog.qt.digia.com/blog/2011/02/23/alien-widgets-on-mac/ so you might indeed have found a bug.
Did you check the "bug report system":http://bugreports.qt-project.org to see whether it's something known ? If not you could consider opening a bug report with a minimal example and your findings to help fix this.