[PATCH xi2.1 xserver] Reallocate touches outside of signal context

Chase Douglas chase.douglas at canonical.com
Thu Feb 10 15:04:20 PST 2011


To be squashed into xi2.1 commit

BeginTouchPoint is called in signal context. Instead, check the
allocation of touches whenever a touch event is handled. If the
allocation is 50% used, double the allocation.

This also fixes a big bug where we were reallocating the entire touch
class, not just the array of touches. It also memsets the new touches.

Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
---
 Xi/exevents.c      |   34 ++++++++++++++++++++++++++++++++++
 dix/devices.c      |    9 ++++++---
 dix/inpututils.c   |   17 +++++------------
 include/inputstr.h |    1 +
 4 files changed, 46 insertions(+), 15 deletions(-)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 8185a0e..e391147 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1373,6 +1373,40 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr sourcedev)
     if (!t)
         return;
 
+    /* If we hit 50% utilization of touches, double the number of touch
+     * frames. */
+    if (t->active_touches > t->num_touches / 2)
+    {
+        void *tmp;
+
+        tmp = realloc(t->touches, (t->num_touches * 2) * sizeof(*t->touches));
+        if (tmp)
+        {
+            int i;
+
+            t->touches = tmp;
+            memset(t->touches + t->num_touches, 0,
+                   t->num_touches * sizeof(*t->touches));
+
+            for (i = t->num_touches; i < t->num_touches * 2; i++)
+            {
+                if (!InitTouchPoint(t, i))
+                {
+                    LogMessage(X_ERROR,
+                               "%s: failed to initialize new touchpoint %d\n",
+                               sourcedev->name, i);
+                    break;
+                }
+            }
+            t->num_touches = i;
+
+            LogMessage(X_INFO, "%s: reallocated %d touches\n", sourcedev->name,
+                       t->num_touches);
+        } else
+            LogMessage(X_ERROR, "%s: failed to allocate more touches (%d)\n",
+                       sourcedev->name, t->num_touches * 2);
+    }
+
     if (ev->any.type == ET_TouchOwnership)
         touchid = ev->touch_ownership_event.touchid;
     else
diff --git a/dix/devices.c b/dix/devices.c
index 2e75b49..105e6b8 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -1653,11 +1653,14 @@ InitTouchClassDeviceStruct(DeviceIntPtr device, unsigned int max_touches,
     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));
+
+    /* Need cushion for clients who may hold on to touches after they physically
+     * end. So double the initial allocation of touches. */
+    touch->touches = calloc(max_touches * 2, sizeof(*touch->touches));
     if (!touch->touches)
         goto err;
-    touch->num_touches = max_touches;
-    for (i = 0; i < max_touches; i++)
+    touch->num_touches = max_touches * 2;
+    for (i = 0; i < touch->num_touches; i++)
         InitTouchPoint(touch, i);
 
     touch->mode = mode;
diff --git a/dix/inpututils.c b/dix/inpututils.c
index c2016c0..2b37cae 100644
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
@@ -618,7 +618,6 @@ BeginTouchPoint(DeviceIntPtr dev, uint32_t ddx_id)
     int i;
     TouchClassPtr t = dev->touch;
     TouchPointInfoPtr ti;
-    void *tmp;
 
     if (!t)
         return NULL;
@@ -630,7 +629,6 @@ BeginTouchPoint(DeviceIntPtr dev, uint32_t ddx_id)
     if (FindTouchPointByDDXID(dev, ddx_id))
         return NULL;
 
-try_find_touch:
     for (i = 0; i < t->num_touches; i++)
     {
         ti = &t->touches[i];
@@ -638,6 +636,7 @@ try_find_touch:
             ti->active = TRUE;
             ti->ddx_id = ddx_id;
             ti->client_id = t->next_client_id;
+            t->active_touches++;
 next_touch_id:
             t->next_client_id++;
             if (t->next_client_id == 0)
@@ -648,16 +647,8 @@ next_touch_id:
         }
     }
 
-    /* If we get here, then we've run out of touches: enlarge dev->touch and
-     * try again. */
-    tmp = realloc(t, (t->num_touches + 1) * sizeof(*t));
-    if (tmp)
-    {
-        dev->touch = tmp;
-        t->num_touches++;
-        if (InitTouchPoint(t, t->num_touches - 1))
-            goto try_find_touch;
-    }
+    /* If we get here, then we've run out of touches. */
+    LogMessage(X_WARNING, "%s: no more touches available\n", dev->name);
 
     return NULL;
 }
@@ -671,6 +662,7 @@ void
 EndTouchPoint(DeviceIntPtr dev, TouchPointInfoPtr ti)
 {
     int i;
+    TouchClassPtr t = dev->touch;
 
     ti->active = FALSE;
     ti->pending_finish = FALSE;
@@ -681,6 +673,7 @@ EndTouchPoint(DeviceIntPtr dev, TouchPointInfoPtr ti)
     ti->num_grabs = 0;
     ti->client_id = 0;
     ti->ddx_id = 0;
+    t->active_touches--;
 
     for (i = 0; i < ti->num_valuators; i++)
         ti->valuators[i] = 0;
diff --git a/include/inputstr.h b/include/inputstr.h
index 3d86b34..b23a23b 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -319,6 +319,7 @@ typedef struct _TouchClassRec {
     TouchPointInfoPtr  touches;
     unsigned short     num_touches;    /* number of allocated touches */
     unsigned short     max_touches;    /* maximum number of touches, may be 0 */
+    unsigned short     active_touches; /* number of active touches */
     CARD8              mode;           /* ::XIDirectTouch, XIDependentTouch */
     uint32_t           next_client_id; /* next client_id to give out */
     int                x_axis;         /* axis number of x axis */
-- 
1.7.2.3



More information about the xorg-devel mailing list