diff options
-rw-r--r-- | Xi/exevents.c | 61 | ||||
-rw-r--r-- | Xi/xiquerydevice.c | 39 | ||||
-rw-r--r-- | Xi/xiquerydevice.h | 1 | ||||
-rw-r--r-- | dix/Makefile.am | 1 | ||||
-rw-r--r-- | dix/devices.c | 87 | ||||
-rw-r--r-- | dix/touch.c | 94 | ||||
-rw-r--r-- | include/input.h | 27 | ||||
-rw-r--r-- | include/inputstr.h | 53 |
8 files changed, 362 insertions, 1 deletions
diff --git a/Xi/exevents.c b/Xi/exevents.c index 2db605302..ffb48d1c7 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -44,6 +44,32 @@ SOFTWARE. ********************************************************/ +/* + * Copyright © 2010 Collabora Ltd. + * Copyright © 2011 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Daniel Stone <daniel@fooishbar.org> + */ + /******************************************************************** * * Routines to register and initialize extension input devices. @@ -641,6 +667,41 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to) classes->proximity = to->proximity; to->proximity = NULL; } + + if (from->touch) + { + TouchPointInfoPtr tmp; + if (!to->touch) + { + classes = to->unused_classes; + to->touch = classes->touch; + if (!to->touch) + { + int i; + to->touch = calloc(1, sizeof(TouchClassRec)); + if (!to->touch) + FatalError("[Xi] no memory for class shift.\n"); + to->touch->num_touches = from->touch->num_touches; + to->touch->touches = calloc(to->touch->num_touches, + sizeof(TouchPointInfoRec)); + for (i = 0; i < to->touch->num_touches; i++) + TouchInitTouchPoint(to->touch, to->valuator, i); + if (!to->touch) + FatalError("[Xi] no memory for class shift.\n"); + } else + classes->touch = NULL; + } + tmp = to->touch->touches; + memcpy(to->touch, from->touch, sizeof(TouchClassRec)); + to->touch->touches = tmp; + to->touch->sourceid = from->id; + } else if (to->touch) + { + ClassesPtr classes; + classes = to->unused_classes; + classes->touch = to->touch; + to->touch = NULL; + } } /** diff --git a/Xi/xiquerydevice.c b/Xi/xiquerydevice.c index 5f543f620..0879080ad 100644 --- a/Xi/xiquerydevice.c +++ b/Xi/xiquerydevice.c @@ -240,6 +240,8 @@ SizeDeviceClasses(DeviceIntPtr dev) } } + if (dev->touch) + len += sizeof(xXITouchInfo); return len; } @@ -427,6 +429,31 @@ SwapScrollInfo(DeviceIntPtr dev, xXIScrollInfo* info) swapl(&info->increment.frac); } +/** + * List multitouch information + * + * @return The number of bytes written into info. + */ +int +ListTouchInfo(DeviceIntPtr dev, xXITouchInfo *touch) +{ + touch->type = XITouchClass; + touch->length = sizeof(xXITouchInfo) >> 2; + touch->sourceid = touch->sourceid; + touch->mode = dev->touch->mode; + touch->num_touches = dev->touch->num_touches; + + return touch->length << 2; +} + +static void +SwapTouchInfo(DeviceIntPtr dev, xXITouchInfo* touch) +{ + swaps(&touch->type); + swaps(&touch->length); + swaps(&touch->sourceid); +} + int GetDeviceUse(DeviceIntPtr dev, uint16_t *attachment) { DeviceIntPtr master = GetMaster(dev, MASTER_ATTACHED); @@ -525,6 +552,14 @@ ListDeviceClasses(ClientPtr client, DeviceIntPtr dev, total_len += len; } + if (dev->touch) + { + (*nclasses)++; + len = ListTouchInfo(dev, (xXITouchInfo*)any); + any += len; + total_len += len; + } + return total_len; } @@ -554,6 +589,10 @@ SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info) case XIScrollClass: SwapScrollInfo(dev, (xXIScrollInfo*)any); break; + case XITouchClass: + SwapTouchInfo(dev, (xXITouchInfo*)any); + break; + } any += len * 4; diff --git a/Xi/xiquerydevice.h b/Xi/xiquerydevice.h index 9db6aa293..632c42eeb 100644 --- a/Xi/xiquerydevice.h +++ b/Xi/xiquerydevice.h @@ -45,4 +45,5 @@ int ListKeyInfo(DeviceIntPtr dev, xXIKeyInfo* info); int ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info, int axisnumber, Bool reportState); int ListScrollInfo(DeviceIntPtr dev, xXIScrollInfo* info, int axisnumber); +int ListTouchInfo(DeviceIntPtr dev, xXITouchInfo* info); #endif /* QUERYDEV_H */ diff --git a/dix/Makefile.am b/dix/Makefile.am index f5af619e3..b7358aa72 100644 --- a/dix/Makefile.am +++ b/dix/Makefile.am @@ -39,6 +39,7 @@ libdix_la_SOURCES = \ swaprep.c \ swapreq.c \ tables.c \ + touch.c \ window.c EXTRA_DIST = buildatoms BuiltInAtoms Xserver.d Xserver-dtrace.h.in diff --git a/dix/devices.c b/dix/devices.c index 9ca8fe055..7478ad67a 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -263,6 +263,7 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart) return (DeviceIntPtr)NULL; dev->last.scroll = NULL; + dev->last.touches = NULL; dev->id = devid; dev->public.processInputProc = ProcessOtherEvent; dev->public.realInputProc = ProcessOtherEvent; @@ -761,6 +762,21 @@ FreeDeviceClass(int type, pointer *class) free((*v)); break; } + case XITouchClass: + { + TouchClassPtr *t = (TouchClassPtr*)class; + int i; + + for (i = 0; i < (*t)->num_touches; i++) + { + free((*t)->touches[i].sprite.spriteTrace); + free((*t)->touches[i].listeners); + free((*t)->touches[i].valuators); + } + + free((*t)); + break; + } case FocusClass: { FocusClassPtr *f = (FocusClassPtr*)class; @@ -869,6 +885,7 @@ FreeAllDeviceClasses(ClassesPtr classes) FreeDeviceClass(KeyClass, (pointer)&classes->key); FreeDeviceClass(ValuatorClass, (pointer)&classes->valuator); + FreeDeviceClass(XITouchClass, (pointer)&classes->touch); FreeDeviceClass(ButtonClass, (pointer)&classes->button); FreeDeviceClass(FocusClass, (pointer)&classes->focus); FreeDeviceClass(ProximityClass, (pointer)&classes->proximity); @@ -948,6 +965,9 @@ CloseDevice(DeviceIntPtr dev) free(dev->deviceGrab.sync.event); free(dev->config_info); /* Allocated in xf86ActivateDevice. */ free(dev->last.scroll); + for (j = 0; j < dev->last.num_touches; j++) + free(dev->last.touches[j].valuators); + free(dev->last.touches); dev->config_info = NULL; dixFreeObjectWithPrivates(dev, PRIVATE_DEVICE); } @@ -1419,7 +1439,6 @@ InitPtrFeedbackClassDeviceStruct(DeviceIntPtr dev, PtrCtrlProcPtr controlProc) return TRUE; } - static LedCtrl defaultLedControl = { DEFAULT_LEDS, DEFAULT_LEDS_MASK, 0}; @@ -1542,6 +1561,72 @@ InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, Atom* btn_ InitPtrFeedbackClassDeviceStruct(dev, controlProc)); } +/** + * Sets up multitouch capabilities on @device. + * + * @max_touches The maximum number of simultaneous touches, or 0 for unlimited. + * @mode The mode of the touch device (XIDirectTouch or XIDependentTouch). + * @num_axes The number of touch valuator axes. + */ +Bool +InitTouchClassDeviceStruct(DeviceIntPtr device, unsigned int max_touches, + unsigned int mode, unsigned int num_axes) +{ + TouchClassPtr touch; + int i; + + if (device->touch || !device->valuator) + return FALSE; + + /* Check the mode is valid, and at least X and Y axes. */ + if (mode != XIDirectTouch && mode != XIDependentTouch) + return FALSE; + if (num_axes < 2) + return FALSE; + + if (num_axes > MAX_VALUATORS) + { + LogMessage(X_WARNING, + "Device '%s' has %d touch axes, only using first %d.\n", + device->name, num_axes, MAX_VALUATORS); + num_axes = MAX_VALUATORS; + } + + touch = calloc(1, sizeof(*touch)); + if (!touch) + return FALSE; + + touch->max_touches = max_touches; + if (max_touches == 0) + max_touches = 5; /* arbitrary number plucked out of the air */ + touch->touches = calloc(max_touches, sizeof(*touch->touches)); + if (!touch->touches) + goto err; + touch->num_touches = max_touches; + for (i = 0; i < max_touches; i++) + TouchInitTouchPoint(touch, device->valuator, i); + + touch->mode = mode; + touch->sourceid = device->id; + + device->touch = touch; + device->last.touches = calloc(max_touches, sizeof(*device->last.touches)); + device->last.num_touches = touch->num_touches; + for (i = 0; i < touch->num_touches; i++) + TouchInitDDXTouchPoint(device, &device->last.touches[i]); + + return TRUE; + +err: + for (i = 0; i < touch->num_touches; i++) + TouchFreeTouchPoint(device, i); + + free(touch->touches); + free(touch); + + return FALSE; +} + /* * Check if the given buffer contains elements between low (inclusive) and * high (inclusive) only. diff --git a/dix/touch.c b/dix/touch.c new file mode 100644 index 000000000..9fa2f3c8d --- /dev/null +++ b/dix/touch.c @@ -0,0 +1,94 @@ +/* + * Copyright © 2011 Collabra Ltd. + * Copyright © 2011 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Daniel Stone <daniel@fooishbar.org> + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "inputstr.h" +#include "scrnintstr.h" + + +void +TouchInitDDXTouchPoint(DeviceIntPtr dev, DDXTouchPointInfoPtr ddxtouch) +{ + memset(ddxtouch, 0, sizeof(*ddxtouch)); + ddxtouch->valuators = valuator_mask_new(dev->valuator->numAxes); +} + + +Bool +TouchInitTouchPoint(TouchClassPtr t, ValuatorClassPtr v, int index) +{ + TouchPointInfoPtr ti; + + if (index >= t->num_touches) + return FALSE; + ti = &t->touches[index]; + + memset(ti, 0, sizeof(*ti)); + + ti->valuators = valuator_mask_new(v->numAxes); + if (!ti->valuators) + return FALSE; + + ti->sprite.spriteTrace = calloc(32, sizeof(*ti->sprite.spriteTrace)); + if (!ti->sprite.spriteTrace) + { + valuator_mask_free(&ti->valuators); + return FALSE; + } + ti->sprite.spriteTraceSize = 32; + ti->sprite.spriteTrace[0] = screenInfo.screens[0]->root; + ti->sprite.hot.pScreen = screenInfo.screens[0]; + ti->sprite.hotPhys.pScreen = screenInfo.screens[0]; + + ti->client_id = -1; + + return TRUE; +} + +void +TouchFreeTouchPoint(DeviceIntPtr device, int index) +{ + TouchPointInfoPtr ti; + + if (!device->touch || index >= device->touch->num_touches) + return; + ti = &device->touch->touches[index]; + + valuator_mask_free(&ti->valuators); + free(ti->sprite.spriteTrace); + ti->sprite.spriteTrace = NULL; + free(ti->listeners); + ti->listeners = NULL; + free(ti->history); + ti->history = NULL; + ti->history_size = 0; + ti->history_elements = 0; +} + + diff --git a/include/input.h b/include/input.h index a94ff942d..0d31edf75 100644 --- a/include/input.h +++ b/include/input.h @@ -124,6 +124,9 @@ typedef struct _DeviceIntRec *DeviceIntPtr; typedef struct _ValuatorClassRec *ValuatorClassPtr; typedef struct _ClassesRec *ClassesPtr; typedef struct _SpriteRec *SpritePtr; +typedef struct _TouchClassRec *TouchClassPtr; +typedef struct _TouchPointInfo *TouchPointInfoPtr; +typedef struct _DDXTouchPointInfo *DDXTouchPointInfoPtr; typedef union _GrabMask GrabMask; typedef struct _ValuatorMask ValuatorMask; @@ -324,6 +327,12 @@ extern _X_EXPORT Bool InitPointerAccelerationScheme( extern _X_EXPORT Bool InitFocusClassDeviceStruct( DeviceIntPtr /*device*/); +extern _X_EXPORT Bool InitTouchClassDeviceStruct( + DeviceIntPtr /*device*/, + unsigned int /*max_touches*/, + unsigned int /*mode*/, + unsigned int /*numAxes*/); + typedef void (*BellProcPtr)( int /*percent*/, DeviceIntPtr /*device*/, @@ -563,6 +572,24 @@ extern void SendDevicePresenceEvent(int deviceid, int type); extern _X_EXPORT InputAttributes *DuplicateInputAttributes(InputAttributes *attrs); extern _X_EXPORT void FreeInputAttributes(InputAttributes *attrs); +enum TouchListenerState{ + LISTENER_AWAITING_BEGIN = 0, /**< Waiting for a TouchBegin event */ + LISTENER_AWAITING_OWNER, /**< Waiting for a TouchOwnership event */ + LISTENER_IS_OWNER, /**< Is the current owner */ + LISTENER_HAS_END, /**< Has already received the end event */ +}; + +enum TouchListenerType { + LISTENER_GRAB, + LISTENER_POINTER_GRAB, + LISTENER_REGULAR, + LISTENER_POINTER_REGULAR, +}; + +extern void TouchInitDDXTouchPoint(DeviceIntPtr dev, DDXTouchPointInfoPtr ddxtouch); +extern Bool TouchInitTouchPoint(TouchClassPtr touch, ValuatorClassPtr v, int index); +extern void TouchFreeTouchPoint(DeviceIntPtr dev, int index); + /* misc event helpers */ extern Mask GetEventMask(DeviceIntPtr dev, xEvent* ev, InputClientsPtr clients); extern Mask GetEventFilter(DeviceIntPtr dev, xEvent *event); diff --git a/include/inputstr.h b/include/inputstr.h index e6847984b..9881c7e46 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -300,6 +300,55 @@ typedef struct _ValuatorClassRec { int v_scroll_axis; /* vert smooth-scrolling axis */ } ValuatorClassRec; +typedef struct _TouchPointInfo { + /* client_id must be first element, see GetTouchEvents */ + uint32_t client_id; /* touch ID as seen in client events */ + int sourceid; /* Source device's ID for this touchpoint */ + Bool active; /* whether or not the touch is active */ + Bool pending_finish; /* true if the touch is physically inactive + * but still owned by a grab */ + SpriteRec sprite; /* window trace for delivery */ + ValuatorMask *valuators; /* last recorded axis values */ + struct _TouchListener { + XID listener; /* grabs/event selection IDs receiving + * events for this touch */ + enum TouchListenerType type; + enum TouchListenerState state; + enum InputLevel level; /* matters only for emulating touches */ + } *listeners; + int num_listeners; + int num_grabs; /* number of open grabs on this touch + * which have not accepted or rejected */ + Bool emulate_pointer; + DeviceEvent *history; /* History of events on this touchpoint */ + size_t history_elements; /* Number of current elements in history */ + size_t history_size; /* Size of history in elements */ +} TouchPointInfoRec; + +typedef struct _TouchListener TouchListener; + +typedef struct _DDXTouchPointInfo { + /* client_id must be first element, see GetTouchEvents */ + uint32_t client_id; /* touch ID as seen in client events */ + Bool active; /* whether or not the touch is active */ + uint32_t ddx_id; /* touch ID given by the DDX */ + Bool emulate_pointer; + + ValuatorMask* valuators; /* last recorded axis values */ +} DDXTouchPointInfoRec; + +typedef struct _TouchClassRec { + int sourceid; + TouchPointInfoPtr touches; + unsigned short num_touches; /* number of allocated touches */ + unsigned short max_touches; /* maximum number of touches, may be 0 */ + CARD8 mode; /* ::XIDirectTouch, XIDependentTouch */ + /* for pointer-emulation */ + CARD8 buttonsDown; /* number of buttons down */ + unsigned short state; /* logical button state */ + Mask motionMask; +} TouchClassRec; + typedef struct _ButtonClassRec { int sourceid; CARD8 numButtons; @@ -383,6 +432,7 @@ typedef struct _LedFeedbackClassRec { typedef struct _ClassesRec { KeyClassPtr key; ValuatorClassPtr valuator; + TouchClassPtr touch; ButtonClassPtr button; FocusClassPtr focus; ProximityClassPtr proximity; @@ -510,6 +560,7 @@ typedef struct _DeviceIntRec { int id; KeyClassPtr key; ValuatorClassPtr valuator; + TouchClassPtr touch; ButtonClassPtr button; FocusClassPtr focus; ProximityClassPtr proximity; @@ -541,6 +592,8 @@ typedef struct _DeviceIntRec { int numValuators; DeviceIntPtr slave; ValuatorMask *scroll; + int num_touches; /* size of the touches array */ + DDXTouchPointInfoPtr touches; } last; /* Input device property handling. */ |