The NVIDIA binary driver doesn't support RandR 1.2 but it does support
Xinerama. Due to a server bug, we still get the current server's RandR
version back when we query, so we need to check to the binary
driver-specific NV-CONTROL extension first. If that or a RandR < 1.2
version is present fall back to Xinerama if we need to.
User commands:
xsetwacom set "device name" MapToOutput HEAD-0
xsetwacom set "device name" MapToOutput HEAD-1
Signed-off-by: Peter Hutterer <[email protected]>
---
Changes to v2:
- test for NV-CONTROL before testing for randr
- move TRACE statements inside set_output_*
configure.ac | 2 +-
man/xsetwacom.man | 3 +-
tools/xsetwacom.c | 93 ++++++++++++++++++++++++++++++++++++++++++----------
3 files changed, 78 insertions(+), 20 deletions(-)
diff --git a/configure.ac b/configure.ac
index 408e75f..c151e54 100644
--- a/configure.ac
+++ b/configure.ac
@@ -53,7 +53,7 @@ AC_CHECK_LIB([m], [rint])
PKG_CHECK_MODULES(XORG, [xorg-server >= 1.7.0] xproto xext kbproto inputproto
randrproto)
# Obtain compiler/linker options for the xsetwacom tool
-PKG_CHECK_MODULES(X11, x11 xi xrandr)
+PKG_CHECK_MODULES(X11, x11 xi xrandr xinerama)
# Obtain compiler/linker options for libudev used by ISDV4 code
PKG_CHECK_MODULES(UDEV, libudev)
diff --git a/man/xsetwacom.man b/man/xsetwacom.man
index 3a5fa40..564e1d0 100644
--- a/man/xsetwacom.man
+++ b/man/xsetwacom.man
@@ -126,7 +126,8 @@ outputs may be obtained with the xrandr tool. The output
mapping
configuration is a onetime setting and does not track output
reconfigurations; the command needs to be re-run whenever the output
configuration changes. When used with tablet rotation, the tablet must be
-rotated before it is mapped to the new screen.
+rotated before it is mapped to the new screen. When running the NVIDIA
+binary driver, the output names are "HEAD-0" and "HEAD-1".
This parameter is write-only and cannot be queried.
.TP
\fBMode\fR Absolute|Relative
diff --git a/tools/xsetwacom.c b/tools/xsetwacom.c
index c0cf707..9a73078 100644
--- a/tools/xsetwacom.c
+++ b/tools/xsetwacom.c
@@ -37,6 +37,7 @@
#include <X11/Xatom.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/Xrandr.h>
+#include <X11/extensions/Xinerama.h>
#include <X11/XKBlib.h>
#define TRACE(...) \
@@ -57,6 +58,7 @@ enum prop_flags {
PROP_FLAG_READONLY = 2,
PROP_FLAG_WRITEONLY = 4,
PROP_FLAG_INVERTED = 8, /* only valid with PROP_FLAG_BOOLEAN */
+ PROP_FLAG_OUTPUT = 16,
};
@@ -416,7 +418,7 @@ static param_t parameters[] =
.desc = "Map the device to the given output. ",
.set_func = set_output,
.arg_count = 1,
- .prop_flags = PROP_FLAG_WRITEONLY
+ .prop_flags = PROP_FLAG_WRITEONLY | PROP_FLAG_OUTPUT,
},
{
.name = "all",
@@ -1483,7 +1485,16 @@ static Bool convert_value_from_user(const param_t
*param, const char *value, int
if (param->prop_flags & PROP_FLAG_INVERTED)
*return_value = !(*return_value);
}
- else
+ else if (param->prop_flags & PROP_FLAG_OUTPUT)
+ {
+ const char *prefix = "HEAD-";
+ /* We currently support HEAD-X, where X is 0-9 */
+ if (strlen(value) != strlen(prefix) + 1 ||
+ strncasecmp(value, prefix, strlen(prefix)) != 0)
+ return False;
+
+ *return_value = value[strlen(prefix)] - '0';
+ } else
{
char *end;
long conversion = strtol(value, &end, 10);
@@ -2000,7 +2011,6 @@ static void _set_matrix(Display *dpy, XDevice *dev,
static void set_output_xrandr(Display *dpy, XDevice *dev, param_t *param, int
argc, char **argv)
{
- int min, maj;
int i, found = 0;
char *output_name;
XRRScreenResources *res;
@@ -2009,20 +2019,6 @@ static void set_output_xrandr(Display *dpy, XDevice
*dev, param_t *param, int ar
output_name = argv[0];
- if (!XRRQueryExtension(dpy, &maj, &min)) /* using min/maj as dummy */
- {
- fprintf(stderr, "Server does not support RandR");
- return;
- }
-
- if (!XRRQueryVersion(dpy, &maj, &min) ||
- (maj * 1000 + min) < 1002)
- {
- fprintf(stderr, "Server does not support RandR 1.2");
- return;
- }
-
-
res = XRRGetScreenResources(dpy, DefaultRootWindow(dpy));
for (i = 0; i < res->noutput && !found; i++)
@@ -2049,6 +2045,7 @@ static void set_output_xrandr(Display *dpy, XDevice *dev,
param_t *param, int ar
/* crtc holds our screen info, need to compare to actual screen size */
if (found)
{
+ TRACE("Setting CRTC %s\n", output_name);
_set_matrix(dpy, dev, crtc_info->x, crtc_info->y,
crtc_info->width, crtc_info->height);
} else
@@ -2058,8 +2055,60 @@ static void set_output_xrandr(Display *dpy, XDevice
*dev, param_t *param, int ar
XRRFreeScreenResources(res);
}
+/**
+ * Adjust the transformation matrix based on the Xinerama settings. For
+ * TwinView This would better be done with libXNVCtrl but until they learn
+ * to package it properly, rely on Xinerama. Besides, libXNVCtrl isn't
+ * available on RHEL, so we'd have to do it through Xinerama there anyway.
+ */
+static void set_output_xinerama(Display *dpy, XDevice *dev, param_t *param,
int argc, char **argv)
+{
+ int event, error;
+ XineramaScreenInfo *screens;
+ int nscreens;
+ int head;
+
+ if (!XineramaQueryExtension(dpy, &event, &error))
+ {
+ fprintf(stderr, "Unable to set screen mapping. Xinerama
extension not found\n");
+ return;
+ }
+
+ if (!convert_value_from_user(param, argv[0], &head))
+ {
+ fprintf(stderr, "Please specify the output name as HEAD-X,"
+ "where X is the screen number\n");
+ return;
+ }
+
+ screens = XineramaQueryScreens(dpy, &nscreens);
+
+ if (nscreens == 0)
+ {
+ fprintf(stderr, "Xinerama failed to query screens.\n");
+ goto out;
+ } else if (nscreens <= head)
+ {
+ fprintf(stderr, "Found %d screens, but you requested %s.\n",
+ nscreens, argv[0]);
+ goto out;
+ }
+
+ TRACE("Setting xinerama head %d\n", head);
+
+ _set_matrix(dpy, dev,
+ screens[head].x_org, screens[head].y_org,
+ screens[head].width, screens[head].height);
+
+out:
+ XFree(screens);
+}
+
static void set_output(Display *dpy, XDevice *dev, param_t *param, int argc,
char **argv)
{
+ int opcode, event, error;
+ int maj, min;
+
if (argc != param->arg_count)
{
fprintf(stderr, "'%s' requires exactly %d value(s).\n",
param->name,
@@ -2067,7 +2116,15 @@ static void set_output(Display *dpy, XDevice *dev,
param_t *param, int argc, cha
return;
}
- set_output_xrandr(dpy, dev, param, argc, argv);
+ /* Check for RandR 1.2. Server bug causes the NVIDIA driver to
+ * report with RandR 1.3 support but it doesn't expose RandR CRTCs.
+ * Force Xinerama if NV-CONTROL is present */
+ if (XQueryExtension(dpy, "NV-CONTROL", &opcode, &event, &error) ||
+ !XQueryExtension(dpy, "RANDR", &opcode, &event, &error) ||
+ !XRRQueryVersion(dpy, &maj, &min) || (maj * 1000 + min) < 1002)
+ set_output_xinerama(dpy, dev, param, argc, argv);
+ else
+ set_output_xrandr(dpy, dev, param, argc, argv);
}
--
1.7.5.4
------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure contains a
definitive record of customers, application performance, security
threats, fraudulent activity and more. Splunk takes this data and makes
sense of it. Business sense. IT sense. Common sense..
http://p.sf.net/sfu/splunk-d2d-c1
_______________________________________________
Linuxwacom-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel