diff options
Diffstat (limited to 'xorg-server/dix')
-rw-r--r-- | xorg-server/dix/devices.c | 10 | ||||
-rw-r--r-- | xorg-server/dix/eventconvert.c | 2 | ||||
-rw-r--r-- | xorg-server/dix/events.c | 664 | ||||
-rw-r--r-- | xorg-server/dix/getevents.c | 204 | ||||
-rw-r--r-- | xorg-server/dix/inpututils.c | 28 |
5 files changed, 560 insertions, 348 deletions
diff --git a/xorg-server/dix/devices.c b/xorg-server/dix/devices.c index 3f46ad6fb..9a4498b9f 100644 --- a/xorg-server/dix/devices.c +++ b/xorg-server/dix/devices.c @@ -2365,10 +2365,10 @@ RecalculateMasterButtons(DeviceIntPtr slave) * Generate release events for all keys/button currently down on this * device. */ -static void +void ReleaseButtonsAndKeys(DeviceIntPtr dev) { - EventListPtr eventlist = InitEventList(GetMaximumEventsNum()); + InternalEvent* eventlist = InitEventList(GetMaximumEventsNum()); ButtonClassPtr b = dev->button; KeyClassPtr k = dev->key; int i, j, nevents; @@ -2383,7 +2383,7 @@ ReleaseButtonsAndKeys(DeviceIntPtr dev) { nevents = GetPointerEvents(eventlist, dev, ButtonRelease, i, 0, NULL); for (j = 0; j < nevents; j++) - mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL); + mieqProcessDeviceEvent(dev, &eventlist[j], NULL); } } @@ -2394,7 +2394,7 @@ ReleaseButtonsAndKeys(DeviceIntPtr dev) { nevents = GetKeyboardEvents(eventlist, dev, KeyRelease, i, NULL); for (j = 0; j < nevents; j++) - mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL); + mieqProcessDeviceEvent(dev, &eventlist[j], NULL); } } @@ -2434,8 +2434,6 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master) free(dev->spriteInfo->sprite); } - ReleaseButtonsAndKeys(dev); - oldmaster = GetMaster(dev, MASTER_ATTACHED); dev->master = master; diff --git a/xorg-server/dix/eventconvert.c b/xorg-server/dix/eventconvert.c index 14731f4f6..024f2e833 100644 --- a/xorg-server/dix/eventconvert.c +++ b/xorg-server/dix/eventconvert.c @@ -156,7 +156,7 @@ EventToCore(InternalEvent *event, xEvent **core_out, int *count_out) case ET_RawButtonRelease: case ET_RawMotion: ret = BadMatch; - goto out; + break; default: /* XXX: */ ErrorF("[dix] EventToCore: Not implemented yet \n"); diff --git a/xorg-server/dix/events.c b/xorg-server/dix/events.c index d70d62fd8..14f6f909e 100644 --- a/xorg-server/dix/events.c +++ b/xorg-server/dix/events.c @@ -176,12 +176,23 @@ typedef const char *string; #define AllEventMasks (LastEventMask|(LastEventMask-1)) -#define CORE_EVENT(event) \ - (!((event)->u.u.type & EXTENSION_EVENT_BASE) && \ - (event)->u.u.type != GenericEvent) -#define XI2_EVENT(event) \ - (((event)->u.u.type == GenericEvent) && \ - ((xGenericEvent*)(event))->extension == IReqCode) +/* @return the core event type or 0 if the event is not a core event */ +static inline int +core_get_type(const xEvent *event) +{ + int type = event->u.u.type; + + return ((type & EXTENSION_EVENT_BASE) || type == GenericEvent) ? 0 : type; +} + +/* @return the XI2 event type or 0 if the event is not a XI2 event */ +static inline int +xi2_get_type(const xEvent *event) +{ + xGenericEvent* e = (xGenericEvent*)event; + + return (e->type != GenericEvent || e->extension != IReqCode) ? 0 : e->evtype; +} /** * Used to indicate a implicit passive grab created by a ButtonPress event. @@ -345,8 +356,8 @@ extern int DeviceMotionNotify; /** * Event masks for each event type. * - * One set of filters for each device, but only the first layer - * is initialized. The rest is memcpy'd in InitEvents. + * One set of filters for each device, initialized by memcpy of + * default_filter in InitEvents. * * Filters are used whether a given event may be delivered to a client, * usually in the form of if (window-event-mask & filter); then deliver event. @@ -355,7 +366,9 @@ extern int DeviceMotionNotify; * time a button is pressed, the filter is modified to also contain the * matching ButtonXMotion mask. */ -static Mask filters[MAXDEVICES][128] = { +static Mask filters[MAXDEVICES][128]; + +static const Mask default_filter[128] = { NoSuchEvent, /* 0 */ NoSuchEvent, /* 1 */ @@ -392,7 +405,7 @@ static Mask filters[MAXDEVICES][128] = { ColormapChangeMask, /* ColormapNotify */ CantBeFiltered, /* ClientMessage */ CantBeFiltered /* MappingNotify */ -}}; +}; /** * For the given event, return the matching event filter. This filter may then @@ -412,10 +425,12 @@ static Mask filters[MAXDEVICES][128] = { Mask GetEventFilter(DeviceIntPtr dev, xEvent *event) { + int evtype = 0; + 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)); + else if ((evtype = xi2_get_type(event))) + return (1 << (evtype % 8)); ErrorF("[dix] Unknown device type %d. No filter\n", event->u.u.type); return 0; } @@ -430,7 +445,7 @@ GetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev) int filter; int evtype; - if (!inputMasks || !XI2_EVENT(ev)) + if (!inputMasks || xi2_get_type(ev) == 0) return 0; evtype = ((xGenericEvent*)ev)->evtype; @@ -444,14 +459,16 @@ GetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev) Mask GetEventMask(DeviceIntPtr dev, xEvent *event, InputClients* other) { + int evtype; + /* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */ - if (XI2_EVENT(event)) + if ((evtype = xi2_get_type(event))) { - int byte = ((xGenericEvent*)event)->evtype / 8; + int byte = evtype / 8; return (other->xi2mask[dev->id][byte] | other->xi2mask[XIAllDevices][byte] | (IsMaster(dev)? other->xi2mask[XIAllMasterDevices][byte] : 0)); - } else if (CORE_EVENT(event)) + } else if (core_get_type(event) != 0) return other->mask[XIAllDevices]; else return other->mask[dev->id]; @@ -1937,6 +1954,159 @@ TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents, return 1; } +static BOOL +ActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win, + xEvent *event, Mask deliveryMask) +{ + GrabRec tempGrab; + OtherInputMasks *inputMasks; + CARD8 type = event->u.u.type; + GrabType grabtype; + + if (type == ButtonPress) + grabtype = GRABTYPE_CORE; + else if (type == DeviceButtonPress) + grabtype = GRABTYPE_XI; + else if ((type = xi2_get_type(event)) == XI_ButtonPress) + grabtype = GRABTYPE_XI2; + else + return FALSE; + + memset(&tempGrab, 0, sizeof(GrabRec)); + tempGrab.next = NULL; + tempGrab.device = dev; + tempGrab.resource = client->clientAsMask; + tempGrab.window = win; + tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; + tempGrab.eventMask = deliveryMask; + tempGrab.keyboardMode = GrabModeAsync; + tempGrab.pointerMode = GrabModeAsync; + tempGrab.confineTo = NullWindow; + tempGrab.cursor = NullCursor; + tempGrab.type = type; + tempGrab.grabtype = grabtype; + + /* get the XI and XI2 device mask */ + inputMasks = wOtherInputMasks(win); + tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id]: 0; + + if (inputMasks) + memcpy(tempGrab.xi2mask, inputMasks->xi2mask, + sizeof(tempGrab.xi2mask)); + + (*dev->deviceGrab.ActivateGrab)(dev, &tempGrab, + currentTime, TRUE | ImplicitGrabMask); + return TRUE; +} + +enum EventDeliveryState { + EVENT_DELIVERED, /**< Event has been delivered to a client */ + EVENT_NOT_DELIVERED, /**< Event was not delivered to any client */ + EVENT_SKIP, /**< Event can be discarded by the caller */ + EVENT_REJECTED, /**< Event was rejected for delivery to the client */ +}; + +/** + * Attempt event delivery to the client owning the window. + */ +static enum EventDeliveryState +DeliverToWindowOwner(DeviceIntPtr dev, WindowPtr win, + xEvent *events, int count, Mask filter, + GrabPtr grab) +{ + /* if nobody ever wants to see this event, skip some work */ + if (filter != CantBeFiltered && + !((wOtherEventMasks(win)|win->eventMask) & filter)) + return EVENT_SKIP; + + if (IsInterferingGrab(wClient(win), dev, events)) + return EVENT_SKIP; + + if (!XaceHook(XACE_RECEIVE_ACCESS, wClient(win), win, events, count)) + { + int attempt = TryClientEvents(wClient(win), dev, events, + count, win->eventMask, + filter, grab); + if (attempt > 0) + return EVENT_DELIVERED; + if (attempt < 0) + return EVENT_REJECTED; + } + + return EVENT_NOT_DELIVERED; +} + +/** + * Deliver events to clients registered on the window. + * + * @param client_return On successful delivery, set to the recipient. + * @param mask_return On successful delivery, set to the recipient's event + * mask for this event. + */ +static enum EventDeliveryState +DeliverEventToClients(DeviceIntPtr dev, WindowPtr win, xEvent *events, + int count, Mask filter, GrabPtr grab, + ClientPtr *client_return, Mask *mask_return) +{ + int attempt; + enum EventDeliveryState rc = EVENT_SKIP; + InputClients *other; + + if (core_get_type(events) != 0) + other = (InputClients *)wOtherClients(win); + else if (xi2_get_type(events) != 0) + { + OtherInputMasks *inputMasks = wOtherInputMasks(win); + /* Has any client selected for the event? */ + if (!GetWindowXI2Mask(dev, win, events)) + goto out; + other = inputMasks->inputClients; + } else { + OtherInputMasks *inputMasks = wOtherInputMasks(win); + /* Has any client selected for the event? */ + if (!inputMasks || + !(inputMasks->inputEvents[dev->id] & filter)) + goto out; + + other = inputMasks->inputClients; + } + + rc = EVENT_NOT_DELIVERED; + + for (; other; other = other->next) + { + Mask mask; + ClientPtr client = rClient(other); + + if (IsInterferingGrab(client, dev, events)) + continue; + + mask = GetEventMask(dev, events, other); + + if (XaceHook(XACE_RECEIVE_ACCESS, client, win, + events, count)) + /* do nothing */; + else if ( (attempt = TryClientEvents(client, dev, + events, count, + mask, filter, grab)) ) + { + if (attempt > 0) + { + rc = EVENT_DELIVERED; + *client_return = client; + *mask_return = mask; + /* Success overrides non-success, so if we've been + * successful on one client, return that */ + } else if (rc == EVENT_NOT_DELIVERED) + rc = EVENT_REJECTED; + } + } + +out: + return rc; +} + + /** * Deliver events to a window. At this point, we do not yet know if the event * actually needs to be delivered. May activate a grab if the event is a @@ -1955,152 +2125,84 @@ TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents, * @param filter Mask based on event type. * @param grab Possible grab on the device that caused the event. * - * @return Number of events delivered to various clients. + * @return a positive number if at least one successful delivery has been + * made, 0 if no events were delivered, or a negative number if the event + * has not been delivered _and_ rejected by at least one client. */ int DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent *pEvents, int count, Mask filter, GrabPtr grab) { int deliveries = 0, nondeliveries = 0; - int attempt; - InputClients *other; ClientPtr client = NullClient; Mask deliveryMask = 0; /* If a grab occurs due to a button press, then this mask is the mask of the grab. */ int type = pEvents->u.u.type; - /* Deliver to window owner */ - if ((filter == CantBeFiltered) || CORE_EVENT(pEvents)) + if ((filter == CantBeFiltered) || core_get_type(pEvents) != 0) { - /* if nobody ever wants to see this event, skip some work */ - if (filter != CantBeFiltered && - !((wOtherEventMasks(pWin)|pWin->eventMask) & filter)) - return 0; + enum EventDeliveryState rc; - if (IsInterferingGrab(wClient(pWin), pDev, pEvents)) - return 0; + rc = DeliverToWindowOwner(pDev, pWin, pEvents, count, filter, grab); - if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count)) - /* do nothing */; - else if ( (attempt = TryClientEvents(wClient(pWin), pDev, pEvents, - count, pWin->eventMask, - filter, grab)) ) - { - if (attempt > 0) - { - deliveries++; - client = wClient(pWin); - deliveryMask = pWin->eventMask; - } else - nondeliveries--; - } + switch(rc) + { + case EVENT_SKIP: + return 0; + case EVENT_REJECTED: + nondeliveries--; + break; + case EVENT_DELIVERED: + /* We delivered to the owner, with our event mask */ + deliveries++; + client = wClient(pWin); + deliveryMask = pWin->eventMask; + break; + case EVENT_NOT_DELIVERED: + break; + } } /* CantBeFiltered means only window owner gets the event */ if (filter != CantBeFiltered) { - if (CORE_EVENT(pEvents)) - other = (InputClients *)wOtherClients(pWin); - else if (XI2_EVENT(pEvents)) - { - OtherInputMasks *inputMasks = wOtherInputMasks(pWin); - /* Has any client selected for the event? */ - if (!GetWindowXI2Mask(pDev, pWin, pEvents)) - return 0; - other = inputMasks->inputClients; - } else { - OtherInputMasks *inputMasks = wOtherInputMasks(pWin); - /* Has any client selected for the event? */ - if (!inputMasks || - !(inputMasks->inputEvents[pDev->id] & filter)) - return 0; + enum EventDeliveryState rc; - other = inputMasks->inputClients; - } + rc = DeliverEventToClients(pDev, pWin, pEvents, count, filter, grab, + &client, &deliveryMask); - for (; other; other = other->next) + switch(rc) { - 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, - mask, filter, grab)) ) - { - if (attempt > 0) - { - deliveries++; - client = rClient(other); - deliveryMask = mask; - } else - nondeliveries--; - } + case EVENT_SKIP: + return 0; + case EVENT_REJECTED: + nondeliveries--; + break; + case EVENT_DELIVERED: + deliveries++; + break; + case EVENT_NOT_DELIVERED: + break; } } - /* - * Note that since core events are delivered first, an implicit grab may - * be activated on a core grab, stopping the XI events. - */ - if ((type == DeviceButtonPress || type == ButtonPress || - ((XI2_EVENT(pEvents) && ((xGenericEvent*)pEvents)->evtype == XI_ButtonPress))) - && deliveries - && (!grab)) - { - GrabRec tempGrab; - OtherInputMasks *inputMasks; - memset(&tempGrab, 0, sizeof(GrabRec)); - tempGrab.next = NULL; - tempGrab.device = pDev; - tempGrab.resource = client->clientAsMask; - tempGrab.window = pWin; - tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; - tempGrab.eventMask = deliveryMask; - tempGrab.keyboardMode = GrabModeAsync; - tempGrab.pointerMode = GrabModeAsync; - tempGrab.confineTo = NullWindow; - tempGrab.cursor = NullCursor; - tempGrab.type = type; - if (type == ButtonPress) - tempGrab.grabtype = GRABTYPE_CORE; - else if (type == DeviceButtonPress) - tempGrab.grabtype = GRABTYPE_XI; - else - { - tempGrab.type = ((xGenericEvent*)pEvents)->evtype; - tempGrab.grabtype = GRABTYPE_XI2; - } - - /* get the XI and XI2 device mask */ - inputMasks = wOtherInputMasks(pWin); - tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[pDev->id]: 0; - - if (inputMasks) - memcpy(tempGrab.xi2mask, inputMasks->xi2mask, - sizeof(tempGrab.xi2mask)); - - (*pDev->deviceGrab.ActivateGrab)(pDev, &tempGrab, - currentTime, TRUE | ImplicitGrabMask); - } - else if ((type == MotionNotify) && deliveries) - pDev->valuator->motionHintWindow = pWin; - else - { - if ((type == DeviceMotionNotify || type == DeviceButtonPress) && - deliveries) - CheckDeviceGrabAndHintWindow (pWin, type, - (deviceKeyButtonPointer*) pEvents, - grab, client, deliveryMask); - } if (deliveries) + { + /* + * Note that since core events are delivered first, an implicit grab may + * be activated on a core grab, stopping the XI events. + */ + if (!grab && ActivateImplicitGrab(pDev, client, pWin, pEvents, deliveryMask)) + /* grab activated */; + else if ((type == MotionNotify)) + pDev->valuator->motionHintWindow = pWin; + else if (type == DeviceMotionNotify || type == DeviceButtonPress) + CheckDeviceGrabAndHintWindow (pWin, type, + (deviceKeyButtonPointer*) pEvents, + grab, client, deliveryMask); return deliveries; + } return nondeliveries; } @@ -2180,7 +2282,7 @@ MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, static Window FindChildForEvent(SpritePtr pSprite, WindowPtr event) { - WindowPtr w = pSprite->spriteTrace[pSprite->spriteTraceGood-1]; + WindowPtr w = DeepestSpriteWin(pSprite); Window child = None; /* If the search ends up past the root should the child field be @@ -2224,22 +2326,29 @@ FixUpEventFromWindow( Window child, Bool calcChild) { + int evtype; + if (calcChild) child = FindChildForEvent(pSprite, pWin); - if (XI2_EVENT(xE)) + if ((evtype = xi2_get_type(xE))) { xXIDeviceEvent* event = (xXIDeviceEvent*)xE; - if (event->evtype == XI_RawKeyPress || - event->evtype == XI_RawKeyRelease || - event->evtype == XI_RawButtonPress || - event->evtype == XI_RawButtonRelease || - event->evtype == XI_RawMotion || - event->evtype == XI_DeviceChanged || - event->evtype == XI_HierarchyChanged || - event->evtype == XI_PropertyEvent) - return; + switch (evtype) + { + case XI_RawKeyPress: + case XI_RawKeyRelease: + case XI_RawButtonPress: + case XI_RawButtonRelease: + case XI_RawMotion: + case XI_DeviceChanged: + case XI_HierarchyChanged: + case XI_PropertyEvent: + return; + default: + break; + } event->root = RootWindow(pSprite)->drawable.id; event->event = pWin->drawable.id; @@ -2375,7 +2484,7 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, xEvent *xE = NULL, *core = NULL; int rc, mask, count = 0; - CHECKEVENT(event); + verify_internal_event(event); while (pWin) { @@ -2623,7 +2732,7 @@ XYToWindow(SpritePtr pSprite, int x, int y) else pWin = pWin->nextSib; } - return pSprite->spriteTrace[pSprite->spriteTraceGood-1]; + return DeepestSpriteWin(pSprite); } /** @@ -2661,7 +2770,8 @@ ActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) event.deviceid = dev->id; event.sourceid = dev->id; event.detail.button = 0; - rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, TRUE) != NULL); + rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE, + TRUE) != NULL); if (rc) DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); return rc; @@ -2698,7 +2808,8 @@ ActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) event.deviceid = dev->id; event.sourceid = dev->id; event.detail.button = 0; - rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, TRUE) != NULL); + rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE, + TRUE) != NULL); if (rc) DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab); return rc; @@ -2721,7 +2832,7 @@ CheckMotion(DeviceEvent *ev, DeviceIntPtr pDev) WindowPtr prevSpriteWin, newSpriteWin; SpritePtr pSprite = pDev->spriteInfo->sprite; - CHECKEVENT(ev); + verify_internal_event(ev); prevSpriteWin = pSprite->win; @@ -3385,7 +3496,7 @@ GrabPtr CheckPassiveGrabsOnWindow( WindowPtr pWin, DeviceIntPtr device, - DeviceEvent *event, + InternalEvent *event, BOOL checkCore, BOOL activate) { @@ -3402,9 +3513,22 @@ CheckPassiveGrabsOnWindow( return NULL; /* Fill out the grab details, but leave the type for later before * comparing */ + switch (event->any.type) + { + case ET_KeyPress: + case ET_KeyRelease: + tempGrab.detail.exact = event->device_event.detail.key; + break; + case ET_ButtonPress: + case ET_ButtonRelease: + tempGrab.detail.exact = event->device_event.detail.button; + break; + default: + tempGrab.detail.exact = 0; + break; + } tempGrab.window = pWin; tempGrab.device = device; - tempGrab.detail.exact = event->detail.key; tempGrab.detail.pMask = NULL; tempGrab.modifiersDetail.pMask = NULL; tempGrab.next = NULL; @@ -3412,6 +3536,8 @@ CheckPassiveGrabsOnWindow( { DeviceIntPtr gdev; XkbSrvInfoPtr xkbi = NULL; + xEvent *xE = NULL; + int count, rc; gdev= grab->modifierDevice; if (grab->grabtype == GRABTYPE_CORE) @@ -3437,16 +3563,15 @@ CheckPassiveGrabsOnWindow( tempGrab.modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0; /* Check for XI2 and XI grabs first */ - tempGrab.type = GetXI2Type((InternalEvent*)event); + tempGrab.type = GetXI2Type(event); tempGrab.grabtype = GRABTYPE_XI2; if (GrabMatchesSecond(&tempGrab, grab, FALSE)) match = XI2_MATCH; - tempGrab.detail.exact = event->detail.key; if (!match) { tempGrab.grabtype = GRABTYPE_XI; - if ((tempGrab.type = GetXIType((InternalEvent*)event)) && + if ((tempGrab.type = GetXIType(event)) && (GrabMatchesSecond(&tempGrab, grab, FALSE))) match = XI_MATCH; } @@ -3455,122 +3580,134 @@ CheckPassiveGrabsOnWindow( if (!match && checkCore) { tempGrab.grabtype = GRABTYPE_CORE; - if ((tempGrab.type = GetCoreType((InternalEvent*)event)) && + if ((tempGrab.type = GetCoreType(event)) && (GrabMatchesSecond(&tempGrab, grab, TRUE))) match = CORE_MATCH; } - if (match && (!grab->confineTo || - (grab->confineTo->realized && - BorderSizeNotEmpty(device, grab->confineTo)))) - { - int rc, count = 0; - xEvent *xE = NULL; - - event->corestate &= 0x1f00; - event->corestate |= tempGrab.modifiersDetail.exact & (~0x1f00); - grabinfo = &device->deviceGrab; - /* In some cases a passive core grab may exist, but the client - * already has a core grab on some other device. In this case we - * must not get the grab, otherwise we may never ungrab the - * device. - */ - - if (grab->grabtype == GRABTYPE_CORE) + if (!match || (grab->confineTo && + (!grab->confineTo->realized || + !BorderSizeNotEmpty(device, grab->confineTo)))) + continue; + + grabinfo = &device->deviceGrab; + /* In some cases a passive core grab may exist, but the client + * already has a core grab on some other device. In this case we + * must not get the grab, otherwise we may never ungrab the + * device. + */ + + if (grab->grabtype == GRABTYPE_CORE) + { + DeviceIntPtr other; + BOOL interfering = FALSE; + + /* A passive grab may have been created for a different device + than it is assigned to at this point in time. + Update the grab's device and modifier device to reflect the + current state. + Since XGrabDeviceButton requires to specify the + modifierDevice explicitly, we don't override this choice. + */ + if (tempGrab.type < GenericEvent) { - DeviceIntPtr other; - BOOL interfering = FALSE; - - /* A passive grab may have been created for a different device - than it is assigned to at this point in time. - Update the grab's device and modifier device to reflect the - current state. - Since XGrabDeviceButton requires to specify the - modifierDevice explicitly, we don't override this choice. - */ - if (tempGrab.type < GenericEvent) - { - grab->device = device; - grab->modifierDevice = GetPairedDevice(device); - } + grab->device = device; + grab->modifierDevice = GetPairedDevice(device); + } - for (other = inputInfo.devices; other; other = other->next) + for (other = inputInfo.devices; other; other = other->next) + { + GrabPtr othergrab = other->deviceGrab.grab; + if (othergrab && othergrab->grabtype == GRABTYPE_CORE && + SameClient(grab, rClient(othergrab)) && + ((IsPointerDevice(grab->device) && + IsPointerDevice(othergrab->device)) || + (IsKeyboardDevice(grab->device) && + IsKeyboardDevice(othergrab->device)))) { - GrabPtr othergrab = other->deviceGrab.grab; - if (othergrab && othergrab->grabtype == GRABTYPE_CORE && - SameClient(grab, rClient(othergrab)) && - ((IsPointerDevice(grab->device) && - IsPointerDevice(othergrab->device)) || - (IsKeyboardDevice(grab->device) && - IsKeyboardDevice(othergrab->device)))) - { - interfering = TRUE; - break; - } + interfering = TRUE; + break; } - if (interfering) - continue; } + if (interfering) + continue; + } - if (!activate) - return grab; + if (!activate) + { + return grab; + } + else if (!GetXIType(event) && !GetCoreType(event)) + { + ErrorF("Event type %d in CheckPassiveGrabsOnWindow is neither" + " XI 1.x nor core\n", event->any.type); + return NULL; + } - if (match & CORE_MATCH) + /* The only consumers of corestate are Xi 1.x and core events, which + * are guaranteed to come from DeviceEvents. */ + if (match & (XI_MATCH | CORE_MATCH)) + { + event->device_event.corestate &= 0x1f00; + event->device_event.corestate |= tempGrab.modifiersDetail.exact & + (~0x1f00); + } + + if (match & CORE_MATCH) + { + rc = EventToCore(event, &xE, &count); + if (rc != Success) { - rc = EventToCore((InternalEvent*)event, &xE, &count); - if (rc != Success) - { - if (rc != BadMatch) - ErrorF("[dix] %s: core conversion failed in CPGFW " - "(%d, %d).\n", device->name, event->type, rc); - continue; - } - } else if (match & XI2_MATCH) + if (rc != BadMatch) + ErrorF("[dix] %s: core conversion failed in CPGFW " + "(%d, %d).\n", device->name, event->any.type, rc); + continue; + } + } else if (match & XI2_MATCH) + { + rc = EventToXI2(event, &xE); + if (rc != Success) { - rc = EventToXI2((InternalEvent*)event, &xE); - if (rc != Success) - { - if (rc != BadMatch) - ErrorF("[dix] %s: XI2 conversion failed in CPGFW " - "(%d, %d).\n", device->name, event->type, rc); - continue; - } - count = 1; - } else + if (rc != BadMatch) + ErrorF("[dix] %s: XI2 conversion failed in CPGFW " + "(%d, %d).\n", device->name, event->any.type, rc); + continue; + } + count = 1; + } else + { + rc = EventToXI(event, &xE, &count); + if (rc != Success) { - rc = EventToXI((InternalEvent*)event, &xE, &count); - if (rc != Success) - { - if (rc != BadMatch) - ErrorF("[dix] %s: XI conversion failed in CPGFW " - "(%d, %d).\n", device->name, event->type, rc); - continue; - } + if (rc != BadMatch) + ErrorF("[dix] %s: XI conversion failed in CPGFW " + "(%d, %d).\n", device->name, event->any.type, rc); + continue; } + } - (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE); + (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE); - if (xE) - { - FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE); + if (xE) + { + FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE); - /* XXX: XACE? */ - TryClientEvents(rClient(grab), device, xE, count, - GetEventFilter(device, xE), - GetEventFilter(device, xE), grab); - } + /* XXX: XACE? */ + TryClientEvents(rClient(grab), device, xE, count, + GetEventFilter(device, xE), + GetEventFilter(device, xE), grab); + } - if (grabinfo->sync.state == FROZEN_NO_EVENT) - { - if (!grabinfo->sync.event) - grabinfo->sync.event = calloc(1, sizeof(InternalEvent)); - *grabinfo->sync.event = *event; - grabinfo->sync.state = FROZEN_WITH_EVENT; - } + if (grabinfo->sync.state == FROZEN_NO_EVENT) + { + if (!grabinfo->sync.event) + grabinfo->sync.event = calloc(1, sizeof(DeviceEvent)); + *grabinfo->sync.event = event->device_event; + grabinfo->sync.state = FROZEN_WITH_EVENT; + } - free(xE); - return grab; - } + free(xE); + return grab; } return NULL; #undef CORE_MATCH @@ -3639,7 +3776,8 @@ CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor) for (; i < focus->traceGood; i++) { pWin = focus->trace[i]; - if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore, TRUE)) + if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event, + sendCore, TRUE)) { ret = TRUE; goto out; @@ -3655,7 +3793,8 @@ CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor) for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) { pWin = device->spriteInfo->sprite->spriteTrace[i]; - if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore, TRUE)) + if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event, + sendCore, TRUE)) { ret = TRUE; goto out; @@ -3766,8 +3905,10 @@ unwind: * grab. If not, TryClientEvents() is used. * * @param deactivateGrab True if the device's grab should be deactivated. + * + * @return The number of events delivered. */ -void +int DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev, Bool deactivateGrab) { @@ -3935,6 +4076,8 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev, free(core); free(xi); free(xi2); + + return deliveries; } /* This function is used to set the key pressed or key released state - @@ -4977,12 +5120,9 @@ InitEvents(void) inputInfo.off_devices = (DeviceIntPtr)NULL; inputInfo.keyboard = (DeviceIntPtr)NULL; inputInfo.pointer = (DeviceIntPtr)NULL; - /* The mask for pointer motion events may have changed in the last server - * generation. See comment above definition of filters. */ - filters[0][PointerMotionMask] = MotionNotify; - for (i = 1; i < MAXDEVICES; i++) + for (i = 0; i < MAXDEVICES; i++) { - memcpy(&filters[i], filters[0], sizeof(filters[0])); + memcpy(&filters[i], default_filter, sizeof(default_filter)); } syncEvents.replayDev = (DeviceIntPtr)NULL; @@ -5006,8 +5146,7 @@ InitEvents(void) DontPropagateRefCnts[i] = 0; } - InputEventListLen = GetMaximumEventsNum(); - InputEventList = InitEventList(InputEventListLen); + InputEventList = InitEventList(GetMaximumEventsNum()); if (!InputEventList) FatalError("[dix] Failed to allocate input event list.\n"); } @@ -5015,8 +5154,7 @@ InitEvents(void) void CloseDownEvents(void) { - FreeEventList(InputEventList, InputEventListLen); - InputEventListLen = 0; + FreeEventList(InputEventList, GetMaximumEventsNum()); InputEventList = NULL; } diff --git a/xorg-server/dix/getevents.c b/xorg-server/dix/getevents.c index 4267b61cb..13789f6a2 100644 --- a/xorg-server/dix/getevents.c +++ b/xorg-server/dix/getevents.c @@ -47,6 +47,7 @@ #include "eventstr.h" #include "eventconvert.h" #include "inpututils.h" +#include "mi.h" #include <X11/extensions/XKBproto.h> #include "xkbsrv.h" @@ -67,19 +68,12 @@ /* Number of motion history events to store. */ #define MOTION_HISTORY_SIZE 256 -/* InputEventList is the container list for all input events generated by the - * DDX. The DDX is expected to call GetEventList() and then pass the list into - * Get{Pointer|Keyboard}Events. +/** + * InputEventList is the storage for input events generated by + * QueuePointerEvents, QueueKeyboardEvents, and QueueProximityEvents. + * This list is allocated on startup by the DIX. */ -EventListPtr InputEventList = NULL; -int InputEventListLen = 0; - -int -GetEventList(EventListPtr* list) -{ - *list = InputEventList; - return InputEventListLen; -} +InternalEvent* InputEventList = NULL; /** * Pick some arbitrary size for Xi motion history. @@ -223,7 +217,7 @@ set_valuators(DeviceIntPtr dev, DeviceEvent* event, ValuatorMask *mask) } void -CreateClassesChangedEvent(EventList* event, +CreateClassesChangedEvent(InternalEvent* event, DeviceIntPtr master, DeviceIntPtr slave, int type) @@ -232,7 +226,7 @@ CreateClassesChangedEvent(EventList* event, DeviceChangedEvent *dce; CARD32 ms = GetTimeInMillis(); - dce = (DeviceChangedEvent*)event->event; + dce = &event->changed_event; memset(dce, 0, sizeof(DeviceChangedEvent)); dce->deviceid = slave->id; dce->masterid = master->id; @@ -676,15 +670,15 @@ clipValuators(DeviceIntPtr pDev, ValuatorMask *mask) * is done in the event processing). * Pull in the coordinates from the MD if necessary. * - * @param events Pointer to a pre-allocated event list. + * @param events Pointer to a pre-allocated event array. * @param dev The slave device that generated an event. * @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT * @param num_events The current number of events, returns the number of * events if a DCCE was generated. * @return The updated @events pointer. */ -EventListPtr -UpdateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_events) +InternalEvent* +UpdateFromMaster(InternalEvent* events, DeviceIntPtr dev, int type, int *num_events) { DeviceIntPtr master; @@ -924,16 +918,49 @@ updateHistory(DeviceIntPtr dev, ValuatorMask *mask, CARD32 ms) } } +static void +queueEventList(DeviceIntPtr device, InternalEvent *events, int nevents) +{ + int i; + for (i = 0; i < nevents; i++) + mieqEnqueue(device, &events[i]); +} + +/** + * Generate internal events representing this keyboard event and enqueue + * them on the event queue. + * + * This function is not reentrant. Disable signals before calling. + * + * FIXME: flags for relative/abs motion? + * + * @param device The device to generate the event for + * @param type Event type, one of KeyPress or KeyRelease + * @param keycode Key code of the pressed/released key + * @param mask Valuator mask for valuators present for this event. + * + */ +void +QueueKeyboardEvents(DeviceIntPtr device, int type, + int keycode, const ValuatorMask *mask) +{ + int nevents; + + nevents = GetKeyboardEvents(InputEventList, device, type, keycode, mask); + queueEventList(device, InputEventList, nevents); +} + /** * Returns a set of InternalEvents for KeyPress/KeyRelease, optionally * also with valuator events. * - * events is not NULL-terminated; the return value is the number of events. - * The DDX is responsible for allocating the event structure in the first - * place via GetMaximumEventsNum(), and for freeing it. + * The DDX is responsible for allocating the event list in the first + * place via InitEventList(), and for freeing it. + * + * @return the number of events written into events. */ int -GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, +GetKeyboardEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int key_code, const ValuatorMask *mask_in) { int num_events = 0; CARD32 ms = 0; @@ -966,7 +993,7 @@ GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, ms = GetTimeInMillis(); - raw = (RawDeviceEvent*)events->event; + raw = &events->raw_event; events++; num_events++; @@ -979,7 +1006,7 @@ GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, set_raw_valuators(raw, &mask, raw->valuators.data); - event = (DeviceEvent*) events->event; + event = &events->device_event; init_event(pDev, event, ms); event->detail.key = key_code; @@ -1000,37 +1027,16 @@ GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, } /** - * Initialize an event list and fill with 32 byte sized events. + * Initialize an event array large enough for num_events arrays. * This event list is to be passed into GetPointerEvents() and * GetKeyboardEvents(). * * @param num_events Number of elements in list. */ -EventListPtr +InternalEvent* InitEventList(int num_events) { - EventListPtr events; - int i; - - events = (EventListPtr)calloc(num_events, sizeof(EventList)); - if (!events) - return NULL; - - for (i = 0; i < num_events; i++) - { - events[i].evlen = sizeof(InternalEvent); - events[i].event = calloc(1, sizeof(InternalEvent)); - if (!events[i].event) - { - /* rollback */ - while(i--) - free(events[i].event); - free(events); - events = NULL; - break; - } - } - + InternalEvent *events = calloc(num_events, sizeof(InternalEvent)); return events; } @@ -1041,41 +1047,50 @@ InitEventList(int num_events) * @param num_events Number of elements in list. */ void -FreeEventList(EventListPtr list, int num_events) +FreeEventList(InternalEvent *list, int num_events) { - if (!list) - return; - while(num_events--) - free(list[num_events].event); free(list); } static void -transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask) +transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask, int *x, int *y) { - struct pixman_f_vector p; - - /* p' = M * p in homogeneous coordinates */ - p.v[0] = (valuator_mask_isset(mask, 0) ? valuator_mask_get(mask, 0) : - dev->last.valuators[0]); - p.v[1] = (valuator_mask_isset(mask, 1) ? valuator_mask_get(mask, 1) : - dev->last.valuators[1]); - p.v[2] = 1.0; + struct pixman_f_vector p = {.v = {*x, *y, 1}}; pixman_f_transform_point(&dev->transform, &p); - if (lround(p.v[0]) != dev->last.valuators[0]) - valuator_mask_set(mask, 0, lround(p.v[0])); - if (lround(p.v[1]) != dev->last.valuators[1]) - valuator_mask_set(mask, 1, lround(p.v[1])); + *x = lround(p.v[0]); + *y = lround(p.v[1]); } /** - * Generate a series of InternalEvents (filled into the EventList) - * representing pointer motion, or button presses. + * Generate internal events representing this pointer event and enqueue them + * on the event queue. + * + * This function is not reentrant. Disable signals before calling. * - * events is not NULL-terminated; the return value is the number of events. - * The DDX is responsible for allocating the event structure in the first + * @param device The device to generate the event for + * @param type Event type, one of ButtonPress, ButtonRelease, MotionNotify + * @param buttons Button number of the buttons modified. Must be 0 for + * MotionNotify + * @param flags Event modification flags + * @param mask Valuator mask for valuators present for this event. + */ +void +QueuePointerEvents(DeviceIntPtr device, int type, + int buttons, int flags, const ValuatorMask *mask) +{ + int nevents; + + nevents = GetPointerEvents(InputEventList, device, type, buttons, flags, mask); + queueEventList(device, InputEventList, nevents); +} + +/** + * Generate a series of InternalEvents representing pointer motion, or + * button presses. + * + * The DDX is responsible for allocating the events in the first * place via InitEventList() and GetMaximumEventsNum(), and for freeing it. * * In the generated events rootX/Y will be in absolute screen coords and @@ -1085,9 +1100,11 @@ transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask) * last.valuators[x] of the master device is in absolute screen coords. * * master->last.valuators[x] for x > 2 is undefined. + * + * @return the number of events written into events. */ int -GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, +GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons, int flags, const ValuatorMask *mask_in) { int num_events = 1; CARD32 ms; @@ -1125,7 +1142,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); - raw = (RawDeviceEvent*)events->event; + raw = &events->raw_event; events++; num_events++; @@ -1158,7 +1175,16 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, } } - transformAbsolute(pDev, &mask); + x = (valuator_mask_isset(&mask, 0) ? valuator_mask_get(&mask, 0) : + pDev->last.valuators[0]); + y = (valuator_mask_isset(&mask, 1) ? valuator_mask_get(&mask, 1) : + pDev->last.valuators[1]); + transformAbsolute(pDev, &mask, &x, &y); + if (valuator_mask_isset(&mask, 0)) + valuator_mask_set(&mask, 0, x); + if (valuator_mask_isset(&mask, 1)) + valuator_mask_set(&mask, 1, y); + moveAbsolute(pDev, &x, &y, &mask); } else { if (flags & POINTER_ACCELERATE) { @@ -1185,7 +1211,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, clipValuators(pDev, &mask); - event = (DeviceEvent*) events->event; + event = &events->device_event; init_event(pDev, event, ms); if (type == MotionNotify) { @@ -1214,17 +1240,39 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, return num_events; } +/** + * Generate internal events representing this proximity event and enqueue + * them on the event queue. + * + * This function is not reentrant. Disable signals before calling. + * + * @param device The device to generate the event for + * @param type Event type, one of ProximityIn or ProximityOut + * @param keycode Key code of the pressed/released key + * @param mask Valuator mask for valuators present for this event. + * + */ +void +QueueProximityEvents(DeviceIntPtr device, int type, + const ValuatorMask *mask) +{ + int nevents; + + nevents = GetProximityEvents(InputEventList, device, type, mask); + queueEventList(device, InputEventList, nevents); +} /** * Generate ProximityIn/ProximityOut InternalEvents, accompanied by * valuators. * - * events is not NULL-terminated; the return value is the number of events. - * The DDX is responsible for allocating the event structure in the first - * place via GetMaximumEventsNum(), and for freeing it. + * The DDX is responsible for allocating the events in the first place via + * InitEventList(), and for freeing it. + * + * @return the number of events written into events. */ int -GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, const ValuatorMask *mask_in) +GetProximityEvents(InternalEvent *events, DeviceIntPtr pDev, int type, const ValuatorMask *mask_in) { int num_events = 1, i; DeviceEvent *event; @@ -1256,7 +1304,7 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, const Valuato events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); - event = (DeviceEvent *) events->event; + event = &events->device_event; init_event(pDev, event, GetTimeInMillis()); event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut; diff --git a/xorg-server/dix/inpututils.c b/xorg-server/dix/inpututils.c index 077ffce01..aeace6ef8 100644 --- a/xorg-server/dix/inpututils.c +++ b/xorg-server/dix/inpututils.c @@ -36,6 +36,7 @@ #include "xkbsrv.h" #include "xkbstr.h" #include "inpututils.h" +#include "eventstr.h" /* Check if a button map change is okay with the device. * Returns -1 for BadValue, as it collides with MappingBusy. */ @@ -556,3 +557,30 @@ CountBits(const uint8_t *mask, int len) return ret; } + +/** + * Verifies sanity of the event. If the event is not an internal event, + * memdumps the first 32 bytes of event to the log, a backtrace, then kill + * the server. + */ +void verify_internal_event(const InternalEvent *ev) +{ + if (ev && ev->any.header != ET_Internal) + { + int i; + unsigned char *data = (unsigned char*)ev; + + ErrorF("dix: invalid event type %d\n", ev->any.header); + + for (i = 0; i < sizeof(xEvent); i++, data++) + { + ErrorF("%02hx ", *data); + + if ((i % 8) == 7) + ErrorF("\n"); + } + + xorg_backtrace(); + FatalError("Wrong event type %d. Aborting server\n", ev->any.header); + } +} |