Commit f84703b5 authored by Keith Packard's avatar Keith Packard

dix: Reallocate touchpoint buffer at input event time [v2]

Now that input is threaded, malloc can be used at event time to resize
the touchpoint buffer as needed.x

v2: Remove "Need to grow the queue means dropping events."
    from comment as it no longer applies. (Peter Hutterer)
Signed-off-by: Keith Packard's avatarKeith Packard <keithp@keithp.com>
Reviewed-by: Peter Hutterer's avatarPeter Hutterer <peter.hutterer@who-t.net>
parent e2df803f
...@@ -42,9 +42,6 @@ ...@@ -42,9 +42,6 @@
#define TOUCH_HISTORY_SIZE 100 #define TOUCH_HISTORY_SIZE 100
/* If a touch queue resize is needed, the device id's bit is set. */
static unsigned char resize_waiting[(MAXDEVICES + 7) / 8];
/** /**
* Some documentation about touch points: * Some documentation about touch points:
* The driver submits touch events with it's own (unique) touch point ID. * The driver submits touch events with it's own (unique) touch point ID.
...@@ -74,47 +71,27 @@ static unsigned char resize_waiting[(MAXDEVICES + 7) / 8]; ...@@ -74,47 +71,27 @@ static unsigned char resize_waiting[(MAXDEVICES + 7) / 8];
* @return Always True. If we fail to grow we probably will topple over soon * @return Always True. If we fail to grow we probably will topple over soon
* anyway and re-executing this won't help. * anyway and re-executing this won't help.
*/ */
static Bool static Bool
TouchResizeQueue(ClientPtr client, void *closure) TouchResizeQueue(DeviceIntPtr dev)
{ {
int i; DDXTouchPointInfoPtr tmp;
size_t size;
input_lock();
/* first two ids are reserved */
for (i = 2; i < MAXDEVICES; i++) {
DeviceIntPtr dev;
DDXTouchPointInfoPtr tmp;
size_t size;
if (!BitIsOn(resize_waiting, i))
continue;
ClearBit(resize_waiting, i); /* Grow sufficiently so we don't need to do it often */
size = dev->last.num_touches + dev->last.num_touches / 2 + 1;
/* device may have disappeared by now */ tmp = reallocarray(dev->last.touches, size, sizeof(*dev->last.touches));
dixLookupDevice(&dev, i, serverClient, DixWriteAccess); if (tmp) {
if (!dev) int j;
continue;
/* Need to grow the queue means dropping events. Grow sufficiently so we
* don't need to do it often */
size = dev->last.num_touches + dev->last.num_touches / 2 + 1;
tmp = reallocarray(dev->last.touches, size, sizeof(*dev->last.touches));
if (tmp) {
int j;
dev->last.touches = tmp;
for (j = dev->last.num_touches; j < size; j++)
TouchInitDDXTouchPoint(dev, &dev->last.touches[j]);
dev->last.num_touches = size;
}
dev->last.touches = tmp;
for (j = dev->last.num_touches; j < size; j++)
TouchInitDDXTouchPoint(dev, &dev->last.touches[j]);
dev->last.num_touches = size;
return TRUE;
} }
input_unlock(); return FALSE;
return TRUE;
} }
/** /**
...@@ -172,14 +149,20 @@ TouchBeginDDXTouch(DeviceIntPtr dev, uint32_t ddx_id) ...@@ -172,14 +149,20 @@ TouchBeginDDXTouch(DeviceIntPtr dev, uint32_t ddx_id)
if (TouchFindByDDXID(dev, ddx_id, FALSE)) if (TouchFindByDDXID(dev, ddx_id, FALSE))
return NULL; return NULL;
for (i = 0; i < dev->last.num_touches; i++) { for (;;) {
/* Only emulate pointer events on the first touch */ for (i = 0; i < dev->last.num_touches; i++) {
if (dev->last.touches[i].active) /* Only emulate pointer events on the first touch */
emulate_pointer = FALSE; if (dev->last.touches[i].active)
else if (!ti) /* ti is now first non-active touch rec */ emulate_pointer = FALSE;
ti = &dev->last.touches[i]; else if (!ti) /* ti is now first non-active touch rec */
ti = &dev->last.touches[i];
if (!emulate_pointer && ti) if (!emulate_pointer && ti)
break;
}
if (ti)
break;
if (!TouchResizeQueue(dev))
break; break;
} }
...@@ -194,21 +177,8 @@ TouchBeginDDXTouch(DeviceIntPtr dev, uint32_t ddx_id) ...@@ -194,21 +177,8 @@ TouchBeginDDXTouch(DeviceIntPtr dev, uint32_t ddx_id)
next_client_id = 1; next_client_id = 1;
ti->client_id = client_id; ti->client_id = client_id;
ti->emulate_pointer = emulate_pointer; ti->emulate_pointer = emulate_pointer;
return ti;
} }
return ti;
/* If we get here, then we've run out of touches and we need to drop the
* event (we're inside the SIGIO handler here) schedule a WorkProc to
* grow the queue for us for next time. */
ErrorFSigSafe("%s: not enough space for touch events (max %u touchpoints). "
"Dropping this event.\n", dev->name, dev->last.num_touches);
if (!BitIsOn(resize_waiting, dev->id)) {
SetBit(resize_waiting, dev->id);
QueueWorkProc(TouchResizeQueue, serverClient, NULL);
}
return NULL;
} }
void void
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment