On Wed, Sep 07, 2011 at 04:36:56PM -0700, Jason Gerecke wrote:
> Adds an optional "KeepShape" paramater to the MapToOutput command.
> If provided, the AspectRatio property is updated to match the aspect
> ratio of the new output. If not provided, the AspectRatio property is
> reset to allow full use of the tablet's area.
>
> Signed-off-by: Jason Gerecke <[email protected]>
> ---
> Changes from v2:
> * Corresponds to patch v2 9/9
I take the original AspectRatio patch is still the most current one then?
Sorry, haven't been able to review this earlier.
> * Boolean "match" argument replaced with the "KeepShape" keyword for
> more semantic meaning.
>
> * Helper functions (finally) modified to return booleans
there's a bit of noise in this patch because of this change. Why not split
this out so that the actual aspect ratio patch is limited to aspect
ratio fetures?
>
> * '_set_aspect' renamed to '_update_aspect'
>
> * Helper functions no longer take an additional boolean argument;
> '_update_aspect' should be called manually.
>
> man/xsetwacom.man | 19 ++++---
> tools/xsetwacom.c | 146 +++++++++++++++++++++++++++++++++++++++++-----------
> 2 files changed, 126 insertions(+), 39 deletions(-)
>
> diff --git a/man/xsetwacom.man b/man/xsetwacom.man
> index edc97c4..d87f24d 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]
> +\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 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. Users of the NVIDIA
> -binary driver should use the output names "HEAD-0" and "HEAD-1" until proper
> -XRandR support is included.
> +desktop if 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 X11 geometry string of the form WIDTHxHEIGHT+X+Y. The
> +relative output "next" will cycle the mapping through all available outputs,
> +including the desktop as a whole. 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 5377c97..d3a237f 100644
> --- a/tools/xsetwacom.c
> +++ b/tools/xsetwacom.c
> @@ -410,7 +410,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,
> },
> {
> @@ -2036,7 +2036,61 @@ Bool get_mapped_area(Display *dpy, XDevice *dev, int
> *width, int *height, int *x
> return matrix_is_valid;
> }
>
> -static void _set_matrix_prop(Display *dpy, XDevice *dev, const float
> fmatrix[9])
> +/**
> + * Updates device's aspect ratio property so that it 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)
> +{
> + Atom aspect_prop = XInternAtom(dpy, "Wacom Aspect Ratio", True);
> + Atom type;
> + int format;
> + unsigned long nitems, bytes_after;
> + char *data = NULL;
> + int w, h, x_org, y_org;
> + Bool success = False;
> +
> + 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");
xsetwacom is always built from the tree anyway, we can use the #define for
the property name here.
> + return success;
> + }
> +
> + if (!get_mapped_area(dpy, dev, &w, &h, &x_org, &y_org))
> + return False;
> +
> + if (!do_match) {
> + w = 0;
> + h = 0;
> + }
> +
> + TRACE("Setting aspect ratio of device to %d:%d.\n", w, h);
> +
> + ((int*)data)[0] = w;
> + ((int*)data)[1] = h;
> + XChangeDeviceProperty(dpy, dev, aspect_prop, type, format,
> + PropModeReplace, (unsigned char*)data, nitems);
> +
> + XFlush(dpy);
> + free(data);
> +
> + return True;
> +}
> +
> +/**
> + * 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
> + * in modifying the transformation matrix, it returns 'true'.
> + */
> +static Bool _set_matrix_prop(Display *dpy, XDevice *dev, const float
> fmatrix[9])
> {
> Atom matrix_prop = XInternAtom(dpy, "Coordinate Transformation Matrix",
> True);
> Atom type;
> @@ -2049,7 +2103,7 @@ static void _set_matrix_prop(Display *dpy, XDevice
> *dev, const float fmatrix[9])
> if (!matrix_prop)
> {
> fprintf(stderr, "Server does not support transformation\n");
> - return;
> + return False;
> }
>
> /* XI1 expects 32 bit properties (including float) as long,
> @@ -2065,21 +2119,24 @@ static void _set_matrix_prop(Display *dpy, XDevice
> *dev, const float fmatrix[9])
> {
> fprintf(stderr, "Property for '%s' has unexpected type - this
> is a bug.\n",
> "Coordinate Transformation Matrix");
> - return;
> + return False;
> }
>
> XChangeDeviceProperty(dpy, dev, matrix_prop, type, format,
> PropModeReplace, (unsigned char*)matrix, 9);
> XFree(data);
> XFlush(dpy);
> +
> + return True;
> }
>
> /**
> * Adjust the transformation matrix based on a user-defined area.
> * This function will attempt to map the given pointer to an arbitrary
> - * rectangular portion of the desktop.
> + * rectangular portion of the desktop. If this function succeeds in
> + * modifying the transformation matrix, it returns 'true'.
> */
> -static void set_output_area(Display *dpy, XDevice *dev,
> +static Bool set_output_area(Display *dpy, XDevice *dev,
> int offset_x, int offset_y,
> int output_width, int output_height)
> {
> @@ -2110,15 +2167,17 @@ static void set_output_area(Display *dpy, XDevice
> *dev,
> 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);
> + return _set_matrix_prop(dpy, dev, matrix);
> }
>
> +
> /**
> * Adjust the transformation matrix based on RandR settings. This function
> * will attempt to map the given device to the output with the given RandR
> - * output name.
> + * output name. If this function succeeds in modifying the transformation
> + * matrix, it returns 'true'.
> */
> -static void set_output_xrandr(Display *dpy, XDevice *dev, char *output_name)
> +static Bool set_output_xrandr(Display *dpy, XDevice *dev, char *output_name)
> {
> int i, found = 0;
> int x, y, width, height;
> @@ -2158,33 +2217,38 @@ static void set_output_xrandr(Display *dpy, XDevice
> *dev, char *output_name)
> if (found)
> {
> TRACE("Setting CRTC %s\n", output_name);
> - set_output_area(dpy, dev, x, y, width, height);
> + return set_output_area(dpy, dev, x, y, width, height);
> } else
> + {
> printf("Unable to find output '%s'. "
> "Output may not be connected.\n", output_name);
>
> + return False;
> + }
> }
>
> /**
> * Adjust the transformation matrix based on the Xinerama settings. This
> * function will attempt to map the given device to the specified Xinerama
> - * head number.
> + * head number. 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, we need to rely on Xinerama. Besides,
> * libXNVCtrl isn't available on RHEL, so we'd have to do it through
> * Xinerama there anyway.
> */
> -static void set_output_xinerama(Display *dpy, XDevice *dev, int head)
> +static Bool set_output_xinerama(Display *dpy, XDevice *dev, int head)
> {
> int event, error;
> XineramaScreenInfo *screens;
> int nscreens;
> + Bool success = False;
>
> if (!XineramaQueryExtension(dpy, &event, &error))
> {
> fprintf(stderr, "Unable to set screen mapping. Xinerama
> extension not found\n");
> - return;
> + return success;
> }
>
> screens = XineramaQueryScreens(dpy, &nscreens);
> @@ -2202,12 +2266,13 @@ static void set_output_xinerama(Display *dpy, XDevice
> *dev, int head)
>
> TRACE("Setting xinerama head %d\n", head);
>
> - set_output_area(dpy, dev,
> + success = set_output_area(dpy, dev,
> screens[head].x_org, screens[head].y_org,
> screens[head].width, screens[head].height);
>
> out:
> XFree(screens);
> + return success;
> }
>
> /**
> @@ -2215,12 +2280,12 @@ out:
> * This function will attempt to map the given device to the entire
> * desktop.
> */
> -static void set_output_desktop(Display *dpy, XDevice *dev)
> +static Bool 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);
> + return set_output_area(dpy, dev, 0, 0, display_width, display_height);
> }
>
> /**
> @@ -2230,7 +2295,7 @@ static void set_output_desktop(Display *dpy, XDevice
> *dev)
> * 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)
> +static Bool set_output_next(Display *dpy, XDevice *dev)
> {
> XineramaScreenInfo *screens;
> int event, error, nscreens, head;
> @@ -2238,12 +2303,12 @@ static void set_output_next(Display *dpy, XDevice
> *dev)
> Bool success = False;
>
> if (!get_mapped_area(dpy, dev, &width, &height, &x_org, &y_org))
> - return;
> + return success;
>
> if (!XineramaQueryExtension(dpy, &event, &error))
> {
> fprintf(stderr, "Unable to get screen mapping. Xinerama
> extension not found\n");
> - return;
> + return success;
> }
>
> screens = XineramaQueryScreens(dpy, &nscreens);
> @@ -2260,30 +2325,43 @@ static void set_output_next(Display *dpy, XDevice
> *dev)
> 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);
> + success = set_output_xinerama(dpy, dev, head+1);
> else
> - set_output_desktop(dpy, dev);
> + success = set_output_desktop(dpy, dev);
> +
> + if (!success)
> + goto out;
> }
> }
>
> if (!success)
> - set_output_xinerama(dpy, dev, 0);
> + success = set_output_xinerama(dpy, dev, 0);
>
> out:
> XFree(screens);
> + return success;
> }
>
> static void set_output(Display *dpy, XDevice *dev, param_t *param, int argc,
> char **argv)
> {
> int tmp_int[2];
> unsigned int tmp_uint[2];
> + Bool success = False;
>
> - 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;
> }
> @@ -2291,28 +2369,34 @@ static void set_output(Display *dpy, XDevice *dev,
> param_t *param, int argc, cha
> if (MaskIsSet(XParseGeometry(argv[0], &tmp_int[0], &tmp_int[1],
> &tmp_uint[0], &tmp_uint[1]),
> XValue|YValue|WidthValue|HeightValue))
> {
> - set_output_area(dpy, dev, tmp_int[0], tmp_int[1], tmp_uint[0],
> tmp_uint[1]);
> + success = set_output_area(dpy, dev, tmp_int[0], tmp_int[1],
> tmp_uint[0], tmp_uint[1]);
> }
> else if (strcasecmp(argv[0], "next") == 0)
> {
> - set_output_next(dpy, dev);
> + success = set_output_next(dpy, dev);
> }
> else if (strcasecmp(argv[0], "desktop") == 0)
> {
> - set_output_desktop(dpy, dev);
> + success = set_output_desktop(dpy, dev);
> }
> else if (!need_xinerama(dpy))
> {
> - set_output_xrandr(dpy, dev, argv[0]);
> + success = set_output_xrandr(dpy, dev, argv[0]);
> }
> else if (convert_value_from_user(param, argv[0], &tmp_int[0]))
> {
> - set_output_xinerama(dpy, dev, tmp_int[0]);
> + success = set_output_xinerama(dpy, dev, tmp_int[0]);
> }
> else
> {
> fprintf(stderr, "Unable to find an output '%s'.\n", argv[0]);
> }
> +
> + if (!success)
> + return;
> +
> + Bool do_match = argc > 1 && strcasecmp(argv[1], "KeepShape") == 0;
declarations at the top please.
this seems at odds with the man page, which requires it to be "true".
Cheers,
Peter
> + _update_aspect(dpy, dev, do_match);
> }
>
>
> --
> 1.7.6
------------------------------------------------------------------------------
Doing More with Less: The Next Generation Virtual Desktop
What are the key obstacles that have prevented many mid-market businesses
from deploying virtual desktops? How do next-generation virtual desktops
provide companies an easier-to-deploy, easier-to-manage and more affordable
virtual desktop model.http://www.accelacomm.com/jaw/sfnl/114/51426474/
_______________________________________________
Linuxwacom-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel