dix: Process an input event as a single event, instead of two separate ones.

This is a significant shift in how input events are perceived. The common
approach was to treat a core event as a different entity than the XI event.
This could result in the XI event being delivered to a different client than
the core event. This doesn't work nicely if they come from the same device.

Instead, we treat an input event as a single event, that is delivered through
two separate APIs. So when delivering an event, we first try the XI event,
then the core event. If the window want's neither, we go to the parent and
repeat. Once either core or XI has been delivered, the processing stops.

Important: Different to the previous method, if a client registers for core
button events, the parent window will not get XI events. This should only
cause problems when you're mixing core and XI events, so don't do that!

Generic events don't fit into this yet, they cause me headaches.
This commit is contained in:
Peter Hutterer 2008-01-15 15:22:39 +10:30
parent 0969a9f749
commit 32aa252e98
2 changed files with 145 additions and 120 deletions

View File

@ -724,32 +724,13 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
deactivateDeviceGrab = TRUE; deactivateDeviceGrab = TRUE;
} }
if (sendCore)
{
core = *xE;
core.u.u.type = coretype;
}
if (grab) if (grab)
{
if (sendCore) /* never deactivate from core */
DeliverGrabbedEvent(&core, device, FALSE , 1);
DeliverGrabbedEvent(xE, device, deactivateDeviceGrab, count); DeliverGrabbedEvent(xE, device, deactivateDeviceGrab, count);
}
else if (device->focus) else if (device->focus)
{
if (sendCore)
DeliverFocusedEvent(device, &core, GetSpriteWindow(device), 1);
DeliverFocusedEvent(device, xE, GetSpriteWindow(device), count); DeliverFocusedEvent(device, xE, GetSpriteWindow(device), count);
}
else else
{
if (sendCore)
DeliverDeviceEvents(GetSpriteWindow(device), &core, NullGrab,
NullWindow, device, 1);
DeliverDeviceEvents(GetSpriteWindow(device), xE, NullGrab, NullWindow, DeliverDeviceEvents(GetSpriteWindow(device), xE, NullGrab, NullWindow,
device, count); device, count);
}
if (deactivateDeviceGrab == TRUE) if (deactivateDeviceGrab == TRUE)
(*device->deviceGrab.DeactivateGrab) (device); (*device->deviceGrab.DeactivateGrab) (device);

View File

