dix: change the filters to be per-device.

If we have one global filter, one pointer may change the filter value and
affect another pointer.

Reproduceable effect:
blackbox and xterm, start dragging xterm then click anywhere with the other
pointer (attached to different masterd device!).  The button release resets
the filter[Motion_Filter(button)] value, thus stopping dragging and no event
is sent to the client anymore.
Having the filters set per device gets around this.
This commit is contained in:
Peter Hutterer 2007-12-04 19:07:46 +10:30
parent 0931f40bf1
commit f44d7dcb5f
4 changed files with 52 additions and 29 deletions

View File

@ -550,7 +550,7 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
return DONT_PROCESS; return DONT_PROCESS;
if (b->map[key] <= 5) if (b->map[key] <= 5)
b->state |= (Button1Mask >> 1) << b->map[key]; b->state |= (Button1Mask >> 1) << b->map[key];
SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify); SetMaskForEvent(device->id, Motion_Filter(b), DeviceMotionNotify);
} else if (xE->u.u.type == DeviceButtonRelease) { } else if (xE->u.u.type == DeviceButtonRelease) {
if (!b) if (!b)
return DONT_PROCESS; return DONT_PROCESS;
@ -567,7 +567,7 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
return DONT_PROCESS; return DONT_PROCESS;
if (b->map[key] <= 5) if (b->map[key] <= 5)
b->state &= ~((Button1Mask >> 1) << b->map[key]); b->state &= ~((Button1Mask >> 1) << b->map[key]);
SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify); SetMaskForEvent(device->id, Motion_Filter(b), DeviceMotionNotify);
} else if (xE->u.u.type == ProximityIn) } else if (xE->u.u.type == ProximityIn)
device->valuator->mode &= ~OutOfProximity; device->valuator->mode &= ~OutOfProximity;
else if (xE->u.u.type == ProximityOut) else if (xE->u.u.type == ProximityOut)

View File

