Adds a boolean "match" parameter to the MapToOutput command which
instructs the utility to (re)set the AspectRatio property appropriately.
---
 man/xsetwacom.man |   17 ++++---
 tools/xsetwacom.c |  152 +++++++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 140 insertions(+), 29 deletions(-)

diff --git a/man/xsetwacom.man b/man/xsetwacom.man
index fbdfc16..68c3c88 100644
--- a/man/xsetwacom.man
+++ b/man/xsetwacom.man
@@ -119,14 +119,17 @@ 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]
+\fBMapToOutput\fR [output] [match_aspect]
 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 defined area of the
-desktop with the form WIDTHxHEIGHT@X,Y. To switch to the next available output,
-the "next" keyword is also supported. Users of the NVIDIA binary driver
-should use the output names "HEAD-0" and "HEAD-1" until proper XRandR support
-is included.
+desktop of no output is provided. If the match_aspect option is 'true', the
+the active area of the tablet will be restricted to match the aspect ratio of
+the output; if 'false' or unspecified, the entire tablet area will be usable.
+
+Output names may either be the name of a head available through the XRandR
+extension, or an defined area of the desktop with the form WIDTHxHEIGHT@X,Y.
+The relative output "next" will map the pointer to the next available output.
+Users of the NVIDIA binary driver should use the output names "HEAD-0" and
+"HEAD-1" until proper XRandR support is included.
 
 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 23d06f2..eada809 100644
--- a/tools/xsetwacom.c
+++ b/tools/xsetwacom.c
@@ -408,7 +408,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,
        },
        {
@@ -1977,12 +1977,47 @@ static void _set_matrix_prop(Display *dpy, XDevice 
*dev, const float fmatrix[9])
 }
 
 /**
+ * Sets the aspect ratio of the given device to be equal to
+ * screen_width : screen_height.
+ */
+static void _set_aspect(Display *dpy, XDevice *dev, int screen_width, int 
screen_height)
+{
+       Atom aspect_prop = XInternAtom(dpy, "Wacom Aspect Ratio", True);
+       Atom type;
+       int format;
+       unsigned long nitems, bytes_after;
+       char *data = NULL;
+
+       XGetDeviceProperty(dpy, dev, aspect_prop, 0, 2, False,
+                               AnyPropertyType, &type, &format, &nitems,
+                               &bytes_after, (unsigned char**)&data);
+
+       if (format != 32 || nitems != 2)
+       {
+               fprintf(stderr, "Property for '%s' has unexpected type - this 
is a bug.\n",
+                       "Wacom Aspect Ratio");
+       }
+       else
+       {
+               ((long*)data)[0] = screen_width;
+               ((long*)data)[1] = screen_height;
+               XChangeDeviceProperty(dpy, dev, aspect_prop, type, format,
+                                       PropModeReplace, data, nitems);
+
+               XFlush(dpy);
+       }
+       free(data);
+}
+
+/**
  * Set the matrix for the given device for the screen defined by offset and
- * dimensions.
+ * dimensions. If 'match_aspect' is true, AspectRatio is set equal to the
+ * output aspect ratio; otherwise it is reset to floating.
  */
 static void _set_matrix(Display *dpy, XDevice *dev,
                        int offset_x, int offset_y,
-                       int screen_width, int screen_height)
+                       int screen_width, int screen_height,
+                       Bool match_aspect)
 {
        int width = DisplayWidth(dpy, DefaultScreen(dpy));
        int height = DisplayHeight(dpy, DefaultScreen(dpy));
@@ -2009,12 +2044,18 @@ static void _set_matrix(Display *dpy, XDevice *dev,
        TRACE(" [ %f %f %f ]\n", matrix[6], matrix[7], matrix[8]);
 
        _set_matrix_prop(dpy, dev, matrix);
+       if (match_aspect)
+               _set_aspect(dpy, dev, screen_width, screen_height);
+       else
+               _set_aspect(dpy, dev, 0, 0);
 }
 
 /**
  * Adjust the transformation matrix based on RandR settings. This function
  * will attempt to map the given device to the output named in the first
- * command-line argument. If the function succeeds, it returns 'true'.
+ * command-line argument. An optional true/false argument may follow to
+ * indicate if the aspect ratio should be matched. If the function succeeds,
+ * it returns 'true'.
  */
 static Bool set_output_xrandr(Display *dpy, XDevice *dev, param_t *param, int 
argc, char **argv)
 {
@@ -2026,6 +2067,7 @@ static Bool set_output_xrandr(Display *dpy, XDevice *dev, 
param_t *param, int ar
        XRRScreenResources *res;
        XRROutputInfo *output_info;
        XRRCrtcInfo *crtc_info;
+       Bool match_aspect = False;
 
        if (!XQueryExtension(dpy, "RANDR", &opcode, &event, &error) ||
            !XRRQueryVersion(dpy, &maj, &min) || (maj * 1000 + min) < 1002 ||
@@ -2043,6 +2085,18 @@ static Bool set_output_xrandr(Display *dpy, XDevice 
*dev, param_t *param, int ar
        }
 
        output_name = argv[0];
+       if (argc > 1)
+       {
+               if (strcasecmp(argv[1], "true") == 0)
+                       match_aspect = True;
+               else if (strcasecmp(argv[1], "false") == 0)
+                       match_aspect = False;
+               else
+               {
+                       TRACE("Unable to interpret the parameter '%s'\n", 
argv[1]);
+                       return False;
+               }
+       }
 
        res = XRRGetScreenResources(dpy, DefaultRootWindow(dpy));
        for (i = 0; i < res->noutput && !found; i++)
@@ -2077,7 +2131,7 @@ static Bool set_output_xrandr(Display *dpy, XDevice *dev, 
param_t *param, int ar
        {
                fprintf(stderr, "Remapping to output area obtained via 
RandR.\n", output_name);
                _set_matrix(dpy, dev, crtc_info->x, crtc_info->y,
-                           crtc_info->width, crtc_info->height);
+                           crtc_info->width, crtc_info->height, match_aspect);
 
                return True;
        } else
@@ -2091,8 +2145,9 @@ static Bool set_output_xrandr(Display *dpy, XDevice *dev, 
param_t *param, int ar
  * Adjust the transformation matrix based on the Xinerama settings. This
  * function will attempt to map the given pointer to the Xinerama head
  * (which should be formatted as 'HEAD-N') specified in the first command-
- * line argument. If this function succeeds in modifying the transformation
- * matrix, it returns 'true'.
+ * line argument. An optional true/false argument may follow to indicate
+ * if the aspect ratio should be matched. If this function succeeds in
+ * modifying the transformation matrix, it returns 'true'.
  *
  * For TwinView This would better be done with libXNVCtrl but until they
  * learn to package it properly, rely on Xinerama. Besides, libXNVCtrl isn't
@@ -2106,6 +2161,7 @@ static Bool set_output_xinerama(Display *dpy, XDevice 
*dev, param_t *param, int
        int nscreens;
        int head;
        Bool success = False;
+       Bool match_aspect = False;
 
        if (XQueryExtension(dpy, "RANDR", &opcode, &event, &error) &&
            XRRQueryVersion(dpy, &maj, &min) && (maj * 1000 + min) >= 1002 &&
@@ -2145,10 +2201,24 @@ static Bool set_output_xinerama(Display *dpy, XDevice 
*dev, param_t *param, int
                goto out;
        }
 
+       if (argc > 1)
+       {
+               if (strcasecmp(argv[1], "true") == 0)
+                       match_aspect = True;
+               else if (strcasecmp(argv[1], "false") == 0)
+                       match_aspect = False;
+               else
+               {
+                       fprintf(stderr, "Unable to interpret the parameter 
'%s'\n", argv[1]);
+                       return False;
+               }
+       }
+
        fprintf(stderr, "Remapping to output area obtained via Xinerama.\n", 
argv[0]);
        _set_matrix(dpy, dev,
                    screens[head].x_org, screens[head].y_org,
-                   screens[head].width, screens[head].height);
+                   screens[head].width, screens[head].height,
+                   match_aspect);
 
        success = True;
 
@@ -2317,17 +2387,30 @@ Bool get_mapped_area(Display *dpy, XDevice *dev, int 
*width, int *height, int *x
 * Adjust the transformation matrix based on a user-defined area.
 * This function will attempt to map the given pointer to the area defined
 * in the first command-line argument (which should be formatted as
-* 'WIDTHxHEIGHT@X,Y'). If this function succeeds in modifying the
-* transformation matrix, it returns 'true'.
+* 'WIDTHxHEIGHT@X,Y'). An optional true/false argument may follow to
+* indicate if the aspect ratio should be matched. If this function
+* succeeds in modifying the transformation matrix, it returns 'true'.
 */
 static Bool set_output_area(Display *dpy, XDevice *dev, param_t *param, int 
argc, char **argv)
 {
        int width, height, xorig, yorig;
+       Bool match_output = False;
+
+       if (argc == 2)
+       {
+               if (strcasecmp(argv[1], "true") == 0)
+                       match_output = True;
+               else if (strcasecmp(argv[1], "false") != 0)
+               {
+                       TRACE("Unable to interpret the argument '%s'.\n", 
argv[1]);
+                       return False;
+               }
+       }
 
        if (sscanf(argv[0], "%dx%d@%d,%d", &width, &height, &xorig, &yorig) == 
4)
        {
                fprintf(stderr, "Remapping to output area obtained via 
parsing.\n", argv[0]);
-               _set_matrix(dpy, dev, xorig, yorig, width, height);
+               _set_matrix(dpy, dev, xorig, yorig, width, height, 
match_output);
                return True;
        }
        else
@@ -2343,19 +2426,32 @@ static Bool set_output_area(Display *dpy, XDevice *dev, 
param_t *param, int argc
  * desired relative direction the mapping should move. At the moment,
  * this function only supports the command-line argument "next" (indicating
  * the user's desire to switch to the next output in an arbitrary list).
- * If this function succeeds in modifying the transformation matrix, it
- * returns 'true'.
+ * An optional true/false argument may follow to indicate if the aspect
+ * ratio should be matched. If this function succeeds in modifying the
+ * transformation matrix, it returns 'true'.
  */
 static Bool set_output_relative(Display *dpy, XDevice *dev, param_t *param, 
int argc, char **argv)
 {
        int w, h, x_org, y_org;
+       Bool match_output = False;
+
+       if (argc == 2)
+       {
+               if (strcasecmp(argv[1], "true") == 0)
+                       match_output = True;
+               else if (strcasecmp(argv[1], "false") != 0)
+               {
+                       TRACE("Unable to interpret the argument '%s'.\n", 
argv[1]);
+                       return False;
+               }
+       }
 
        if (strcasecmp(argv[0], "next") == 0)
        {
                if (get_mapped_area(dpy, dev, &w, &h, &x_org, &y_org))
                        if (get_next_output_area(dpy, &w, &h, &x_org, &y_org))
                        {
-                               _set_matrix(dpy, dev, x_org, y_org, w, h);
+                               _set_matrix(dpy, dev, x_org, y_org, w, h, 
match_output);
                                fprintf(stderr, "Remapping to output area 
obtained by relative position.\n");
                                return True;
                        }
@@ -2370,22 +2466,34 @@ static Bool set_output_relative(Display *dpy, XDevice 
*dev, param_t *param, int
 
 /**
  * Adjust the transformation matrix to map the given device to the entire
- * desktop. No command-line arguments are accepted for this function. If
- * this function succeeds in modifying the transformation matrix, it
- * returns 'true'.
+ * desktop. It takes no arguments of its own. An optional true/false argument
+ * may be given to indicate if the aspect ratio should be matched. If this
+ * function succeeds in modifying the transformation matrix, it returns 'true'.
  */
 static Bool set_output_desktop(Display *dpy, XDevice *dev, param_t *param, int 
argc, char **argv)
 {
-       if (argc > 0)
+       Bool match_output = False;
+
+       if (argc > 1)
        {
-               TRACE("Desktop mapping helper does not take arguments.");
+               TRACE("Desktop mapping helper only takes the optional 
'match_aspect' argument.\n");
                return False;
        }
+       if (argc == 1)
+       {
+               if (strcasecmp(argv[0], "true") == 0)
+                       match_output = True;
+               else if (strcasecmp(argv[0], "false") != 0)
+               {
+                       TRACE("Unable to interpret the argument '%s'.\n", 
argv[0]);
+                       return False;
+               }
+       }
 
        int width = DisplayWidth(dpy, DefaultScreen(dpy));
        int height = DisplayHeight(dpy, DefaultScreen(dpy));
 
-       _set_matrix(dpy, dev, 0, 0, width, height);
+       _set_matrix(dpy, dev, 0, 0, width, height, match_output);
 
        return True;
 }
@@ -2396,9 +2504,9 @@ static void set_output(Display *dpy, XDevice *dev, 
param_t *param, int argc, cha
        { set_output_desktop, set_output_relative, set_output_area,
          set_output_xinerama, set_output_xrandr };
 
-       if (argc != 0 && argc != param->arg_count)
+       if (argc > param->arg_count)
        {
-               fprintf(stderr, "'%s' requires exactly 0 or %d value(s).\n", 
param->name,
+               fprintf(stderr, "'%s' accepts no more than %d value(s).\n", 
param->name,
                        param->arg_count);
                return;
        }
-- 
1.7.6


------------------------------------------------------------------------------
Get a FREE DOWNLOAD! and learn more about uberSVN rich system, 
user administration capabilities and model configuration. Take 
the hassle out of deploying and managing Subversion and the 
tools developers use with it. http://p.sf.net/sfu/wandisco-d2d-2
_______________________________________________
Linuxwacom-devel mailing list
Linuxwacom-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel

Reply via email to