On Wed, Sep 07, 2011 at 04:36:53PM -0700, Jason Gerecke wrote:
> At the moment, this helper is only capable of understanding the
> keyword "next". This will cause it to move to the next available
> output, with the order determined by the underlying list of heads.
>
> Its hoped this can be expanded to support other keywords, most
> notably "left" and "right", which would choose the correct head
> based on its relative position in space.
>
> Signed-off-by: Jason Gerecke <[email protected]>
> ---
> Changes from v2:
> * Corresponds to patch v2 6/9 (interim patches now gone)
>
> * 'get_next_output_area' and 'set_output_relative' joined into a
> singular 'set_output_next' since there's not likely to be any
> other type of relative movement offered in the near future
>
> * Introduce 'set_output_desktop' early (it'd show up in the next
> patch anyway, but is also useful here)
>
> * Numerous stylistic changes
>
> man/xsetwacom.man | 7 ++-
> tools/xsetwacom.c | 140
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 145 insertions(+), 2 deletions(-)
>
> diff --git a/man/xsetwacom.man b/man/xsetwacom.man
> index 84c91e9..edc97c4 100644
> --- a/man/xsetwacom.man
> +++ b/man/xsetwacom.man
> @@ -123,8 +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 proper XRandR support is included.
> +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.
>
> 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 f887064..298da44 100644
> --- a/tools/xsetwacom.c
> +++ b/tools/xsetwacom.c
> @@ -1958,6 +1958,76 @@ 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++)
> + {
> + if (i == 0)
> + *width = rint(display_width * data[i]);
> + else if (i == 2)
> + *x_org = rint(display_width * data[i]);
> + else if (i == 4)
> + *height = rint(display_height * data[i]);
> + else if (i == 5)
> + *y_org = rint(display_height * data[i]);
> + else if (i == 8)
> + {
> + if (data[i] != 1)
> + matrix_is_valid = False;
> + }
> + else if (data[i] != 0)
> + matrix_is_valid = False;
any reason you didn't use switch here? not that it matters much, but it's
nicer to read, I think.
> + }
> + 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);
> @@ -2132,6 +2202,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; 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);
break missing here.
Reviewed-by: Peter Hutterer <[email protected]> otherwise
Cheers,
Peter
> + }
> + }
> +
> + 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 tmp_int[2];
> @@ -2157,6 +2293,10 @@ static void set_output(Display *dpy, XDevice *dev,
> param_t *param, int argc, cha
> {
> 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);
> + }
> else if (!need_xinerama(dpy))
> {
> set_output_xrandr(dpy, dev, argv[0]);
> --
> 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