@ -1369,11 +1369,10 @@ ComputeFreezes(void)
DeviceIntPtr replayDev = syncEvents.replayDev; DeviceIntPtr replayDev = syncEvents.replayDev;
int i; int i;
WindowPtr w; WindowPtr w;
xEvent *xE, core; xEvent *xE;
int count; int count;
GrabPtr grab; GrabPtr grab;
DeviceIntPtr dev; DeviceIntPtr dev;
BOOL sendCore;
for (dev = inputInfo.devices; dev; dev = dev->next) for (dev = inputInfo.devices; dev; dev = dev->next)
FreezeThaw(dev, dev->deviceGrab.sync.other || FreezeThaw(dev, dev->deviceGrab.sync.other ||
@ -1394,24 +1393,11 @@ ComputeFreezes(void)
replayDev->spriteInfo->sprite->spriteTrace[i]) replayDev->spriteInfo->sprite->spriteTrace[i])
{ {
if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) { if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) {
sendCore = (replayDev->coreEvents && replayDev->isMaster);
core = *xE;
core.u.u.type = XItoCoreType(xE->u.u.type);
if (replayDev->focus) if (replayDev->focus)
{
if (sendCore)
DeliverFocusedEvent(replayDev, &core, w, 1);
DeliverFocusedEvent(replayDev, xE, w, count); DeliverFocusedEvent(replayDev, xE, w, count);
}
else else
{
if (sendCore)
DeliverDeviceEvents(w, &core, NullGrab,
NullWindow, replayDev, 1);
DeliverDeviceEvents(w, xE, NullGrab, NullWindow, DeliverDeviceEvents(w, xE, NullGrab, NullWindow,
replayDev, count); replayDev, count);
}
} }
goto playmore; goto playmore;
} }
@ -2439,92 +2425,97 @@ DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab,
int type = xE->u.u.type; int type = xE->u.u.type;
Mask filter = filters[dev->id][type]; Mask filter = filters[dev->id][type];
int deliveries = 0; int deliveries = 0;
OtherInputMasks *inputMasks;
int mskidx = dev->id;
xEvent core;
if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count)) if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count))
return 0; return 0;
if (type & EXTENSION_EVENT_BASE) /* handle generic events */
/* XXX: Generic events aren't quite handled correctly yet. They should
* eventually fit in with the rest of the stuff
*/
if (type == GenericEvent)
{ {
OtherInputMasks *inputMasks; WindowPtr win = pWin;
int mskidx = dev->id; xGenericEvent* ge = (xGenericEvent*)xE;
inputMasks = wOtherInputMasks(pWin); if (count > 1)
if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx]))
return 0;
while (pWin)
{
if (inputMasks && (inputMasks->inputEvents[mskidx] & filter))
{
FixUpEventFromWindow(dev, xE, pWin, child, FALSE);
deliveries = DeliverEventsToWindow(dev, pWin, xE, count, filter,
grab, mskidx);
if (deliveries > 0)
return deliveries;
}
if ((deliveries < 0) ||
(pWin == stopAt) ||
(inputMasks &&
(filter & inputMasks->dontPropagateMask[mskidx])))
return 0;
child = pWin->drawable.id;
pWin = pWin->parent;
if (pWin)
inputMasks = wOtherInputMasks(pWin);
}
}
else
{
/* handle generic events */
if (type == GenericEvent)
{ {
xGenericEvent* ge = (xGenericEvent*)xE; ErrorF("[dix] Do not send more than one GenericEvent at a time!\n");
return 0;
if (count > 1)
{
ErrorF("[dix] Do not send more than one GenericEvent at a time!\n");
return 0;
}
filter = generic_filters[GEEXTIDX(xE)][ge->evtype];
while(pWin)
{
if (GEMaskIsSet(pWin, GEEXT(xE), filter))
{
if (GEExtensions[GEEXTIDX(xE)].evfill)
GEExtensions[GEEXTIDX(xE)].evfill(ge, dev, pWin, grab);
deliveries = DeliverEventsToWindow(dev, pWin, xE, count,
filter, grab, 0);
if (deliveries > 0)
return deliveries;
}
pWin = pWin->parent;
}
} }
else filter = generic_filters[GEEXTIDX(xE)][ge->evtype];
while(win)
{ {
/* core protocol events */ if (GEMaskIsSet(win, GEEXT(xE), filter))
if (!(filter & pWin->deliverableEvents)) {
if (GEExtensions[GEEXTIDX(xE)].evfill)
GEExtensions[GEEXTIDX(xE)].evfill(ge, dev, win, grab);
deliveries = DeliverEventsToWindow(dev, win, xE, count,
filter, grab, 0);
if (deliveries > 0)
return deliveries;
}
win = win->parent;
}
}
while (pWin && type != GenericEvent)
{
/* First try XI event delivery */
inputMasks = wOtherInputMasks(pWin);
if (inputMasks && (filter & inputMasks->deliverableEvents[mskidx]))
{
if (inputMasks && (inputMasks->inputEvents[mskidx] & filter))
{
FixUpEventFromWindow(dev, xE, pWin, child, FALSE);
deliveries = DeliverEventsToWindow(dev, pWin, xE, count,
filter, grab, mskidx);
if (deliveries > 0)
return deliveries;
}
if ((deliveries < 0) ||
(pWin == stopAt) ||
(inputMasks &&
(filter & inputMasks->dontPropagateMask[mskidx])))
return 0; return 0;
while (pWin) }
if (dev->isMaster && dev->coreEvents)
{
/* no XI event delivered. Try core event */
core = *xE;
core.u.u.type = XItoCoreType(xE->u.u.type);
if (filter & pWin->deliverableEvents)
{ {
if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter) if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter)
{ {
FixUpEventFromWindow(dev, xE, pWin, child, FALSE); FixUpEventFromWindow(dev, &core, pWin, child, FALSE);
deliveries = DeliverEventsToWindow(dev, pWin, xE, count, filter, deliveries = DeliverEventsToWindow(dev, pWin, &core, 1,
grab, 0); filter, grab, 0);
if (deliveries > 0) if (deliveries > 0)
return deliveries; return deliveries;
} }
if ((deliveries < 0) || if ((deliveries < 0) ||
(pWin == stopAt) || (pWin == stopAt) ||
(filter & wDontPropagateMask(pWin))) (filter & wDontPropagateMask(pWin)))
return 0; return 0;
child = pWin->drawable.id;
pWin = pWin->parent;
} }
} }
child = pWin->drawable.id;
pWin = pWin->parent;
} }
return 0; return 0;
} }
@ -3604,7 +3595,10 @@ DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
{ {
DeviceIntPtr pointer; DeviceIntPtr pointer;
WindowPtr focus = keybd->focus->win; WindowPtr focus = keybd->focus->win;
int mskidx = 0; BOOL sendCore = (keybd->isMaster && keybd->coreEvents);
xEvent core;
int deliveries = 0;
if (focus == FollowKeyboardWin) if (focus == FollowKeyboardWin)
focus = inputInfo.keyboard->focus->win; focus = inputInfo.keyboard->focus->win;
if (!focus) if (!focus)
@ -3622,13 +3616,29 @@ DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
pointer = GetPairedDevice(keybd); pointer = GetPairedDevice(keybd);
if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count)) if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count))
return; return;
if (sendCore)
{
core = *xE;
core.u.u.type = XItoCoreType(xE->u.u.type);
}
/* just deliver it to the focus window */ /* just deliver it to the focus window */
FixUpEventFromWindow(pointer, xE, focus, None, FALSE); FixUpEventFromWindow(pointer, xE, focus, None, FALSE);
if (xE->u.u.type & EXTENSION_EVENT_BASE) deliveries = DeliverEventsToWindow(keybd, focus, xE, count,
mskidx = keybd->id; filters[keybd->id][xE->u.u.type],
(void)DeliverEventsToWindow(keybd, focus, xE, count, NullGrab, keybd->id);
filters[keybd->id][xE->u.u.type],
NullGrab, mskidx); if (deliveries > 0)
return;
if (sendCore)
{
FixUpEventFromWindow(keybd, &core, focus, None, FALSE);
deliveries = DeliverEventsToWindow(keybd, focus, &core, 1,
filters[keybd->id][xE->u.u.type],
NullGrab, 0);
}
} }
/** /**
@ -3646,8 +3656,9 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
GrabInfoPtr grabinfo; GrabInfoPtr grabinfo;
int deliveries = 0; int deliveries = 0;
DeviceIntPtr dev; DeviceIntPtr dev;
xEvent *dxE; xEvent *dxE, core;
SpritePtr pSprite = thisDev->spriteInfo->sprite; SpritePtr pSprite = thisDev->spriteInfo->sprite;
BOOL sendCore = FALSE;
grabinfo = &thisDev->deviceGrab; grabinfo = &thisDev->deviceGrab;
grab = grabinfo->grab; grab = grabinfo->grab;
@ -3697,23 +3708,56 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
} else } else
{ {
Mask mask = grab->eventMask; Mask mask = grab->eventMask;
if (grabinfo->fromPassiveGrab &&
grabinfo->implicitGrab &&
(xE->u.u.type & EXTENSION_EVENT_BASE))
mask = grab->deviceMask;
FixUpEventFromWindow(thisDev, xE, grab->window, None, TRUE); sendCore = (thisDev->isMaster && thisDev->coreEvents);
/* try core event */
if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, grab->window, xE, if (sendCore && grab->coreGrab)
count) ||
XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), grab->window,
xE, count))
deliveries = 1; /* don't send, but pretend we did */
else if (!(!(xE->u.u.type & EXTENSION_EVENT_BASE) &&
IsInterferingGrab(rClient(grab), thisDev, xE)))
{ {
deliveries = TryClientEvents(rClient(grab), xE, count, core = *xE;
mask, filters[thisDev->id][xE->u.u.type], grab); core.u.u.type = XItoCoreType(xE->u.u.type);
FixUpEventFromWindow(thisDev, &core, grab->window,
None, TRUE);
if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
grab->window, &core, 1) ||
XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
grab->window, &count, 1))
deliveries = 1; /* don't send, but pretend we did */
else if (!IsInterferingGrab(rClient(grab), thisDev,
&core))
{
deliveries = TryClientEvents(rClient(grab), &core, 1,
mask,
filters[thisDev->id][core.u.u.type],
grab);
}
}
if (!deliveries)
{
/* try XI event */
if (grabinfo->fromPassiveGrab &&
grabinfo->implicitGrab &&
(xE->u.u.type & EXTENSION_EVENT_BASE))
mask = grab->deviceMask;
FixUpEventFromWindow(thisDev, xE, grab->window,
None, TRUE);
if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
grab->window, xE, count) ||
XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
grab->window,
xE, count))
deliveries = 1; /* don't send, but pretend we did */
else
{
deliveries =
TryClientEvents(rClient(grab),
xE, count,
mask,
filters[thisDev->id][xE->u.u.type],
grab);
}
} }
} }
if (deliveries && (xE->u.u.type == MotionNotify if (deliveries && (xE->u.u.type == MotionNotify