summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Xi/exevents.c61
-rw-r--r--Xi/xiquerydevice.c39
-rw-r--r--Xi/xiquerydevice.h1
-rw-r--r--dix/Makefile.am1
-rw-r--r--dix/devices.c87
-rw-r--r--dix/touch.c94
-rw-r--r--include/input.h27
-rw-r--r--include/inputstr.h53
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. */