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:
parent
0969a9f749
commit
32aa252e98
|
@ -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);
|
||||||
|
|
246
dix/events.c
246
dix/events.c
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue