diff --git a/dix/events.c b/dix/events.c index 72b077ba2..177fa0514 100644 --- a/dix/events.c +++ b/dix/events.c @@ -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 -