Merge branch 'touch-selection-conflict-fixes' into for-keith

This commit is contained in:
Peter Hutterer 2012-12-12 17:25:23 +10:00
commit f961c3a3b9
4 changed files with 84 additions and 33 deletions

View File

@ -36,6 +36,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;
}
}

View File

@ -1015,6 +1015,21 @@ xi2mask_free(XI2Mask **mask)
*mask = NULL;
}
/**
* Test if the bit for event type is set for this device only.
*
* @return TRUE if the bit is set, FALSE otherwise
*/
Bool
xi2mask_isset_for_device(XI2Mask *mask, const DeviceIntPtr dev, int event_type)
{
BUG_WARN(dev->id < 0);
BUG_WARN(dev->id >= mask->nmasks);
BUG_WARN(bits_to_bytes(event_type + 1) > mask->mask_size);
return BitIsOn(mask->masks[dev->id], event_type);
}
/**
* Test if the bit for event type is set for this device, or the
* XIAllDevices/XIAllMasterDevices (if applicable) is set.
@ -1026,15 +1041,12 @@ xi2mask_isset(XI2Mask *mask, const DeviceIntPtr dev, int event_type)
{
int set = 0;
BUG_WARN(dev->id < 0);
BUG_WARN(dev->id >= mask->nmasks);
BUG_WARN(bits_to_bytes(event_type + 1) > mask->mask_size);
set = ! !BitIsOn(mask->masks[XIAllDevices], event_type);
if (!set)
set = ! !BitIsOn(mask->masks[dev->id], event_type);
if (!set && IsMaster(dev))
set = ! !BitIsOn(mask->masks[XIAllMasterDevices], event_type);
if (xi2mask_isset_for_device(mask, inputInfo.all_devices, event_type))
set = 1;
else if (xi2mask_isset_for_device(mask, dev, event_type))
set = 1;
else if (IsMaster(dev) && xi2mask_isset_for_device(mask, inputInfo.all_master_devices, event_type))
set = 1;
return set;
}

View File

@ -57,6 +57,7 @@ XI2Mask *xi2mask_new(void);
XI2Mask *xi2mask_new_with_size(size_t, size_t); /* don't use it */
void xi2mask_free(XI2Mask **mask);
Bool xi2mask_isset(XI2Mask *mask, const DeviceIntPtr dev, int event_type);
Bool xi2mask_isset_for_device(XI2Mask *mask, const DeviceIntPtr dev, int event_type);
void xi2mask_set(XI2Mask *mask, int deviceid, int event_type);
void xi2mask_zero(XI2Mask *mask, int deviceid);
void xi2mask_merge(XI2Mask *dest, const XI2Mask *source);

View File

@ -36,8 +36,14 @@ xi2mask_test(void)
XI2Mask *xi2mask = NULL, *mergemask = NULL;
unsigned char *mask;
DeviceIntRec dev;
DeviceIntRec all_devices, all_master_devices;
int i;
all_devices.id = XIAllDevices;
inputInfo.all_devices = &all_devices;
all_master_devices.id = XIAllMasterDevices;
inputInfo.all_master_devices = &all_master_devices;
/* size >= nmasks * 2 for the test cases below */
xi2mask = xi2mask_new_with_size(MAXDEVICES + 2, (MAXDEVICES + 2) * 2);
assert(xi2mask);