From a511c445debbd13e8c48146ecd2d7c97e793f788 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 28 Sep 2007 18:46:41 +0930 Subject: [PATCH] Remove generation of core events, long live XI! Let the drivers only generate XI events and put those into the event queue. When processing events, generate core events as needed. This fixes a number of problems with XKB and the DIX in general. The previous approach was to put core events and XI events as separate events into the event queue. When being processed, the server had no knowledge of them coming from the same device state change. Anything that would then change the state of the device accordingly was in danger of changing it twice, leading to some funny (i.e. not funny at all) results. Emulating core events while processing XI events fixes this, there is only one path that actually changes the device state now. Although we have to be careful when replaying events from synced devices, otherwise we may lose events. Note: XI has precedence over core for passive grabs, but core events are delivered to the client first. This removes the wrapping added in 340911d7243a7f1095d79b5b2dcfa81b145c2474 --- Xi/exevents.c | 69 ++++++++++++++++++++++++++++++++------------- dix/events.c | 74 +++++++++++++++++++++++++++++++++++++++++++++---- dix/getevents.c | 44 +++++++---------------------- include/dix.h | 1 + mi/mieq.c | 3 +- 5 files changed, 131 insertions(+), 60 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index d844eefea..35669061e 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -149,7 +149,15 @@ RegisterOtherDevice(DeviceIntPtr device) WRAP_PROCESS_INPUT_PROC(device, xiPrivPtr, ProcessOtherEvent); } - /*ARGSUSED*/ void +/** + * Main device event processing function. + * Called from when processing the events from the event queue. + * Generates core events for XI events as needed. + * + * Note that these core events are then delivered first. For passive grabs, XI + * events have preference over core. + */ +void ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count) { BYTE *kptr; @@ -163,19 +171,13 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count) KeyClassPtr k = device->key; ValuatorClassPtr v = device->valuator; deviceValuator *xV = (deviceValuator *) xE; + BOOL sendCore = FALSE; + xEvent core; + int coretype = 0; - /* Handle core events. */ - if (xE->u.u.type < LASTEvent && xE->u.u.type != GenericEvent) - { - ProcessInputProc backupproc; - xiDevPrivatePtr xiPrivPtr = - (xiDevPrivatePtr)device->devPrivates[xiDevPrivateIndex].ptr; - UNWRAP_PROCESS_INPUT_PROC(device, xiPrivPtr, backupproc); - device->public.processInputProc(xE, device, count); - /* only rewraps is the processInputProc hasn't been modified */ - REWRAP_PROCESS_INPUT_PROC(device, xiPrivPtr, backupproc); - return; - } + coretype = XItoCoreType(xE->u.u.type); + if (device->coreEvents && coretype) + sendCore = TRUE; CheckMotion(xE, device); @@ -280,7 +282,12 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count) modifiers &= ~mask; } } - if (!grab && CheckDeviceGrabs(device, xE, 0, count)) { + /* XI grabs have priority */ + core = *xE; + core.u.u.type = coretype; + if (!grab && + (CheckDeviceGrabs(device, xE, 0, count) || + (sendCore && CheckDeviceGrabs(device, &core, 0, 1)))) { device->deviceGrab.activatingKey = key; return; } @@ -308,7 +315,6 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count) } if (device->deviceGrab.fromPassiveGrab && - !device->deviceGrab.grab->coreGrab && (key == device->deviceGrab.activatingKey)) deactivateDeviceGrab = TRUE; } else if (xE->u.u.type == DeviceButtonPress) { @@ -328,10 +334,17 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count) b->state |= (Button1Mask >> 1) << xE->u.u.detail; SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify); if (!grab) - if (CheckDeviceGrabs(device, xE, 0, count)) + { + core = *xE; + core.u.u.type = coretype; + if (CheckDeviceGrabs(device, xE, 0, count) || + (sendCore && CheckDeviceGrabs(device, &core, 0, 1))) + { /* if a passive grab was activated, the event has been sent * already */ return; + } + } } else if (xE->u.u.type == DeviceButtonRelease) { if (!b) @@ -350,21 +363,39 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count) b->state &= ~((Button1Mask >> 1) << xE->u.u.detail); SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify); if (!b->state - && device->deviceGrab.fromPassiveGrab - && !device->deviceGrab.grab->coreGrab) + && device->deviceGrab.fromPassiveGrab) deactivateDeviceGrab = TRUE; } else if (xE->u.u.type == ProximityIn) device->valuator->mode &= ~OutOfProximity; else if (xE->u.u.type == ProximityOut) device->valuator->mode |= OutOfProximity; + if (sendCore) + { + core = *xE; + core.u.u.type = coretype; + } + if (grab) - DeliverGrabbedEvent(xE, device, deactivateDeviceGrab, count); + { + if (sendCore) /* never deactivate from core */ + DeliverGrabbedEvent(&core, device, FALSE , 1); + DeliverGrabbedEvent(xE, device, deactivateDeviceGrab, count); + } else if (device->focus) + { + if (sendCore) + DeliverFocusedEvent(device, &core, GetSpriteWindow(device), 1); DeliverFocusedEvent(device, xE, GetSpriteWindow(device), count); + } else + { + if (sendCore) + DeliverDeviceEvents(GetSpriteWindow(device), &core, NullGrab, + NullWindow, device, 1); DeliverDeviceEvents(GetSpriteWindow(device), xE, NullGrab, NullWindow, device, count); + } if (deactivateDeviceGrab == TRUE) (*device->deviceGrab.DeactivateGrab) (device); diff --git a/dix/events.c b/dix/events.c index 45ff943fb..6eac09049 100644 --- a/dix/events.c +++ b/dix/events.c @@ -294,6 +294,27 @@ static struct { static xEvent* swapEvent = NULL; static int swapEventLen = 0; +/** + * Convert the given event type from an XI event to a core event. + * @return The matching core event type or 0 if there is none. + */ +_X_EXPORT int +XItoCoreType(int xitype) +{ + int coretype = 0; + if (xitype == DeviceMotionNotify) + coretype = MotionNotify; + else if (xitype == DeviceButtonPress) + coretype = ButtonPress; + else if (xitype == DeviceButtonRelease) + coretype = ButtonRelease; + else if (xitype == DeviceKeyPress) + coretype = KeyPress; + else if (xitype == DeviceKeyRelease) + coretype = KeyRelease; + return coretype; +} + /** * True if device owns a cursor, false if device shares a cursor sprite with * another device. @@ -775,9 +796,15 @@ XineramaChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor) void SetMaskForEvent(Mask mask, int event) { + int coretype; if ((event < LASTEvent) || (event >= 128)) FatalError("SetMaskForEvent: bogus event number"); filters[event] = mask; + + /* Need to change the mask for the core events too */ + coretype = XItoCoreType(event); + if (coretype) + filters[coretype] = mask; } _X_EXPORT void @@ -1343,10 +1370,11 @@ ComputeFreezes(void) DeviceIntPtr replayDev = syncEvents.replayDev; int i; WindowPtr w; - xEvent *xE; + xEvent *xE, core; int count; GrabPtr grab; DeviceIntPtr dev; + BOOL sendCore; for (dev = inputInfo.devices; dev; dev = dev->next) FreezeThaw(dev, dev->deviceGrab.sync.other || @@ -1367,11 +1395,38 @@ ComputeFreezes(void) replayDev->spriteInfo->sprite->spriteTrace[i]) { if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) { + /* There is no other client that gets a passive grab on + * the event anymore. Emulate core event if necessary and + * deliver it too. + * However, we might get here with a core event, in which + * case we mustn't emulate a core event. + * XXX: I think this may break things. If a client has a + * device grab, and another client a core grab on an + * inferior window, we never get the core grab. (whot) + */ + sendCore = (replayDev->coreEvents && + (xE->u.u.type & EXTENSION_EVENT_BASE && + XItoCoreType(xE->u.u.type))); + + if (sendCore) + { + core = *xE; + core.u.u.type = XItoCoreType(xE->u.u.type); + } if (replayDev->focus) + { + if (sendCore) + DeliverFocusedEvent(replayDev, &core, w, 1); DeliverFocusedEvent(replayDev, xE, w, count); + } else + { + if (sendCore) + DeliverDeviceEvents(w, &core, NullGrab, + NullWindow, replayDev, 1); DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count); + } } goto playmore; } @@ -2089,7 +2144,13 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent } } } - if ((type == ButtonPress) && deliveries && (!grab)) + /* + * 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) + && deliveries + && (!grab)) { GrabRec tempGrab; OtherInputMasks *inputMasks; @@ -2104,7 +2165,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent tempGrab.pointerMode = GrabModeAsync; tempGrab.confineTo = NullWindow; tempGrab.cursor = NullCursor; - tempGrab.coreGrab = True; + tempGrab.coreGrab = (type == ButtonPress); /* get the XI device mask */ inputMasks = wOtherInputMasks(pWin); @@ -2127,9 +2188,8 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent tempGrab.genericMasks->next = NULL; } } - (*inputInfo.pointer->deviceGrab.ActivateGrab)(pDev, &tempGrab, - currentTime, - TRUE | ImplicitGrabMask); + (*pDev->deviceGrab.ActivateGrab)(pDev, &tempGrab, + currentTime, TRUE | ImplicitGrabMask); } else if ((type == MotionNotify) && deliveries) pDev->valuator->motionHintWindow = pWin; @@ -3182,6 +3242,8 @@ CheckPassiveGrabsOnWindow( XkbSrvInfoPtr xkbi; gdev= grab->modifierDevice; + if (grab->coreGrab) + gdev = GetPairedKeyboard(device); xkbi= gdev->key->xkbInfo; #endif tempGrab.modifierDevice = grab->modifierDevice; diff --git a/dix/getevents.c b/dix/getevents.c index fda4e27f8..7457078e5 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -191,10 +191,10 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator, */ _X_EXPORT int GetMaximumEventsNum(void) { - /* Three base events -- raw event, core and device, plus valuator events. + /* Three base events -- raw event and device, plus valuator events. * Multiply by two if we're doing key repeats. */ - int ret = 3 + MAX_VALUATOR_EVENTS; + int ret = 2 + MAX_VALUATOR_EVENTS; #ifdef XKB if (noXkbExtension) @@ -366,6 +366,9 @@ GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) * Returns a set of keyboard events for KeyPress/KeyRelease, optionally * also with valuator events. Handles Xi and XKB. * + * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the + * event (ProcessOtherEvent). + * * 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. @@ -399,10 +402,7 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, (pDev->coreEvents && !inputInfo.keyboard->key)) return 0; - if (pDev->coreEvents) - numEvents = 2; - else - numEvents = 1; + numEvents = 1; if (num_valuators) { if ((num_valuators / 6) + 1 > MAX_VALUATOR_EVENTS) @@ -469,12 +469,6 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, num_valuators, valuators); } - if (pDev->coreEvents) { - events->event->u.keyButtonPointer.time = ms; - events->event->u.u.type = type; - events->event->u.u.detail = key_code; - } - return numEvents; } @@ -533,6 +527,9 @@ FreeEventList(EventListPtr list, int num_events) * Generate a series of xEvents (filled into the EventList) representing * pointer motion, or button presses. Xi and XKB-aware. * + * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the + * event (ProcessOtherEvent). + * * 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 InitEventList() and GetMaximumEventsNum(), and for freeing it. @@ -567,10 +564,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, if (!pDev->valuator) return 0; - if (!coreOnly && pDev->coreEvents) - num_events = 3; - else - num_events = 2; + num_events = 2; if (type == MotionNotify && num_valuators <= 0) return 0; @@ -703,24 +697,6 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, } } - /* for some reason inputInfo.pointer does not have coreEvents set */ - if (coreOnly || pDev->coreEvents) { - events->event->u.u.type = type; - events->event->u.keyButtonPointer.time = ms; - events->event->u.keyButtonPointer.rootX = x; - events->event->u.keyButtonPointer.rootY = y; - - if (type == ButtonPress || type == ButtonRelease) { - /* We hijack SetPointerMapping to work on all core-sending - * devices, so we use the device-specific map here instead of - * the core one. */ - events->event->u.u.detail = pDev->button->map[buttons]; - } - else { - events->event->u.u.detail = 0; - } - } - return num_events; } diff --git a/include/dix.h b/include/dix.h index bec19dd4c..34abb2d87 100644 --- a/include/dix.h +++ b/include/dix.h @@ -689,6 +689,7 @@ typedef struct { extern int xstrcasecmp(char *s1, char *s2); #endif +extern int XItoCoreType(int xi_type); extern Bool DevHasCursor(DeviceIntPtr pDev); extern Bool IsPointerDevice( DeviceIntPtr dev); diff --git a/mi/mieq.c b/mi/mieq.c index 78e57adc4..9e0f5befb 100644 --- a/mi/mieq.c +++ b/mi/mieq.c @@ -300,7 +300,8 @@ mieqProcessInputEvents(void) } /* Update the sprite now. Next event may be from different device. */ - if (e->events->event[0].u.u.type == MotionNotify && e->pDev->coreEvents) + if (e->events->event[0].u.u.type == DeviceMotionNotify + && e->pDev->coreEvents) { miPointerUpdateSprite(e->pDev); }