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

Pali Rohár pali.rohar at gmail.com
Wed Oct 17 16:40:37 UTC 2018


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 at 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
> 

-- 
Pali Rohár
pali.rohar at gmail.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
URL: <https://lists.x.org/archives/xorg-devel/attachments/20181017/f23257cb/attachment.sig>


More information about the xorg-devel mailing list