From c289bad9007cb672c994f726d967f6e5682f200d Mon Sep 17 00:00:00 2001 From: Kyle Schaefer Date: Mon, 22 Mar 2021 11:22:31 -0700 Subject: [PATCH] In x11, GetDisplayDPI can give incorrect or unusable DPI information. Using XGetDefaults to get the Xft DPI if it's available and returning that. This could allow you to figure out DPI scale. --- src/video/x11/SDL_x11modes.c | 32 ++++++++++++++++++++++++++++++++ src/video/x11/SDL_x11sym.h | 1 + 2 files changed, 33 insertions(+) diff --git a/src/video/x11/SDL_x11modes.c b/src/video/x11/SDL_x11modes.c index f35e34b94..3e1d45639 100644 --- a/src/video/x11/SDL_x11modes.c +++ b/src/video/x11/SDL_x11modes.c @@ -345,6 +345,29 @@ SetXRandRDisplayName(Display *dpy, Atom EDID, char *name, const size_t namelen, #endif } +static int +GetXftDPI(Display* dpy) +{ + char* xdefault_resource; + int xft_dpi, err; + + xdefault_resource = X11_XGetDefault(dpy, "Xft", "dpi"); + + if(!xdefault_resource) { + return 0; + } + + /* + * It's possible for SDL_atoi to call strtol, if it fails due to a + * overflow or an underflow, it will return LONG_MAX or LONG_MIN and set + * errno to ERANGE. So we need to check for this so we dont get crazy dpi + * values + */ + xft_dpi = SDL_atoi(xdefault_resource); + err = errno; + + return err == ERANGE ? 0 : xft_dpi; +} static int X11_InitModes_XRandR(_THIS) @@ -417,6 +440,7 @@ X11_InitModes_XRandR(_THIS) RRMode modeID; RRCrtc output_crtc; XRRCrtcInfo *crtc; + float xft_dpi; /* The primary output _should_ always be sorted first, but just in case... */ if ((looking_for_primary && (res->outputs[output] != primary)) || @@ -471,6 +495,14 @@ X11_InitModes_XRandR(_THIS) displaydata->hdpi = display_mm_width ? (((float) mode.w) * 25.4f / display_mm_width) : 0.0f; displaydata->vdpi = display_mm_height ? (((float) mode.h) * 25.4f / display_mm_height) : 0.0f; displaydata->ddpi = SDL_ComputeDiagonalDPI(mode.w, mode.h, ((float) display_mm_width) / 25.4f,((float) display_mm_height) / 25.4f); + + /* if xft dpi is available we will use this over xrandr */ + xft_dpi = (float)GetXftDPI(dpy); + if(xft_dpi > 0) { + displaydata->hdpi = xft_dpi; + displaydata->vdpi = xft_dpi; + } + displaydata->scanline_pad = scanline_pad; displaydata->x = display_x; displaydata->y = display_y; diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index b6e3a8726..6433b9310 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -138,6 +138,7 @@ SDL_X11_SYM(int,XWarpPointer,(Display* a,Window b,Window c,int d,int e,unsigned SDL_X11_SYM(int,XWindowEvent,(Display* a,Window b,long c,XEvent* d),(a,b,c,d),return) SDL_X11_SYM(Status,XWithdrawWindow,(Display* a,Window b,int c),(a,b,c),return) SDL_X11_SYM(VisualID,XVisualIDFromVisual,(Visual* a),(a),return) +SDL_X11_SYM(char*,XGetDefault,(Display* a,char* b, char* c),(a,b,c),return) #if SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY SDL_X11_SYM(XExtDisplayInfo*,XextAddDisplay,(XExtensionInfo* a,Display* b,_Xconst char* c,XExtensionHooks* d,int e,XPointer f),(a,b,c,d,e,f),return) #else