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

Reply via email to