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

Submitted by Pali Rohár on May 7, 2018, 9:34 p.m.

Details

Message ID 20180507213423.8781-1-pali.rohar@gmail.com
State New
Series "Use XRANDR 1.2 extension for reporting dimensions and resolution per output"
Headers show

Commit Message

Pali Rohár May 7, 2018, 9:34 p.m.
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, present and user requested
for it, instead use XRRGetScreenResources() and XRRGetOutputInfo() calls to
get correct dimensions and resolution information. Core dimensions from
DisplayWidthMM() and DisplayHeightMM() are still reported.

Otherwise when XRANDR 1.2 extension is enabled, present and user did not
request for it (which is default), show note that printed dimension does
not have to be correct and instruct user to run xdpyinfo with -ext RANDR.

Also update manual page and add information that xdpyinfo does not provide
correct information about DPI.

Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
---
Changes since v3:
* Always show core x screen output

Changes since v2:
* Fixed dimensions calculation when rotation is active
* Show XRANDR output only when explicitly requested
* Update manpage

Changes since v1:
* Fixed detection of presence of XRANDR 1.2
* Fixed resolution calculation when dimensions are zero
---
 Makefile.am      |   2 +
 configure.ac     |  12 ++++++
 man/xdpyinfo.man |   7 +++
 xdpyinfo.c       | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 4 files changed, 140 insertions(+), 10 deletions(-)

Patch hide | download patch | download mbox

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/man/xdpyinfo.man b/man/xdpyinfo.man
index c3d5c6d..5df44ea 100644
--- a/man/xdpyinfo.man
+++ b/man/xdpyinfo.man
@@ -51,6 +51,13 @@  Detailed information about a particular extension is displayed with the
 \fBall\fP, information about all extensions supported by both \fIxdpyinfo\fP
 and the server is displayed.
 .PP
+Do not use this utility for determining dimensions of monitor when XRANDR 1.2+
+extension is enabled for X screen, because it does not provide them. For
+determining physical dimensions or DPI of particular monitor use either
+.IR xrandr (__appmansuffix__)
+utility or call xdpyinfo with parameter \fB\-ext RANDR\fP (supported since
+xdpyinfo version 1.3.3).
+.PP
 If \fB-version\fP is specified, xdpyinfo prints its version and exits, without
 contacting the X server.
 .SH ENVIRONMENT
diff --git a/xdpyinfo.c b/xdpyinfo.c
index 152e32c..8d24b40 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>
@@ -442,6 +449,10 @@  print_visual_info(XVisualInfo *vip)
 	    vip->bits_per_rgb);
 }
 
+#ifdef XRANDR
+static Bool print_xrandr = False;
+#endif
+
 static void
 print_screen_info(Display *dpy, int scr)
 {
@@ -455,6 +466,14 @@  print_screen_info(Display *dpy, int scr)
     double xres, yres;
     int ndepths = 0, *depths = NULL;
     unsigned int width, height;
+    Bool has_xrandr = False;
+#ifdef XRANDR
+    int event_base, error_base;
+    int major, minor;
+    XRRScreenResources *res;
+    XRROutputInfo *output;
+    XRRCrtcInfo *crtc;
+#endif
 
     /*
      * there are 2.54 centimeters to an inch; so there are 25.4 millimeters.
@@ -464,18 +483,93 @@  print_screen_info(Display *dpy, int scr)
      *         = 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 ("\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)))
+        has_xrandr = True;
+#endif
+
+#ifdef XRANDR
+    if (has_xrandr && print_xrandr)
+    {
+        res = XRRGetScreenResources (dpy, RootWindow (dpy, scr));
+        if (res) {
+            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;
+                }
+
+                /* width and height is reported according to rotation, but mm_width and mm_height not */
+                if (crtc->rotation == RR_Rotate_0 || crtc->rotation == RR_Rotate_180) {
+                    width = crtc->width;
+                    height = crtc->height;
+                } else {
+                    width = crtc->height;
+                    height = crtc->width;
+                }
+
+                printf ("  output: %s\n", output->name);
+                printf ("    dimensions:    %ux%u pixels (%lux%lu millimeters)\n",
+                        width, height, output->mm_width, output->mm_height);
+
+                if (output->mm_width && output->mm_height) {
+                    xres = ((((double) width) * 25.4) / ((double) output->mm_width));
+                    yres = ((((double) 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);
+        }
+
+        printf ("  screen output: (union of all configured monitors)\n");
+        printf ("    dimensions:    %dx%d pixels (%dx%d millimeters)\n",
+                DisplayWidth (dpy, scr),  DisplayHeight (dpy, scr),
+                DisplayWidthMM(dpy, scr), DisplayHeightMM (dpy, scr));
+
+        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));
+    }
+    else
+#endif
+    {
+        printf ("  dimensions:    %dx%d pixels (%dx%d millimeters)\n",
+                DisplayWidth (dpy, scr),  DisplayHeight (dpy, scr),
+                DisplayWidthMM(dpy, scr), DisplayHeightMM (dpy, scr));
+
+        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));
+
+        if (has_xrandr)
+            printf ("    NOTE: above information is obsoleted and may be incorrect\n"
+                    "          instead run `%s -ext RANDR' for correct output\n\n",
+                    ProgramName);
+    }
+
     depths = XListDepths (dpy, scr, &ndepths);
     if (!depths) ndepths = 0;
     printf ("  depths (%d):    ", ndepths);
@@ -1316,6 +1410,10 @@  static int print_dmx_info(Display *dpy, const char *extname)
 
 #endif /* DMX */
 
+#ifdef XRANDR
+static int print_none_info(Display *dpy, const char *extname) { return 1; }
+#endif
+
 /* utilities to manage the list of recognized extensions */
 
 
@@ -1369,6 +1467,9 @@  static ExtensionPrintInfo known_extensions[] =
 #ifdef DMX
     {"DMX", print_dmx_info, False},
 #endif
+#ifdef XRANDR
+    {RANDR_NAME, print_none_info, False},
+#endif
     /* add new extensions here */
 };
 
@@ -1397,8 +1498,16 @@  mark_extension_for_printing(const char *extname)
 {
     int i;
 
+#ifdef XRANDR
+    if (strcmp(extname, RANDR_NAME) == 0)
+	print_xrandr = True;
+#endif
+
     if (strcmp(extname, "all") == 0)
     {
+#ifdef XRANDR
+	print_xrandr = True;
+#endif
 	for (i = 0; i < num_known_extensions; i++)
 	    known_extensions[i].printit = True;
     }

Comments

Pali Rohár Oct. 17, 2018, 4:40 p.m.
Hello, can you review 4th version of this patch below?

On Monday 07 May 2018 23:34:22 Pali Rohár wrote:
> 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, present and user requested
> for it, instead use XRRGetScreenResources() and XRRGetOutputInfo() calls to
> get correct dimensions and resolution information. Core dimensions from
> DisplayWidthMM() and DisplayHeightMM() are still reported.
> 
> Otherwise when XRANDR 1.2 extension is enabled, present and user did not
> request for it (which is default), show note that printed dimension does
> not have to be correct and instruct user to run xdpyinfo with -ext RANDR.
> 
> Also update manual page and add information that xdpyinfo does not provide
> correct information about DPI.
> 
> Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
> ---
> Changes since v3:
> * Always show core x screen output
> 
> Changes since v2:
> * Fixed dimensions calculation when rotation is active
> * Show XRANDR output only when explicitly requested
> * Update manpage
> 
> Changes since v1:
> * Fixed detection of presence of XRANDR 1.2
> * Fixed resolution calculation when dimensions are zero
> ---
>  Makefile.am      |   2 +
>  configure.ac     |  12 ++++++
>  man/xdpyinfo.man |   7 +++
>  xdpyinfo.c       | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
>  4 files changed, 140 insertions(+), 10 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/man/xdpyinfo.man b/man/xdpyinfo.man
> index c3d5c6d..5df44ea 100644
> --- a/man/xdpyinfo.man
> +++ b/man/xdpyinfo.man
> @@ -51,6 +51,13 @@ Detailed information about a particular extension is displayed with the
>  \fBall\fP, information about all extensions supported by both \fIxdpyinfo\fP
>  and the server is displayed.
>  .PP
> +Do not use this utility for determining dimensions of monitor when XRANDR 1.2+
> +extension is enabled for X screen, because it does not provide them. For
> +determining physical dimensions or DPI of particular monitor use either
> +.IR xrandr (__appmansuffix__)
> +utility or call xdpyinfo with parameter \fB\-ext RANDR\fP (supported since
> +xdpyinfo version 1.3.3).
> +.PP
>  If \fB-version\fP is specified, xdpyinfo prints its version and exits, without
>  contacting the X server.
>  .SH ENVIRONMENT
> diff --git a/xdpyinfo.c b/xdpyinfo.c
> index 152e32c..8d24b40 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>
> @@ -442,6 +449,10 @@ print_visual_info(XVisualInfo *vip)
>  	    vip->bits_per_rgb);
>  }
>  
> +#ifdef XRANDR
> +static Bool print_xrandr = False;
> +#endif
> +
>  static void
>  print_screen_info(Display *dpy, int scr)
>  {
> @@ -455,6 +466,14 @@ print_screen_info(Display *dpy, int scr)
>      double xres, yres;
>      int ndepths = 0, *depths = NULL;
>      unsigned int width, height;
> +    Bool has_xrandr = False;
> +#ifdef XRANDR
> +    int event_base, error_base;
> +    int major, minor;
> +    XRRScreenResources *res;
> +    XRROutputInfo *output;
> +    XRRCrtcInfo *crtc;
> +#endif
>  
>      /*
>       * there are 2.54 centimeters to an inch; so there are 25.4 millimeters.
> @@ -464,18 +483,93 @@ print_screen_info(Display *dpy, int scr)
>       *         = 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 ("\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)))
> +        has_xrandr = True;
> +#endif
> +
> +#ifdef XRANDR
> +    if (has_xrandr && print_xrandr)
> +    {
> +        res = XRRGetScreenResources (dpy, RootWindow (dpy, scr));
> +        if (res) {
> +            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;
> +                }
> +
> +                /* width and height is reported according to rotation, but mm_width and mm_height not */
> +                if (crtc->rotation == RR_Rotate_0 || crtc->rotation == RR_Rotate_180) {
> +                    width = crtc->width;
> +                    height = crtc->height;
> +                } else {
> +                    width = crtc->height;
> +                    height = crtc->width;
> +                }
> +
> +                printf ("  output: %s\n", output->name);
> +                printf ("    dimensions:    %ux%u pixels (%lux%lu millimeters)\n",
> +                        width, height, output->mm_width, output->mm_height);
> +
> +                if (output->mm_width && output->mm_height) {
> +                    xres = ((((double) width) * 25.4) / ((double) output->mm_width));
> +                    yres = ((((double) 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);
> +        }
> +
> +        printf ("  screen output: (union of all configured monitors)\n");
> +        printf ("    dimensions:    %dx%d pixels (%dx%d millimeters)\n",
> +                DisplayWidth (dpy, scr),  DisplayHeight (dpy, scr),
> +                DisplayWidthMM(dpy, scr), DisplayHeightMM (dpy, scr));
> +
> +        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));
> +    }
> +    else
> +#endif
> +    {
> +        printf ("  dimensions:    %dx%d pixels (%dx%d millimeters)\n",
> +                DisplayWidth (dpy, scr),  DisplayHeight (dpy, scr),
> +                DisplayWidthMM(dpy, scr), DisplayHeightMM (dpy, scr));
> +
> +        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));
> +
> +        if (has_xrandr)
> +            printf ("    NOTE: above information is obsoleted and may be incorrect\n"
> +                    "          instead run `%s -ext RANDR' for correct output\n\n",
> +                    ProgramName);
> +    }
> +
>      depths = XListDepths (dpy, scr, &ndepths);
>      if (!depths) ndepths = 0;
>      printf ("  depths (%d):    ", ndepths);
> @@ -1316,6 +1410,10 @@ static int print_dmx_info(Display *dpy, const char *extname)
>  
>  #endif /* DMX */
>  
> +#ifdef XRANDR
> +static int print_none_info(Display *dpy, const char *extname) { return 1; }
> +#endif
> +
>  /* utilities to manage the list of recognized extensions */
>  
>  
> @@ -1369,6 +1467,9 @@ static ExtensionPrintInfo known_extensions[] =
>  #ifdef DMX
>      {"DMX", print_dmx_info, False},
>  #endif
> +#ifdef XRANDR
> +    {RANDR_NAME, print_none_info, False},
> +#endif
>      /* add new extensions here */
>  };
>  
> @@ -1397,8 +1498,16 @@ mark_extension_for_printing(const char *extname)
>  {
>      int i;
>  
> +#ifdef XRANDR
> +    if (strcmp(extname, RANDR_NAME) == 0)
> +	print_xrandr = True;
> +#endif
> +
>      if (strcmp(extname, "all") == 0)
>      {
> +#ifdef XRANDR
> +	print_xrandr = True;
> +#endif
>  	for (i = 0; i < num_known_extensions; i++)
>  	    known_extensions[i].printit = True;
>      }
> -- 
> 2.11.0
>
Giuseppe Bilotta Oct. 18, 2018, 7:17 a.m.
Hello,

this is still not acceptable. _Do not alter the main section output_,
and move the XRANDR-specific information into its own
extension-dedicated output function, instead of hacking around it with
the print_none_info function.

On Mon, May 7, 2018 at 11:34 PM Pali Rohár <pali.rohar@gmail.com> wrote:
> -    xres = ((((double) DisplayWidth(dpy,scr)) * 25.4) /
> -           ((double) DisplayWidthMM(dpy,scr)));
> -    yres = ((((double) DisplayHeight(dpy,scr)) * 25.4) /
> -           ((double) DisplayHeightMM(dpy,scr)));
> -
>      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)))
> +        has_xrandr = True;
> +#endif
> +
> +#ifdef XRANDR
> +    if (has_xrandr && print_xrandr)
> +    {
> +        res = XRRGetScreenResources (dpy, RootWindow (dpy, scr));
> +        if (res) {
> +            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;
> +                }
> +
> +                /* width and height is reported according to rotation, but mm_width and mm_height not */
> +                if (crtc->rotation == RR_Rotate_0 || crtc->rotation == RR_Rotate_180) {
> +                    width = crtc->width;
> +                    height = crtc->height;
> +                } else {
> +                    width = crtc->height;
> +                    height = crtc->width;
> +                }
> +
> +                printf ("  output: %s\n", output->name);
> +                printf ("    dimensions:    %ux%u pixels (%lux%lu millimeters)\n",
> +                        width, height, output->mm_width, output->mm_height);
> +
> +                if (output->mm_width && output->mm_height) {
> +                    xres = ((((double) width) * 25.4) / ((double) output->mm_width));
> +                    yres = ((((double) 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);
> +        }
> +
> +        printf ("  screen output: (union of all configured monitors)\n");
> +        printf ("    dimensions:    %dx%d pixels (%dx%d millimeters)\n",
> +                DisplayWidth (dpy, scr),  DisplayHeight (dpy, scr),
> +                DisplayWidthMM(dpy, scr), DisplayHeightMM (dpy, scr));
> +
> +        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));
> +    }
> +    else
> +#endif
> +    {
> +        printf ("  dimensions:    %dx%d pixels (%dx%d millimeters)\n",
> +                DisplayWidth (dpy, scr),  DisplayHeight (dpy, scr),
> +                DisplayWidthMM(dpy, scr), DisplayHeightMM (dpy, scr));
> +
> +        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));
> +
> +        if (has_xrandr)
> +            printf ("    NOTE: above information is obsoleted and may be incorrect\n"
> +                    "          instead run `%s -ext RANDR' for correct output\n\n",
> +                    ProgramName);
> +    }
> +
>      depths = XListDepths (dpy, scr, &ndepths);
>      if (!depths) ndepths = 0;
>      printf ("  depths (%d):    ", ndepths);
> @@ -1316,6 +1410,10 @@ static int print_dmx_info(Display *dpy, const char *extname)
>
>  #endif /* DMX */
>
> +#ifdef XRANDR
> +static int print_none_info(Display *dpy, const char *extname) { return 1; }
> +#endif
> +
>  /* utilities to manage the list of recognized extensions */
>
>
> @@ -1369,6 +1467,9 @@ static ExtensionPrintInfo known_extensions[] =
>  #ifdef DMX
>      {"DMX", print_dmx_info, False},
>  #endif
> +#ifdef XRANDR
> +    {RANDR_NAME, print_none_info, False},
> +#endif
>      /* add new extensions here */
>  };
>
> @@ -1397,8 +1498,16 @@ mark_extension_for_printing(const char *extname)
>  {
>      int i;
>
> +#ifdef XRANDR
> +    if (strcmp(extname, RANDR_NAME) == 0)
> +       print_xrandr = True;
> +#endif
> +
>      if (strcmp(extname, "all") == 0)
>      {
> +#ifdef XRANDR
> +       print_xrandr = True;
> +#endif
>         for (i = 0; i < num_known_extensions; i++)
>             known_extensions[i].printit = True;
>      }
> --
> 2.11.0
>