Details
-
Bug
-
Resolution: Done
-
P2: Important
-
None
-
5.5.1
-
None
Description
QDesktopWidget fails to reliably trigger signals when the screen geometry or the screen count changes. I tested this with Qt 5.5 since I cannot yet install Qt 5.6 (I'm on Debian, and some of the platform plugins are compiled against 5.5). Judging from the code, however, I don't expect Qt 5.6 to make any difference.
To reproduce this, you need two screens. In my examples, they are called LVDS1 (1366x768) and HDMI1 (1920x1200). I attached the sources of the sample application.
When we start, both screens are enabled and LVDS is primary.
$ ./test &
Inited
$ xrandr --output LVDS1 --off
Screen removed
Screen count changed: 1
Screen resized: 0
$ xrandr --output LVDS1 --auto --primary
Screen count changed: 2
Screen resized: 0
Screen added
$ xrandr --output LVDS1 --off
Screen removed
As you can see, after the last xrandr call, the screenCountChanged signal of QDesktopWidget is not triggered. At this point, QDesktopWidget entirely lost track of the only remaining screen; even if its resolution changes, there will be no notification.
The reason this happens is that QDesktopWidgetPrivate::_q_updateScreens makes the implicit assumption that new screens are added at the end of the screen list. The for loop starts at index screens.size() and iterates until it reaches screenList.length(), assuming that this covers all screens that are in screenList, but not in screens. However, for a freshly appearing primary screen, that is simply not true – that new primary screen is added at the beginning of the list returned by QGuiApplication. As a result, QDesktopWidgetPrivate does not connect to the signals of the new QScreen, and loses track of it.
I am using Qt 5.5 from Debian (which backported some patches from Qt 5.6 to make multi-screen less than entirely broken), plus some more patches I took from Ubuntu (because even the Debian version is still too broken for a dynamic multi-screen setup). That may lead to this bug, so I'd appreciate if someone could test on vanilla Qt 5.6 (and maybe give a hint which additional patches to backport to fix the issue?).
In Qt 5.6, the code for QDesktopWidget is still the same, it is still making this assumption. Furthermore, QGuiApplication still swaps the order of screens around (<https://github.com/qtproject/qtbase/blob/dev/src/gui/kernel/qplatformintegration.cpp#L515>). I hence suspect the bug still still present.
In any case, there is not even a comment in QDesktopWidgetPrivate::_q_updateScreens explaining that this assumption is being relied upon.