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

View File

@ -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;

View File

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

View File

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

View File

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