[PyQt] Heads up about window corruption on X11 when HiDPI scaling enabled in Qt 5

Damon Lynch damonlynch at gmail.com
Fri Apr 10 06:55:14 BST 2020


Hi fellow developers,

Did you know that by enabling HiDPI support in your PyQt5 application you
could inadvertently be causing some Linux users to end up with an
application with a completely scrambled appearance? I don't know how rare
it is, but it can happen. The Qt versions were 5.12 and 5.14.2. An example:



The window should be approximating this (with some differences obviously):



The workaround I developed is to enable HiDPI scaling support only if a
monitor on the machine has scaling enabled. The good news is that on Qt
that's really easy to figure out, but the bad news is that it never works
under a Gtk derived desktop! Therefore I wrote this:

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


The basic idea is that if no monitor has scaling enabled, then don't enable
it in the application. I'm optimistic this should work (let's see).

Hopefully this might be useful to someone else. I've tested it under Gtk
Wayland & X11, and Qt X11. If you have a better approach or any thoughts in
general about it, please feel free to share them. I'm surely far from the
first to be confronted by this problem.

Damon

-- 
http://www.damonlynch.net
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20200410/7810dfc4/attachment.htm>


More information about the PyQt mailing list