On Tue, Sep 20, 2011 at 03:54:26PM -0700, Jason Gerecke wrote:
> Adds a helper function for MapToOutput which determines which
> output the device is currently mapped to, and moves to the next
> available output. Repeatedly calling this function will result
> in the device being mapped to every available output (including
> the desktop as a whole) in turn.
> 
> Signed-off-by: Jason Gerecke <killert...@gmail.com>
> ---
> Changes from v3:
> 
>  * Corresponds to patch v3 4/7
>  * Updated commit message
>  * Changed from if/else-if to switch statement
>  * Exit loop as soon as matrix is determined invalid

Reviewed-by: Peter Hutterer <peter.hutte...@who-t.net>

Cheers,
  Peter
 
>  man/xsetwacom.man |    8 ++-
>  tools/xsetwacom.c |  137 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 142 insertions(+), 3 deletions(-)
> 
> diff --git a/man/xsetwacom.man b/man/xsetwacom.man
> index 9375e5b..10832ad 100644
> --- a/man/xsetwacom.man
> +++ b/man/xsetwacom.man
> @@ -123,9 +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 the driver supports XRandr 1.2 or
> -later.
> +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 the
> +driver supports XRandR 1.2 or later.
>  
>  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 dea6e99..c9c090c 100644
> --- a/tools/xsetwacom.c
> +++ b/tools/xsetwacom.c
> @@ -1955,6 +1955,75 @@ 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++)
> +     {
> +             switch (i) {
> +                     case 0: *width  = rint(display_width  * data[i]); break;
> +                     case 2: *x_org  = rint(display_width  * data[i]); break;
> +                     case 4: *height = rint(display_height * data[i]); break;
> +                     case 5: *y_org  = rint(display_height * data[i]); break;
> +                     case 8:
> +                             if (data[i] != 1)
> +                                     matrix_is_valid = False;
> +                             break;
> +                     default:
> +                             if (data[i] != 0)
> +                                     matrix_is_valid = False;
> +                             break;
> +             }
> +     }
> +     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);
> @@ -2129,6 +2198,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 && !success; 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);
> +             }
> +     }
> +
> +     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 head_no;
> @@ -2153,6 +2288,8 @@ static void set_output(Display *dpy, XDevice *dev, 
> param_t *param, int argc, cha
>  
>       if (MaskIsSet(flags, XValue|YValue|WidthValue|HeightValue))
>               set_output_area(dpy, dev, x, y, width, height);
> +     else if (strcasecmp(argv[0], "next") == 0)
> +             set_output_next(dpy, dev);
>       else if (!need_xinerama(dpy))
>               set_output_xrandr(dpy, dev, argv[0]);
>       else if  (convert_value_from_user(param, argv[0], &head_no))
> -- 
> 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