From 340911d7243a7f1095d79b5b2dcfa81b145c2474 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 26 Sep 2007 15:12:49 +0930 Subject: [PATCH] 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. --- Xi/exevents.c | 59 ++++++++++++++++++++++++++++------ hw/xfree86/common/xf86Xinput.c | 30 +++++++++++++---- mi/mieq.c | 20 ++---------- 3 files changed, 77 insertions(+), 32 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index aa2b4c9de..2baaa58e3 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -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) { diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c index 243623166..31c300811 100644 --- a/hw/xfree86/common/xf86Xinput.c +++ b/hw/xfree86/common/xf86Xinput.c @@ -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", diff --git a/mi/mieq.c b/mi/mieq.c index c3f63fb8b..78e57adc4 100644 --- a/mi/mieq.c +++ b/mi/mieq.c @@ -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);