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?
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.
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.
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.
To answer my own question, I've now tried three approaches:
DisplayWidth/Height
and DisplayWidthMM/HeightMM
xdpyinfo
outputNeither 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With