Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get system scale factor in X11

Tags:

c

linux

x11

gtk

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?

like image 408
Andreas Avatar asked Mar 02 '18 15:03

Andreas


People also ask

How do I show the scale in Linux?

One is System Settings > Displays. At the bottom, there's an option called "Scaling factor" where—at the time of writing—you can adjust scaling by whole integers (one, two, or three). If you want to adjust text only, you can do so at System Settings > Desktop > Text.

How do I scale a screen in XFCE?

Xfce supports HiDPI scaling which can be enabled using the settings manager: 1. Go to Settings Manager > Appearance > Settings > Window Scaling and select 2 as the scaling factor.

What is Gdk_scale?

Since Java 9 the GDK_SCALE environment variable is used to scale Swing applications accordingly. Note that at this point, Java AWT/Swing (up to including OpenJDK 13) only effectively supports integer values. A setting of -Dsun. java2d. uiScale=250% or GDK_SCALE=2.5 will be treated as if it were set to -Dsun.


1 Answers

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.

like image 155
Andreas Avatar answered Nov 07 '22 23:11

Andreas