Discussion:
[PATCH app/xdpyinfo v2] Use XRANDR 1.2 extension for reporting dimensions and resolution per output
Pali Rohár
2017-05-16 20:04:57 UTC
Permalink
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 <***@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

_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.
Pali Rohár
2018-03-10 02:20:28 UTC
Permalink
Hi! I would like to remind this patch which fixes dimensions values in
xdpyinfo output which are broken for many years...
Post by Pali Rohár
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.
---
* 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);
--
Pali Rohár
***@gmail.com
Pali Rohár
2018-04-03 20:15:43 UTC
Permalink
Gently reminder of this patch. Can you comment/review it?
Post by Pali Rohár
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.
---
* 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
--
Pali Rohár
***@gmail.com
Giuseppe Bilotta
2018-04-04 07:47:59 UTC
Permalink
Hello Pali,

I like the idea of this patch, wasn't aware of its existence, thanks
Post by Pali Rohár
@@ -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
- */
You may want to keep this comment here, rather than in the else block below,
since the formula applies to any conversion, regardless if it's core
or per-output DPI.
Post by Pali Rohár
- 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));
I would unconditionally show the core output, regardless of RANDR
state. Even if it's fictitious when RANDR is enabled,
it can still be useful to spot inconsistencies. It also ensures that
the xdpyinfo output is "less" broken by this patch (search for
xdpyinfo grep resolution to get an idea of how used this is as a debug tool).
Post by Pali Rohár
+
+#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))))
+ {
I'm pondering whether it would be a good idea to print the RANDR
version here, something like:
printf(" RANDR (%d.%d) outputs:\n", major, minor);
and then nesting the per-output data even more.
Post by Pali Rohár
+ 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));
This doesn't work correctly when the display is rotated, since the
width/height in pixel will follow the orientation,
but the physical sizes won't. You should probably take that into
account, and possibly show the output orientation (e.g. in the
dimensions line, or in the name line if you do add the "RANDR
<version> outputs" header).

Also (please don't hate me), for RANDR versions 1.5 or higher we
should include RANDR monitors too (possibly in place of individual
outputs, I'm not sure about this actually, it depends on how detailed
we want to be; I would go with both, but then again I'm an information
junkie).

Cheers,
--
Giuseppe "Oblomov" Bilotta
_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Pali Rohár
2018-04-04 09:26:36 UTC
Permalink
Hi!
Post by Giuseppe Bilotta
Hello Pali,
I like the idea of this patch, wasn't aware of its existence, thanks
Post by Pali Rohár
@@ -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
- */
You may want to keep this comment here, rather than in the else block below,
since the formula applies to any conversion, regardless if it's core
or per-output DPI.
Ok, no problem.
Post by Giuseppe Bilotta
Post by Pali Rohár
- 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));
I would unconditionally show the core output, regardless of RANDR
state. Even if it's fictitious when RANDR is enabled,
it can still be useful to spot inconsistencies. It also ensures that
the xdpyinfo output is "less" broken by this patch (search for
xdpyinfo grep resolution to get an idea of how used this is as a debug tool).
XRANDR code below provides that 'grep resolution' support correctly and
in the same format. It is there for all those scripts which expects
resolution and dimensions to be correct.
Post by Giuseppe Bilotta
Post by Pali Rohár
+
+#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))))
+ {
I'm pondering whether it would be a good idea to print the RANDR
printf(" RANDR (%d.%d) outputs:\n", major, minor);
and then nesting the per-output data even more.
I as a user, would expect to find XRANDR version in "xrandr" utility
output, not in xdpyinfo output.

But if you really think that it would make sense to have it also in
xdpyinfo, it can be included somewhere...
Post by Giuseppe Bilotta
Post by Pali Rohár
+ 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));
This doesn't work correctly when the display is rotated, since the
width/height in pixel will follow the orientation,
but the physical sizes won't. You should probably take that into
account, and possibly show the output orientation (e.g. in the
dimensions line, or in the name line if you do add the "RANDR
<version> outputs" header).
Hm... I have not thinking about it. If this is a real problem I can look
at it and try to fix it.
Post by Giuseppe Bilotta
Also (please don't hate me), for RANDR versions 1.5 or higher we
should include RANDR monitors too (possibly in place of individual
outputs, I'm not sure about this actually, it depends on how detailed
we want to be; I would go with both, but then again I'm an information
junkie).
I know that I RANDR 1.5+ supports "monitors" which is needed for display
port outputs, but unfortunately I do not have such configuration for
testing. And I do not like idea to write and send code without real
testing.

This patch is just to fix long standing bug, that scripts which parse
xdpyinfo output and users who looking at it too just get wrong
information about dimensions and DPI.
--
Pali Rohár
***@gmail.com
_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo
Giuseppe Bilotta
2018-04-04 11:59:15 UTC
Permalink
Hello,

I took the liberty of moving the last paragraph of your email to the
top because the reply I'm giving to that part covers both.
Post by Pali Rohár
Post by Giuseppe Bilotta
Post by Pali Rohár
- 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));
I would unconditionally show the core output, regardless of RANDR
state. Even if it's fictitious when RANDR is enabled,
it can still be useful to spot inconsistencies. It also ensures that
the xdpyinfo output is "less" broken by this patch (search for
xdpyinfo grep resolution to get an idea of how used this is as a debug tool).
XRANDR code below provides that 'grep resolution' support correctly and
in the same format. It is there for all those scripts which expects
resolution and dimensions to be correct.
This patch is just to fix long standing bug, that scripts which parse
xdpyinfo output and users who looking at it too just get wrong
information about dimensions and DPI.
For users, having both pieces of information would be better than
having just the
RANDR one, especially for debugging, as that's exactly what the server
is providing
via its core protocol, and what legacy (non-RANDR-aware) clients will
get and use.
For scripts, the situation is a bit hairier, but I wonder how such a
script would work on a
server with multiple active outputs, where you patch introduces
multiple “resolution”
lines anyway.
If you think it's important for the primary RANDR output information
to be first,
maybe you can move the core information to _after_ the RANDR information,
but I still think it's important enough that it should stick around.

(And of course it would be better to fix the scripts themselves, but I
assume not all of them are
open source.)
Post by Pali Rohár
Post by Giuseppe Bilotta
Post by Pali Rohár
+
+#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))))
+ {
I'm pondering whether it would be a good idea to print the RANDR
printf(" RANDR (%d.%d) outputs:\n", major, minor);
and then nesting the per-output data even more.
I as a user, would expect to find XRANDR version in "xrandr" utility
output, not in xdpyinfo output.
But if you really think that it would make sense to have it also in
xdpyinfo, it can be included somewhere...
I'm not sure if it'd be useful or not, really. We could do without.
(I do show it in my xdpi <https://github.com/Oblomov/xdpi/>, but as I said,
I'm an information junkie).

(BTW, I don't think xrandr actually prints the version).
Post by Pali Rohár
Post by Giuseppe Bilotta
This doesn't work correctly when the display is rotated, since the
width/height in pixel will follow the orientation,
but the physical sizes won't. You should probably take that into
account, and possibly show the output orientation (e.g. in the
dimensions line, or in the name line if you do add the "RANDR
<version> outputs" header).
Hm... I have not thinking about it. If this is a real problem I can look
at it and try to fix it.
Here's how it looks for a rotated output:

output: eDP-1
dimensions: 1800x3200 pixels (346x194 millimeters)
resolution: 132x419 dots per inch

whereas non-rotated:

output: eDP-1
dimensions: 3200x1800 pixels (346x194 millimeters)
resolution: 235x236 dots per inch

Example from my aforementioned xdpi, rotated:

eDP-1: 1800x3200 pixels, (R, connected) 194x346 mm: 236x235
dpi, 92x92 dpcm, dot pitch 0.11mm

right side up:

eDP-1: 3200x1800 pixels, (U, connected) 346x194 mm: 235x236
dpi, 92x92 dpcm, dot pitch 0.11mm

The resolution should be rotational invariant (the monitor dot pitch
does not change if I put it on its side),
but the RANDR protocol doesn't take care of swapping the physical
dimensions, so you have to do it yourself.
Post by Pali Rohár
Post by Giuseppe Bilotta
Also (please don't hate me), for RANDR versions 1.5 or higher we
should include RANDR monitors too (possibly in place of individual
outputs, I'm not sure about this actually, it depends on how detailed
we want to be; I would go with both, but then again I'm an information
junkie).
I know that I RANDR 1.5+ supports "monitors" which is needed for display
port outputs, but unfortunately I do not have such configuration for
testing. And I do not like idea to write and send code without real
testing.
If no monitors are manually created, the X server will automatically generate
one per output, so you should be able to test the code even without an
actual MST monitor.
--
Giuseppe "Oblomov" Bilotta
_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
In
Pali Rohár
2018-04-04 12:45:56 UTC
Permalink
Post by Giuseppe Bilotta
Hello,
I took the liberty of moving the last paragraph of your email to the
top because the reply I'm giving to that part covers both.
Post by Pali Rohár
Post by Giuseppe Bilotta
Post by Pali Rohár
- 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));
I would unconditionally show the core output, regardless of RANDR
state. Even if it's fictitious when RANDR is enabled,
it can still be useful to spot inconsistencies. It also ensures that
the xdpyinfo output is "less" broken by this patch (search for
xdpyinfo grep resolution to get an idea of how used this is as a debug tool).
XRANDR code below provides that 'grep resolution' support correctly and
in the same format. It is there for all those scripts which expects
resolution and dimensions to be correct.
This patch is just to fix long standing bug, that scripts which parse
xdpyinfo output and users who looking at it too just get wrong
information about dimensions and DPI.
For users, having both pieces of information would be better than
having just the
RANDR one, especially for debugging, as that's exactly what the server
is providing
via its core protocol, and what legacy (non-RANDR-aware) clients will
get and use.
Agree.
Post by Giuseppe Bilotta
For scripts, the situation is a bit hairier, but I wonder how such a
script would work on a
server with multiple active outputs, where you patch introduces
multiple “resolution”
lines anyway.
Multiple resolution lines are there already. Just enable more Xscreens.
Such setups were common in past for dual head or for Xinerama
configurations. Old script needs to be aware of it, otherwise there were
broken in past too.
Post by Giuseppe Bilotta
If you think it's important for the primary RANDR output information
to be first,
maybe you can move the core information to _after_ the RANDR information,
but I still think it's important enough that it should stick around.
(And of course it would be better to fix the scripts themselves, but I
assume not all of them are
open source.)
I have no idea, but I was told that more people do (or did?)
'xdpyinfo | grep resolution' optionally with '| head -1' to get current
display DPI.

But I have no problem to modify output of xdpyinfo to provide:

1. Information from XRANDR1.2+
for all outputs, primary first
2. Information from core
Post by Giuseppe Bilotta
Post by Pali Rohár
Post by Giuseppe Bilotta
Post by Pali Rohár
+
+#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))))
+ {
I'm pondering whether it would be a good idea to print the RANDR
printf(" RANDR (%d.%d) outputs:\n", major, minor);
and then nesting the per-output data even more.
I as a user, would expect to find XRANDR version in "xrandr" utility
output, not in xdpyinfo output.
But if you really think that it would make sense to have it also in
xdpyinfo, it can be included somewhere...
I'm not sure if it'd be useful or not, really. We could do without.
(I do show it in my xdpi <https://github.com/Oblomov/xdpi/>, but as I said,
I'm an information junkie).
(BTW, I don't think xrandr actually prints the version).
Seems, yes xrandr output does not contain it.
Post by Giuseppe Bilotta
Post by Pali Rohár
Post by Giuseppe Bilotta
This doesn't work correctly when the display is rotated, since the
width/height in pixel will follow the orientation,
but the physical sizes won't. You should probably take that into
account, and possibly show the output orientation (e.g. in the
dimensions line, or in the name line if you do add the "RANDR
<version> outputs" header).
Hm... I have not thinking about it. If this is a real problem I can look
at it and try to fix it.
output: eDP-1
dimensions: 1800x3200 pixels (346x194 millimeters)
resolution: 132x419 dots per inch
output: eDP-1
dimensions: 3200x1800 pixels (346x194 millimeters)
resolution: 235x236 dots per inch
Ok, this should be fixed!

Question is: Should output from xdpyinfo respect rotation or provides
normalized output (as if no rotation was activated)?
Post by Giuseppe Bilotta
eDP-1: 1800x3200 pixels, (R, connected) 194x346 mm: 236x235
dpi, 92x92 dpcm, dot pitch 0.11mm
eDP-1: 3200x1800 pixels, (U, connected) 346x194 mm: 235x236
dpi, 92x92 dpcm, dot pitch 0.11mm
The resolution should be rotational invariant (the monitor dot pitch
does not change if I put it on its side),
but the RANDR protocol doesn't take care of swapping the physical
dimensions, so you have to do it yourself.
Post by Pali Rohár
Post by Giuseppe Bilotta
Also (please don't hate me), for RANDR versions 1.5 or higher we
should include RANDR monitors too (possibly in place of individual
outputs, I'm not sure about this actually, it depends on how detailed
we want to be; I would go with both, but then again I'm an information
junkie).
I know that I RANDR 1.5+ supports "monitors" which is needed for display
port outputs, but unfortunately I do not have such configuration for
testing. And I do not like idea to write and send code without real
testing.
If no monitors are manually created, the X server will automatically generate
one per output, so you should be able to test the code even without an
actual MST monitor.
Currently on my machines I have only Xservers with RandR 1.4.

So I would postpone 1.5+ support. Anyway, xdpyinfo should provide
reasonable output also when 1.5+ is not supported by server, therefore
we would need to have code for pre-1.5 and also for 1.5+ support. You
can also compile client application with 1.5+ support, but it should
work also when connected to just server with 1.4 support (e.g. when
doing SSH X11 forwarding).
--
Pali Rohár
***@gmail.com
_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Inf
Adam Jackson
2018-04-04 15:12:53 UTC
Permalink
Post by Pali Rohár
Gently reminder of this patch. Can you comment/review it?
Nack. The whole point of (that part of) xdpyinfo is to show you what
was sent in the initial connection block. xrandr already exists, and
code exists that depends on xdpyinfo's output.

- ajax
_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: htt
Giuseppe Bilotta
2018-04-04 19:30:45 UTC
Permalink
Post by Adam Jackson
Post by Pali Rohár
Gently reminder of this patch. Can you comment/review it?
Nack. The whole point of (that part of) xdpyinfo is to show you what
was sent in the initial connection block. xrandr already exists, and
code exists that depends on xdpyinfo's output.
Would it make sense to add the output from RANDR via an explicit `-ext
RANDR` query similar to what is already done for XINERAMA,
XInputExtension, etc?
--
Giuseppe "Oblomov" Bilotta
_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listi
Adam Jackson
2018-04-04 20:00:39 UTC
Permalink
Post by Giuseppe Bilotta
Post by Adam Jackson
Post by Pali Rohár
Gently reminder of this patch. Can you comment/review it?
Nack. The whole point of (that part of) xdpyinfo is to show you what
was sent in the initial connection block. xrandr already exists, and
code exists that depends on xdpyinfo's output.
Would it make sense to add the output from RANDR via an explicit `-ext
RANDR` query similar to what is already done for XINERAMA,
XInputExtension, etc?
If it's going to be in xdpyinfo at all - and I kinda don't think it
needs to be, given xrandr already exists, but I don't insist on that -
then yes, it should be behind -ext RANDR.

- ajax
_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/
Pali Rohár
2018-04-08 14:33:14 UTC
Permalink
Post by Adam Jackson
Post by Giuseppe Bilotta
Post by Adam Jackson
Post by Pali Rohár
Gently reminder of this patch. Can you comment/review it?
Nack. The whole point of (that part of) xdpyinfo is to show you what
was sent in the initial connection block. xrandr already exists, and
code exists that depends on xdpyinfo's output.
Would it make sense to add the output from RANDR via an explicit `-ext
RANDR` query similar to what is already done for XINERAMA,
XInputExtension, etc?
If it's going to be in xdpyinfo at all - and I kinda don't think it
needs to be, given xrandr already exists, but I don't insist on that -
then yes, it should be behind -ext RANDR.
- ajax
The main problem is that majority of users use xdpyinfo for getting DPI
of their monitors. And xdpyinfo reports totally bogus values. There are
plenty of bugs and lot of reports about this problem.

Really what is the purpose of reporting bogus values?
--
Pali Rohár
***@gmail.com
Giuseppe Bilotta
2018-04-08 17:22:28 UTC
Permalink
Post by Pali Rohár
The main problem is that majority of users use xdpyinfo for getting DPI
of their monitors.
And in the case of multiple monitors, they'll have to get used to
using `xdpyinfo -ext RANDR`, provided support for that information is
offered this way. I think that's a good compromise between backwards
compatibility and providing the correct information.
Post by Pali Rohár
And xdpyinfo reports totally bogus values.
The values reported by xdpyinfo aren't bogus, they are what the core
protocol is providing.
Post by Pali Rohár
There are plenty of bugs and lot of reports about this problem.
Because people are using the wrong tool.
Post by Pali Rohár
Really what is the purpose of reporting bogus values?
As mentioned, the purpose of xdpyinfo is to report what the core
protocol reports (modulo use of the -ext flag and related ones).

Now why does core report bogus values by default?

The root of the issue is that in the case of multiple monitors with
potentially inconsistent DPI values, the core protocol value is
ambiguous at best. It also has the downside that its value is only
communicated at connection time, so it doesn't dynamically change even
when the circumstances change (e.g. resolution change, move to a
different output with a different DPI, etc). Clients need to be aware
of the possibilities that different outputs may have different DPI
values, and that the values can change, and that requires RANDR
support and listening to the appropriate change notification masks.

So it is important that xdpyinfo keeps reporting what is reporting
because (1) it's its purpose and (2) it's the only way to get what
legacy (non-RANDR-aware) clients get.

Now one could argue that in the case of single output X11 could
automatically set the DPI to the one of the only connected output
(something I actually agree with), but that's (a) a separate issue and
(b) not without its downsides (e.g. should it automatically change
whenever the output changes? what should be done when a new output
gets connected? what should be done when an output gets disconnected
and we're left with one output again? etc).
--
Giuseppe "Oblomov" Bilotta
_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.o
Pali Rohár
2018-04-08 18:25:43 UTC
Permalink
Post by Giuseppe Bilotta
Post by Pali Rohár
The main problem is that majority of users use xdpyinfo for getting DPI
of their monitors.
And in the case of multiple monitors, they'll have to get used to
using `xdpyinfo -ext RANDR`, provided support for that information is
offered this way. I think that's a good compromise between backwards
compatibility and providing the correct information.
Post by Pali Rohár
And xdpyinfo reports totally bogus values.
The values reported by xdpyinfo aren't bogus, they are what the core
protocol is providing.
For users as human readable output from xdpyinfo, those values are
bogus. For users it does not matter how xdpyinfo obtain those values.
Just that it provides values which do not match reality.

I understand that those values comes from X server and xdpyinfo just
print what it receive. But for end-users of xdpyinfo this is really
irrelevant. That tool worked correctly prior changes in X server (do not
remember version).
Post by Giuseppe Bilotta
Post by Pali Rohár
There are plenty of bugs and lot of reports about this problem.
Because people are using the wrong tool.
I agree, but you can look at it from other side. This tool worked with
older X servers. If it is stopped working with new X servers, then
either tool itself should write information about it or do not report
those values at all.

Providing wrong information without any warning either in --help,
manpage or in stdout is really the worst solution.
Post by Giuseppe Bilotta
Post by Pali Rohár
Really what is the purpose of reporting bogus values?
As mentioned, the purpose of xdpyinfo is to report what the core
protocol reports (modulo use of the -ext flag and related ones).
The main problem is that this is not documented, nor written anywhere.
And output of xdpyinfo does not looks like core information for
end-users.

What end user reads? He sees resolution (which for with the most common
variant for one monitor) matches what he has configured and the he sees
DPI which does not match his monitor. So it is fully bogus for him.
Post by Giuseppe Bilotta
Now why does core report bogus values by default?
I understand reasons, for multimontitor setups with different DPIs
function DisplayWidthMM() and DisplayHeightMM() report meaningless
values (or at least values which should not be used for anything in
"correctly" written new applications).
Post by Giuseppe Bilotta
The root of the issue is that in the case of multiple monitors with
potentially inconsistent DPI values, the core protocol value is
ambiguous at best. It also has the downside that its value is only
communicated at connection time, so it doesn't dynamically change even
when the circumstances change (e.g. resolution change, move to a
different output with a different DPI, etc). Clients need to be aware
of the possibilities that different outputs may have different DPI
values, and that the values can change, and that requires RANDR
support and listening to the appropriate change notification masks.
Agree.
Post by Giuseppe Bilotta
So it is important that xdpyinfo keeps reporting what is reporting
because (1) it's its purpose and (2) it's the only way to get what
legacy (non-RANDR-aware) clients get.
Ok, it makes sense to retrieve this information, but for sure it should
not be used by new applications, scripts and also users to retrieve DPI.

But main problem is that xdpyinfo does not look like for end-users that
it reports "legacy" values which end-users should not read for xrandr
1.2+ display.
Post by Giuseppe Bilotta
Now one could argue that in the case of single output X11 could
automatically set the DPI to the one of the only connected output
(something I actually agree with), but that's (a) a separate issue and
(b) not without its downsides (e.g. should it automatically change
whenever the output changes? what should be done when a new output
gets connected? what should be done when an output gets disconnected
and we're left with one output again? etc).
Those are separate issues, which are really out-of-scope of this
discussion. Personally I like idea that DisplayWidthMM() and
DisplayHeightMM() are calculated to 96 DPI as 96 DPI is sane default for
legacy applications. And special case for one monitor setup is bad
because it would change behavior of applications when more then one
monitor is connected.
--
Pali Rohár
***@gmail.com
Giuseppe Bilotta
2018-04-09 10:11:18 UTC
Permalink
Post by Pali Rohár
Post by Giuseppe Bilotta
The values reported by xdpyinfo aren't bogus, they are what the core
protocol is providing.
For users as human readable output from xdpyinfo, those values are
bogus. For users it does not matter how xdpyinfo obtain those values.
Just that it provides values which do not match reality.
I understand that those values comes from X server and xdpyinfo just
print what it receive. But for end-users of xdpyinfo this is really
irrelevant. That tool worked correctly prior changes in X server (do not
remember version).
If your issue is with the default DPI reported by the X server, that's
the thing you should be fixing,
not what xdpyinfo is reporting.
Post by Pali Rohár
Post by Giuseppe Bilotta
Post by Pali Rohár
There are plenty of bugs and lot of reports about this problem.
Because people are using the wrong tool.
I agree, but you can look at it from other side. This tool worked with
older X servers. If it is stopped working with new X servers, then
either tool itself should write information about it or do not report
those values at all.
Providing wrong information without any warning either in --help,
manpage or in stdout is really the worst solution.
There is no other side. The tool still work as intended regardless of
the X server release, the information it provides is still exactly the
same, and as correct as it used to be —in the sense that it matches
exactly what the server claims. Users using it for a different purpose
fall in the category of this relevant XKCD https://xkcd.com/1172/

Again, your issue isn't what xdpyinfo reports, but what the _server_
reports, and you're trying to fix it in the wrong place.
Post by Pali Rohár
Post by Giuseppe Bilotta
Post by Pali Rohár
Really what is the purpose of reporting bogus values?
As mentioned, the purpose of xdpyinfo is to report what the core
protocol reports (modulo use of the -ext flag and related ones).
The main problem is that this is not documented, nor written anywhere.
If you feel that the man page and usage help text should better
clarify that all shown values are what the X core protocol reports,
modulo -ext option usage, that can be fixed.
Post by Pali Rohár
And output of xdpyinfo does not looks like core information for
end-users.
What end user reads? He sees resolution (which for with the most common
variant for one monitor) matches what he has configured and the he sees
DPI which does not match his monitor. So it is fully bogus for him.
And as above, xdpyinfo is not where this should be fixed.
Post by Pali Rohár
Post by Giuseppe Bilotta
So it is important that xdpyinfo keeps reporting what is reporting
because (1) it's its purpose and (2) it's the only way to get what
legacy (non-RANDR-aware) clients get.
Ok, it makes sense to retrieve this information, but for sure it should
not be used by new applications, scripts and also users to retrieve DPI.
But main problem is that xdpyinfo does not look like for end-users that
it reports "legacy" values which end-users should not read for xrandr
1.2+ display.
And that's why the solution to this is to put support for the RANDR
extension in xdpyinfo the correct way (i.e. accessible with -ext
RANDR), and teach users and scripts to rely on that information as
appropriate.
Post by Pali Rohár
Post by Giuseppe Bilotta
Now one could argue that in the case of single output X11 could
automatically set the DPI to the one of the only connected output
(something I actually agree with), but that's (a) a separate issue and
(b) not without its downsides (e.g. should it automatically change
whenever the output changes? what should be done when a new output
gets connected? what should be done when an output gets disconnected
and we're left with one output again? etc).
Those are separate issues, which are really out-of-scope of this
discussion. Personally I like idea that DisplayWidthMM() and
DisplayHeightMM() are calculated to 96 DPI as 96 DPI is sane default for
legacy applications. And special case for one monitor setup is bad
because it would change behavior of applications when more then one
monitor is connected.
But that's the core of the issue: xdpyinfo reporting the core value
when there are two monitors and the monitor value when there is a
single one would be no less inconsistent.

The only consistent solution is for xdpyinfo to keep working as
designed, provide the RANDR data via -ext RANDR, consistently with the
rest, and teach users and script to use that information when
possible.

Changes to what the core protocol should report by default remain a
separate matter, which may be worth discussing, but which remains
independent from the scope of this patch.
--
Giuseppe "Oblomov" Bilotta
_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo
Pali Rohár
2018-04-08 14:35:46 UTC
Permalink
Post by Adam Jackson
code exists that depends on xdpyinfo's output.
Exactly and that code expects that xdpyinfo provides correct output. But
it is broken since XServer for RandR 1.2+ capable screens started
reporting fixed values.
--
Pali Rohár
***@gmail.com
Pali Rohár
2018-04-12 18:47:34 UTC
Permalink
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.

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 <***@gmail.com>
---
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 | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
4 files changed, 128 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..ac2526f 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,81 @@ 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);
+ }
+ }
+ 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 +1398,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 +1455,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 +1486,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

_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Inf
Adam Jackson
2018-04-12 20:34:15 UTC
Permalink
Post by Pali Rohár
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.
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.
This should print the RANDR data in a separate stanza after the main
output, like the other extensions do. Again: the purpose of the core of
xdpyinfo is to tell you what the connection block says. Don't make it
print something else.

- ajax
_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.or
Pali Rohár
2018-04-18 13:33:42 UTC
Permalink
Post by Adam Jackson
This should print the RANDR data in a separate stanza after the main
output, like the other extensions do. Again: the purpose of the core of
xdpyinfo is to tell you what the connection block says. Don't make it
print something else.
This patch does not change anything in the output when command line
option for RANDR is not used. Therefore you would get same output as
before (without applying patch).

And when RANDR is explicitly requested then it outputs correct dimension
information. Yes, it hides what is reported by connection block, but the
main problem is that this tools is not already used like you said. Users
and also scripts expects that they would get correct monitor/output
dimension from xdpyinfo and not something which do not match with their
physical monitor device.

As Giuseppe said, this seems like a good compromise. When no parameter
is specified then xdpyinfo reports exactly same data as without this
patch. And with this patch which adds support for optional RANDR
parameter, then it reports dimensions for each monitor/output correctly.
So users would see what they are already expecting and want.
--
Pali Rohár
***@gmail.com
_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Giuseppe Bilotta
2018-04-18 13:45:20 UTC
Permalink
Post by Pali Rohár
Post by Adam Jackson
This should print the RANDR data in a separate stanza after the main
output, like the other extensions do. Again: the purpose of the core of
xdpyinfo is to tell you what the connection block says. Don't make it
print something else.
This patch does not change anything in the output when command line
option for RANDR is not used. Therefore you would get same output as
before (without applying patch).
And when RANDR is explicitly requested then it outputs correct dimension
information. Yes, it hides what is reported by connection block, but the
main problem is that this tools is not already used like you said. Users
and also scripts expects that they would get correct monitor/output
dimension from xdpyinfo and not something which do not match with their
physical monitor device.
As Giuseppe said, this seems like a good compromise. When no parameter
is specified then xdpyinfo reports exactly same data as without this
patch. And with this patch which adds support for optional RANDR
parameter, then it reports dimensions for each monitor/output correctly.
So users would see what they are already expecting and want.
No, in the RANDR case you are still replacing the core output, which
is not what I suggested. Instead, the RANDR information should be
provided _separately_ and _in addition to_ the core output. So instead
of defining a useless print_none_info, put the RANDR code in
print_randr_info and add _that_ to the known_extensions array.
--
Giuseppe "Oblomov" Bilotta
_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lis
Pali Rohár
2018-10-17 16:40:37 UTC
Permalink
Hello, can you review 4th version of this patch below?
Post by Pali Rohár
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.
---
* Always show core x screen output
* Fixed dimensions calculation when rotation is active
* Show XRANDR output only when explicitly requested
* Update manpage
* 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
***@gmail.com
Giuseppe Bilotta
2018-10-18 07:17:42 UTC
Permalink
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.
Post by Pali Rohár
- 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 "Oblomov" Bilotta
_______________________________________________
xorg-***@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: ht
Loading...