Search code examples
clinuxgtkx11

How to get system scale factor in X11


I want to make my application, which is purely in X11, high DPI aware. In order to do this, I need a way to find out the system scale factor that is configured in the display settings. Is there any way to get this system scale factor from an X11 app without resorting to higher level APIs like GTK?

FWIW, I've checked the GTK sources to see how gdk_window_get_scale_factor() does it and it seems to read an environment variable named GDK_SCALE. This environment variable, however, isn't there on my system at all, even though I've set scaling to 1.75 on my 4K monitor.

So how can I programmatically retrieve the system scaling factor?


Solution

  • To answer my own question, I've now tried three approaches:

    1. XRandR
    2. X11's DisplayWidth/Height and DisplayWidthMM/HeightMM
    3. Looking at xdpyinfo output

    Neither returns the correct DPI. Instead, the Xft.dpi Xresource seems to be the key to this problem. Xft.dpi always seems to carry the correct DPI so we can just read it to get the system scale factor.

    Here's some source taken from here:

    #include <X11/Xlib.h>
    #include <X11/Xatom.h>
    #include <X11/Xresource.h>
    
    double _glfwPlatformGetMonitorDPI(_GLFWmonitor* monitor)
    {
        char *resourceString = XResourceManagerString(_glfw.x11.display);
        XrmDatabase db;
        XrmValue value;
        char *type = NULL;
        double dpi = 0.0;
    
        XrmInitialize(); /* Need to initialize the DB before calling Xrm* functions */
    
        db = XrmGetStringDatabase(resourceString);
    
        if (resourceString) {
            printf("Entire DB:\n%s\n", resourceString);
            if (XrmGetResource(db, "Xft.dpi", "String", &type, &value) == True) {
                if (value.addr) {
                    dpi = atof(value.addr);
                }
            }
        }
    
        printf("DPI: %f\n", dpi);
        return dpi;
    }
    

    This does the trick for me.