浏览代码

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.

Kyle Schaefer 4 年之前
父节点
当前提交
c289bad900
共有 2 个文件被更改,包括 33 次插入0 次删除
  1. 32 0
      src/video/x11/SDL_x11modes.c
  2. 1 0
      src/video/x11/SDL_x11sym.h

+ 32 - 0
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;

+ 1 - 0
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