Browse Source

Return xrandr-scaled display modes

XRandR supports applying transformations to an output's picture
including changes to scale. Such scaling is used by some desktop
environments under feature names such as "fractional scaling" to
accomodate HiDPI devices. Alternatively, such scaling can be enabled by
a command such as the following:

xrandr --output DP1 --scale 0.5x0.5 --filter nearest

XRandR scaling has no "HiDPI awareness" or other way for an application
to signal that it wants to work with physical display pixels, and so all
we do is scale SDL's returned display modes so that applications receive
the number of usable pixels that they expect.
Jeffrey Knockel 3 years ago
parent
commit
e4eab186ec
2 changed files with 12 additions and 4 deletions
  1. 11 4
      src/video/x11/SDL_x11modes.c
  2. 1 0
      src/video/x11/SDL_x11sym.h

+ 11 - 4
src/video/x11/SDL_x11modes.c

@@ -397,19 +397,26 @@ static SDL_bool SetXRandRModeInfo(Display *display, XRRScreenResources *res, RRC
         if (info->id == modeID) {
             XRRCrtcInfo *crtcinfo;
             Rotation rotation = 0;
+            XFixed scale_w = 0x10000, scale_h = 0x10000;
+            XRRCrtcTransformAttributes *attr;
 
             crtcinfo = X11_XRRGetCrtcInfo(display, res, crtc);
             if (crtcinfo) {
                 rotation = crtcinfo->rotation;
                 X11_XRRFreeCrtcInfo(crtcinfo);
             }
+            if (X11_XRRGetCrtcTransform(display, crtc, &attr) && attr) {
+                scale_w = attr->currentTransform.matrix[0][0];
+                scale_h = attr->currentTransform.matrix[1][1];
+                X11_XFree(attr);
+            }
 
             if (rotation & (XRANDR_ROTATION_LEFT | XRANDR_ROTATION_RIGHT)) {
-                mode->w = info->height;
-                mode->h = info->width;
+                mode->w = (info->height * scale_w + 0xffff) >> 16;
+                mode->h = (info->width * scale_h + 0xffff) >> 16;
             } else {
-                mode->w = info->width;
-                mode->h = info->height;
+                mode->w = (info->width * scale_w + 0xffff) >> 16;
+                mode->h = (info->height * scale_h + 0xffff) >> 16;
             }
             mode->refresh_rate = CalculateXRandRRefreshRate(info);
             ((SDL_DisplayModeData *)mode->driverdata)->xrandr_mode = modeID;

+ 1 - 0
src/video/x11/SDL_x11sym.h

@@ -309,6 +309,7 @@ SDL_X11_SYM(XRRPropertyInfo*,XRRQueryOutputProperty,(Display *dpy,RROutput outpu
 SDL_X11_SYM(int,XRRGetOutputProperty,(Display *dpy,RROutput output, Atom property, long offset, long length, Bool _delete, Bool pending, Atom req_type, Atom *actual_type, int *actual_format, unsigned long *nitems, unsigned long *bytes_after, unsigned char **prop),(dpy,output,property,offset,length, _delete, pending, req_type, actual_type, actual_format, nitems, bytes_after, prop),return)
 SDL_X11_SYM(RROutput,XRRGetOutputPrimary,(Display *dpy,Window window),(dpy,window),return)
 SDL_X11_SYM(void,XRRSelectInput,(Display *dpy, Window window, int mask),(dpy,window,mask),)
+SDL_X11_SYM(Status,XRRGetCrtcTransform,(Display *dpy,RRCrtc crtc,XRRCrtcTransformAttributes **attributes),(dpy,crtc,attributes),return)
 #endif
 
 /* MIT-SCREEN-SAVER support */