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

Pali Rohár pali.rohar at gmail.com
Fri May 5 08:08:14 UTC 2017


PING.

I would like to know if there is some problem with this and something
needs to be reworked or if it can be accepted.

Currently xdpyinfo report bogus dimensions and resolution values and lot
of people complain about this problem. It should be fixed.

On Wednesday 12 April 2017 18:29:19 Pali Rohár wrote:
> Current usage of DisplayWidthMM() and DisplayHeightMM() does not make sense
> for multi-monitor configuration. In most cases DPI is set to 96 as there is
> no sane value.
> 
> Instead when XRANDR 1.2 extension is supported, report dimensions and
> resolution information per XRANDR monitor output. It should provide
> correct DPI value.
> 
> Lot of users complains about incorrect DPI reported by xdpyinfo, see bug:
> https://bugs.freedesktop.org/show_bug.cgi?id=23705
> 
> Signed-off-by: Pali Rohár <pali.rohar at gmail.com>
> ---
> Without this patch `xdpyinfo | grep -A 4 ^screen` reports:
> 
> screen #0:
>   dimensions:    1600x900 pixels (423x238 millimeters)
>   resolution:    96x96 dots per inch
>   depths (7):    24, 1, 4, 8, 15, 16, 32
>   root window id:    0xf8
> 
> Where DPI and also monitor dimensions in millimeters is incorrect.
> After applying this patch `xdpyinfo | grep -A 4 ^screen` reports:
> 
> screen #0:
>   output: eDP1
>     dimensions:    1600x900 pixels (310x170 millimeters)
>     resolution:    131x134 dots per inch
>   depths (7):    24, 1, 4, 8, 15, 16, 32
> 
> And both DPI and monitor dimensions (for eDP1) are correct.
> ---
>  Makefile.am  |    2 ++
>  configure.ac |   12 ++++++++
>  xdpyinfo.c   |   86 ++++++++++++++++++++++++++++++++++++++++++++++------------
>  3 files changed, 82 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..7a75fdc 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,70 @@ 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);
> +
> +            xres = ((((double) crtc->width) * 25.4) / ((double) output->mm_width));
> +            yres = ((((double) crtc->height) * 25.4) / ((double) output->mm_height));
> +            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);

-- 
Pali Rohár
pali.rohar at gmail.com


More information about the xorg-devel mailing list