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 340911d724
This commit is contained in:
Peter Hutterer 2007-09-28 18:46:41 +09:30
parent be466d8df8
commit a511c445de
5 changed files with 131 additions and 60 deletions

View File

@ -149,7 +149,15 @@ RegisterOtherDevice(DeviceIntPtr device)
WRAP_PROCESS_INPUT_PROC(device, xiPrivPtr, ProcessOtherEvent); 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) ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
{ {
BYTE *kptr; BYTE *kptr;
@ -163,19 +171,13 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
KeyClassPtr k = device->key; KeyClassPtr k = device->key;
ValuatorClassPtr v = device->valuator; ValuatorClassPtr v = device->valuator;
deviceValuator *xV = (deviceValuator *) xE; deviceValuator *xV = (deviceValuator *) xE;
BOOL sendCore = FALSE;
xEvent core;
int coretype = 0;
/* Handle core events. */ coretype = XItoCoreType(xE->u.u.type);
if (xE->u.u.type < LASTEvent && xE->u.u.type != GenericEvent) if (device->coreEvents && coretype)
{ sendCore = TRUE;
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;
}
CheckMotion(xE, device); CheckMotion(xE, device);
@ -280,7 +282,12 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
modifiers &= ~mask; 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; device->deviceGrab.activatingKey = key;
return; return;
} }
@ -308,7 +315,6 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
} }
if (device->deviceGrab.fromPassiveGrab && if (device->deviceGrab.fromPassiveGrab &&
!device->deviceGrab.grab->coreGrab &&
(key == device->deviceGrab.activatingKey)) (key == device->deviceGrab.activatingKey))
deactivateDeviceGrab = TRUE; deactivateDeviceGrab = TRUE;
} else if (xE->u.u.type == DeviceButtonPress) { } 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; b->state |= (Button1Mask >> 1) << xE->u.u.detail;
SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify); SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
if (!grab) 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 /* if a passive grab was activated, the event has been sent
* already */ * already */
return; return;
}
}
} else if (xE->u.u.type == DeviceButtonRelease) { } else if (xE->u.u.type == DeviceButtonRelease) {
if (!b) if (!b)
@ -350,21 +363,39 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
b->state &= ~((Button1Mask >> 1) << xE->u.u.detail); b->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify); SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
if (!b->state if (!b->state
&& device->deviceGrab.fromPassiveGrab && device->deviceGrab.fromPassiveGrab)
&& !device->deviceGrab.grab->coreGrab)
deactivateDeviceGrab = TRUE; deactivateDeviceGrab = TRUE;
} else if (xE->u.u.type == ProximityIn) } else if (xE->u.u.type == ProximityIn)
device->valuator->mode &= ~OutOfProximity; device->valuator->mode &= ~OutOfProximity;
else if (xE->u.u.type == ProximityOut) else if (xE->u.u.type == ProximityOut)
device->valuator->mode |= OutOfProximity; device->valuator->mode |= OutOfProximity;
if (sendCore)
{
core = *xE;
core.u.u.type = coretype;
}
if (grab) 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) else if (device->focus)
{
if (sendCore)
DeliverFocusedEvent(device, &core, GetSpriteWindow(device), 1);
DeliverFocusedEvent(device, xE, GetSpriteWindow(device), count); DeliverFocusedEvent(device, xE, GetSpriteWindow(device), count);
}
else else
{
if (sendCore)
DeliverDeviceEvents(GetSpriteWindow(device), &core, NullGrab,
NullWindow, device, 1);
DeliverDeviceEvents(GetSpriteWindow(device), xE, NullGrab, NullWindow, DeliverDeviceEvents(GetSpriteWindow(device), xE, NullGrab, NullWindow,
device, count); device, count);
}
if (deactivateDeviceGrab == TRUE) if (deactivateDeviceGrab == TRUE)
(*device->deviceGrab.DeactivateGrab) (device); (*device->deviceGrab.DeactivateGrab) (device);

View File

