Merge branch 'touch-selection-conflict-fixes' into for-keith
This commit is contained in:
commit
f961c3a3b9
|
@ -36,6 +36,57 @@
|
||||||
|
|
||||||
#include "xiselectev.h"
|
#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.
|
* Check the given mask (in len bytes) for invalid mask bits.
|
||||||
* Invalid mask bits are any bits above XI2LastEvent.
|
* Invalid mask bits are any bits above XI2LastEvent.
|
||||||
|
@ -169,30 +220,11 @@ ProcXISelectEvents(ClientPtr client)
|
||||||
* same devices, including master devices.
|
* same devices, including master devices.
|
||||||
* XXX: This breaks if a device goes from floating to attached. */
|
* XXX: This breaks if a device goes from floating to attached. */
|
||||||
if (BitIsOn(bits, XI_TouchBegin)) {
|
if (BitIsOn(bits, XI_TouchBegin)) {
|
||||||
OtherInputMasks *inputMasks = wOtherInputMasks(win);
|
rc = check_for_touch_selection_conflicts(client,
|
||||||
InputClients *iclient = NULL;
|
win,
|
||||||
|
evmask->deviceid);
|
||||||
if (inputMasks)
|
if (rc != Success)
|
||||||
iclient = inputMasks->inputClients;
|
return rc;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1015,6 +1015,21 @@ xi2mask_free(XI2Mask **mask)
|
||||||
*mask = NULL;
|
*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
|
* Test if the bit for event type is set for this device, or the
|
||||||
* XIAllDevices/XIAllMasterDevices (if applicable) is set.
|
* XIAllDevices/XIAllMasterDevices (if applicable) is set.
|
||||||
|
@ -1026,15 +1041,12 @@ xi2mask_isset(XI2Mask *mask, const DeviceIntPtr dev, int event_type)
|
||||||
{
|
{
|
||||||
int set = 0;
|
int set = 0;
|
||||||
|
|
||||||
BUG_WARN(dev->id < 0);
|
if (xi2mask_isset_for_device(mask, inputInfo.all_devices, event_type))
|
||||||
BUG_WARN(dev->id >= mask->nmasks);
|
set = 1;
|
||||||
BUG_WARN(bits_to_bytes(event_type + 1) > mask->mask_size);
|
else if (xi2mask_isset_for_device(mask, dev, event_type))
|
||||||
|
set = 1;
|
||||||
set = ! !BitIsOn(mask->masks[XIAllDevices], event_type);
|
else if (IsMaster(dev) && xi2mask_isset_for_device(mask, inputInfo.all_master_devices, event_type))
|
||||||
if (!set)
|
set = 1;
|
||||||
set = ! !BitIsOn(mask->masks[dev->id], event_type);
|
|
||||||
if (!set && IsMaster(dev))
|
|
||||||
set = ! !BitIsOn(mask->masks[XIAllMasterDevices], event_type);
|
|
||||||
|
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ XI2Mask *xi2mask_new(void);
|
||||||
XI2Mask *xi2mask_new_with_size(size_t, size_t); /* don't use it */
|
XI2Mask *xi2mask_new_with_size(size_t, size_t); /* don't use it */
|
||||||
void xi2mask_free(XI2Mask **mask);
|
void xi2mask_free(XI2Mask **mask);
|
||||||
Bool xi2mask_isset(XI2Mask *mask, const DeviceIntPtr dev, int event_type);
|
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_set(XI2Mask *mask, int deviceid, int event_type);
|
||||||
void xi2mask_zero(XI2Mask *mask, int deviceid);
|
void xi2mask_zero(XI2Mask *mask, int deviceid);
|
||||||
void xi2mask_merge(XI2Mask *dest, const XI2Mask *source);
|
void xi2mask_merge(XI2Mask *dest, const XI2Mask *source);
|
||||||
|
|
|
@ -36,8 +36,14 @@ xi2mask_test(void)
|
||||||
XI2Mask *xi2mask = NULL, *mergemask = NULL;
|
XI2Mask *xi2mask = NULL, *mergemask = NULL;
|
||||||
unsigned char *mask;
|
unsigned char *mask;
|
||||||
DeviceIntRec dev;
|
DeviceIntRec dev;
|
||||||
|
DeviceIntRec all_devices, all_master_devices;
|
||||||
int i;
|
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 */
|
/* size >= nmasks * 2 for the test cases below */
|
||||||
xi2mask = xi2mask_new_with_size(MAXDEVICES + 2, (MAXDEVICES + 2) * 2);
|
xi2mask = xi2mask_new_with_size(MAXDEVICES + 2, (MAXDEVICES + 2) * 2);
|
||||||
assert(xi2mask);
|
assert(xi2mask);
|
||||||
|
|
Loading…
Reference in New Issue