summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Xi/exevents.c47
-rw-r--r--Xi/xiallowev.c51
2 files changed, 72 insertions, 26 deletions
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 1e43a5ccd..4f9d3e25f 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1042,7 +1042,7 @@ DeliverTouchGrabEvents(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
xEvent *xi2 = NULL;
Mask filter;
WindowPtr win;
- int i, j, err, deliveries;
+ int i, j, err, deliveries, ownerskipped = 0;
ti->num_grabs = 0;
for (i = 0; i < sprite->spriteTraceGood; i++)
@@ -1090,6 +1090,14 @@ DeliverTouchGrabEvents(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
continue;
}
+ /* The owner does not need to see an owner accepted event. */
+ if (ev->flags & XITouchOwnerAccepted && !ownerskipped)
+ {
+ ownerskipped = 1;
+ ev->flags &= ~XITouchOwner;
+ continue;
+ }
+
if (XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), win,
(xEvent *) xi2, 1) != Success)
continue;
@@ -1098,11 +1106,33 @@ DeliverTouchGrabEvents(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
if (deliveries > 0)
{
ti->num_grabs++;
+
+ /* If this isn't the last listener of a TouchEnd event, notify
+ * other listeners of a pending finish. */
+ if (ev->type == ET_TouchEnd &&
+ ti->listeners[ti->num_listeners - 1] != grab->resource)
+ {
+ ev->type = ET_TouchMotion;
+ ev->flags |= XITouchPendingFinish;
+ ti->pending_finish = TRUE;
+ }
+
/* If we've made a delivery, the next one definitely won't be
* to the owner. */
ev->flags &= ~XITouchOwner;
if (ev->type == ET_TouchBegin)
ti->listeners[ti->num_listeners++] = grab->resource;
+ else if (ev->type == ET_TouchMotion &&
+ !(ev->flags & XITouchOwnerAccepted))
+ {
+ /* These motion events with no valuators convey change of
+ * ownership. Only the new owner cares. */
+ for (j = 0; j < sizeof(ev->valuators.mask); j++)
+ if (ev->valuators.mask[j] != 0)
+ break;
+ if (j == sizeof(ev->valuators.mask))
+ break;
+ }
}
}
@@ -1257,18 +1287,11 @@ ProcessTouchEvent(DeviceEvent *ev, DeviceIntPtr sourcedev)
ti = &t->touches[touch];
sprite = &ti->sprite;
- /* If we get a TouchEnd event but someone still has an open grab, just
- * flip pending_finish and wait for ownership to settle. */
- if (ev->type == ET_TouchEnd && ti->num_grabs)
- {
- ev->type = ET_TouchMotion;
- ev->flags |= XITouchPendingFinish;
- ti->pending_finish = TRUE;
- }
-
/* The first delivery we make will be to the owner, so set the owner flag
- * here, and clear it once we've made a delivery. */
- ev->flags |= XITouchOwner;
+ * here, and clear it once we've made a delivery. Touch acceptance does not
+ * need to be sent to the owner. */
+ if (!(ev->flags & XITouchOwnerAccepted))
+ ev->flags |= XITouchOwner;
/* Make sure we have a valid window trace for event delivery. */
if (!EnsureTouchSprite(sourcedev, ti, ev))
diff --git a/Xi/xiallowev.c b/Xi/xiallowev.c
index 93905fd67..793dc8778 100644
--- a/Xi/xiallowev.c
+++ b/Xi/xiallowev.c
@@ -169,16 +169,33 @@ ProcXIAllowTouchEvents(ClientPtr client)
ti->emulate_pointer = FALSE;
flags |= XITouchOwnerAccepted;
- nev = GetTouchEvents(events, dev, stuff->touchid, mask, 0, flags);
- if (nev == 0)
- return BadAlloc;
- for (i = 0; i < nev; i++)
+
+ if (ti->pending_finish)
+ {
+ flags |= XITouchPendingFinish;
+
+ /* The touch ended, so owner doesn't need another event */
+ for (i = 0; i < ti->num_listeners - 1; i++)
+ ti->listeners[i] = ti->listeners[i + 1];
+ ti->num_listeners--;
+ }
+
+ if (ti->num_listeners > 0)
{
- ev = (DeviceEvent *)((events + i)->event);
- mieqProcessDeviceEvent(dev, (InternalEvent *) ev, NULL);
+ nev = GetTouchEvents(events, dev, stuff->touchid, mask, 0, flags);
+ if (nev == 0)
+ return BadAlloc;
+ for (i = 0; i < nev; i++)
+ {
+ ev = (DeviceEvent *)((events + i)->event);
+ mieqProcessDeviceEvent(dev, (InternalEvent *) ev, NULL);
+ }
}
- ti->num_listeners = 1;
+ if (ti->pending_finish)
+ FinishTouchPoint(dev, stuff->touchid);
+ else
+ ti->num_listeners = 1;
}
else if (stuff->mode & XITouchOwnerReject)
{
@@ -192,15 +209,21 @@ ProcXIAllowTouchEvents(ClientPtr client)
ti->listeners[i] = ti->listeners[i + 1];
ti->num_listeners--;
- ProcessInputEvents();
- nev = GetTouchEvents(events, dev, stuff->touchid, mask, 0, 0);
- if (nev == 0)
- return BadAlloc;
- for (i = 0; i < nev; i++)
+ if (ti->num_listeners > 0)
{
- ev = (DeviceEvent *)((events + i)->event);
- mieqProcessDeviceEvent(dev, (InternalEvent *) ev, NULL);
+ ProcessInputEvents();
+ nev = GetTouchEvents(events, dev, stuff->touchid, mask,
+ ti->pending_finish, 0);
+ if (nev == 0)
+ return BadAlloc;
+ for (i = 0; i < nev; i++)
+ {
+ ev = (DeviceEvent *)((events + i)->event);
+ mieqProcessDeviceEvent(dev, (InternalEvent *) ev, NULL);
+ }
}
+ else
+ FinishTouchPoint(dev, stuff->touchid);
}
else
{