[PATCH app/xdpyinfo v2] Use XRANDR 1.2 extension for reporting dimensions and resolution per output

Pali Rohár pali.rohar at gmail.com
Tue May 16 20:04:57 UTC 2017


XServer with enabled XRANDR 1.2 extension does not provide correct
dimensions from DisplayWidthMM() and DisplayHeightMM() calls anymore.
Values are calculated from fixed DPI 96.

Therefore when XRANDR 1.2 extension is enabled and present, instead use
XRRGetScreenResources() and XRRGetOutputInfo() calls to get correct
dimensions and resolution information.

Signed-off-by: Pali Rohár <pali.rohar at gmail.com>
---
Changes since v1:
* Fixed detection of presence of XRANDR 1.2
* Fixed resolution calculation when dimensions are zero
---
 Makefile.am  |    2 ++
 configure.ac |   12 ++++++++
 xdpyinfo.c   |   91 ++++++++++++++++++++++++++++++++++++++++++++++------------
 3 files changed, 87 insertions(+), 18 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 2f21dda..496094e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -35,6 +35,7 @@ AM_CFLAGS = \
 	$(DPY_XCOMPOSITE_CFLAGS) \
 	$(DPY_XINERAMA_CFLAGS) \
 	$(DPY_DMX_CFLAGS) \
+	$(DPY_XRANDR_CFLAGS) \
 	$(DPY_XTST_CFLAGS)
 
 xdpyinfo_LDADD = \
@@ -49,6 +50,7 @@ xdpyinfo_LDADD = \
 	$(DPY_XCOMPOSITE_LIBS) \
 	$(DPY_XINERAMA_LIBS) \
 	$(DPY_DMX_LIBS) \
+	$(DPY_XRANDR_LIBS) \
 	$(DPY_XTST_LIBS)
 
 xdpyinfo_SOURCES =	\
diff --git a/configure.ac b/configure.ac
index 73dce26..4473faa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -132,6 +132,18 @@ else
 	echo "without dmx"
 fi
 
+AC_ARG_WITH(xrandr, AS_HELP_STRING([--without-xrandr],[Disable xrandr 1.2 support.]),
+		[USE_XRANDR="$withval"], [USE_XRANDR="yes"])
+if test "x$USE_XRANDR" != "xno" ; then
+	PKG_CHECK_MODULES(DPY_XRANDR, xrandr >= 1.2,
+		[SAVE_CPPFLAGS="$CPPFLAGS"
+		CPPFLAGS="$CPPFLAGS $DPY_XRANDR_CFLAGS $DPY_X11_CFLAGS"
+		AC_CHECK_HEADERS([X11/extensions/Xrandr.h],,,[#include <X11/Xlib.h>])
+		CPPFLAGS="$SAVE_CPPFLAGS"],[echo "not found"])
+else
+	echo "without xrandr 1.2"
+fi
+
 PKG_CHECK_MODULES(DPY_XTST, xtst,
 	[SAVE_CPPFLAGS="$CPPFLAGS"
 	CPPFLAGS="$CPPFLAGS $DPY_XTST_CFLAGS $DPY_X11_CFLAGS"
diff --git a/xdpyinfo.c b/xdpyinfo.c
index 152e32c..409968c 100644
--- a/xdpyinfo.c
+++ b/xdpyinfo.c
@@ -76,6 +76,10 @@ in this Software without prior written authorization from The Open Group.
 #  define DMX
 # endif
 
+# if HAVE_X11_EXTENSIONS_XRANDR_H
+#  define XRANDR
+# endif
+
 #endif
 
 #ifdef WIN32
@@ -137,6 +141,9 @@ in this Software without prior written authorization from The Open Group.
 #ifdef DMX
 #include <X11/extensions/dmxext.h>
 #endif
+#ifdef XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
 #include <X11/Xos.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -455,27 +462,75 @@ print_screen_info(Display *dpy, int scr)
     double xres, yres;
     int ndepths = 0, *depths = NULL;
     unsigned int width, height;
-
-    /*
-     * there are 2.54 centimeters to an inch; so there are 25.4 millimeters.
-     *
-     *     dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch))
-     *         = N pixels / (M inch / 25.4)
-     *         = N * 25.4 pixels / M inch
-     */
-
-    xres = ((((double) DisplayWidth(dpy,scr)) * 25.4) /
-	    ((double) DisplayWidthMM(dpy,scr)));
-    yres = ((((double) DisplayHeight(dpy,scr)) * 25.4) /
-	    ((double) DisplayHeightMM(dpy,scr)));
+#ifdef XRANDR
+    int event_base, error_base;
+    int major, minor;
+    XRRScreenResources *res = NULL;
+    XRROutputInfo *output;
+    XRRCrtcInfo *crtc;
+#endif
 
     printf ("\n");
     printf ("screen #%d:\n", scr);
-    printf ("  dimensions:    %dx%d pixels (%dx%d millimeters)\n",
-	    XDisplayWidth (dpy, scr),  XDisplayHeight (dpy, scr),
-	    XDisplayWidthMM(dpy, scr), XDisplayHeightMM (dpy, scr));
-    printf ("  resolution:    %dx%d dots per inch\n",
-	    (int) (xres + 0.5), (int) (yres + 0.5));
+
+#ifdef XRANDR
+    if (XRRQueryExtension (dpy, &event_base, &error_base) &&
+        XRRQueryVersion (dpy, &major, &minor) &&
+        (major > 1 || (major == 1 && minor >= 2)) &&
+        (res = XRRGetScreenResources (dpy, RootWindow (dpy, scr))))
+    {
+        for (i = 0; i < res->noutput; ++i) {
+            output = XRRGetOutputInfo (dpy, res, res->outputs[i]);
+            if (!output || !output->crtc || output->connection != RR_Connected)
+                continue;
+
+            crtc = XRRGetCrtcInfo (dpy, res, output->crtc);
+            if (!crtc) {
+                XRRFreeOutputInfo (output);
+                continue;
+            }
+
+            printf ("  output: %s\n", output->name);
+            printf ("    dimensions:    %ux%u pixels (%lux%lu millimeters)\n",
+                    crtc->width, crtc->height, output->mm_width, output->mm_height);
+
+            if (output->mm_width && output->mm_height) {
+                xres = ((((double) crtc->width) * 25.4) / ((double) output->mm_width));
+                yres = ((((double) crtc->height) * 25.4) / ((double) output->mm_height));
+            } else {
+                xres = 0;
+                yres = 0;
+            }
+            printf ("    resolution:    %dx%d dots per inch\n",
+                    (int) (xres + 0.5), (int) (yres + 0.5));
+
+            XRRFreeCrtcInfo (crtc);
+            XRRFreeOutputInfo (output);
+        }
+        XRRFreeScreenResources (res);
+    }
+    else
+#endif
+    {
+        printf ("  dimensions:    %dx%d pixels (%dx%d millimeters)\n",
+                DisplayWidth (dpy, scr),  DisplayHeight (dpy, scr),
+                DisplayWidthMM(dpy, scr), DisplayHeightMM (dpy, scr));
+
+        /*
+         * there are 2.54 centimeters to an inch; so there are 25.4 millimeters.
+         *
+         *     dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch))
+         *         = N pixels / (M inch / 25.4)
+         *         = N * 25.4 pixels / M inch
+         */
+        xres = ((((double) DisplayWidth(dpy,scr)) * 25.4) /
+                ((double) DisplayWidthMM(dpy,scr)));
+        yres = ((((double) DisplayHeight(dpy,scr)) * 25.4) /
+                ((double) DisplayHeightMM(dpy,scr)));
+        printf ("  resolution:    %dx%d dots per inch\n",
+                (int) (xres + 0.5), (int) (yres + 0.5));
+    }
+
     depths = XListDepths (dpy, scr, &ndepths);
     if (!depths) ndepths = 0;
     printf ("  depths (%d):    ", ndepths);
-- 
1.7.9.5



More information about the xorg-devel mailing list