Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No way to access the correct DPI on X11 #1019

Closed
kovidgoyal opened this issue May 19, 2017 · 11 comments
Closed

No way to access the correct DPI on X11 #1019

kovidgoyal opened this issue May 19, 2017 · 11 comments
Labels
duplicate Issues duplicating another issue enhancement Feature suggestions and PRs High DPI High resolution display specific
Milestone

Comments

@kovidgoyal
Copy link
Contributor

kovidgoyal commented May 19, 2017

Modern toolkits under X11 generally use Xft.dpi resource to get the "logical" screen dpi. If that does not exist, then the physical dpi as reported by xrandr is used.

In order for text sizes in glfw applications specified in pts to match text sizes in other applications on the desktop, the logical dpi needs to be used rather than the physical one. There should be an API to query this value, as far as I can see there isn't one at the moment.

As evidence for my claim that modern toolkits use Xft.dpi, see Qt source code for the logicalDpi function:

https://code.qt.io/cgit/qt/qtbase.git/tree/src/plugins/platforms/xcb/qxcbscreen.cpp?id=b393641888f18e3accf094c91808e2189c2138cc#n478

you can see that it uses m_forcedDpi, if available. m_forcedDpi is set from Xft.dpi, here:
https://code.qt.io/cgit/qt/qtbase.git/tree/src/plugins/platforms/xcb/qxcbscreen.cpp?id=b393641888f18e3accf094c91808e2189c2138cc#n860

I'm not that familiar with DPI handling on other platforms, but alt least on X11, there needs to be a way to query a Monitor object for its logical DPI. Currently I hack around this in my application by using xrdb but
that is less than optimal.

EDIT: Another resource that mentions Xft.dpi: https://wiki.archlinux.org/index.php/HiDPI#X_Resources

@felselva
Copy link
Contributor

felselva commented May 19, 2017

A little research, and I found that it's easy to get the dpi on X11 using these functions: https://linux.die.net/man/3/displaywidthmm

If there's no way possible, will make an implementation and send a PR. But, if GLFW already provides somehow a way to get the screen size in millimiters, it would be possible to find the DPI with the current API.

@kovidgoyal
Copy link
Contributor Author

DisplayWidthMM is not useful - that information is already available in glfw in the monitor object via getMonitorPhysicalSize. However, the DPI calculated using getMonitorPhysicalSize often does not match the value set via Xft. Usually desktop environments/startup scripts, set Xft.dpi to a simple multiple of 96. For example on my 4K display, it is set to 192, while the actual physical dpi as reported by xrandr is 160. All non-glfw applications on my desktop use 192 as the dpi, not 160.

What should be done is query the xrdb database to get the Xft.dpi resource. The equivalent of doing

xrdb -query | grep Xft.dpi

For an example of doing that, look at the qxcbscreen.c source file I linked to earlier.

Also, while currently in X11 there is no per-monitor dpi there will likely be a per monitor dpi in the future with wayland. So the API you create should take a monitor object as an argument, which will be currently unused.

@linkmauve
Copy link
Member

HiDPI is already properly supported on Wayland, you can use it by building GLFW with -DGLFW_USE_WAYLAND=ON.

@kovidgoyal
Copy link
Contributor Author

kovidgoyal commented May 19, 2017

How do I get the same DPI that other applications are using on wayland? I need the actual DPI value to pass to freetype to render fonts given a font size in pts.

@felselva
Copy link
Contributor

felselva commented May 19, 2017

Are you using C or C++? In case you are, here is the implementation if you urgently needs it:

#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;
}

It gets the DPI from the Xft.dpi as a string and convert to double. The _glfw.X11.display can be replaced with a call to glfwGetX11Display() to pass the native X11 display.

I will wait to see what @elmindreda think, because there's a branch already for per-monitor-dpi

@kovidgoyal
Copy link
Contributor Author

Thanks, currently, I just shell out to xrdb right now in my app, see https://github.com/kovidgoyal/kitty/blob/master/kitty/utils.py#L53

It will just be nice to be able to drop the dependency on xrdb.

@elmindreda
Copy link
Member

elmindreda commented May 23, 2017

@kovidgoyal A function that returns logical DPI or window contents scale (calculated from some base DPI) is planned for 3.3. See #677.

Thank you for pointing out Xft.dpi. Wasn't aware of it and it looks very useful.

@elmindreda
Copy link
Member

elmindreda commented May 23, 2017

The per-monitor-dpi branch is about returning more accurate physical dimensions on Windows 8.1 and later and isn't (directly) related to this feature, though it will add some internal bits that will come in handy.

@kovidgoyal
Copy link
Contributor Author

@elmindreda Cool feel free to close this issue in that case.

@elmindreda elmindreda added duplicate Issues duplicating another issue enhancement Feature suggestions and PRs labels Jun 9, 2017
@elmindreda
Copy link
Member

Closing this as a duplicate of #677. Thank you again for Xft.dpi!

@elmindreda elmindreda added this to the None milestone Jun 9, 2017
@elmindreda elmindreda added the High DPI High resolution display specific label Aug 6, 2017
elmindreda added a commit that referenced this issue Aug 31, 2017
This adds glfwGetWindowContentScale and glfwGetMonitorContentScale for
querying the recommended scale factor for pixel content based on user
and/or system settings.

Parts of this patch are based on code by @ferreiradaselva.

TODO: Windows size scaling window hint
TODO: Windows size scaling at creation
TODO: macOS monitor content scale
TODO: Wayland implementation
TODO: Mir implementation
TODO: Documentation

Related to #235.
Related to #439.
Related to #698.
Related to #845.
Related to #898.
Related to #919.
Related to #1019.
@hanyetinggithub
Copy link

Hello, How to get multi monitor's DPI using this method?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
duplicate Issues duplicating another issue enhancement Feature suggestions and PRs High DPI High resolution display specific
Projects
None yet
Development

No branches or pull requests

5 participants