Merge remote-tracking branch 'whot/for-keith'

I've looked at these patches, but I can't say I've actually
reviewed them...
This commit is contained in:
Keith Packard 2012-12-17 11:45:45 -08:00
commit 6d508b8185
9 changed files with 151 additions and 71 deletions

View File

@ -1409,7 +1409,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 {
@ -1566,32 +1566,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) {

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

@ -1503,11 +1503,27 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
{
GrabPtr grab = mouse->deviceGrab.grab;
DeviceIntPtr dev;
Bool wasPassive = mouse->deviceGrab.fromPassiveGrab;
Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
mouse->deviceGrab.implicitGrab);
XID grab_resource = grab->resource;
int i;
/* If an explicit grab was deactivated, we must remove it from the head of
* all the touches' listener lists. */
for (i = 0; !wasPassive && mouse->touch && i < mouse->touch->num_touches; i++) {
TouchPointInfoPtr ti = mouse->touch->touches + i;
if (ti->active && TouchResourceIsOwner(ti, grab_resource)) {
/* Rejecting will generate a TouchEnd, but we must not
emulate a ButtonRelease here. So pretend the listener
already has the end event */
if (grab->grabtype == CORE || grab->grabtype == XI ||
!xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin))
ti->listeners[0].state = LISTENER_HAS_END;
TouchListenerAcceptReject(mouse, ti, 0, XIRejectTouch);
}
}
TouchRemovePointerGrab(mouse);
mouse->valuator->motionHintWindow = NullWindow;

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

@ -915,6 +915,8 @@ TouchRemovePointerGrab(DeviceIntPtr dev)
ti = TouchFindByClientID(dev, ev->touchid);
if (!ti)
return;
/* FIXME: missing a bit of code here... */
}
/* As touch grabs don't turn into active grabs with their own resources, we
@ -987,8 +989,6 @@ TouchListenerAcceptReject(DeviceIntPtr dev, TouchPointInfoPtr ti, int listener,
for (i = 0; i < nev; i++)
mieqProcessDeviceEvent(dev, events + i, NULL);
ProcessInputEvents();
FreeEventList(events, GetMaximumEventsNum());
return nev ? Success : BadMatch;

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);

View File

@ -74,7 +74,7 @@ ProcXFixesQueryVersion(ClientPtr client)
if (version_compare(stuff->majorVersion, stuff->minorVersion,
SERVER_XFIXES_MAJOR_VERSION,
SERVER_XFIXES_MAJOR_VERSION) < 0) {
SERVER_XFIXES_MINOR_VERSION) < 0) {
rep.majorVersion = stuff->majorVersion;
rep.minorVersion = stuff->minorVersion;
}

View File

@ -723,23 +723,27 @@ ProcessPointerEvent(InternalEvent *ev, DeviceIntPtr mouse)
changed |= XkbPointerButtonMask;
}
else if (event->type == ET_ButtonRelease) {
if (xkbi) {
xkbi->lockedPtrButtons &= ~(1 << (event->detail.key & 0x7));
if (IsMaster(dev)) {
DeviceIntPtr source;
int rc;
if (IsMaster(dev)) {
DeviceIntPtr source;
int rc;
rc = dixLookupDevice(&source, event->sourceid, serverClient,
DixWriteAccess);
if (rc != Success)
ErrorF("[xkb] bad sourceid '%d' on button release event.\n",
event->sourceid);
else if (!IsXTestDevice(source, GetMaster(dev, MASTER_POINTER))) {
DeviceIntPtr xtest_device;
rc = dixLookupDevice(&source, event->sourceid, serverClient,
DixWriteAccess);
if (rc != Success)
ErrorF("[xkb] bad sourceid '%d' on button release event.\n",
event->sourceid);
else if (!IsXTestDevice(source, GetMaster(dev, MASTER_POINTER)))
xtest_device = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
if (button_is_down(xtest_device, ev->device_event.detail.button, BUTTON_PROCESSED))
XkbFakeDeviceButton(dev, FALSE, event->detail.key);
}
}
if (xkbi)
xkbi->lockedPtrButtons &= ~(1 << (event->detail.key & 0x7));
changed |= XkbPointerButtonMask;
}