From 8d71400633abb6de7570991b90034cfcf95f120d Mon Sep 17 00:00:00 2001 From: Chase Douglas Date: Sun, 13 Feb 2011 16:02:38 -0500 Subject: new stuff --- Xi/exevents.c | 650 ++++++++++++++++++++++++++++++++++++++++++++--------- Xi/xiallowev.c | 10 +- dix/events.c | 24 ++ include/inputstr.h | 25 ++- 4 files changed, 592 insertions(+), 117 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 1b618d35a..a9ba99f8e 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -953,27 +953,57 @@ ProcessRawEvent(RawDeviceEvent *ev, DeviceIntPtr device) } } +static Bool +AddTouchClient(TouchPointInfoPtr ti, int client_id, WindowPtr window, + TouchClientType type, DeviceIntPtr dev, DeviceIntPtr sourcedev, + GrabPtr grab) +{ + TouchClientPtr client; + + ti->active_clients++; + if (ti->active_clients >= ti->num_clients) + { + TouchClientPtr tmp; + tmp = realloc(ti->clients, + ti->num_clients * 2 * sizeof(TouchClientRec)); + if (tmp) + { + ti->clients = tmp; + ti->num_clients *= 2; + } else { + LogMessage(X_ERROR, "failed to reallocate touch clients\n"); + return TRUE; + } + } + + client = &ti->clients[ti->active_clients - 1]; + client->client = clients[client_id]; + client->window = window; + client->type = type; + client->device = dev; + client->source = sourcedev; + client->grab = grab; + + return (type == POINTER_GRAB_ASYNC); +} + /** * Ensure a window trace is present in ti->sprite, constructing one for * TouchBegin events. */ static Bool -EnsureTouchSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, - InternalEvent *ev) +EnsureTouchClients(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, + InternalEvent *ev) { TouchClassPtr t = sourcedev->touch; SpritePtr sprite = &ti->sprite; + DeviceIntPtr masterdev = sourcedev->u.master; + WindowPtr grab_window = NullWindow; + Bool grab_window_seen = FALSE; int i; - /* We may not have a sprite if there are no applicable grabs or - * event selections, or if they've disappeared, or if all the grab - * owners have rejected the touch. Don't bother delivering motion - * events if not, but TouchEnd events still need to be processed so - * we can call FinishTouchPoint and release it for later use. */ - if (ev->any.type == ET_TouchEnd) - return TRUE; - else if (ev->any.type != ET_TouchBegin) - return (sprite->spriteTraceGood > 0); + if (ev->any.type != ET_TouchBegin) + return (ti->num_clients > 0) if (t->mode == XIDirectTouch) { @@ -992,22 +1022,42 @@ EnsureTouchSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, * device's sprite. */ for (i = 0; i < t->num_touches; i++) if (!t->touches[i].pending_finish && - t->touches[i].sprite.spriteTraceGood > 0) + t->touches[i].active_clients > 0) break; - if (i < t->num_touches) + if (i < t->num_touches) { srcsprite = &t->touches[i].sprite; + ti->active_clients = t->touches[i].active_clients; + + if (ti->active_clients > ti->num_clients) + { + TouchClientPtr tmp; + + tmp = realloc(ti->clients, + ti->active_clients * sizeof(TouchClientRec)); + if (!tmp) + { + ti->active_clients = 0; + return FALSE; + } + ti->clients = tmp; + ti->num_clients = ti->active_clients; + } + memcpy(ti->clients, t->touches[i].clients, + ti->active_clients * sizeof(TouchClientRec)); + } else if (sourcedev->spriteInfo->sprite) - srcsprite = sourcedev->spriteInfo->sprite; + srcprite = sourcedev->spriteInfo->sprite; else return FALSE; if (srcsprite->spriteTraceGood > sprite->spriteTraceSize) - { + { trace = realloc(sprite->spriteTrace, srcsprite->spriteTraceSize * sizeof(*trace)); if (!trace) - { + { sprite->spriteTraceGood = 0; + ti->active_clients = 0; return FALSE; } sprite->spriteTrace = trace; @@ -1016,22 +1066,192 @@ EnsureTouchSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, memcpy(sprite->spriteTrace, srcsprite->spriteTrace, srcsprite->spriteTraceGood * sizeof(*trace)); sprite->spriteTraceGood = srcsprite->spriteTraceGood; + + if (ti->active_clients) + return TRUE; } if (sprite->spriteTraceGood <= 0) return FALSE; - /* Mark which grabs/event selections we're delivering to: max one grab per - * window plus the bottom-most event selection. */ - ti->listeners = calloc(sprite->spriteTraceGood + 1, sizeof(*ti->listeners)); - if (!ti->listeners) + for (i = 0; i < sprite->spriteTraceGood; i++) { - sprite->spriteTraceGood = 0; - return FALSE; + WindowPtr win = sprite->spriteTrace[i]; + DeviceIntPtr deliverdev = sourcedev; + GrabPtr grab; + TouchClientPtr client; + TouchClientType type; + InternalEvent ev; + + if (win == grab_window) + { + grab_window_seen = TRUE; + continue; + } + else if (grab_window && !grab_window_seen) + continue; + + ev.any.type = ET_TouchBegin; + if ((grab = CheckPassiveGrabsOnWindow(win, sourcedev, ev, FALSE, + FALSE))) + { + if (AddTouchClient(ti, CLIENT_ID(grab->resource), win, TOUCH_GRAB, + sourcedev, sourcedev, grab)) + goto done; + continue; + } + if (masterdev && + (grab = CheckPassiveGrabsOnWindow(win, masterdev, ev, FALSE, + FALSE))) + { + if (AddTouchClient(ti, CLIENT_ID(grab->resource), win, TOUCH_GRAB, + masterdev, sourcedev, grab)) + goto done; + continue; + } + + ev.any.type = ET_ButtonPress; + ev.device_event.detail.button = 1; + if ((grab = CheckPassiveGrabsOnWindow(win, sourcedev, ev, FALSE, + FALSE))) + { + if (grab->pointerMode == GrabModeSync) + type = POINTER_GRAB_SYNC; + else + type = POINTER_GRAB_ASYNC; + if (AddTouchClient(ti, CLIENT_ID(grab->resource), win, type, + sourcedev, sourcedev, grab)) + goto done; + continue; + } + if (masterdev && + (grab = CheckPassiveGrabsOnWindow(win, masterdev, ev, FALSE, + FALSE))) + { + if (grab->pointerMode == GrabModeSync) + type = POINTER_GRAB_SYNC; + else + type = POINTER_GRAB_ASYNC; + if (AddTouchClient(ti, CLIENT_ID(grab->resource), win, type, + masterdev, sourcedev, grab)) + goto done; + continue; + } } - ti->num_listeners = 0; - return TRUE; + for (i = sprite->spriteTraceGood - 1; i >= 0; i--) + { + WindowPtr win = sprite->spriteTrace[i]; + OtherInputMasks *inputMasks = wOtherInputMasks(win); + Bool select_seen = FALSE; + + if (inputMasks && + (BitIsOn(inputMasks->xi2mask[XIAllDevices], + XI_TouchMotionUnowned) || + BitIsOn(inputMasks->xi2mask[sourcedev->id], + XI_TouchMotionUnowned) || + (masterdev && + (BitIsOn(inputMasks->xi2mask[XIAllMasterDevices], + XI_TouchMotionUnowned) || + BitIsOn(inputMasks->xi2mask[masterdev->id], + XI_TouchMotionUnowned))))) + { + InputClientsPtr inputClients = inputMasks->inputClients; + + for (inputClients = inputMasks->inputClients; + inputClients; + inputClients = inputClients->next) + { + if (BitIsOn(inputClients->xi2mask[XIAllDevices], + XI_TouchMotionUnowned) || + BitIsOn(inputClients->xi2mask[sourcedev->id], + XI_TouchMotionUnowned)) + { + if (AddTouchClient(ti, CLIENT_ID(inputClients->resource), + win, TOUCH_SELECT_UNOWNED, sourcedev, + sourcedev, grab)) + goto done; + select_seen = TRUE; + continue; + } + else if (masterdev && + (BitIsOn(inputClients->xi2mask[XIAllMasterDevices], + XI_TouchMotionUnowned) || + BitIsOn(inputClients->xi2mask[masterdev->id], + XI_TouchMotionUnowned))) + { + if (AddTouchClient(ti, CLIENT_ID(inputClients->resource), + win, TOUCH_SELECT_UNOWNED, masterdev, + sourcedev, grab)) + goto done; + select_seen = TRUE; + continue; + } + } + } + + if (inputMasks && + (BitIsOn(inputMasks->xi2mask[XIAllDevices], XI_TouchMotion) || + BitIsOn(inputMasks->xi2mask[sourcedev->id], XI_TouchMotion) || + (masterdev && + (BitIsOn(inputMasks->xi2mask[XIAllMasterDevices], + XI_TouchMotion) || + BitIsOn(inputMasks->xi2mask[masterdev->id], + XI_TouchMotion))))) + { + InputClientsPtr inputClients = inputMasks->inputClients; + + for (inputClients = inputMasks->inputClients; + inputClients; + inputClients = inputClients->next) + { + if (BitIsOn(inputClients->xi2mask[XIAllDevices], + XI_TouchMotion) || + BitIsOn(inputClients->xi2mask[sourcedev->id], + XI_TouchMotion)) + { + AddTouchClient(ti, CLIENT_ID(inputClients->resource), win, + TOUCH_SELECT, sourcedev, sourcedev, grab); + goto done; + } + else if (masterdev && + (BitIsOn(inputClients->xi2mask[XIAllMasterDevices], + XI_TouchMotion) || + BitIsOn(inputClients->xi2mask[masterdev->id], + XI_TouchMotion))) + { + AddTouchClient(ti, CLIENT_ID(inputClients->resource), win, + TOUCH_SELECT, masterdev, sourcedev, grab); + goto done; + } + } + } + + for (j = 0; j < 3; j++) + { + static const enum EventType events[] = {ET_ButtonPress, + ET_ButtonRelease, + ET_Motion}; + InternalEvent ev; + + ev.any.type = events[j]; + if (EventIsDeliverable(sourcedev, &ev, win)) + { + AddTouchClient(ti, 0, win, POINTER_SELECT, sourcedev, + sourcedev, grab); + goto done; + } + else if (masterdev && EventIsDeliverable(masterdev, &ev, win)) + { + AddTouchClient(ti, 0, win, POINTER_SELECT, masterdev, + sourcedev, grab); + goto done; + } + } + } + +done: + return (ti->active_clients > 0); } /** @@ -1066,8 +1286,8 @@ TouchResourceIsOwner(TouchPointInfoPtr ti, XID resource) * Attempts to deliver a touch event to the given client. */ static Bool -DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti, - WindowPtr win, InternalEvent *ev) +DeliverOneTouchEvent(TouchClientPtr client, TouchPointInfoPtr ti, + InternalEvent *ev) { int err; xEvent *xi2; @@ -1078,13 +1298,15 @@ DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti, err = EventToXI2(ev, &xi2); if (err != Success) FatalError("[Xi] %s: XI2 conversion failed in DeliverOneTouchEvent" - " (%d)\n", dev->name, err); + " (%d)\n", client->device->name, err); - FixUpEventFromWindow(&ti->sprite, xi2, win, child, FALSE); - filter = GetEventFilter(dev, xi2); - if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success) + FixUpEventFromWindow(&ti->sprite, xi2, client->window, child, FALSE); + filter = GetEventFilter(client->device, xi2); + if (XaceHook(XACE_RECEIVE_ACCESS, client->client, client->window, xi2, 1) + != Success) return FALSE; - err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab); + err = TryClientEvents(client->client, client->device, xi2, 1, filter, + filter, NullGrab); free(xi2); /* Returning the value from TryClientEvents isn't useful, since all our @@ -1092,6 +1314,26 @@ DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti, return TRUE; } +int +DeliverTouchOwnershipEvent(TouchClientPtr client, TouchPointInfoPtr ti) +{ + TouchClassPtr t = pDev->touch; + TouchOwnershipEvent event; + + memset(&event, 0, sizeof(TouchOwnershipEvent)); + event.header = ET_Internal; + event.type = ET_TouchOwnership; + event.length = sizeof(TouchOwnershipEvent); + event.time = GetTimeInMillis(); + event.deviceid = client->device->id; + event.sourceid = client->source->id; + event.touchid = ti->client_id; + + DeliverOneTouchEvent(client, ti, (InternalEvent *)&event); + + return 1; +} + static DeviceIntPtr CheckXI2Masks(OtherInputMasks *inputMasks, DeviceIntPtr sourcedev, uint16_t evtype) @@ -1306,29 +1548,6 @@ static void TouchPointerEmulation(enum EventType evtype, DeviceIntPtr dev, ValuatorMask *mask) { - EventList *emulationEvents = GetEvents(); - int i, nevents; - - if (evtype == ET_TouchBegin) - { - nevents = GetPointerEvents(emulationEvents, dev, - MotionNotify, 0, POINTER_ABSOLUTE, mask); - nevents += GetPointerEvents(emulationEvents + nevents, dev, - ButtonPress, 1, POINTER_ABSOLUTE, mask); - } - else if (evtype == ET_TouchMotion) - nevents = GetPointerEvents(emulationEvents, dev, MotionNotify, 0, - POINTER_ABSOLUTE, mask); - else if (evtype == ET_TouchEnd) - { - nevents = GetPointerEvents(emulationEvents, dev, MotionNotify, 0, - POINTER_ABSOLUTE, mask); - nevents += GetPointerEvents(emulationEvents + nevents, dev, - ButtonRelease, 1, POINTER_ABSOLUTE, mask); - } - - for (i = 0; i < nevents; i++) - mieqEnqueue(dev, (InternalEvent*)((emulationEvents + i)->event)); } /* Helper function to set up touch pointer emulation. */ @@ -1347,9 +1566,13 @@ SetTouchEmulationMask(InternalEvent *ev, ValuatorMask *mask, int x_axis, /* Process touch emulation. */ static void -EmulateTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev) +EmulateTouchEvents(TouchClientPtr client, TouchPointInfoPtr ti, + InternalEvent *ev) { + DeviceIntPtr dev = client->source; + EventList *emulationEvents = GetEvents(); ValuatorMask mask; + int nevents = 0; int x_axis = dev->touch->x_axis; int y_axis = dev->touch->y_axis; @@ -1357,34 +1580,35 @@ EmulateTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev) * at a time. */ dev->touch->emulate = ti; - if (ev->any.type != ET_TouchOwnership) + /* Emulate a normal event. */ + SetTouchEmulationMask(ev, &mask, x_axis, y_axis); + + if (evtype == ET_TouchBegin) { - /* Emulate a normal event. */ - SetTouchEmulationMask(ev, &mask, x_axis, y_axis); - TouchPointerEmulation(ev->any.type, dev, &mask); + nevents = GetPointerEvents(emulationEvents, dev, + MotionNotify, 0, POINTER_ABSOLUTE, mask); + nevents += GetPointerEvents(emulationEvents + nevents, dev, + ButtonPress, 1, POINTER_ABSOLUTE, mask); } - else + else if (evtype == ET_TouchMotion) + nevents = GetPointerEvents(emulationEvents, dev, MotionNotify, 0, + POINTER_ABSOLUTE, mask); + else if (evtype == ET_TouchEnd) { - /* If we got here, then a grabbing client rejected the touch. Replay - all the touches buffered up. */ - ev = ti->begin_event; - - SetTouchEmulationMask(ev, &mask, x_axis, y_axis); - TouchPointerEmulation(ev->any.type, dev, &mask); + nevents = GetPointerEvents(emulationEvents, dev, MotionNotify, 0, + POINTER_ABSOLUTE, mask); + nevents += GetPointerEvents(emulationEvents + nevents, dev, + ButtonRelease, 1, POINTER_ABSOLUTE, mask); + } - ev = ti->first_history; - while (ev != ti->next_history) - { - SetTouchEmulationMask(ev, &mask, x_axis, y_axis); - TouchPointerEmulation(ev->any.type, dev, &mask); + for (i = 0; i < nevents; i++) + { + InternalEvent *event = (InternalEvent *)((emulationEvents + i)->event); - if (ev->any.type == ET_TouchEnd) - break; + event->device_event.flags |= XITouchPointer; - ev++; - if (ev == ti->history + ti->history_size) - ev = ti->history; - } + dev->public.processInputProc( + (InternalEvent*)((emulationEvents + i)->event), dev); } } @@ -1396,11 +1620,8 @@ EmulateTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev) * resource. */ static void -DeliverTouchEvents(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, - InternalEvent *ev, XID resource) +DeliverTouchEvents(TouchClientPtr client, InternalEvent *ev, DeviceIntPtr dev) { - SpritePtr sprite = &ti->sprite; - DeviceIntPtr masterdev = sourcedev->u.master; DeviceIntPtr deliverdev; GrabPtr grab; WindowPtr win; @@ -1408,6 +1629,8 @@ DeliverTouchEvents(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, int i; Bool ret; + ret = DeliverOneTouchEvent(clients[client], dev, ti, client->window, ev); + /* First, deliver to all grabbing clients, going from the root window down * to the deepest child window. */ for (i = 0; i < sprite->spriteTraceGood; i++) @@ -1629,6 +1852,166 @@ ProcessTouchOwnershipEvent(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, } } +void +RemoveTouchPointerEvents() +{ + QdEventPtr qe; + QdEventPtr prev_qe = NULL; + + for (qe = syncEvents.pending; qe; qe->next) + { + InternalEvent *ev = qe->event; + + if ((ev->any.type == ET_ButtonPress || + ev->any.type == ET_ButtonRelease || + ev->any.type == ET_Motion) && + (ev->device_event.flags & XITouchPointer)) + { + if (prev_qe) + prev_qe->next = qe->next; + else + syncEvents.pending = qe->next; + free(qe); + } + else + prev_qe = qe; + } + syncEvents.pendtail = prev_qe; +} + +Bool +FindNextGrab(DevIntPtr dev, TouchPointInfoPtr ti, WindowPtr start_win) +{ + Bool seen_win = FALSE; + DeviceIntPtr master = dev->u.master; + InternalEvent p_event; + InternalEvent t_event; + int i, j; + + if (dev->deviceGrab.grab) + return TRUE; + + p_event->any.type == ET_ButtonPress; + t_event->any.type == ET_TouchBegin; + + j = ti->owner; + + for (i = 0; i < ti->sprite.spriteTraceGood; i++) + { + WindowPtr win = ti->sprite.spriteTrace[i]; + TouchClientPtr client = ti->clients[j]; + + if (win == start_win) + seen_win = TRUE; + else if (!seen_win) + goto next; + + if (win == client->window && client->type == TOUCH_GRAB) + { + client->device->deviceGrab.ActivateGrab(client->device, + client->grab, + currentTime, TRUE); + ti->owner = j; + return TRUE; + } + + if (CheckPassiveGrabsOnWindow(win, dev, &p_event, TRUE, + TRUE) || + (master && CheckPassiveGrabsOnWindow(win, master, &p_event, TRUE, + TRUE))) + return TRUE; + +next: + if (win == client->window) + j++; + } + + return FALSE; +} + +void +ProcessTouchOwnership(DevIntPtr dev, TouchPointInfoPtr ti, uint8_t reason) +{ + Bool touch_grab = TRUE; + + if (!ti) { + ti = dev->emulate_touch; + touch_grab = FALSE; + } + + if (reason == XITouchOwnerAccept) + { + DeviceEvent event; + int i; + + if (!touch_grab) + { + ti->active_clients = 0; + return; + } + + init_event(client->device, &event, GetTimeInMillis()); + event.type = ET_TouchEnd; + event.detail = ti->client_id; + + for (i = ti->owner + 1; i < ti->active_clients; i++) + { + TouchClientPtr client = ti->clients[i]; + + if (client->type == TOUCH_GRAB || + client->type == TOUCH_SELECT_UNOWNED) + { + event.deviceid = client->device->id; + event.sourceid = client->source->id; + + DeliverOneTouchEvent(client, ti, (InternalEvent *)&ev); + } + } + ti->active_clients = ti->owner + 1; + + RemoveTouchPointerEvents(); + } else { + TouchClientPtr client = &ti->clients[ti->owner]; + + if (touch_grab) + { + DeviceIntPtr master = client->source->u.master; + DeviceEvent event; + + init_event(client->device, &event, GetTimeInMillis()); + event.type = ET_TouchEnd; + event.detail = ti->client_id; + event.deviceid = client->device->id; + event.sourceid = client->source->id; + + DeliverOneTouchEvent(client, ti, (InternalEvent *)&ev); + + ti->owner++; + + dev->deviceGrab.DeactivateGrab(dev, FALSE); + } + + if (ti->owner >= ti->active_clients) + ti->active_clients = 0; + else { + if (FindNextGrab(client->device, ti, client->window)) + return; + + client = &ti->clients[ti->owner]; + + if (client->type == TOUCH_SELECT_UNOWNED) + { + DeliverTouchOwnershipEvent(client, ti); + RemoveTouchPointerEvents(); + } + else if (client->type == TOUCH_SELECT) + RemoveTouchPointerEvents(); + else + ti->active_clients = 0; + } + } +} + /** * Processes and delivers a TouchBegin, TouchMotion, TouchMotionOwned, or a * TouchEnd event. @@ -1645,6 +2028,7 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr sourcedev) TouchPointInfoPtr ti; SpritePtr sprite; uint32_t touchid; + Bool emulated = FALSE; /* We handle deliveries to MDs through the SD, rather than copying * the event and processing it twice. */ @@ -1690,10 +2074,7 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr sourcedev) sourcedev->name, t->num_touches * 2); } - if (ev->any.type == ET_TouchOwnership) - touchid = ev->touch_ownership_event.touchid; - else - touchid = ev->device_event.detail.touch; + touchid = ev->device_event.detail.touch; ti = FindTouchPointByClientID(sourcedev, touchid); if (!ti) { @@ -1701,35 +2082,92 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr sourcedev) sourcedev->name, touchid); return; } - sprite = &ti->sprite; - - /* We only send TouchEnd events when no client will ever receive any more - * events from that touch stream. If there are still open grabs, just - * set the PendingFinish flag until they've all accepted or rejected the - * touch. */ - if (ev->any.type == ET_TouchEnd && ti->num_grabs > 0) - { - ev->any.type = ET_TouchMotion; - ev->device_event.flags |= XITouchPendingFinish; - ti->pending_finish = TRUE; - } /* Make sure we have a valid window trace for event delivery; must be * called after event type mutation. */ - if (!EnsureTouchSprite(sourcedev, ti, ev)) + if (!EnsureTouchClients(sourcedev, ti, ev)) + { + EmulateTouchEvents(sourcedev, ti, ev); return; + } - /* TouchOwnership events are handled separately from the rest, as they - * have more complex semantics. */ - if (ev->any.type == ET_TouchOwnership) + if (ev->any.type == ET_TouchBegin) + FindNextGrab(sourcedev, ti, ev->device_event.root); + + client = &ti->clients[ti->owner]; + + if (client->type == TOUCH_GRAB) { - ProcessTouchOwnershipEvent(sourcedev, ti, &ev->touch_ownership_event); + if (ev->any.type == ET_TouchEnd) + { + ev->any.type = ET_TouchMotion; + ev->device_event.flags |= XITouchPendingFinish; + } + + ev->device_event.deviceid = client->device; + ev->device_event.deviceid = client->source; + + DeliverOneTouchEvent(client, ti, (InternalEvent *)ev); + if (ev->any.type == ET_TouchBegin && !client->device->deviceGrab.grab) + DeliverTouchOwnershipEvent(client, ti); } - else + else if (client->type == TOUCH_SELECT || + client->type == TOUCH_SELECT_UNOWNED || + client->type == POINTER_SELECT) { - DeliverTouchEvents(sourcedev, ti, (InternalEvent *) ev, 0); - if (ev->any.type == ET_TouchEnd && ti->num_listeners == 0) - EndTouchPoint(sourcedev, ti); + for (i = ti->owner; i < ti->active_clients; i++) + { + client = &ti->clients[ti->owner]; + + ev->device_event.deviceid = client->device; + ev->device_event.deviceid = client->source; + + if (client->type == TOUCH_SELECT) + DeliverOneTouchEvent(client, ti, (InternalEvent *)ev); + else if (client->type == TOUCH_SELECT_UNOWNED) + { + DeliverOneTouchEvent(client, ti, (InternalEvent *)ev); + if (ev->any.type == ET_TouchBegin) + DeliverTouchOwnershipEvent(client, ti); + } + else + EmulateTouchEvents(sourcedev, ti, InternalEvent *ev); + + return; + } + } + else if (client->type == POINTER_GRAB_SYNC || + client->type == POINTER_GRAB_ASYNC) + { + EmulateTouchEvents(sourcedev, ti, InternalEvent *ev); + emulated = TRUE; + } + + if (ev->any.type == ET_TouchMotion) + ev->any.type = ET_TouchMotionUnowned; + else if (ev->any.type == ET_TouchEnd || + (ev->device_event.flags & XITouchPendingFinish)) + { + ev->any.type = ET_TouchMotionUnowned; + ev->device_event.flags |= XITouchPendingFinish; + } + + for (i = ti->owner + 1; i < ti->active_clients; i++) + { + TouchClientPtr client = &ti->clients[i]; + + ev->device_event.deviceid = client->device; + ev->device_event.deviceid = client->source; + + if (client->type == TOUCH_GRAB || + client->type == TOUCH_SELECT_UNOWNED) + DeliverOneTouchEvent(client, ti, (InternalEvent *)ev); + else if (!emulated && (client->type == POINTER_GRAB_SYNC || + client->type == POINTER_GRAB_ASYNC)) + { + EmulateTouchEvents(sourcedev, ti, InternalEvent *ev); + emulated = TRUE; + } } } diff --git a/Xi/xiallowev.c b/Xi/xiallowev.c index c7056efbe..eb2dfd761 100644 --- a/Xi/xiallowev.c +++ b/Xi/xiallowev.c @@ -181,15 +181,7 @@ ProcXIAllowTouchEvents(ClientPtr client) return BadValue; } - nev = GetTouchOwnershipEvents(events, dev, ti, reason, ti->listeners[0], 0); - if (nev == 0) - return BadAlloc; - for (i = 0; i < nev; i++) - { - ev = (InternalEvent *)((events + i)->event); - mieqProcessDeviceEvent(dev, ev, NULL); - } - ProcessInputEvents(); + ProcessTouchOwnership(dev, ti, reason); return Success; } diff --git a/dix/events.c b/dix/events.c index 733bf333f..d64b615d7 100644 --- a/dix/events.c +++ b/dix/events.c @@ -1287,8 +1287,12 @@ ComputeFreezes(void) if (replayDev->focus && !IsPointerEvent((InternalEvent*)event)) DeliverFocusedEvent(replayDev, (InternalEvent*)event, w); else + { DeliverDeviceEvents(w, (InternalEvent*)event, NullGrab, NullWindow, replayDev); + if (event->flags & XITouchPointer) + ProcessTouchOwnership(replayDev, NULL, XITouchOwnerAccept); + } } } for (dev = inputInfo.devices; dev; dev = dev->next) @@ -1488,6 +1492,7 @@ DeactivatePointerGrab(DeviceIntPtr mouse) DeviceIntPtr dev; Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab && mouse->deviceGrab.implicitGrab); + QdEventPtr qe; mouse->valuator->motionHintWindow = NullWindow; mouse->deviceGrab.grab = NullGrab; @@ -1510,6 +1515,25 @@ DeactivatePointerGrab(DeviceIntPtr mouse) if (!wasImplicit && grab->grabtype == GRABTYPE_XI2) ReattachToOldMaster(mouse); + for (qe = syncEvents.pending; qe; qe = qe->next) + { + if ((qe->event->any.type == ET_ButtonPress || + qe->event->any.type == ET_ButtonRelease || + qe->event->any.type == ET_Motion) && + (qe->event->device_event.flags & XITouchPointer)) + { + ProcessTouchOwnership(mouse, NULL, XITouchOwnerReject); + return; + } + } + + if (mouse->touch) + { + ProcessTouchOwnership(mouse, NULL, XITouchOwnerReject); + if (mouse->deviceGrab.grab) + return; + } + ComputeFreezes(); } diff --git a/include/inputstr.h b/include/inputstr.h index bdab35884..e3c9fd7bd 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -289,13 +289,33 @@ typedef struct _ValuatorClassRec { ValuatorAccelerationRec accelScheme; } ValuatorClassRec, *ValuatorClassPtr; +typedef enum { + TOUCH_GRAB, + TOUCH_SELECT, + TOUCH_SELECT_UNOWNED, + POINTER_GRAB_SYNC, + POINTER_GRAB_ASYNC, + POINTER_SELECT +} TouchClientType; + +typedef struct _TouchClientRec { + ClientPtr client; + WindowPtr window; + TouchClientType type; + DeviceIntPtr device; + DeviceIntPtr source; + GrabPtr grab; +} TouchClientRec, *TouchClientPtr; + typedef struct _TouchPointInfo { 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 */ uint32_t client_id; /* touch ID as seen in client events */ uint32_t ddx_id; /* touch ID given by the DDX */ - SpriteRec sprite; /* window trace for delivery */ + TouchClientPtr clients; + int num_clients; + int active_clients; int *valuators; /* last recorded axis values */ int num_valuators; /* == TouchClassInfo::num_axes */ XID *listeners; /* grabs/event selection IDs receiving @@ -513,7 +533,8 @@ typedef struct _GrabInfoRec { TimeStamp /*time*/, Bool /*autoGrab*/); void (*DeactivateGrab)( - DeviceIntPtr /*device*/); + DeviceIntPtr /*device*/, + Bool /* computeFreezes */); struct { Bool frozen; int state; -- cgit v1.2.3