dix: add DIX API to create touchpoints
The DIX touchpoints are the ones used for event processing. Co-authored-by: Daniel Stone <daniel@fooishbar.org> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Chase Douglas <chase.douglas@canonical.com>
This commit is contained in:
parent
7f8127d203
commit
5c63dc6dbc
123
dix/touch.c
123
dix/touch.c
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "inputstr.h"
|
#include "inputstr.h"
|
||||||
#include "scrnintstr.h"
|
#include "scrnintstr.h"
|
||||||
|
#include "dixgrabs.h"
|
||||||
|
|
||||||
#include "eventstr.h"
|
#include "eventstr.h"
|
||||||
#include "exevents.h"
|
#include "exevents.h"
|
||||||
|
@ -262,6 +263,9 @@ TouchFreeTouchPoint(DeviceIntPtr device, int index)
|
||||||
return;
|
return;
|
||||||
ti = &device->touch->touches[index];
|
ti = &device->touch->touches[index];
|
||||||
|
|
||||||
|
if (ti->active)
|
||||||
|
TouchEndTouch(device, ti);
|
||||||
|
|
||||||
valuator_mask_free(&ti->valuators);
|
valuator_mask_free(&ti->valuators);
|
||||||
free(ti->sprite.spriteTrace);
|
free(ti->sprite.spriteTrace);
|
||||||
ti->sprite.spriteTrace = NULL;
|
ti->sprite.spriteTrace = NULL;
|
||||||
|
@ -273,4 +277,123 @@ TouchFreeTouchPoint(DeviceIntPtr device, int index)
|
||||||
ti->history_elements = 0;
|
ti->history_elements = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a client-facing ID (e.g. DeviceEvent::detail.touch), find the
|
||||||
|
* associated TouchPointInfoRec.
|
||||||
|
*/
|
||||||
|
TouchPointInfoPtr
|
||||||
|
TouchFindByClientID(DeviceIntPtr dev, uint32_t client_id)
|
||||||
|
{
|
||||||
|
TouchClassPtr t = dev->touch;
|
||||||
|
TouchPointInfoPtr ti;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!t)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < t->num_touches; i++)
|
||||||
|
{
|
||||||
|
ti = &t->touches[i];
|
||||||
|
if (ti->active && ti->client_id == client_id)
|
||||||
|
return ti;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a unique ID for a touchpoint, create a touchpoint record in the
|
||||||
|
* server.
|
||||||
|
*
|
||||||
|
* Returns NULL on failure (i.e. if another touch with that ID is already active,
|
||||||
|
* allocation failure).
|
||||||
|
*/
|
||||||
|
TouchPointInfoPtr
|
||||||
|
TouchBeginTouch(DeviceIntPtr dev, int sourceid, uint32_t touchid,
|
||||||
|
Bool emulate_pointer)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
TouchClassPtr t = dev->touch;
|
||||||
|
TouchPointInfoPtr ti;
|
||||||
|
void *tmp;
|
||||||
|
|
||||||
|
if (!t)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Look for another active touchpoint with the same client ID. It's
|
||||||
|
* technically legitimate for a touchpoint to still exist with the same
|
||||||
|
* ID but only once the 32 bits wrap over and you've used up 4 billion
|
||||||
|
* touch ids without lifting that one finger off once. In which case
|
||||||
|
* you deserve a medal or something, but not error handling code. */
|
||||||
|
if (TouchFindByClientID(dev, touchid))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
try_find_touch:
|
||||||
|
for (i = 0; i < t->num_touches; i++)
|
||||||
|
{
|
||||||
|
ti = &t->touches[i];
|
||||||
|
if (!ti->active) {
|
||||||
|
ti->active = TRUE;
|
||||||
|
ti->client_id = touchid;
|
||||||
|
ti->sourceid = sourceid;
|
||||||
|
ti->emulate_pointer = emulate_pointer;
|
||||||
|
return ti;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we get here, then we've run out of touches: enlarge dev->touch and
|
||||||
|
* try again. */
|
||||||
|
tmp = realloc(t->touches, (t->num_touches + 1) * sizeof(*ti));
|
||||||
|
if (tmp)
|
||||||
|
{
|
||||||
|
t->touches = tmp;
|
||||||
|
t->num_touches++;
|
||||||
|
if (TouchInitTouchPoint(t, dev->valuator, t->num_touches - 1))
|
||||||
|
goto try_find_touch;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Releases a touchpoint for use: this must only be called after all events
|
||||||
|
* related to that touchpoint have been sent and finalised. Called from
|
||||||
|
* ProcessTouchEvent and friends. Not by you.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
TouchEndTouch(DeviceIntPtr dev, TouchPointInfoPtr ti)
|
||||||
|
{
|
||||||
|
if (ti->emulate_pointer)
|
||||||
|
{
|
||||||
|
GrabPtr grab;
|
||||||
|
DeviceEvent ev;
|
||||||
|
memset(&ev, 0, sizeof(ev));
|
||||||
|
ev.type = ET_TouchEnd;
|
||||||
|
ev.detail.button = 1;
|
||||||
|
ev.touchid = ti->client_id;
|
||||||
|
ev.flags = TOUCH_POINTER_EMULATED|TOUCH_END;
|
||||||
|
UpdateDeviceState(dev, &ev);
|
||||||
|
|
||||||
|
if ((grab = dev->deviceGrab.grab))
|
||||||
|
{
|
||||||
|
if (dev->deviceGrab.fromPassiveGrab &&
|
||||||
|
!dev->button->buttonsDown &&
|
||||||
|
!dev->touch->buttonsDown &&
|
||||||
|
GrabIsPointerGrab(grab))
|
||||||
|
(*dev->deviceGrab.DeactivateGrab)(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ti->active = FALSE;
|
||||||
|
ti->pending_finish = FALSE;
|
||||||
|
ti->sprite.spriteTraceGood = 0;
|
||||||
|
free(ti->listeners);
|
||||||
|
ti->listeners = NULL;
|
||||||
|
ti->num_listeners = 0;
|
||||||
|
ti->num_grabs = 0;
|
||||||
|
ti->client_id = 0;
|
||||||
|
|
||||||
|
valuator_mask_zero(ti->valuators);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -594,6 +594,11 @@ extern DDXTouchPointInfoPtr TouchFindByDDXID(DeviceIntPtr dev,
|
||||||
Bool create);
|
Bool create);
|
||||||
extern Bool TouchInitTouchPoint(TouchClassPtr touch, ValuatorClassPtr v, int index);
|
extern Bool TouchInitTouchPoint(TouchClassPtr touch, ValuatorClassPtr v, int index);
|
||||||
extern void TouchFreeTouchPoint(DeviceIntPtr dev, int index);
|
extern void TouchFreeTouchPoint(DeviceIntPtr dev, int index);
|
||||||
|
extern TouchPointInfoPtr TouchBeginTouch(DeviceIntPtr dev, int sourceid,
|
||||||
|
uint32_t touchid, Bool emulate_pointer);
|
||||||
|
extern TouchPointInfoPtr TouchFindByClientID(DeviceIntPtr dev,
|
||||||
|
uint32_t client_id);
|
||||||
|
extern void TouchEndTouch(DeviceIntPtr dev, TouchPointInfoPtr ti);
|
||||||
|
|
||||||
/* misc event helpers */
|
/* misc event helpers */
|
||||||
extern Mask GetEventMask(DeviceIntPtr dev, xEvent* ev, InputClientsPtr clients);
|
extern Mask GetEventMask(DeviceIntPtr dev, xEvent* ev, InputClientsPtr clients);
|
||||||
|
|
70
test/touch.c
70
test/touch.c
|
@ -28,6 +28,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "inputstr.h"
|
#include "inputstr.h"
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
|
#include "scrnintstr.h"
|
||||||
|
|
||||||
static void touch_grow_queue(void)
|
static void touch_grow_queue(void)
|
||||||
{
|
{
|
||||||
|
@ -190,11 +191,80 @@ static void touch_begin_ddxtouch(void)
|
||||||
last_client_id = ti->client_id;
|
last_client_id = ti->client_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void touch_begin_touch(void)
|
||||||
|
{
|
||||||
|
DeviceIntRec dev;
|
||||||
|
TouchClassRec touch;
|
||||||
|
ValuatorClassRec val;
|
||||||
|
TouchPointInfoPtr ti;
|
||||||
|
int touchid = 12434;
|
||||||
|
int sourceid = 23;
|
||||||
|
SpriteInfoRec sprite;
|
||||||
|
ScreenRec screen;
|
||||||
|
|
||||||
|
screenInfo.screens[0] = &screen;
|
||||||
|
|
||||||
|
memset(&dev, 0, sizeof(dev));
|
||||||
|
dev.id = 2;
|
||||||
|
|
||||||
|
memset(&sprite, 0, sizeof(sprite));
|
||||||
|
dev.spriteInfo = &sprite;
|
||||||
|
|
||||||
|
memset(&touch, 0, sizeof(touch));
|
||||||
|
touch.num_touches = 0;
|
||||||
|
|
||||||
|
memset(&val, 0, sizeof(val));
|
||||||
|
dev.valuator = &val;
|
||||||
|
val.numAxes = 2;
|
||||||
|
|
||||||
|
ti = TouchBeginTouch(&dev, sourceid, touchid, TRUE);
|
||||||
|
assert(!ti);
|
||||||
|
|
||||||
|
dev.touch = &touch;
|
||||||
|
ti = TouchBeginTouch(&dev, sourceid, touchid, TRUE);
|
||||||
|
assert(ti);
|
||||||
|
assert(ti->client_id == touchid);
|
||||||
|
assert(ti->active);
|
||||||
|
assert(ti->sourceid == sourceid);
|
||||||
|
assert(ti->emulate_pointer);
|
||||||
|
|
||||||
|
assert(touch.num_touches == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void touch_init(void)
|
||||||
|
{
|
||||||
|
DeviceIntRec dev;
|
||||||
|
Atom labels[2] = {0};
|
||||||
|
int rc;
|
||||||
|
SpriteInfoRec sprite;
|
||||||
|
ScreenRec screen;
|
||||||
|
|
||||||
|
screenInfo.screens[0] = &screen;
|
||||||
|
|
||||||
|
memset(&dev, 0, sizeof(dev));
|
||||||
|
|
||||||
|
memset(&sprite, 0, sizeof(sprite));
|
||||||
|
dev.spriteInfo = &sprite;
|
||||||
|
|
||||||
|
InitAtoms();
|
||||||
|
rc = InitTouchClassDeviceStruct(&dev, 1, XIDirectTouch, 2);
|
||||||
|
assert(rc == FALSE);
|
||||||
|
|
||||||
|
InitValuatorClassDeviceStruct(&dev, 2, labels, 10, Absolute);
|
||||||
|
rc = InitTouchClassDeviceStruct(&dev, 1, XIDirectTouch, 2);
|
||||||
|
assert(rc == TRUE);
|
||||||
|
assert(dev.touch);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
touch_grow_queue();
|
touch_grow_queue();
|
||||||
touch_find_ddxid();
|
touch_find_ddxid();
|
||||||
touch_begin_ddxtouch();
|
touch_begin_ddxtouch();
|
||||||
|
touch_init();
|
||||||
|
touch_begin_touch();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue