On Tue, Sep 27, 2011 at 06:03:57PM -0700, Jason Gerecke wrote: > Adds an optional "KeepShape" paramater to the MapToOutput command. > If provided, the Area property is updated to match the aspect ratio > of the new output. If not provided, the Area property is reset to > the full tablet dimensions. > > This commit causes the MapToOutput command to break existing scripts > that rely on the Area property for device calibration. It is not > expected that this will result in actual problems since calibration > utilities do not currently handle multi-head setups properly anyway.
imo the better argument here is that if you're doing calibration, you're implicitly getting the KeepShape through the calibration anyway. > > Signed-off-by: Jason Gerecke <killert...@gmail.com> > --- > man/xsetwacom.man | 21 +++++---- > tools/xsetwacom.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 134 insertions(+), 12 deletions(-) > > diff --git a/man/xsetwacom.man b/man/xsetwacom.man > index dc0995f..43da602 100644 > --- a/man/xsetwacom.man > +++ b/man/xsetwacom.man > @@ -119,15 +119,18 @@ the device will ignore events from other tools. A > serial of 0 means the > device is unbound and will react to any tool of the matching type. > Default: 0 > .TP > -\fBMapToOutput\fR [output] > -Map the tablet's input area to a given output (e.g. "VGA1"). Output names may > -either be the name of a head available through the XRandR extension, or an > -X11 geometry string of 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. The mapping may be reset to the entire desktop at any time with the > -output name "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. > +\fBMapToOutput\fR [output] [KeepShape] > +Map the tablet's input area to a given output (e.g. "VGA1"). If the > "KeepShape" > +argument is passed in, the the active area of the tablet will be restricted > +to match the aspect ratio of the output; if unspecified, the entire tablet > +area will be usable. looking at this without any sentimental attachment to the name "KeepShape", a better name would be "MatchAspectRatio" or somesuch. KeepShape doesn't really specify which shape to keep, my tablet will look the same after all ;) also, we need to state that the tablet's input area starts at the tablet's 0/0 (after accommmodating rotation), the input area matched is not centered or so. > + > +Outputs may be specified by their XRandR name (users of the NVIDIA binary > +should use the names "HEAD-0" and "HEAD-1" until the driver supports XRandR > +1.2 or later). To map the tablet to an arbitrary portion of the desktop, you > +may provide an X11 geometry string of the form WIDTHxHEIGHT+X+Y. To map to > +the entire desktop, use "desktop". To cycle through all attached displays and > +the desktop, use "next". > > 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 acc57c7..8480b0c 100644 > --- a/tools/xsetwacom.c > +++ b/tools/xsetwacom.c > @@ -434,7 +434,7 @@ static param_t parameters[] = > .name = "MapToOutput", > .desc = "Map the device to the given output. ", > .set_func = set_output, > - .arg_count = 1, > + .arg_count = 2, > .prop_flags = PROP_FLAG_WRITEONLY | PROP_FLAG_OUTPUT, > }, > { > @@ -2137,6 +2137,108 @@ Bool get_mapped_area(Display *dpy, XDevice *dev, int > *width, int *height, int *x > return matrix_is_valid; > } > > +static Bool shrink(float aspect_ratio, long *width, long *height) > +{ > + if (!isfinite(aspect_ratio)) > + return False; > + else if (aspect_ratio == 0) > + return True; > + > + if ((float)*width / (float)*height > aspect_ratio) > + *width = *height * aspect_ratio; > + else > + *height = *width / aspect_ratio; > + > + return True; > +} > + > +static Bool rectangle_to_aspect(float aspect_ratio, int rotate, long *x1, > long *y1, > + long *x2, long *y2) > +{ > + long width = *x2 - *x1; > + long height = *y2 - *y1; > + > + if (rotate == ROTATE_CW || rotate == ROTATE_CCW) > + aspect_ratio = 1/aspect_ratio; > + > + shrink(aspect_ratio, &width, &height); > + > + switch (rotate) > + { > + case ROTATE_NONE: > + *x2 = *x1 + width; > + *y2 = *y1 + height; > + break; > + > + case ROTATE_CW: > + *x1 = *x2 - width; > + *y2 = *y1 + height; > + break; > + > + case ROTATE_HALF: > + *x1 = *x2 - width; > + *y1 = *y2 - height; > + break; > + > + case ROTATE_CCW: > + *x2 = *x1 + width; > + *y1 = *y2 - height; > + break; > + > + default: > + return False; > + } > + > + return True; > +} I'd really like to see some basic tests for this to ensure this keeps working if we ever change it. > + > +/** > + * Updates device's area property so that it's aspect ratio matches > + * that of the currently defied output area (if 'do_match' is true), > + * or to allow use of the entire area (if 'do_match' is false). > + * > + * If this function succeeds in modifying the aspect ratio, it returns > + * 'true'. > + */ > +static Bool _update_aspect(Display *dpy, XDevice *dev, Bool do_match) > +{ > + param_t* area_param = find_parameter("Area"); > + param_t* rotate_param = find_parameter("Rotate"); > + int w, h, x_org, y_org; > + float aspect; > + long area[4] = {-1, -1, -1, -1}; > + > + if (!get_mapped_area(dpy, dev, &w, &h, &x_org, &y_org)) > + { > + fprintf(stderr, "Unable to get the output area.\n"); > + return False; > + } > + aspect = (float)w/(float)h; > + > + _set(dpy, dev, area_param->prop_name, area_param->prop_offset, &area, > + area_param->prop_format, XA_INTEGER, area_param->arg_count); > + > + if (do_match) > + { > + long *rotptr = _get(dpy, dev, rotate_param->prop_name, > rotate_param->prop_offset, > + rotate_param->prop_format, XA_INTEGER, > rotate_param->arg_count); > + long *areaptr = _get(dpy, dev, area_param->prop_name, > area_param->prop_offset, > + area_param->prop_format, XA_INTEGER, > area_param->arg_count); > + > + if(rectangle_to_aspect(aspect, rotptr[0], &areaptr[0], > &areaptr[1], &areaptr[2], &areaptr[3])) > + { > + _set(dpy, dev, area_param->prop_name, > area_param->prop_offset, areaptr, > + area_param->prop_format, XA_INTEGER, > area_param->arg_count); > + } > + > + return False; > + } > + else > + { > + return True; > + } > +} > + > /** > * Modifies the server's transformation matrix property for the given > * device. It takes as input a 9-element array of floats interpreted > @@ -2417,10 +2519,21 @@ static void set_output(Display *dpy, XDevice *dev, > param_t *param, int argc, cha > unsigned int width, height; > int flags = XParseGeometry(argv[0], &x, &y, &width, &height); > Bool success = False; > + Bool do_match; > > - if (argc != param->arg_count) > + if (argc == 0) > { > - fprintf(stderr, "'%s' requires exactly %d value(s).\n", > param->name, > + fprintf(stderr, "'%s' requires at least one argument.\n", > param->name); > + return; > + } > + else if (argc == param->arg_count && strcasecmp(argv[1], "KeepShape") > != 0) > + { > + fprintf(stderr, "'%s' could not understand the provided > argument '%s'.\n", > + param->name, argv[1]); > + } > + else if (argc > param->arg_count) > + { > + fprintf(stderr, "'%s' accepts no more than %d value(s).\n", > param->name, > param->arg_count); > return; > } > @@ -2437,6 +2550,12 @@ static void set_output(Display *dpy, XDevice *dev, > param_t *param, int argc, cha > success = set_output_xinerama(dpy, dev, head_no); > else > fprintf(stderr, "Unable to find an output '%s'.\n", argv[0]); > + > + if (!success) > + return; > + > + do_match = argc > 1 && strcasecmp(argv[1], "KeepShape") == 0; > + _update_aspect(dpy, dev, do_match); given that you only pass in one boolean to _update_aspect, you could pass the same boolean into set_output_foo() and do the calculation there, right after you've parsed the respective output geometries. Saves you from having to re-fetch the property. Cheers, Peter ------------------------------------------------------------------------------ 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