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.

Signed-off-by: Jason Gerecke <killert...@gmail.com>
---
Changes from v3:

 * Broken out from patch v3 7/7
 * Handles only the introduction of KeepShape
 * AspectRatio property does not exist anymore, so we modify the
   Area property directly.

 man/xsetwacom.man |   21 ++++++-----
 tools/xsetwacom.c |  104 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 113 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.
+
+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 a3998d2..08fe6b2 100644
--- a/tools/xsetwacom.c
+++ b/tools/xsetwacom.c
@@ -407,7 +407,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,
        },
        {
@@ -2025,6 +2025,90 @@ Bool get_mapped_area(Display *dpy, XDevice *dev, int 
*width, int *height, int *x
 }
 
 /**
+ * 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* param = find_parameter("Area");
+       Atom prop, type;
+       int format;
+       unsigned char* data = NULL;
+       unsigned long nitems, bytes_after;
+       long *ldata;
+       int w, h, x_org, y_org;
+       float width, height, aspect;
+       Bool success = False;
+
+       if (!get_mapped_area(dpy, dev, &w, &h, &x_org, &y_org))
+       {
+               fprintf(stderr, "Unable to get the output area.\n");
+               return success;
+       }
+       aspect = (float)w/(float)h;
+
+       prop = XInternAtom(dpy, param->prop_name, True);
+       if (!prop)
+       {
+               fprintf(stderr, "Property for '%s' not available.\n",
+                       param->name);
+               return success;
+       }
+
+       XGetDeviceProperty(dpy, dev, prop, 0, 1000, False, AnyPropertyType,
+                               &type, &format, &nitems, &bytes_after, &data);
+
+       if (nitems <= param->prop_offset)
+       {
+               fprintf(stderr, "Property offset doesn't exist, this is a 
bug.\n");
+               goto out;
+       }
+
+       ldata = (long*)data;
+       ldata[0] = -1;
+       ldata[1] = -1;
+       ldata[2] = -1;
+       ldata[3] = -1;
+
+       XChangeDeviceProperty(dpy, dev, prop, type, format,
+                               PropModeReplace, data, nitems);
+       XFlush(dpy);
+
+       if (do_match)
+       {
+               XGetDeviceProperty(dpy, dev, prop, 0, 1000, False, 
AnyPropertyType,
+                                       &type, &format, &nitems, &bytes_after, 
&data);
+
+               ldata = (long*)data;
+               width  = ldata[2] - ldata[0];
+               height = ldata[3] - ldata[1];
+
+               if (width / height > aspect)
+                       width = height * aspect;
+               else
+                       height = width / aspect;
+
+               ldata[2] = ldata[0] + width;
+               ldata[3] = ldata[1] + height;
+
+               XChangeDeviceProperty(dpy, dev, prop, type, format,
+                                       PropModeReplace, data, nitems);
+               XFlush(dpy);
+       }
+
+       success = True;
+
+out:
+       free(data);
+
+       return success;
+}
+
+/**
  * Modifies the server's transformation matrix property for the given
  * device. It takes as input a 9-element array of floats interpreted
  * as the row-major 3x3 matrix to be set. If this function succeeds
@@ -2290,10 +2374,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;
        }
@@ -2313,6 +2408,9 @@ static void set_output(Display *dpy, XDevice *dev, 
param_t *param, int argc, cha
 
        if (!success)
                return;
+
+       do_match = argc > 1 && strcasecmp(argv[1], "KeepShape") == 0;
+       _update_aspect(dpy, dev, do_match);
 }
 
 
-- 
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

Reply via email to