Provides a new xsetwacom parameter to restrict the tablet to a given RandR 1.2 output. The output has to be active. The command
xsetwacom set <device name> "MapToOutput" VGA1 maps the coordinates of the tablet to the given output. This is a once-off effect only. xsetwacom does not track the output for reconfiguration. If the output is reconfigured, re-running the command will re-configure the tablet with the new configuration. A list of outputs can be obtained with e.g. xrandr. If used together with rotation, the tablet must be rotated before being mapped to the output. Requires the "Coordinate Transformation Matrix" property to be present and handled by the X server. Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net> --- configure.ac | 2 +- man/xsetwacom.man | 12 +++++ tools/xsetwacom.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 1 deletions(-) diff --git a/configure.ac b/configure.ac index 93be614..0e156a7 100644 --- a/configure.ac +++ b/configure.ac @@ -54,7 +54,7 @@ PKG_CHECK_MODULES(XORG, [xorg-server >= 1.7.0] xproto xext kbproto inputproto $R XORG_DRIVER_CHECK_EXT(RANDR, randrproto) # Obtain compiler/linker options for the xsetwacom tool -PKG_CHECK_MODULES(X11, x11 xi) +PKG_CHECK_MODULES(X11, x11 xi xrandr) # X Server SDK location is required to install wacom header files # This location is also relayed in the xorg-wacom.pc file diff --git a/man/xsetwacom.man b/man/xsetwacom.man index bbfa8f8..a975ef1 100644 --- a/man/xsetwacom.man +++ b/man/xsetwacom.man @@ -83,6 +83,18 @@ Set the parameter value on the given device to the value provided. Note that not all parameters are writable, some are read-only and result in an error when trying to be modified. +.SH "PARAMETERS" +.TP +\fBMapToOutput\fR output +Map the tablet's input area to the given output (e.g. "VGA1"). The output +must specify one of those available through the XRandR extension. A list of +outputs may be obtained with the xrandr tool. The output mapping +configuration is a once-off 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. +This parameter is write-only and cannot be queried. + .SH "AUTHORS" Peter Hutterer <peter.hutte...@redhat.com> diff --git a/tools/xsetwacom.c b/tools/xsetwacom.c index 385b3b4..c1e81ab 100644 --- a/tools/xsetwacom.c +++ b/tools/xsetwacom.c @@ -34,6 +34,7 @@ #include <X11/Xlib.h> #include <X11/Xatom.h> #include <X11/extensions/XInput.h> +#include <X11/extensions/Xrandr.h> #include <X11/XKBlib.h> #define TRACE(...) \ @@ -106,6 +107,7 @@ static void get_twinview(Display *dpy, XDevice *dev, param_t *param, int argc, c static void set_xydefault(Display *dpy, XDevice *dev, param_t *param, int argc, char **argv); static void get_all(Display *dpy, XDevice *dev, param_t *param, int argc, char **argv); static void get_param(Display *dpy, XDevice *dev, param_t *param, int argc, char **argv); +static void set_output(Display *dpy, XDevice *dev, param_t *param, int argc, char **argv); static param_t parameters[] = { @@ -870,6 +872,12 @@ static param_t parameters[] = .prop_flags = PROP_FLAG_READONLY }, { + .name = "MapToOutput", + .desc = "Map the device to the given output. ", + .set_func = set_output, + .prop_flags = PROP_FLAG_WRITEONLY + }, + { .name = "all", .desc = "Get value for all parameters.", .get_func = get_all, @@ -2214,6 +2222,116 @@ static void get_button(Display *dpy, XDevice *dev, param_t *param, int argc, XFlush(dpy); } +static void _set_matrix_prop(Display *dpy, XDevice *dev, const float matrix[9]) +{ + Atom matrix_prop = XInternAtom(dpy, "Coordinate Transformation Matrix", True); + Atom type; + int format; + unsigned long nitems, bytes_after; + float *data; + + if (!matrix_prop) + { + fprintf(stderr, "Server does not support transformation"); + return; + } + + XGetDeviceProperty(dpy, dev, matrix_prop, 0, 9, False, + AnyPropertyType, &type, &format, &nitems, + &bytes_after, (unsigned char**)&data); + + if (format != 32 || type != XInternAtom(dpy, "FLOAT", True)) + return; + + XChangeDeviceProperty(dpy, dev, matrix_prop, type, format, + PropModeReplace, (unsigned char*)matrix, 9); + XFree(data); + XFlush(dpy); +} + +static void set_output(Display *dpy, XDevice *dev, param_t *param, int argc, char **argv) +{ + int min, maj; + int i, found = 0; + char *output_name; + XRRScreenResources *res; + XRROutputInfo *output_info; + XRRCrtcInfo *crtc_info; + + 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++) + { + output_info = XRRGetOutputInfo(dpy, res, res->outputs[i]); + + TRACE("Found output '%s' (%s)\n", output_info->name, + output_info->connection == RR_Connected ? "connected" : "disconnnected"); + + if (!output_info->crtc || output_info->connection != RR_Connected) + continue; + + crtc_info = XRRGetCrtcInfo (dpy, res, output_info->crtc); + TRACE("CRTC (%dx%d) %dx%d\n", crtc_info->x, crtc_info->y, + crtc_info->width, crtc_info->height); + + if (strcmp(output_info->name, output_name) == 0) + { + found = 1; + break; + } + } + + /* crtc holds our screen info, need to compare to actual screen size */ + if (found) + { + int width = DisplayWidth(dpy, DefaultScreen(dpy)); + int height = DisplayHeight(dpy, DefaultScreen(dpy)); + + /* offset */ + float x = 1.0 * crtc_info->x/width; + float y = 1.0 * crtc_info->y/height; + + /* mapping */ + float w = 1.0 * crtc_info->width/width; + float h = 1.0 * crtc_info->height/height; + + float matrix[9] = { 1, 0, 0, + 0, 1, 0, + 0, 0, 1}; + matrix[2] = x; + matrix[5] = y; + matrix[0] = w; + matrix[4] = h; + + TRACE("Transformation matrix:\n"); + TRACE(" [ %f %f %f ]\n", matrix[0], matrix[1], matrix[2]); + TRACE(" [ %f %f %f ]\n", matrix[3], matrix[4], matrix[5]); + TRACE(" [ %f %f %f ]\n", matrix[6], matrix[7], matrix[8]); + + _set_matrix_prop(dpy, dev, matrix); + } else + printf("Unable to find output '%s'. " + "Output may not be connected.\n", output_name); + + XRRFreeScreenResources(res); +} + static void get_all(Display *dpy, XDevice *dev, param_t *param, int argc, char **argv) { param_t *p = parameters; -- 1.7.2 ------------------------------------------------------------------------------ This SF.net email is sponsored by Make an app they can't live without Enter the BlackBerry Developer Challenge http://p.sf.net/sfu/RIM-dev2dev _______________________________________________ Linuxwacom-devel mailing list Linuxwacom-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel