Significant window corruption with HiDPI scaling enabled on X11 + Qt 5.12 / 5.14
-
Hi, I've got two reports of window corruption that goes away when scaling is totally disabled (screenshots below). As yet I'm unsure what they might have in common as an underlying cause.
Edit #2: both of them are using the Nvidia proprietary driver version 440.64, but one of them is also seeing it with their Intel Intel HD Graphics 5500 enabled.
I've never seen this bug on my own machines, so I can only assume it's a bug in Qt or in libraries Qt uses. For one of the users, reverting to the OS installed Qt 5.9.5 solves the problem.
Short of starting a temporary
QApplication
at startup to determine screen scaling, and totally disabling it if scaling is equal to 1, I'm unsure how to deal with this bug. Until now my code has simply runQApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
at startup after checking environment variables likeQT_AUTO_SCREEN_SCALE_FACTOR
andQT_ENABLE_HIGHDPI_SCALING
.Any other suggestions?
This is what the window should look like:
-
The code to fix this problem was really unexpected and quite time consuming. The kicker is that
QGuiApplication.devicePixelRatio()
always returns 1.0 under Gnome, regardless of what scaling is actually set to. That means Gdk must be called to determine the scaling value.import gi gi.require_version('Gdk', '3.0') from gi.repository import Gdk def any_screen_scaled_gdk() -> bool: """ Detect if any of the screens on this system have scaling enabled. Uses GDK to do the querying. :return: True if found, else False """ try: display = Gdk.Display.get_default() except Exception: import logging logging.exception( 'An unexpected error occurred when querying the systems display parameters. Exception:' ) return False if display: try: for n in range(display.get_n_monitors()): monitor = display.get_monitor(n) if monitor.get_scale_factor() > 1: return True return False except AttributeError: # get_n_monitors() was introduced in gtk 3.22 try: screen = display.get_default_screen() for monitor in range(screen.get_n_monitors()): if screen.get_monitor_scale_factor(monitor) > 1: return True except Exception: import logging logging.exception('An unexpected error occurred when querying Gdk. Exception:') return False def any_screen_scaled_qt() -> bool: """ Detect if any of the screens on this system have scaling enabled. Call before QApplication is initialized. Uses temporary QGuiApplication. :return: True if found, else False """ app = QGuiApplication(sys.argv) return app.devicePixelRatio() > 1.0