diff options
-rw-r--r-- | Xi/xiproperty.c | 4 | ||||
-rw-r--r-- | dix/devices.c | 71 | ||||
-rw-r--r-- | dix/getevents.c | 19 | ||||
-rw-r--r-- | include/inputstr.h | 4 | ||||
-rw-r--r-- | include/xserver-properties.h | 7 |
5 files changed, 104 insertions, 1 deletions
diff --git a/Xi/xiproperty.c b/Xi/xiproperty.c index 8bb19624c..b4d939f99 100644 --- a/Xi/xiproperty.c +++ b/Xi/xiproperty.c @@ -177,7 +177,9 @@ static struct dev_properties {0, BTN_LABEL_PROP_BTN_TOOL_TRIPLETAP}, {0, BTN_LABEL_PROP_BTN_GEAR_DOWN}, - {0, BTN_LABEL_PROP_BTN_GEAR_UP} + {0, BTN_LABEL_PROP_BTN_GEAR_UP}, + + {0, XI_PROP_TRANSFORM} }; static long XIPropHandlerID = 1; diff --git a/dix/devices.c b/dix/devices.c index cf23bc6d0..b0b465326 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -77,6 +77,8 @@ SOFTWARE. #include <X11/extensions/XI.h> #include <X11/extensions/XI2.h> #include <X11/extensions/XIproto.h> +#include <math.h> +#include <pixman.h> #include "exglobals.h" #include "exevents.h" #include "xiquerydevice.h" /* for SizeDeviceClasses */ @@ -91,6 +93,48 @@ SOFTWARE. static void RecalculateMasterButtons(DeviceIntPtr slave); +static void +DeviceSetTransform(DeviceIntPtr dev, float *transform) +{ + struct pixman_f_transform scale; + double sx, sy; + int x, y; + + /** + * calculate combined transformation matrix: + * + * M = InvScale * Transform * Scale + * + * So we can later transform points using M * p + * + * Where: + * Scale scales coordinates into 0..1 range + * Transform is the user supplied (affine) transform + * InvScale scales coordinates back up into their native range + */ + sx = dev->valuator->axes[0].max_value - dev->valuator->axes[0].min_value; + sy = dev->valuator->axes[1].max_value - dev->valuator->axes[1].min_value; + + /* invscale */ + pixman_f_transform_init_scale(&scale, sx, sy); + scale.m[0][2] = dev->valuator->axes[0].min_value; + scale.m[1][2] = dev->valuator->axes[1].min_value; + + /* transform */ + for (y=0; y<3; y++) + for (x=0; x<3; x++) + dev->transform.m[y][x] = *transform++; + + pixman_f_transform_multiply(&dev->transform, &scale, &dev->transform); + + /* scale */ + pixman_f_transform_init_scale(&scale, 1.0 / sx, 1.0 / sy); + scale.m[0][2] = -dev->valuator->axes[0].min_value / sx; + scale.m[1][2] = -dev->valuator->axes[1].min_value / sy; + + pixman_f_transform_multiply(&dev->transform, &dev->transform, &scale); +} + /** * DIX property handler. */ @@ -115,6 +159,21 @@ DeviceSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, else if (!(*((CARD8*)prop->data)) && dev->enabled) DisableDevice(dev, TRUE); } + } else if (property == XIGetKnownProperty(XI_PROP_TRANSFORM)) + { + float *f = (float*)prop->data; + int i; + + if (prop->format != 32 || prop->size != 9 || + prop->type != XIGetKnownProperty(XATOM_FLOAT)) + return BadValue; + + for (i=0; i<9; i++) + if (!isfinite(f[i])) + return BadValue; + + if (!checkonly) + DeviceSetTransform(dev, f); } return Success; @@ -183,6 +242,7 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart) int devid; char devind[MAXDEVICES]; BOOL enabled; + float transform[9]; /* Find next available id, 0 and 1 are reserved */ memset(devind, 0, sizeof(char)*MAXDEVICES); @@ -234,6 +294,17 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart) XA_INTEGER, 8, PropModeReplace, 1, &enabled, FALSE); XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_ENABLED), FALSE); + + /* unity matrix */ + memset(transform, 0, sizeof(transform)); + transform[0] = transform[4] = transform[8] = 1.0f; + + XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_TRANSFORM), + XIGetKnownProperty(XATOM_FLOAT), 32, + PropModeReplace, 9, transform, FALSE); + XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_TRANSFORM), + FALSE); + XIRegisterPropertyHandler(dev, DeviceSetProperty, NULL, NULL); return dev; diff --git a/dix/getevents.c b/dix/getevents.c index 62aaff981..eeef41448 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -33,6 +33,7 @@ #include <X11/X.h> #include <X11/keysym.h> #include <X11/Xproto.h> +#include <math.h> #include "misc.h" #include "resource.h" @@ -56,6 +57,7 @@ #include <X11/extensions/XI.h> #include <X11/extensions/XIproto.h> +#include <pixman.h> #include "exglobals.h" #include "exevents.h" #include "exglobals.h" @@ -997,6 +999,22 @@ FreeEventList(EventListPtr list, int num_events) free(list); } +static void +transformAbsolute(DeviceIntPtr dev, int v[MAX_VALUATORS]) +{ + struct pixman_f_vector p; + + /* p' = M * p in homogeneous coordinates */ + p.v[0] = v[0]; + p.v[1] = v[1]; + p.v[2] = 1.0; + + pixman_f_transform_point(&dev->transform, &p); + + v[0] = lround(p.v[0]); + v[1] = lround(p.v[1]); +} + /** * Generate a series of xEvents (filled into the EventList) representing * pointer motion, or button presses. Xi and XKB-aware. @@ -1068,6 +1086,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, scr->height); } + transformAbsolute(pDev, valuators); moveAbsolute(pDev, &x, &y, first_valuator, num_valuators, valuators); } else { if (flags & POINTER_ACCELERATE) { diff --git a/include/inputstr.h b/include/inputstr.h index c5b9ff71a..a83e863be 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -49,6 +49,7 @@ SOFTWARE. #ifndef INPUTSTRUCT_H #define INPUTSTRUCT_H +#include <pixman.h> #include "input.h" #include "window.h" #include "dixstruct.h" @@ -550,6 +551,9 @@ typedef struct _DeviceIntRec { XIPropertyPtr properties; XIPropertyHandlerPtr handlers; /* NULL-terminated */ } properties; + + /* coordinate transformation matrix for absolute input devices */ + struct pixman_f_transform transform; } DeviceIntRec; typedef struct { diff --git a/include/xserver-properties.h b/include/xserver-properties.h index 30e8efb68..c6259aee1 100644 --- a/include/xserver-properties.h +++ b/include/xserver-properties.h @@ -35,6 +35,13 @@ /* BOOL. If present, device is a virtual XTEST device */ #define XI_PROP_XTEST_DEVICE "XTEST Device" +/* Coordinate transformation matrix for absolute input devices + * FLOAT, 9 values in row-major order, coordinates in 0..1 range: + * [c0 c1 c2] [x] + * [c3 c4 c5] * [y] + * [c6 c7 c8] [1] */ +#define XI_PROP_TRANSFORM "Coordinate Transformation Matrix" + /* Pointer acceleration properties */ /* INTEGER of any format */ #define ACCEL_PROP_PROFILE_NUMBER "Device Accel Profile" |