dix: Enable XI2 delivery for events and focused events.

No support for grabbed events yet.
This commit is contained in:
Peter Hutterer 2009-03-06 14:45:26 +10:00
parent 87ff1159b4
commit 808a158182

View File

@ -409,16 +409,24 @@ static Mask filters[MAXDEVICES][128] = {
* For the given event, return the matching event filter. This filter may then
* be AND'ed with the selected event mask.
*
* For XI2 events, the returned filter is simply the byte containing the event
* mask we're interested in. E.g. for a mask of (1 << 13), this would be
* byte[1].
*
* @param[in] dev The device the event belongs to, may be NULL.
* @param[in] event The event to get the filter for. Only the type of the
* event matters, or the extension + evtype for GenericEvents.
* @return The filter mask for the given event.
*
* @see GetEventMask
*/
static Mask
GetEventFilter(DeviceIntPtr dev, xEvent *event)
{
if (event->u.u.type != GenericEvent)
return filters[dev ? dev->id : 0][event->u.u.type];
else if (XI2_EVENT(event))
return (1 << (((xXIDeviceEvent*)event)->evtype % 8));
ErrorF("[dix] Unknown device type %d. No filter\n", event->u.u.type);
return 0;
}
@ -444,6 +452,21 @@ GetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev)
(inputMasks->xi2mask[AllMasterDevices][evtype/8] && dev->isMaster));
}
static Mask
GetEventMask(DeviceIntPtr dev, xEvent *event, InputClients* other)
{
/* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */
if (XI2_EVENT(event))
{
int byte = ((xGenericEvent*)event)->evtype / 8;
return other->xi2mask[dev->id][byte];
} else if (CORE_EVENT(event))
return other->mask[AllDevices];
else
return other->mask[dev->id];
}
static CARD8 criticalEvents[32] =
{
0x7c, 0x30, 0x40 /* key, button, expose, and configure events */
@ -1969,7 +1992,16 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
{
if (CORE_EVENT(pEvents))
other = (InputClients *)wOtherClients(pWin);
else {
else if (XI2_EVENT(pEvents))
{
OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
int evtype = ((xGenericEvent*)pEvents)->evtype;
/* Has any client selected for the event? */
if (!inputMasks ||
!(inputMasks->xi2mask[mskidx][evtype/8] & filter))
return 0;
other = inputMasks->inputClients;
} else {
OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
/* Has any client selected for the event? */
if (!inputMasks ||
@ -1981,22 +2013,24 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
for (; other; other = other->next)
{
Mask mask;
if (IsInterferingGrab(rClient(other), pDev, pEvents))
continue;
mask = GetEventMask(pDev, pEvents, other);
if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin,
pEvents, count))
/* do nothing */;
else if ( (attempt = TryClientEvents(rClient(other), pDev,
pEvents, count,
other->mask[mskidx],
filter, grab)) )
mask, filter, grab)) )
{
if (attempt > 0)
{
deliveries++;
client = rClient(other);
deliveryMask = other->mask[mskidx];
deliveryMask = mask;
} else
nondeliveries--;
}
@ -2225,6 +2259,7 @@ FixUpEventFromWindow(
#define XI_MASK (1 << 0) /**< XI mask set on window */
#define CORE_MASK (1 << 1) /**< Core mask set on window */
#define DONT_PROPAGATE_MASK (1 << 2) /**< DontPropagate mask set on window */
#define XI2_MASK (1 << 3) /**< XI2 mask set on window */
/* @} */
/**
@ -2236,13 +2271,12 @@ FixUpEventFromWindow(
* @param[in] dev The device this event is being sent for.
* @param[in] event The event that is to be sent.
* @param[in] win The current event window.
* @param[out] filter_out The event filter for this event.
*
* @return Bitmask of ::XI_MASK, ::CORE_MASK, and ::DONT_PROPAGATE_MASK.
* @return Bitmask of ::XI2_MASK, ::XI_MASK, ::CORE_MASK, and
* ::DONT_PROPAGATE_MASK.
*/
static int
EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win,
Mask *filter_out)
EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win)
{
int rc = 0;
int filter = 0;
@ -2250,12 +2284,22 @@ EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win,
OtherInputMasks *inputMasks;
xEvent ev;
/* XXX: this makes me gag */
type = GetXI2Type(event);
ev.u.u.type = GenericEvent; /* GetEventFilter only cares about type and evtype*/
((xGenericEvent*)&ev)->extension = IReqCode;
((xGenericEvent*)&ev)->evtype = type;
filter = GetEventFilter(dev, &ev);
if (type && (inputMasks = wOtherInputMasks(win)) &&
inputMasks->xi2mask[dev->id][type / 8] & filter)
rc |= XI2_MASK;
type = GetXIType(event);
ev.u.u.type = type; /* GetEventFilter only cares about type */
ev.u.u.type = type;
filter = GetEventFilter(dev, &ev);
/* Check for XI mask */
if (type && (inputMasks = wOtherInputMasks(win)) &&
if (type && inputMasks &&
(inputMasks->deliverableEvents[dev->id] & filter) &&
(inputMasks->inputEvents[dev->id] & filter))
rc |= XI_MASK;
@ -2275,7 +2319,6 @@ EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win,
if (type && (filter & wDontPropagateMask(win)))
rc |= DONT_PROPAGATE_MASK;
*filter_out = filter;
return rc;
}
@ -2330,11 +2373,31 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
while (pWin)
{
if ((mask = EventIsDeliverable(dev, event, pWin, &filter)))
if ((mask = EventIsDeliverable(dev, event, pWin)))
{
if (mask & XI2_MASK)
{
xEvent *xi2 = NULL;
rc = EventToXI2(event, &xi2);
if (rc != Success)
{
ErrorF("[dix] %s: XI2 conversion failed in DDE (%d).\n",
dev->name, rc);
goto unwind;
}
filter = GetEventFilter(dev, xi2);
FixUpEventFromWindow(dev, xi2, pWin, child, FALSE);
deliveries = DeliverEventsToWindow(dev, pWin, xi2, 1,
filter, grab, dev->id);
xfree(xi2);
if (deliveries > 0)
goto unwind;
}
/* XI events first */
if (mask & XI_MASK)
{
filter = GetEventFilter(dev, xE);
FixUpEventFromWindow(dev, xE, pWin, child, FALSE);
deliveries = DeliverEventsToWindow(dev, pWin, xE, count,
filter, grab, dev->id);
@ -2354,6 +2417,7 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
goto unwind;
}
filter = GetEventFilter(dev, &core);
FixUpEventFromWindow(dev, &core, pWin, child, FALSE);
deliveries = DeliverEventsToWindow(dev, pWin, &core, 1,
filter, grab, dev->id);
@ -3232,6 +3296,7 @@ CheckPassiveGrabsOnWindow(
xkbi= gdev->key->xkbInfo;
tempGrab.modifierDevice = grab->modifierDevice;
tempGrab.modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
/* FIXME: check for xi2 grabs */
/* Check for XI grabs first */
tempGrab.type = GetXIType((InternalEvent*)event);
@ -3435,7 +3500,7 @@ DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
WindowPtr focus = keybd->focus->win;
BOOL sendCore = (keybd->isMaster && keybd->coreEvents);
xEvent core;
xEvent *xE = NULL;
xEvent *xE = NULL, *xi2 = NULL;
int count, rc;
int deliveries = 0;
@ -3455,7 +3520,6 @@ DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
}
ptr = GetPairedDevice(keybd);
rc = EventToXI(event, &xE, &count);
if (rc != Success)
{
@ -3468,6 +3532,23 @@ DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count))
goto unwind;
rc = EventToXI2(event, &xi2);
if (rc != Success)
{
ErrorF("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n",
keybd->name, event->u.any.type, rc);
goto unwind;
} else if (xi2)
{
int filter = GetEventFilter(keybd, xi2);
/* just deliver it to the focus window */
FixUpEventFromWindow(ptr, xi2, focus, None, FALSE);
deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1,
filter, NullGrab, keybd->id);
if (deliveries > 0)
goto unwind;
}
/* just deliver it to the focus window */
FixUpEventFromWindow(ptr, xE, focus, None, FALSE);
deliveries = DeliverEventsToWindow(keybd, focus, xE, count,
@ -3496,6 +3577,8 @@ DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
unwind:
if (xE)
xfree(xE);
if (xi2)
xfree(xi2);
return;
}
@ -3518,6 +3601,7 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
BOOL sendCore = FALSE;
int rc, count = 0;
xEvent *xi = NULL;
xEvent *xi2 = NULL;
grabinfo = &thisDev->deviceGrab;
grab = grabinfo->grab;
@ -3554,12 +3638,21 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
if (!deliveries)
{
Mask mask;
/* XXX: In theory, we could pass the internal events through to
* everything and only convert just before hitting the wire. We can't
* do that yet, so DGE is the last stop for internal events. From here
* onwards, we deal with core/XI events.
*/
rc = EventToXI2(event, &xi2);
if (rc != Success)
{
ErrorF("[dix] %s: XI2 conversion failed in DGE (%d, %d). Skipping delivery.\n",
thisDev->name, event->u.any.type, rc);
goto unwind;
}
rc = EventToXI(event, &xi, &count);
if (rc != Success)
{
@ -3660,6 +3753,8 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
unwind:
if (xi)
xfree(xi);
if (xi2)
xfree(xi2);
}
/* This function is used to set the key pressed or key released state -