@ -827,13 +827,16 @@ SetExclusiveAccess(Mask mask)
static void static void
SetMaskForExtEvent(Mask mask, int event) SetMaskForExtEvent(Mask mask, int event)
{ {
int i;
EventInfo[ExtEventIndex].mask = mask; EventInfo[ExtEventIndex].mask = mask;
EventInfo[ExtEventIndex++].type = event; EventInfo[ExtEventIndex++].type = event;
if ((event < LASTEvent) || (event >= 128)) if ((event < LASTEvent) || (event >= 128))
FatalError("MaskForExtensionEvent: bogus event number"); FatalError("MaskForExtensionEvent: bogus event number");
SetMaskForEvent(mask, event);
for (i = 0; i < MAX_DEVICES; i++)
SetMaskForEvent(i, mask, event);
} }
/************************************************************************ /************************************************************************
@ -974,13 +977,16 @@ FixExtensionEvents(ExtensionEntry * extEntry)
static void static void
RestoreExtensionEvents(void) RestoreExtensionEvents(void)
{ {
int i; int i, j;
IReqCode = 0; IReqCode = 0;
for (i = 0; i < ExtEventIndex - 1; i++) { for (i = 0; i < ExtEventIndex - 1; i++) {
if ((EventInfo[i].type >= LASTEvent) && (EventInfo[i].type < 128)) if ((EventInfo[i].type >= LASTEvent) && (EventInfo[i].type < 128))
SetMaskForEvent(0, EventInfo[i].type); {
for (j = 0; j < MAX_DEVICES; j++)
SetMaskForEvent(j, 0, EventInfo[i].type);
}
EventInfo[i].mask = 0; EventInfo[i].mask = 0;
EventInfo[i].type = 0; EventInfo[i].type = 0;
} }

View File

@ -367,8 +367,12 @@ static Mask lastEventMask;
extern int DeviceMotionNotify; extern int DeviceMotionNotify;
/**
* Event filters. One set of filters for each device, but only the first layer
* is initialized. The rest is memcpy'd in InitEvents.
*/
#define CantBeFiltered NoEventMask #define CantBeFiltered NoEventMask
static Mask filters[128] = static Mask filters[MAX_DEVICES][128] = {
{ {
NoSuchEvent, /* 0 */ NoSuchEvent, /* 0 */
NoSuchEvent, /* 1 */ NoSuchEvent, /* 1 */
@ -405,7 +409,7 @@ static Mask filters[128] =
ColormapChangeMask, /* ColormapNotify */ ColormapChangeMask, /* ColormapNotify */
CantBeFiltered, /* ClientMessage */ CantBeFiltered, /* ClientMessage */
CantBeFiltered /* MappingNotify */ CantBeFiltered /* MappingNotify */
}; }};
/** /**
@ -787,17 +791,19 @@ XineramaChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
#endif /* PANORAMIX */ #endif /* PANORAMIX */
void void
SetMaskForEvent(Mask mask, int event) SetMaskForEvent(int deviceid, Mask mask, int event)
{ {
int coretype; int coretype;
if (deviceid < 0 || deviceid > MAX_DEVICES)
FatalError("SetMaskForEvent: bogus device id");
if ((event < LASTEvent) || (event >= 128)) if ((event < LASTEvent) || (event >= 128))
FatalError("SetMaskForEvent: bogus event number"); FatalError("SetMaskForEvent: bogus event number");
filters[event] = mask; filters[deviceid][event] = mask;
/* Need to change the mask for the core events too */ /* Need to change the mask for the core events too */
coretype = XItoCoreType(event); coretype = XItoCoreType(event);
if (coretype) if (coretype)
filters[coretype] = mask; filters[deviceid][coretype] = mask;
} }
_X_EXPORT void _X_EXPORT void
@ -2440,7 +2446,7 @@ DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab,
{ {
Window child = None; Window child = None;
int type = xE->u.u.type; int type = xE->u.u.type;
Mask filter = filters[type]; Mask filter = filters[dev->id][type];
int deliveries = 0; int deliveries = 0;
if (type & EXTENSION_EVENT_BASE) if (type & EXTENSION_EVENT_BASE)
@ -2555,7 +2561,9 @@ DeliverEvents(WindowPtr pWin, xEvent *xE, int count,
if (!count) if (!count)
return 0; return 0;
filter = filters[xE->u.u.type]; /* We don't know a device here. However, this should only ever be called
for a non-device event so we are safe to use 0*/
filter = filters[0][xE->u.u.type];
if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify)) if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify))
xE->u.destroyNotify.event = pWin->drawable.id; xE->u.destroyNotify.event = pWin->drawable.id;
if (filter != StructureAndSubMask) if (filter != StructureAndSubMask)
@ -3466,8 +3474,8 @@ CheckPassiveGrabsOnWindow(
FixUpEventFromWindow(device, xE, grab->window, None, TRUE); FixUpEventFromWindow(device, xE, grab->window, None, TRUE);
(void) TryClientEvents(rClient(grab), xE, count, (void) TryClientEvents(rClient(grab), xE, count,
filters[xE->u.u.type], filters[device->id][xE->u.u.type],
filters[xE->u.u.type], grab); filters[device->id][xE->u.u.type], grab);
if (grabinfo->sync.state == FROZEN_NO_EVENT) if (grabinfo->sync.state == FROZEN_NO_EVENT)
{ {
@ -3590,7 +3598,8 @@ DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
FixUpEventFromWindow(pointer, xE, focus, None, FALSE); FixUpEventFromWindow(pointer, xE, focus, None, FALSE);
if (xE->u.u.type & EXTENSION_EVENT_BASE) if (xE->u.u.type & EXTENSION_EVENT_BASE)
mskidx = keybd->id; mskidx = keybd->id;
(void)DeliverEventsToWindow(keybd, focus, xE, count, filters[xE->u.u.type], (void)DeliverEventsToWindow(keybd, focus, xE, count,
filters[keybd->id][xE->u.u.type],
NullGrab, mskidx); NullGrab, mskidx);
} }
@ -3671,7 +3680,7 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
IsInterferingGrab(rClient(grab), thisDev, xE))) IsInterferingGrab(rClient(grab), thisDev, xE)))
{ {
deliveries = TryClientEvents(rClient(grab), xE, count, deliveries = TryClientEvents(rClient(grab), xE, count,
mask, filters[xE->u.u.type], grab); mask, filters[thisDev->id][xE->u.u.type], grab);
} }
} }
if (deliveries && (xE->u.u.type == MotionNotify if (deliveries && (xE->u.u.type == MotionNotify
@ -3989,7 +3998,7 @@ ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
*/ */
if (xE->u.u.detail == 0) if (xE->u.u.detail == 0)
return; return;
filters[MotionNotify] = Motion_Filter(butc); filters[mouse->id][Motion_Filter(butc)] = MotionNotify;
if (!grab) if (!grab)
if (CheckDeviceGrabs(mouse, xE, 0, count)) if (CheckDeviceGrabs(mouse, xE, 0, count))
return; return;
@ -3997,7 +4006,7 @@ ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
case ButtonRelease: case ButtonRelease:
if (xE->u.u.detail == 0) if (xE->u.u.detail == 0)
return; return;
filters[MotionNotify] = Motion_Filter(butc); filters[mouse->id][Motion_Filter(butc)] = MotionNotify;
if (!butc->state && mouse->deviceGrab.fromPassiveGrab) if (!butc->state && mouse->deviceGrab.fromPassiveGrab)
deactivateGrab = TRUE; deactivateGrab = TRUE;
break; break;
@ -4350,14 +4359,14 @@ EnterLeaveEvent(
sendevent = TRUE; sendevent = TRUE;
} }
if ((mask & filters[type]) && sendevent) if ((mask & filters[mouse->id][type]) && sendevent)
{ {
if (grab) if (grab)
(void)TryClientEvents(rClient(grab), &event, 1, mask, (void)TryClientEvents(rClient(grab), &event, 1, mask,
filters[type], grab); filters[mouse->id][type], grab);
else else
(void)DeliverEventsToWindow(mouse, pWin, &event, 1, filters[type], (void)DeliverEventsToWindow(mouse, pWin, &event, 1,
NullGrab, 0); filters[mouse->id][type], NullGrab, 0);
} }
/* we don't have enough bytes, so we squash flags and mode into /* we don't have enough bytes, so we squash flags and mode into
@ -4372,14 +4381,16 @@ EnterLeaveEvent(
mskidx = mouse->id; mskidx = mouse->id;
inputMasks = wOtherInputMasks(pWin); inputMasks = wOtherInputMasks(pWin);
if (inputMasks && if (inputMasks &&
(filters[devEnterLeave->type] & inputMasks->deliverableEvents[mskidx])) (filters[mouse->id][devEnterLeave->type] &
inputMasks->deliverableEvents[mskidx]))
{ {
if (devgrab) if (devgrab)
(void)TryClientEvents(rClient(devgrab), (xEvent*)devEnterLeave, 1, (void)TryClientEvents(rClient(devgrab), (xEvent*)devEnterLeave, 1,
mask, filters[devEnterLeave->type], devgrab); mask, filters[mouse->id][devEnterLeave->type],
devgrab);
else else
(void)DeliverEventsToWindow(mouse, pWin, (xEvent*)devEnterLeave, (void)DeliverEventsToWindow(mouse, pWin, (xEvent*)devEnterLeave,
1, filters[devEnterLeave->type], 1, filters[mouse->id][devEnterLeave->type],
NullGrab, mouse->id); NullGrab, mouse->id);
} }
@ -4579,8 +4590,8 @@ FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
event.u.u.type = type; event.u.u.type = type;
event.u.u.detail = detail; event.u.u.detail = detail;
event.u.focus.window = pWin->drawable.id; event.u.focus.window = pWin->drawable.id;
(void)DeliverEventsToWindow(dev, pWin, &event, 1, filters[type], NullGrab, (void)DeliverEventsToWindow(dev, pWin, &event, 1,
0); filters[dev->id][type], NullGrab, 0);
if ((type == FocusIn) && if ((type == FocusIn) &&
((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
{ {
@ -5528,7 +5539,12 @@ InitEvents(void)
inputInfo.keyboard = (DeviceIntPtr)NULL; inputInfo.keyboard = (DeviceIntPtr)NULL;
inputInfo.pointer = (DeviceIntPtr)NULL; inputInfo.pointer = (DeviceIntPtr)NULL;
lastEventMask = OwnerGrabButtonMask; lastEventMask = OwnerGrabButtonMask;
filters[MotionNotify] = PointerMotionMask; filters[0][PointerMotionMask] = MotionNotify;
for (i = 1; i < MAX_DEVICES; i++)
{
memcpy(&filters[i], filters[0], sizeof(filters[0]));
}
#ifdef XEVIE #ifdef XEVIE
xeviewin = NULL; xeviewin = NULL;
#endif #endif

View File

@ -345,6 +345,7 @@ extern void SetVendorString(char *string);
/* events.c */ /* events.c */
extern void SetMaskForEvent( extern void SetMaskForEvent(
int /* deviceid */,
Mask /* mask */, Mask /* mask */,
int /* event */); int /* event */);