Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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 run QApplication.setAttribute(Qt.AA_EnableHighDpiScaling) at startup after checking environment variables like QT_AUTO_SCREEN_SCALE_FACTOR and QT_ENABLE_HIGHDPI_SCALING.

    Any other suggestions?

    example2
    example1

    This is what the window should look like:
    Regular look



  • 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
    

Log in to reply