[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