diff options
Diffstat (limited to 'xorg-server/Xi')
-rw-r--r-- | xorg-server/Xi/exevents.c | 57 | ||||
-rw-r--r-- | xorg-server/Xi/xiselectev.c | 80 |
2 files changed, 89 insertions, 48 deletions
diff --git a/xorg-server/Xi/exevents.c b/xorg-server/Xi/exevents.c index c22d934d7..823e539e8 100644 --- a/xorg-server/Xi/exevents.c +++ b/xorg-server/Xi/exevents.c @@ -1411,7 +1411,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, ptrev->device_event.corestate = event_get_corestate(dev, kbd); if (grab) { - /* this side-steps the usual activation mechansims, but... */ + /* this side-steps the usual activation mechanisms, but... */ if (ev->any.type == ET_TouchBegin && !dev->deviceGrab.grab) ActivatePassiveGrab(dev, grab, ptrev, ev); /* also delivers the event */ else { @@ -1568,32 +1568,41 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev) else ti = TouchFindByClientID(dev, touchid); - /* Under the following circumstances we create a new touch record for an - * existing touch: - * - * - The touch may be pointer emulated - * - An explicit grab is active on the device - * - The grab is a pointer grab - * - * This allows for an explicit grab to receive pointer events for an already - * active touch. - */ - if (!ti && type != ET_TouchBegin && emulate_pointer && - dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab && + /* Active pointer grab */ + if (emulate_pointer && dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab && (dev->deviceGrab.grab->grabtype == CORE || dev->deviceGrab.grab->grabtype == XI || - !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin))) { - ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid, - emulate_pointer); - if (!ti) { - DebugF("[Xi] %s: Failed to create new dix record for explicitly " - "grabbed touchpoint %d\n", - dev->name, touchid); - return; - } + !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin))) + { + /* Active pointer grab on touch point and we get a TouchEnd - claim this + * touchpoint accepted, otherwise clients waiting for ownership will + * wait on this touchpoint until this client ungrabs, or the cows come + * home, whichever is earlier */ + if (ti && type == ET_TouchEnd) + TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch); + else if (!ti && type != ET_TouchBegin) { + /* Under the following circumstances we create a new touch record for an + * existing touch: + * + * - The touch may be pointer emulated + * - An explicit grab is active on the device + * - The grab is a pointer grab + * + * This allows for an explicit grab to receive pointer events for an already + * active touch. + */ + ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid, + emulate_pointer); + if (!ti) { + DebugF("[Xi] %s: Failed to create new dix record for explicitly " + "grabbed touchpoint %d\n", + dev->name, touchid); + return; + } - TouchBuildSprite(dev, ti, ev); - TouchSetupListeners(dev, ti, ev); + TouchBuildSprite(dev, ti, ev); + TouchSetupListeners(dev, ti, ev); + } } if (!ti) { diff --git a/xorg-server/Xi/xiselectev.c b/xorg-server/Xi/xiselectev.c index 3040aa911..8592747f6 100644 --- a/xorg-server/Xi/xiselectev.c +++ b/xorg-server/Xi/xiselectev.c @@ -37,6 +37,57 @@ #include "xiselectev.h" /** + * Ruleset: + * - if A has XIAllDevices, B may select on device X + * - If A has XIAllDevices, B may select on XIAllMasterDevices + * - If A has XIAllMasterDevices, B may select on device X + * - If A has XIAllMasterDevices, B may select on XIAllDevices + * - if A has device X, B may select on XIAllDevices/XIAllMasterDevices + */ +static int check_for_touch_selection_conflicts(ClientPtr B, WindowPtr win, int deviceid) +{ + OtherInputMasks *inputMasks = wOtherInputMasks(win); + InputClients *A = NULL; + + if (inputMasks) + A = inputMasks->inputClients; + for (; A; A = A->next) { + DeviceIntPtr tmp; + + if (CLIENT_ID(A->resource) == B->index) + continue; + + if (deviceid == XIAllDevices) + tmp = inputInfo.all_devices; + else if (deviceid == XIAllMasterDevices) + tmp = inputInfo.all_master_devices; + else + dixLookupDevice(&tmp, deviceid, serverClient, DixReadAccess); + if (!tmp) + return BadImplementation; /* this shouldn't happen */ + + /* A has XIAllDevices */ + if (xi2mask_isset_for_device(A->xi2mask, inputInfo.all_devices, XI_TouchBegin)) { + if (deviceid == XIAllDevices) + return BadAccess; + } + + /* A has XIAllMasterDevices */ + if (xi2mask_isset_for_device(A->xi2mask, inputInfo.all_master_devices, XI_TouchBegin)) { + if (deviceid == XIAllMasterDevices) + return BadAccess; + } + + /* A has this device */ + if (xi2mask_isset_for_device(A->xi2mask, tmp, XI_TouchBegin)) + return BadAccess; + } + + return Success; +} + + +/** * Check the given mask (in len bytes) for invalid mask bits. * Invalid mask bits are any bits above XI2LastEvent. * @@ -169,30 +220,11 @@ ProcXISelectEvents(ClientPtr client) * same devices, including master devices. * XXX: This breaks if a device goes from floating to attached. */ if (BitIsOn(bits, XI_TouchBegin)) { - OtherInputMasks *inputMasks = wOtherInputMasks(win); - InputClients *iclient = NULL; - - if (inputMasks) - iclient = inputMasks->inputClients; - for (; iclient; iclient = iclient->next) { - DeviceIntPtr tmp; - - if (CLIENT_ID(iclient->resource) == client->index) - continue; - - if (evmask->deviceid == XIAllDevices) - tmp = inputInfo.all_devices; - else if (evmask->deviceid == XIAllMasterDevices) - tmp = inputInfo.all_master_devices; - else - dixLookupDevice(&tmp, evmask->deviceid, serverClient, - DixReadAccess); - if (!tmp) - return BadImplementation; /* this shouldn't happen */ - - if (xi2mask_isset(iclient->xi2mask, tmp, XI_TouchBegin)) - return BadAccess; - } + rc = check_for_touch_selection_conflicts(client, + win, + evmask->deviceid); + if (rc != Success) + return rc; } } |