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); }