@ -294,6 +294,27 @@ static struct {
static xEvent* swapEvent = NULL; static xEvent* swapEvent = NULL;
static int swapEventLen = 0; 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 * True if device owns a cursor, false if device shares a cursor sprite with
* another device. * another device.
@ -775,9 +796,15 @@ XineramaChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
void void
SetMaskForEvent(Mask mask, int event) SetMaskForEvent(Mask mask, int event)
{ {
int coretype;
if ((event < LASTEvent) || (event >= 128)) if ((event < LASTEvent) || (event >= 128))
FatalError("SetMaskForEvent: bogus event number"); FatalError("SetMaskForEvent: bogus event number");
filters[event] = mask; filters[event] = mask;
/* Need to change the mask for the core events too */
coretype = XItoCoreType(event);
if (coretype)
filters[coretype] = mask;
} }
_X_EXPORT void _X_EXPORT void
@ -1343,10 +1370,11 @@ ComputeFreezes(void)
DeviceIntPtr replayDev = syncEvents.replayDev; DeviceIntPtr replayDev = syncEvents.replayDev;
int i; int i;
WindowPtr w; WindowPtr w;
xEvent *xE; xEvent *xE, core;
int count; int count;
GrabPtr grab; GrabPtr grab;
DeviceIntPtr dev; DeviceIntPtr dev;
BOOL sendCore;
for (dev = inputInfo.devices; dev; dev = dev->next) for (dev = inputInfo.devices; dev; dev = dev->next)
FreezeThaw(dev, dev->deviceGrab.sync.other || FreezeThaw(dev, dev->deviceGrab.sync.other ||
@ -1367,11 +1395,38 @@ ComputeFreezes(void)
replayDev->spriteInfo->sprite->spriteTrace[i]) replayDev->spriteInfo->sprite->spriteTrace[i])
{ {
if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) { 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 (replayDev->focus)
{
if (sendCore)
DeliverFocusedEvent(replayDev, &core, w, 1);
DeliverFocusedEvent(replayDev, xE, w, count); DeliverFocusedEvent(replayDev, xE, w, count);
}
else else
{
if (sendCore)
DeliverDeviceEvents(w, &core, NullGrab,
NullWindow, replayDev, 1);
DeliverDeviceEvents(w, xE, NullGrab, NullWindow, DeliverDeviceEvents(w, xE, NullGrab, NullWindow,
replayDev, count); replayDev, count);
}
} }
goto playmore; 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; GrabRec tempGrab;
OtherInputMasks *inputMasks; OtherInputMasks *inputMasks;
@ -2104,7 +2165,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
tempGrab.pointerMode = GrabModeAsync; tempGrab.pointerMode = GrabModeAsync;
tempGrab.confineTo = NullWindow; tempGrab.confineTo = NullWindow;
tempGrab.cursor = NullCursor; tempGrab.cursor = NullCursor;
tempGrab.coreGrab = True; tempGrab.coreGrab = (type == ButtonPress);
/* get the XI device mask */ /* get the XI device mask */
inputMasks = wOtherInputMasks(pWin); inputMasks = wOtherInputMasks(pWin);
@ -2127,9 +2188,8 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
tempGrab.genericMasks->next = NULL; tempGrab.genericMasks->next = NULL;
} }
} }
(*inputInfo.pointer->deviceGrab.ActivateGrab)(pDev, &tempGrab, (*pDev->deviceGrab.ActivateGrab)(pDev, &tempGrab,
currentTime, currentTime, TRUE | ImplicitGrabMask);
TRUE | ImplicitGrabMask);
} }
else if ((type == MotionNotify) && deliveries) else if ((type == MotionNotify) && deliveries)
pDev->valuator->motionHintWindow = pWin; pDev->valuator->motionHintWindow = pWin;
@ -3182,6 +3242,8 @@ CheckPassiveGrabsOnWindow(
XkbSrvInfoPtr xkbi; XkbSrvInfoPtr xkbi;
gdev= grab->modifierDevice; gdev= grab->modifierDevice;
if (grab->coreGrab)
gdev = GetPairedKeyboard(device);
xkbi= gdev->key->xkbInfo; xkbi= gdev->key->xkbInfo;
#endif #endif
tempGrab.modifierDevice = grab->modifierDevice; tempGrab.modifierDevice = grab->modifierDevice;

View File

@ -191,10 +191,10 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator,
*/ */
_X_EXPORT int _X_EXPORT int
GetMaximumEventsNum(void) { 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. * Multiply by two if we're doing key repeats.
*/ */
int ret = 3 + MAX_VALUATOR_EVENTS; int ret = 2 + MAX_VALUATOR_EVENTS;
#ifdef XKB #ifdef XKB
if (noXkbExtension) 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 * Returns a set of keyboard events for KeyPress/KeyRelease, optionally
* also with valuator events. Handles Xi and XKB. * 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. * 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 * The DDX is responsible for allocating the event structure in the first
* place via GetMaximumEventsNum(), and for freeing it. * place via GetMaximumEventsNum(), and for freeing it.
@ -399,10 +402,7 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
(pDev->coreEvents && !inputInfo.keyboard->key)) (pDev->coreEvents && !inputInfo.keyboard->key))
return 0; return 0;
if (pDev->coreEvents) numEvents = 1;
numEvents = 2;
else
numEvents = 1;
if (num_valuators) { if (num_valuators) {
if ((num_valuators / 6) + 1 > MAX_VALUATOR_EVENTS) if ((num_valuators / 6) + 1 > MAX_VALUATOR_EVENTS)
@ -469,12 +469,6 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
num_valuators, valuators); 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; return numEvents;
} }
@ -533,6 +527,9 @@ FreeEventList(EventListPtr list, int num_events)
* Generate a series of xEvents (filled into the EventList) representing * Generate a series of xEvents (filled into the EventList) representing
* pointer motion, or button presses. Xi and XKB-aware. * 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. * 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 * The DDX is responsible for allocating the event structure in the first
* place via InitEventList() and GetMaximumEventsNum(), and for freeing it. * 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) if (!pDev->valuator)
return 0; return 0;
if (!coreOnly && pDev->coreEvents) num_events = 2;
num_events = 3;
else
num_events = 2;
if (type == MotionNotify && num_valuators <= 0) if (type == MotionNotify && num_valuators <= 0)
return 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; return num_events;
} }

View File

@ -689,6 +689,7 @@ typedef struct {
extern int xstrcasecmp(char *s1, char *s2); extern int xstrcasecmp(char *s1, char *s2);
#endif #endif
extern int XItoCoreType(int xi_type);
extern Bool DevHasCursor(DeviceIntPtr pDev); extern Bool DevHasCursor(DeviceIntPtr pDev);
extern Bool IsPointerDevice( DeviceIntPtr dev); extern Bool IsPointerDevice( DeviceIntPtr dev);

View File

@ -300,7 +300,8 @@ mieqProcessInputEvents(void)
} }
/* Update the sprite now. Next event may be from different device. */ /* 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); miPointerUpdateSprite(e->pDev);
} }