Wrap core event handling through ProcessOtherEvents.

When processing events from the EQ, _always_ call the processInputProc of the
matching device. For XI devices, this proc is wrapped in three layers.
Core event handling is wrapped by XI event handling, which is wrapped by XKB.
A core event now passes through XKB -> XI -> DIX.

This gets rid of a sync'd grab problem: with the previous code, core events
did disappear during a sync'd device grab on account of mieqProcessInputEvents
calling the processInputProc of the VCP/VCK instead of the actual device. This
lead to the event being processed as normal instead of being enqueued for
later replaying.
This commit is contained in:
Peter Hutterer 2007-09-26 15:12:49 +09:30
parent b2a4883bd8
commit 340911d724
3 changed files with 77 additions and 32 deletions

View File

@ -89,26 +89,56 @@ Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
static Bool MakeInputMasks(WindowPtr /* pWin */
);
static int xiDevPrivateIndex = 0;
static int _xiServerGeneration = -1;
typedef struct {
ProcessInputProc processInputProc;
ProcessInputProc realInputProc;
} xiDevPrivateRec, *xiDevPrivatePtr;
/**************************************************************************
*
* Procedures for extension device event routing.
*
*/
#define WRAP_PROCESS_INPUT_PROC(device, saveprocs, newproc) \
saveprocs->processInputProc = device->public.processInputProc; \
saveprocs->realInputProc = device->public.realInputProc; \
device->public.processInputProc = newproc; \
device->public.realInputProc = newproc;
#define UNWRAP_PROCESS_INPUT_PROC(device, saveprocs) \
device->public.processInputProc = saveprocs->processInputProc; \
device->public.realInputProc = saveprocs->realInputProc;
void
RegisterOtherDevice(DeviceIntPtr device)
{
device->public.processInputProc = ProcessOtherEvent;
device->public.realInputProc = ProcessOtherEvent;
if (DeviceIsPointerType(device))
xiDevPrivatePtr xiPrivPtr;
if (serverGeneration != _xiServerGeneration)
{
(device)->deviceGrab.ActivateGrab = ActivatePointerGrab;
(device)->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
} else
{
(device)->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
(device)->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
xiDevPrivateIndex = AllocateDevicePrivateIndex();
if (xiDevPrivateIndex == 1)
{
FatalError("[Xi] Could not allocate private index.\n");
}
_xiServerGeneration = serverGeneration;
}
if (!AllocateDevicePrivate(device, xiDevPrivateIndex))
FatalError("[Xi] Dev private allocation failed.\n");
xiPrivPtr = (xiDevPrivatePtr)xcalloc(1, sizeof(xiDevPrivateRec));
if (!xiPrivPtr)
FatalError("[Xi] Cannot get memory for dev private.\n");
device->devPrivates[xiDevPrivateIndex].ptr = xiPrivPtr;
WRAP_PROCESS_INPUT_PROC(device, xiPrivPtr, ProcessOtherEvent);
}
/*ARGSUSED*/ void
@ -126,6 +156,17 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
ValuatorClassPtr v = device->valuator;
deviceValuator *xV = (deviceValuator *) xE;
/* Handle core events. */
if (xE->u.u.type < LASTEvent && xE->u.u.type != GenericEvent)
{
xiDevPrivatePtr xiPrivPtr =
(xiDevPrivatePtr)device->devPrivates[xiDevPrivateIndex].ptr;
UNWRAP_PROCESS_INPUT_PROC(device, xiPrivPtr);
device->public.processInputProc(xE, device, count);
WRAP_PROCESS_INPUT_PROC(device, xiPrivPtr, ProcessOtherEvent);
return;
}
CheckMotion(xE, device);
if (xE->u.u.type != DeviceValuator && xE->u.u.type != GenericEvent) {

View File

@ -179,15 +179,33 @@ xf86ActivateDevice(LocalDevicePtr local)
dev->coreEvents = local->flags & XI86_ALWAYS_CORE;
dev->spriteInfo->spriteOwner = !(local->flags & XI86_SHARED_POINTER);
RegisterOtherDevice(dev);
#ifdef XKB
if (!DeviceIsPointerType(dev) && !noXkbExtension)
if (DeviceIsPointerType(dev))
{
XkbSetExtension(dev, ProcessKeyboardEvent);
}
#ifdef XKB
dev->public.processInputProc = CoreProcessPointerEvent;
dev->public.realInputProc = CoreProcessPointerEvent;
#else
dev->public.processInputProc = ProcessPointerEvent;
dev->public.realInputProc = ProcessPointerEvent;
#endif
dev->deviceGrab.ActivateGrab = ActivatePointerGrab;
dev->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
} else
{
#ifdef XKB
dev->public.processInputProc = CoreProcessKeyboardEvent;
dev->public.realInputProc = CoreProcessKeyboardEvent;
#else
dev->public.processInputProc = ProcessKeyboardEvent;
dev->public.realInputProc = ProcessKeyboardEvent;
#endif
dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
}
RegisterOtherDevice(dev);
if (!noXkbExtension)
XkbSetExtension(dev, ProcessOtherEvent);
if (serverGeneration == 1)
xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n",

View File

@ -232,7 +232,6 @@ mieqProcessInputEvents(void)
{
EventRec *e = NULL;
int x = 0, y = 0;
DeviceIntPtr dev = NULL;
xEvent* event;
while (miEventQueue.head != miEventQueue.tail) {
@ -262,7 +261,8 @@ mieqProcessInputEvents(void)
if (miEventQueue.handlers[e->events->event->u.u.type]) {
miEventQueue.handlers[e->events->event->u.u.type](
DequeueScreen(e->pDev)->myNum,
e->events->event, dev,
e->events->event,
e->pDev,
e->nevents);
return;
}
@ -272,17 +272,7 @@ mieqProcessInputEvents(void)
if (e->events->event[0].u.u.type == KeyPress ||
e->events->event[0].u.u.type == KeyRelease) {
SwitchCoreKeyboard(e->pDev);
dev = inputInfo.keyboard;
}
else if (e->events->event[0].u.u.type == MotionNotify ||
e->events->event[0].u.u.type == ButtonPress ||
e->events->event[0].u.u.type == ButtonRelease) {
dev = inputInfo.pointer;
}
else {
dev = e->pDev;
}
/* FIXME: Bad hack. The only event where we actually get multiple
* events at once is a DeviceMotionNotify followed by
@ -303,11 +293,7 @@ mieqProcessInputEvents(void)
event = e->events->event;
}
/* MPX devices send both core and Xi events.
* Use dev to get the correct processing function but supply
* e->pDev to pass the correct device
*/
dev->public.processInputProc(event, e->pDev, e->nevents);
e->pDev->public.processInputProc(event, e->pDev, e->nevents);
if (e->nevents > 1)
xfree(event);