On Tue, Sep 20, 2011 at 03:54:26PM -0700, Jason Gerecke wrote: > Adds a helper function for MapToOutput which determines which > output the device is currently mapped to, and moves to the next > available output. Repeatedly calling this function will result > in the device being mapped to every available output (including > the desktop as a whole) in turn. > > Signed-off-by: Jason Gerecke <killert...@gmail.com> > --- > Changes from v3: > > * Corresponds to patch v3 4/7 > * Updated commit message > * Changed from if/else-if to switch statement > * Exit loop as soon as matrix is determined invalid
Reviewed-by: Peter Hutterer <peter.hutte...@who-t.net> Cheers, Peter > man/xsetwacom.man | 8 ++- > tools/xsetwacom.c | 137 > +++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 142 insertions(+), 3 deletions(-) > > diff --git a/man/xsetwacom.man b/man/xsetwacom.man > index 9375e5b..10832ad 100644 > --- a/man/xsetwacom.man > +++ b/man/xsetwacom.man > @@ -123,9 +123,11 @@ Default: 0 > Map the tablet's input area to the given output (e.g. "VGA1"), or the entire > desktop if no output is provided. Output names may either be the name of > a head available through the XRandR extension, or an X11 geometry string of > -the from WIDTHxHEIGHT+X+Y. Users of the NVIDIA binary driver should use the > -output names "HEAD-0" and "HEAD-1" until the driver supports XRandr 1.2 or > -later. > +the form WIDTHxHEIGHT+X+Y. To switch to the next available output, the "next" > +keyword is also supported. This will cycle between the individual monitors > +connected to the system, and then the entire desktop. Users of the NVIDIA > +binary driver should use the output names "HEAD-0" and "HEAD-1" until the > +driver supports XRandR 1.2 or later. > > The output mapping configuration is a onetime setting and does not track > output > reconfigurations; the command needs to be re-run whenever the output > diff --git a/tools/xsetwacom.c b/tools/xsetwacom.c > index dea6e99..c9c090c 100644 > --- a/tools/xsetwacom.c > +++ b/tools/xsetwacom.c > @@ -1955,6 +1955,75 @@ static Bool need_xinerama(Display *dpy) > return False; > } > > +/** > + * Uses the area of the desktop and the server's transformation > + * matrix to calculate the dimensions and location of the area > + * the given device is mapped to. If the matrix describes a > + * non-rectangular transform (e.g. rotation or shear), this > + * function returns False. > + */ > +Bool get_mapped_area(Display *dpy, XDevice *dev, int *width, int *height, > int *x_org, int *y_org) > +{ > + Atom matrix_prop = XInternAtom(dpy, "Coordinate Transformation Matrix", > True); > + Atom type; > + int format; > + unsigned long nitems, bytes_after; > + float *data; > + Bool matrix_is_valid = True; > + int i; > + > + int display_width = DisplayWidth(dpy, DefaultScreen(dpy)); > + int display_height = DisplayHeight(dpy, DefaultScreen(dpy)); > + TRACE("Desktop width: %d, height: %d\n", display_width, display_height); > + > + if (!matrix_prop) > + { > + fprintf(stderr, "Server does not support transformation\n"); > + return False; > + } > + > + 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)) > + { > + fprintf(stderr,"Property for '%s' has unexpected type - this is > a bug.\n", > + "Coordinate Transformation Matrix"); > + XFree(data); > + return False; > + } > + > + TRACE("Current transformation matrix:\n"); > + TRACE(" [ %f %f %f ]\n", data[0], data[1], data[2]); > + TRACE(" [ %f %f %f ]\n", data[3], data[4], data[5]); > + TRACE(" [ %f %f %f ]\n", data[6], data[7], data[8]); > + > + for (i = 0; i < nitems && matrix_is_valid; i++) > + { > + switch (i) { > + case 0: *width = rint(display_width * data[i]); break; > + case 2: *x_org = rint(display_width * data[i]); break; > + case 4: *height = rint(display_height * data[i]); break; > + case 5: *y_org = rint(display_height * data[i]); break; > + case 8: > + if (data[i] != 1) > + matrix_is_valid = False; > + break; > + default: > + if (data[i] != 0) > + matrix_is_valid = False; > + break; > + } > + } > + XFree(data); > + > + if (!matrix_is_valid) > + fprintf(stderr, "Non-rectangular transformation matrix > detected.\n"); > + > + return matrix_is_valid; > +} > + > static void _set_matrix_prop(Display *dpy, XDevice *dev, const float > fmatrix[9]) > { > Atom matrix_prop = XInternAtom(dpy, "Coordinate Transformation Matrix", > True); > @@ -2129,6 +2198,72 @@ out: > XFree(screens); > } > > +/** > + * Adjust the transformation matrix based on the desktop size. > + * This function will attempt to map the given device to the entire > + * desktop. > + */ > +static void set_output_desktop(Display *dpy, XDevice *dev) > +{ > + int display_width = DisplayWidth(dpy, DefaultScreen(dpy)); > + int display_height = DisplayHeight(dpy, DefaultScreen(dpy)); > + > + set_output_area(dpy, dev, 0, 0, display_width, display_height); > +} > + > +/** > + * Adjust the transformation matrix based on its current value. This > + * function will attempt to map the given device to the next output > + * exposed in the list of Xinerama heads. If not mapped to a Xinerama > + * head, it maps to the first head. If mapped to the last Xinerama > + * head, it maps to the entire desktop. > + */ > +static void set_output_next(Display *dpy, XDevice *dev) > +{ > + XineramaScreenInfo *screens; > + int event, error, nscreens, head; > + int width, height, x_org, y_org; > + Bool success = False; > + > + if (!get_mapped_area(dpy, dev, &width, &height, &x_org, &y_org)) > + return; > + > + if (!XineramaQueryExtension(dpy, &event, &error)) > + { > + fprintf(stderr, "Unable to get screen mapping. Xinerama > extension not found\n"); > + return; > + } > + > + screens = XineramaQueryScreens(dpy, &nscreens); > + > + if (nscreens == 0) > + { > + fprintf(stderr, "Xinerama failed to query screens.\n"); > + goto out; > + } > + > + TRACE("Remapping to next available output.\n"); > + for (head = 0; head < nscreens && !success; head++) > + { > + if (screens[head].width == width && screens[head].height == > height && > + screens[head].x_org == x_org && screens[head].y_org == > y_org) > + { > + success = True; > + > + if (head + 1 < nscreens) > + set_output_xinerama(dpy, dev, head+1); > + else > + set_output_desktop(dpy, dev); > + } > + } > + > + if (!success) > + set_output_xinerama(dpy, dev, 0); > + > +out: > + XFree(screens); > +} > + > static void set_output(Display *dpy, XDevice *dev, param_t *param, int argc, > char **argv) > { > int head_no; > @@ -2153,6 +2288,8 @@ static void set_output(Display *dpy, XDevice *dev, > param_t *param, int argc, cha > > if (MaskIsSet(flags, XValue|YValue|WidthValue|HeightValue)) > set_output_area(dpy, dev, x, y, width, height); > + else if (strcasecmp(argv[0], "next") == 0) > + set_output_next(dpy, dev); > else if (!need_xinerama(dpy)) > set_output_xrandr(dpy, dev, argv[0]); > else if (convert_value_from_user(param, argv[0], &head_no)) > -- > 1.7.6 ------------------------------------------------------------------------------ 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-d2dcopy1 _______________________________________________ Linuxwacom-devel mailing list Linuxwacom-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel