Details
-
Bug
-
Resolution: Unresolved
-
P3: Somewhat important
-
None
-
6.7.2
-
None
Description
In some cases when a dialog box is created on a system with multiple monitors that have different DPI, it can have wrong size. That is, size of toplevel window does not match the size of the widget.
(Note the size of window's titlebar (which is light gray, and is not very visible in Jira when in light theme) mismatches dialog boxes content. The red parts are just transparent but I've masked to hide content from the main window that is under)
Here are more details:
- this happens only on Linux
- it happens only for some dialog boxes
- behaviour is consistent - it happens on every run
- I failed to reproduce it with a minimal example that opens a simple dialog box
- DPI of monitors must differ, for instance in my use case I had DPI 150, 100, 100 which corresponded to device-pixel-ratio of ~1.55, 1.04, 1.04
- once dialog is rendered on screen if user resizes its window, then the widget size gets fixed
In my use case:
- application is running against a vncserver with 3 screens with DPIs: 150, 100, 100
- application was started on 2nd screen and dialog box is opened on on the same screen
- vncserver is run with arguments:
evncserver.bin -extension DOUBLE-BUFFER +xinerama +kb -pixelformat rgb888 -screen 0 0 0 1600x950x24+0+0 -screen 1 0 0 1600x950x24+1600+0 -screen 2 0 0 1600x950x24+3200+0 -ac -nopn -ShortExitTimeout 0 -core -report-ready-fd 5 -SecurityTypes None :5
- xrandr reports for the screens:
Screen 0: minimum 32 x 32, current 4800 x 950, maximum 16384 x 16384 VNC-0 connected 1600x950+0+0 410mm x 243mm 1600x950 60.00*+ VNC-1 connected 1600x950+1600+0 410mm x 243mm 1600x950 60.00*+ VNC-2 connected 1600x950+3200+0 410mm x 243mm 1600x950 60.00*+
When I was debugging this use case what I could see is:
- dialog box is created initially on screen #1
- QDialog::adjustPosition() (called from QDialog::setVisible()/QWidget::show()) is causing that to be moved to screen #2 (VNC-1)
- WindowScreenChangedEvent is queued to QWindowSystemInterfacePrivate::windowSystemEventQueue with screen #1. That is caused by QXcbWindow::setGeometry() which is triggered by QLayout::activate() causing resize of the widget. QLayout::activate() is caused by a geometry change event caused by a screen change event
- two WindowScreenChangedEvents are queued to QWindowSystemInterfacePrivate::windowSystemEventQueue with screen #2
- top window is conencted to screen #1 as result of processing the 1st queued WindowScreenChangedEvent
- QWidgetWindow::updateSize() is being called but because current screen is #1, windows' geometry is smaller (when converted to device independent units)
- top window is connected to screen #2 as result of processing the 2nd queued WindowScreenChangedEvent
- now window is set to the correct screen but there are no more calls to QWidgetWindow::updateSize() and window and widget are not synced in size
- all that follow are a couple of paintEvents() that render the widget wrong as its size is wrong
This defect can be worked around by:
- adding:
void PreferencesDialog::showEvent(QShowEvent *event) { adjustSize(); updateGeometry(); QDialog::showEvent(event); }
- or using
QT_USE_NATIVE_WINDOWS=1