xserver: Branch 'mpx' - 6 commits

Peter Hutterer whot at kemper.freedesktop.org
Wed Nov 14 16:21:36 PST 2007


 Xi/exevents.c   |  529 +++++++++++++++++++++++++++++++++++++++++---------------
 dix/devices.c   |   27 ++
 dix/getevents.c |   57 ------
 include/input.h |    3 
 mi/mieq.c       |   16 -
 5 files changed, 418 insertions(+), 214 deletions(-)

New commits:
commit c758e5a664a52045ad419340044beebb6774a336
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 15 10:47:20 2007 +1030

    dix: Make sure core MDs copy their initial classes before they are used.
    
    Anything in dev->key, dev->valuator etc. of a MD must always be a copy of the
    original class. The intial classes of an MD (the ones set up before an SD is
    attached) as well, as we may have to restore them if no SD is attached
    anymore.

diff --git a/dix/devices.c b/dix/devices.c
index 2960e09..65d1980 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -402,6 +402,7 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
     XkbComponentNamesRec names;
 #endif
     ClassesPtr classes;
+    DeviceIntRec dummy;
 
     switch (what) {
     case DEVICE_INIT:
@@ -460,6 +461,19 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
         classes->stringfeed = pDev->stringfeed;
         classes->bell = pDev->bell;
         classes->leds = pDev->leds;
+
+        /* Each time we switch classes we free the MD's classes and copy the
+         * SD's classes into the MD. We mustn't lose the first set of classes
+         * though as we need it to restore them when the last SD disconnects.
+         *
+         * So we create a fake device, seem to copy from the fake to the real
+         * one, thus ending up with a copy of the original ones in our MD.
+         *
+         * If we don't do that, we're in SIGABRT territory (double-frees, etc)
+         */
+        memcpy(&dummy, pDev, sizeof(DeviceIntRec));
+        DeepCopyDeviceClasses(&dummy, pDev);
+
         pDev->devPrivates[MasterDevClassesPrivIdx].ptr = classes;
         break;
 
@@ -485,6 +499,7 @@ CorePointerProc(DeviceIntPtr pDev, int what)
     BYTE map[33];
     int i = 0;
     ClassesPtr classes;
+    DeviceIntRec dummy;
 
 
     switch (what) {
@@ -519,6 +534,10 @@ CorePointerProc(DeviceIntPtr pDev, int what)
         classes->bell = pDev->bell;
         classes->leds = pDev->leds;
 
+        /* See comment in CoreKeyboardProc. */
+        memcpy(&dummy, pDev, sizeof(DeviceIntRec));
+        DeepCopyDeviceClasses(&dummy, pDev);
+
         pDev->devPrivates[MasterDevClassesPrivIdx].ptr = classes;
         break;
 
@@ -568,7 +587,6 @@ InitCoreDevices(void)
 
     ActivateDevice(inputInfo.keyboard);
     ActivateDevice(inputInfo.pointer);
-
 }
 
 /**
commit a08665d4d3b0a7d567a90bb9bbfe4abafd6f3887
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 15 10:42:29 2007 +1030

    mi: don't call SwitchCoreKeyboard, we switch during event processing now.

diff --git a/mi/mieq.c b/mi/mieq.c
index 11439cf..5dcc404 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -331,23 +331,13 @@ mieqProcessInputEvents(void)
                 return;
             }
 
-            /* Make sure our keymap, et al, is changed to suit. */
-            if ((e->events->event[0].u.u.type == DeviceKeyPress ||
-                e->events->event[0].u.u.type == DeviceKeyRelease ||
-                e->events->event[0].u.u.type == KeyPress ||
-                e->events->event[0].u.u.type == KeyRelease) &&
-                    !e->pDev->isMaster)
-            {
-                SwitchCoreKeyboard(e->pDev);
-            }
-
             /* FIXME: Bad hack. The only event where we actually get multiple
              * events at once is a DeviceMotionNotify followed by
              * DeviceValuators. For now it's save enough to just take the
              * event directly or copy the bunch of events and pass in the
              * copy. Eventually the interface for the processInputProc needs
              * to be changed. (whot)
-             */ 
+             */
             if (e->nevents > 1)
             {
                 int i;
@@ -372,7 +362,7 @@ mieqProcessInputEvents(void)
 
             if (!e->pDev->isMaster && e->pDev->u.master)
             {
-                e->pDev->u.master->public.processInputProc(master_event, 
+                e->pDev->u.master->public.processInputProc(master_event,
                         e->pDev->u.master, e->nevents);
             }
 
@@ -382,7 +372,7 @@ mieqProcessInputEvents(void)
         }
 
         /* Update the sprite now. Next event may be from different device. */
-        if (e->events->event[0].u.u.type == DeviceMotionNotify 
+        if (e->events->event[0].u.u.type == DeviceMotionNotify
                 && e->pDev->coreEvents)
         {
             miPointerUpdateSprite(e->pDev);
commit 64711a094893e83764bbeda538c6e877ebe2af79
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 15 10:41:34 2007 +1030

    Xi: When switching MD classes, make a deep copy instead of pointer flip.
    
    Turns out it's really really hard synchronising device state across multiple
    duplicated events if they all share the same struct. So instead of doing so,
    when the SD changes deep-copy all it's classes into the MD. The MD then has
    the same capabilities, but the state can be set separately. This should fix
    xkb, key state, repeat etc. problems.
    
    Updating the device state allows us to remove the SwitchCoreKeyboard from the
    event gathering, it's all done during event processing now.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 91035c7..1bf6c51 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -76,7 +76,9 @@ SOFTWARE.
 #include "listdev.h" /* for CopySwapXXXClass */
 
 #ifdef XKB
+#include <X11/extensions/XKBproto.h>
 #include "xkbsrv.h"
+extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies);
 #endif
 
 #define WID(w) ((w) ? ((w)->drawable.id) : 0)
@@ -102,6 +104,154 @@ RegisterOtherDevice(DeviceIntPtr device)
     device->public.realInputProc = ProcessOtherEvent;
 }
 
+/**
+ * Copy the device->key into master->key and send a mapping notify to the
+ * clients if appropriate.
+ * master->key needs to be allocated by the caller.
+ *
+ * Device is the slave device. If it is attached to a master device, we may
+ * need to send a mapping notify to the client because it causes the MD
+ * to change state.
+ *
+ * Mapping notify needs to be sent in the following cases:
+ *      - different slave device on same master
+ *      - different master
+ *
+ * XXX: They way how the code is we also send a map notify if the slave device
+ * stays the same, but the master changes. This isn't really necessary though.
+ *
+ * XXX: this gives you funny behaviour with the ClientPointer. When a
+ * MappingNotify is sent to the client, the client usually responds with a
+ * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
+ * mapping, regardless of which keyboard sent the last mapping notify request.
+ * So depending on the CP setting, your keyboard may change layout in each
+ * app...
+ *
+ * This code is basically the old SwitchCoreKeyboard.
+ */
+
+static void
+CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
+{
+    static DeviceIntPtr lastMapNotifyDevice = NULL;
+    KeyClassPtr mk, dk; /* master, device */
+    BOOL sendNotify = FALSE;
+    int i;
+
+    if (device == master)
+        return;
+
+    dk = device->key;
+    mk = master->key;
+
+    if (master->devPrivates[CoreDevicePrivatesIndex].ptr != device) {
+        memcpy(mk->modifierMap, dk->modifierMap, MAP_LENGTH);
+
+        mk->modifierKeyMap = xcalloc(8, dk->maxKeysPerModifier);
+        if (!mk->modifierKeyMap)
+            FatalError("[Xi] no memory for class shift.\n");
+        memcpy(mk->modifierKeyMap, dk->modifierKeyMap,
+                (8 * dk->maxKeysPerModifier));
+
+        mk->maxKeysPerModifier = dk->maxKeysPerModifier;
+        mk->curKeySyms.minKeyCode = dk->curKeySyms.minKeyCode;
+        mk->curKeySyms.maxKeyCode = dk->curKeySyms.maxKeyCode;
+        SetKeySymsMap(&mk->curKeySyms, &dk->curKeySyms);
+
+        /*
+         * Copy state from the extended keyboard to core.  If you omit this,
+         * holding Ctrl on keyboard one, and pressing Q on keyboard two, will
+         * cause your app to quit.  This feels wrong to me, hence the below
+         * code.
+         *
+         * XXX: If you synthesise core modifier events, the state will get
+         *      clobbered here.  You'll have to work out something sensible
+         *      to fix that.  Good luck.
+         */
+
+#define KEYBOARD_MASK (ShiftMask | LockMask | ControlMask | Mod1Mask | \
+        Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)
+        mk->state &= ~(KEYBOARD_MASK);
+        mk->state |= (dk->state & KEYBOARD_MASK);
+#undef KEYBOARD_MASK
+        for (i = 0; i < 8; i++)
+            mk->modifierKeyCount[i] = dk->modifierKeyCount[i];
+
+#ifdef XKB
+        if (!mk->xkbInfo || !mk->xkbInfo->desc)
+            XkbInitDevice(master);
+        if (!noXkbExtension && dk->xkbInfo && dk->xkbInfo->desc) {
+            if (!XkbCopyKeymap(dk->xkbInfo->desc, mk->xkbInfo->desc, True))
+                FatalError("Couldn't pivot keymap from device to core!\n");
+        }
+#endif
+
+        master->devPrivates[CoreDevicePrivatesIndex].ptr = device;
+        sendNotify = TRUE;
+    } else if (lastMapNotifyDevice != master)
+        sendNotify = TRUE;
+
+    if (sendNotify)
+    {
+        SendMappingNotify(master, MappingKeyboard,
+                           mk->curKeySyms.minKeyCode,
+                          (mk->curKeySyms.maxKeyCode -
+                           mk->curKeySyms.minKeyCode),
+                          serverClient);
+        lastMapNotifyDevice = master;
+    }
+}
+
+_X_EXPORT void
+DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
+{
+#define ALLOC_COPY_CLASS_IF(field, type) \
+    if (from->field)\
+    { \
+        to->field = xcalloc(1, sizeof(type)); \
+        if (!to->field) \
+            FatalError("[Xi] no memory for class shift.\n"); \
+        memcpy(to->field, from->field, sizeof(type)); \
+    }
+
+    ALLOC_COPY_CLASS_IF(key, KeyClassRec);
+    if (to->key)
+    {
+#ifdef XKB
+        to->key->xkbInfo = NULL;
+#endif
+        CopyKeyClass(from, to);
+    }
+
+    if (from->valuator)
+    {
+        ValuatorClassPtr v;
+        to->valuator = xalloc(sizeof(ValuatorClassRec) +
+                from->valuator->numAxes * sizeof(AxisInfo) +
+                from->valuator->numAxes * sizeof(unsigned int));
+        v = to->valuator;
+        if (!v)
+            FatalError("[Xi] no memory for class shift.\n");
+        memcpy(v, from->valuator, sizeof(ValuatorClassRec));
+        v->axes = (AxisInfoPtr)&v[1];
+        memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
+    }
+
+    ALLOC_COPY_CLASS_IF(button, ButtonClassRec);
+        /* XXX: XkbAction needs to be copied */
+    ALLOC_COPY_CLASS_IF(focus, FocusClassRec);
+    ALLOC_COPY_CLASS_IF(proximity, ProximityClassRec);
+    ALLOC_COPY_CLASS_IF(absolute, AbsoluteClassRec);
+    ALLOC_COPY_CLASS_IF(kbdfeed, KbdFeedbackClassRec);
+        /* XXX: XkbSrvLedInfo needs to be copied*/
+    ALLOC_COPY_CLASS_IF(ptrfeed, PtrFeedbackClassRec);
+    ALLOC_COPY_CLASS_IF(intfeed, IntegerFeedbackClassRec);
+    ALLOC_COPY_CLASS_IF(stringfeed, StringFeedbackClassRec);
+    ALLOC_COPY_CLASS_IF(bell, BellFeedbackClassRec);
+    ALLOC_COPY_CLASS_IF(leds, LedFeedbackClassRec);
+        /* XXX: XkbSrvLedInfo needs to be copied. */
+}
+
 static void
 ChangeMasterDeviceClasses(DeviceIntPtr device,
                           deviceClassesChangedEvent *dcce)
@@ -119,21 +269,31 @@ ChangeMasterDeviceClasses(DeviceIntPtr device,
     dcce->num_classes  = 0;
 
     master->public.devicePrivate = device->public.devicePrivate;
-    master->key        = device->key;
-    master->valuator   = device->valuator;
-    master->button     = device->button;
-    master->focus      = device->focus;
-    master->proximity  = device->proximity;
-    master->absolute   = device->absolute;
-    master->kbdfeed    = device->kbdfeed;
-    master->ptrfeed    = device->ptrfeed;
-    master->intfeed    = device->intfeed;
-    master->stringfeed = device->stringfeed;
-    master->bell       = device->bell;
-    master->leds       = device->leds;
+
+    if (master->key)
+        xfree(master->key->modifierKeyMap);
+#ifdef XKB
+    if (master->key && master->key->xkbInfo)
+        XkbFreeInfo(master->key->xkbInfo);
+#endif
+    xfree(master->key);         master->key = NULL;
+    xfree(master->valuator);    master->valuator = NULL;
+    xfree(master->button);      master->button = NULL;
+    xfree(master->focus);       master->focus = NULL;
+    xfree(master->proximity);   master->proximity = NULL;
+    xfree(master->absolute);    master->absolute = NULL;
+    xfree(master->kbdfeed);     master->kbdfeed = NULL;
+    xfree(master->ptrfeed);     master->ptrfeed = NULL;
+    xfree(master->stringfeed);  master->stringfeed = NULL;
+    xfree(master->bell);        master->bell = NULL;
+    xfree(master->leds);        master->leds = NULL;
+    xfree(master->intfeed);     master->intfeed = NULL;
+
+    DeepCopyDeviceClasses(device, master);
 
     /* event is already correct size, see comment in GetPointerEvents */
     classbuff = (char*)&dcce[1];
+
     /* we don't actually swap if there's a NullClient, swapping is done
      * later when event is delivered. */
     CopySwapClasses(NullClient, master, &dcce->num_classes, &classbuff);
@@ -159,9 +319,9 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
     int key = 0,
         bit = 0;
 
-    KeyClassPtr k       = device->key;
-    ButtonClassPtr b    = device->button;
-    ValuatorClassPtr v  = device->valuator;
+    KeyClassPtr k       = NULL;
+    ButtonClassPtr b    = NULL;
+    ValuatorClassPtr v  = NULL;
     deviceValuator *xV  = (deviceValuator *) xE;
     BYTE *kptr          = NULL;
     CARD16 modifiers    = 0,
@@ -181,6 +341,11 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
     if (xE->u.u.type == GenericEvent)
         return DEFAULT;
 
+    k = device->key;
+    v = device->valuator;
+    b = device->button;
+
+
     if (xE->u.u.type != DeviceValuator)
     {
         key = xE->u.u.detail;
@@ -272,10 +437,9 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
 	*kptr |= bit;
 	if (device->valuator)
 	    device->valuator->motionHintWindow = NullWindow;
-        if (!device->isMaster)
-            b->buttonsDown++;
+        b->buttonsDown++;
 	b->motionMask = DeviceButtonMotionMask;
-        if (!device->isMaster && !b->map[key]) /* bit already unset for MDs */
+        if (!b->map[key])
             return DONT_PROCESS;
         if (b->map[key] <= 5)
 	    b->state |= (Button1Mask >> 1) << b->map[key];
@@ -290,9 +454,7 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
 	*kptr &= ~bit;
 	if (device->valuator)
 	    device->valuator->motionHintWindow = NullWindow;
-        if (!device->isMaster)
-            b->buttonsDown--;
-        if (b->buttonsDown >= 1 && !b->buttonsDown)
+        if (b->buttonsDown >= 1 && !--b->buttonsDown)
 	    b->motionMask = 0;
         if (!b->map[key])
             return DONT_PROCESS;
@@ -323,9 +485,9 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
     GrabPtr grab = device->deviceGrab.grab;
     Bool deactivateDeviceGrab = FALSE;
     int key = 0, rootX, rootY;
-    ButtonClassPtr b = device->button;
-    KeyClassPtr k = device->key;
-    ValuatorClassPtr v  = device->valuator;
+    ButtonClassPtr b;
+    KeyClassPtr k;
+    ValuatorClassPtr v;
     deviceValuator *xV  = (deviceValuator *) xE;
     BOOL sendCore = FALSE;
     xEvent core;
@@ -336,6 +498,10 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
     if (ret == DONT_PROCESS)
         return;
 
+    v = device->valuator;
+    b = device->button;
+    k = device->key;
+
     coretype = XItoCoreType(xE->u.u.type);
     if (device->isMaster && device->coreEvents && coretype)
         sendCore = TRUE;
diff --git a/dix/getevents.c b/dix/getevents.c
index b0211b6..20beff3 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -865,63 +865,6 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
     return num_events;
 }
 
-
-/**
- * pDev is the slave device that is about to send an event. If it is attached
- * to a master device, then we need to send a mapping notify to the client.
- * To do so, we need to remember the last master device that sent a mapping
- * event.
- *
- * Mapping notify needs to be sent in the following cases:
- *      - different slave device on same master
- *      - different master
- *
- * Call this just before processInputProc.
- *
- * XXX: They way how the code is we also send a map notify if the slave device
- * stays the same, but the master changes. This isn't really necessary though.
- *
- * XXX: this gives you funny behaviour with the ClientPointer. When a
- * MappingNotify is sent to the client, the client usually responds with a
- * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
- * mapping, regardless of which keyboard sent the last mapping notify request.
- * So depending on the CP setting, your keyboard may change layout in each
- * app...
- */
-_X_EXPORT void
-SwitchCoreKeyboard(DeviceIntPtr pDev)
-{
-    static DeviceIntPtr lastMapNotifyDevice = NULL;
-    DeviceIntPtr master;
-    KeyClassPtr ckeyc;
-    int i = 0;
-    BOOL sendNotify = FALSE;
-
-    if (pDev->isMaster || !pDev->u.master)
-        return;
-
-    master = pDev->u.master;
-    ckeyc = master->key;
-
-    if (master->devPrivates[CoreDevicePrivatesIndex].ptr != pDev) {
-        master->devPrivates[CoreDevicePrivatesIndex].ptr = pDev;
-        sendNotify = TRUE;
-    }
-
-    if (lastMapNotifyDevice != master)
-        sendNotify = TRUE;
-
-    if (sendNotify)
-    {
-        SendMappingNotify(pDev, MappingKeyboard, ckeyc->curKeySyms.minKeyCode,
-                          (ckeyc->curKeySyms.maxKeyCode -
-                           ckeyc->curKeySyms.minKeyCode),
-                          serverClient);
-        lastMapNotifyDevice = master;
-    }
-}
-
-
 /**
  * Note that pDev was the last function to send a core pointer event.
  * Currently a no-op.
diff --git a/include/input.h b/include/input.h
index dbf6aee..91ce4ee 100644
--- a/include/input.h
+++ b/include/input.h
@@ -458,7 +458,6 @@ extern int GetMotionHistory(
     unsigned long stop,
     ScreenPtr pScreen);
 
-extern void SwitchCoreKeyboard(DeviceIntPtr pDev);
 extern void SwitchCorePointer(DeviceIntPtr pDev);
 
 extern DeviceIntPtr LookupDeviceIntRec(
@@ -483,6 +482,8 @@ extern DeviceIntPtr NextFreePointerDevice(void);
 extern int AllocMasterDevice(char* name,
                              DeviceIntPtr* ptr,
                              DeviceIntPtr* keybd);
+extern void DeepCopyDeviceClasses(DeviceIntPtr from,
+                                  DeviceIntPtr to);
 
 /* Window/device based access control */
 extern Bool ACRegisterClient(ClientPtr client);
commit cc4586df600af571815d5cdda2028c0d074c8469
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 14 14:27:52 2007 +1030

    Xi: toggle the public.devPrivate as well when switching device classes.
    
    The master needs to have the same devPrivate as the slave, in case a client
    issues a request that goes down to the driver.
    Example: if a driver wants to ring the keyboard bell, it'll pick a keyboard.
    The KeyClassPtr will direct it to the matching method in the driver, but
    because the MD doesn't have the devPrivate set the driver segfaults.
    Even if all drivers were updated to not dereference the nullpointer, nothing
    would actually ever happen.
    
    To avoid this, we flip the master's public.devPrivate to the last SDs
    devPrivate.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index f60f634..91035c7 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -118,6 +118,7 @@ ChangeMasterDeviceClasses(DeviceIntPtr device,
     dcce->deviceid     = master->id;
     dcce->num_classes  = 0;
 
+    master->public.devicePrivate = device->public.devicePrivate;
     master->key        = device->key;
     master->valuator   = device->valuator;
     master->button     = device->button;
commit b44c1118f3bab6d5f28fa42e0c322fbaec005012
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 14 14:08:21 2007 +1030

    dix: Return Success from ProcBell if no BellProc is set.
    
    We must not return BadDevice, this causes applications to crash. If no
    BellProc is set, just quietly do nothing and report a Success.

diff --git a/dix/devices.c b/dix/devices.c
index fa80a0c..2960e09 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2011,8 +2011,13 @@ ProcBell(ClientPtr client)
     REQUEST(xBellReq);
     REQUEST_SIZE_MATCH(xBellReq);
 
+    /* Seems like no keyboard actually has the BellProc set. Returning
+     * BadDevice (previous code) will make apps crash badly. The man pages
+     * doesn't say anything about a BadDevice being returned either.
+     * So just quietly do nothing and pretend everything has worked.
+     */
     if (!keybd->kbdfeed->BellProc)
-        return BadDevice;
+        return Success;
 
     if (stuff->percent < -100 || stuff->percent > 100) {
 	client->errorValue = stuff->percent;
commit 240b10fa9c32510a380a73a8acdd8267c81e538b
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 14 12:18:08 2007 +1030

    Xi: Move updating the device state from POE into separate function.
    
    POE now only deals with processing the event and calling the appropriate
    delivery methods. Actually modifying the device state is done in
    UpdateDeviceState. This separation should make it easier to avoid setting the
    state twice when master events are processed.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 511930b..f60f634 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -102,6 +102,210 @@ RegisterOtherDevice(DeviceIntPtr device)
     device->public.realInputProc = ProcessOtherEvent;
 }
 
+static void
+ChangeMasterDeviceClasses(DeviceIntPtr device,
+                          deviceClassesChangedEvent *dcce)
+{
+    DeviceIntPtr master = device->u.master;
+    char* classbuff;
+
+    if (device->isMaster)
+        return;
+
+    if (!master) /* if device was set floating between SIGIO and now */
+        return;
+
+    dcce->deviceid     = master->id;
+    dcce->num_classes  = 0;
+
+    master->key        = device->key;
+    master->valuator   = device->valuator;
+    master->button     = device->button;
+    master->focus      = device->focus;
+    master->proximity  = device->proximity;
+    master->absolute   = device->absolute;
+    master->kbdfeed    = device->kbdfeed;
+    master->ptrfeed    = device->ptrfeed;
+    master->intfeed    = device->intfeed;
+    master->stringfeed = device->stringfeed;
+    master->bell       = device->bell;
+    master->leds       = device->leds;
+
+    /* event is already correct size, see comment in GetPointerEvents */
+    classbuff = (char*)&dcce[1];
+    /* we don't actually swap if there's a NullClient, swapping is done
+     * later when event is delivered. */
+    CopySwapClasses(NullClient, master, &dcce->num_classes, &classbuff);
+    SendEventToAllWindows(master, XI_DeviceClassesChangedMask,
+                          (xEvent*)dcce, 1);
+}
+
+/**
+ * Update the device state according to the data in the event.
+ *
+ * return values are
+ *   DEFAULT ... process as normal
+ *   DONT_PROCESS ... return immediately from caller
+ *   IS_REPEAT .. event is a repeat event.
+ */
+#define DEFAULT 0
+#define DONT_PROCESS 1
+#define IS_REPEAT 2
+static int
+UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
+{
+    int i;
+    int key = 0,
+        bit = 0;
+
+    KeyClassPtr k       = device->key;
+    ButtonClassPtr b    = device->button;
+    ValuatorClassPtr v  = device->valuator;
+    deviceValuator *xV  = (deviceValuator *) xE;
+    BYTE *kptr          = NULL;
+    CARD16 modifiers    = 0,
+           mask         = 0;
+
+    /* This event is always the first we get, before the actual events with
+     * the data. However, the way how the DDX is set up, "device" will
+     * actually be the slave device that caused the event.
+     */
+    if (GEIsType(xE, IReqCode, XI_DeviceClassesChangedNotify))
+    {
+        ChangeMasterDeviceClasses(device, (deviceClassesChangedEvent*)xE);
+        return DONT_PROCESS; /* event has been sent already */
+    }
+
+    /* currently no other generic event modifies the device */
+    if (xE->u.u.type == GenericEvent)
+        return DEFAULT;
+
+    if (xE->u.u.type != DeviceValuator)
+    {
+        key = xE->u.u.detail;
+        bit = 1 << (key & 7);
+    }
+
+    /* Update device axis */
+    for (i = 1; i < count; i++) {
+	if ((++xV)->type == DeviceValuator) {
+	    int *axisvals;
+            int first = xV->first_valuator;
+
+	    if (xV->num_valuators &&
+                (!v || (xV->num_valuators &&
+                      (first + xV->num_valuators > v->numAxes))))
+		FatalError("Bad valuators reported for device %s\n",
+			   device->name);
+	    if (v && v->axisVal) {
+		axisvals = v->axisVal;
+		switch (xV->num_valuators) {
+		case 6:
+		    *(axisvals + first + 5) = xV->valuator5;
+		case 5:
+		    *(axisvals + first + 4) = xV->valuator4;
+		case 4:
+		    *(axisvals + first + 3) = xV->valuator3;
+		case 3:
+		    *(axisvals + first + 2) = xV->valuator2;
+		case 2:
+		    *(axisvals + first + 1) = xV->valuator1;
+		case 1:
+		    *(axisvals + first) = xV->valuator0;
+		case 0:
+		default:
+		    break;
+		}
+	    }
+	}
+    }
+
+    if (xE->u.u.type == DeviceKeyPress) {
+        if (!k)
+            return DONT_PROCESS;
+
+	modifiers = k->modifierMap[key];
+	kptr = &k->down[key >> 3];
+	if (*kptr & bit) {	/* allow ddx to generate multiple downs */
+	    return IS_REPEAT;
+	}
+	if (device->valuator)
+	    device->valuator->motionHintWindow = NullWindow;
+	*kptr |= bit;
+	k->prev_state = k->state;
+	for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
+	    if (mask & modifiers) {
+		/* This key affects modifier "i" */
+		k->modifierKeyCount[i]++;
+		k->state |= mask;
+		modifiers &= ~mask;
+	    }
+	}
+    } else if (xE->u.u.type == DeviceKeyRelease) {
+        if (!k)
+            return DONT_PROCESS;
+
+	kptr = &k->down[key >> 3];
+	if (!(*kptr & bit))	/* guard against duplicates */
+	    return DONT_PROCESS;
+	modifiers = k->modifierMap[key];
+	if (device->valuator)
+	    device->valuator->motionHintWindow = NullWindow;
+	*kptr &= ~bit;
+	k->prev_state = k->state;
+	for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
+	    if (mask & modifiers) {
+		/* This key affects modifier "i" */
+		if (--k->modifierKeyCount[i] <= 0) {
+		    k->modifierKeyCount[i] = 0;
+		    k->state &= ~mask;
+		}
+		modifiers &= ~mask;
+	    }
+	}
+    } else if (xE->u.u.type == DeviceButtonPress) {
+        if (!b)
+            return DONT_PROCESS;
+
+	kptr = &b->down[key >> 3];
+	*kptr |= bit;
+	if (device->valuator)
+	    device->valuator->motionHintWindow = NullWindow;
+        if (!device->isMaster)
+            b->buttonsDown++;
+	b->motionMask = DeviceButtonMotionMask;
+        if (!device->isMaster && !b->map[key]) /* bit already unset for MDs */
+            return DONT_PROCESS;
+        if (b->map[key] <= 5)
+	    b->state |= (Button1Mask >> 1) << b->map[key];
+	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
+    } else if (xE->u.u.type == DeviceButtonRelease) {
+        if (!b)
+            return DONT_PROCESS;
+
+	kptr = &b->down[key >> 3];
+        if (!(*kptr & bit))
+            return DONT_PROCESS;
+	*kptr &= ~bit;
+	if (device->valuator)
+	    device->valuator->motionHintWindow = NullWindow;
+        if (!device->isMaster)
+            b->buttonsDown--;
+        if (b->buttonsDown >= 1 && !b->buttonsDown)
+	    b->motionMask = 0;
+        if (!b->map[key])
+            return DONT_PROCESS;
+	if (b->map[key] <= 5)
+	    b->state &= ~((Button1Mask >> 1) << b->map[key]);
+	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
+    } else if (xE->u.u.type == ProximityIn)
+	device->valuator->mode &= ~OutOfProximity;
+    else if (xE->u.u.type == ProximityOut)
+	device->valuator->mode |= OutOfProximity;
+
+    return DEFAULT;
+}
+
 /**
  * Main device event processing function.
  * Called from when processing the events from the event queue.
@@ -113,61 +317,23 @@ RegisterOtherDevice(DeviceIntPtr device)
 void
 ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 {
-    BYTE *kptr;
     int i;
     CARD16 modifiers;
-    CARD16 mask;
     GrabPtr grab = device->deviceGrab.grab;
     Bool deactivateDeviceGrab = FALSE;
-    int key = 0, bit = 0, rootX, rootY;
+    int key = 0, rootX, rootY;
     ButtonClassPtr b = device->button;
     KeyClassPtr k = device->key;
-    ValuatorClassPtr v = device->valuator;
-    deviceValuator *xV = (deviceValuator *) xE;
+    ValuatorClassPtr v  = device->valuator;
+    deviceValuator *xV  = (deviceValuator *) xE;
     BOOL sendCore = FALSE;
     xEvent core;
     int coretype = 0;
+    int ret = 0;
 
-    /* This event is always the first we get, before the actual events with
-     * the data. However, the way how the DDX is set up, "device" will
-     * actually be the slave device that caused the event.
-     */
-    if (GEIsType(xE, IReqCode, XI_DeviceClassesChangedNotify))
-    {
-        deviceClassesChangedEvent* dcce = (deviceClassesChangedEvent*)xE;
-        DeviceIntPtr master = device->u.master;
-        char* classbuff;
-
-        if (device->isMaster)
-            return;
-
-        if (!master) /* if device was set floating between SIGIO and now */
-            return;
-
-        dcce->deviceid     = master->id;
-        dcce->num_classes  = 0;
-
-        master->key        = device->key;
-        master->valuator   = device->valuator;
-        master->button     = device->button;
-        master->focus      = device->focus;
-        master->proximity  = device->proximity;
-        master->absolute   = device->absolute;
-        master->kbdfeed    = device->kbdfeed;
-        master->ptrfeed    = device->ptrfeed;
-        master->intfeed    = device->intfeed;
-        master->stringfeed = device->stringfeed;
-        master->bell       = device->bell;
-        master->leds       = device->leds;
-
-        /* event is already correct size, see comment in GetPointerEvents */
-        classbuff = (char*)&xE[1];
-        /* we don't actually swap if there's a NullClient, swapping is done
-         * later when event is delivered. */
-        CopySwapClasses(NullClient, master, &dcce->num_classes, &classbuff);
-        SendEventToAllWindows(master, XI_DeviceClassesChangedMask, xE, 1);
+    ret = UpdateDeviceState(device, xE, count);
+    if (ret == DONT_PROCESS)
         return;
-    }
 
     coretype = XItoCoreType(xE->u.u.type);
     if (device->isMaster && device->coreEvents && coretype)
@@ -181,7 +347,6 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 	GetSpritePosition(device, &rootX, &rootY);
 	xE->u.keyButtonPointer.rootX = rootX;
 	xE->u.keyButtonPointer.rootY = rootY;
-	key = xE->u.u.detail;
 	NoticeEventTime(xE);
 
         /* If 'device' is a pointer device, we need to get the paired keyboard
@@ -202,7 +367,7 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
         xE->u.keyButtonPointer.state = (kbd) ? (kbd->key->state) : 0;
         xE->u.keyButtonPointer.state |= (mouse) ? (mouse->button->state) : 0;
 
-	bit = 1 << (key & 7);
+        key = xE->u.u.detail;
     }
     if (DeviceEventCallback) {
 	DeviceEventInfoRec eventinfo;
@@ -211,11 +376,11 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 	eventinfo.count = count;
 	CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
     }
-    for (i = 1; i < count; i++)
+
+    /* Valuator event handling */
+    for (i = 1; i < count; i++) {
 	if ((++xV)->type == DeviceValuator) {
 	    int first = xV->first_valuator;
-	    int *axisvals;
-
 	    if (xV->num_valuators
 		&& (!v
 		    || (xV->num_valuators
@@ -227,35 +392,12 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 		xV->device_state |= k->state;
 	    if (b)
 		xV->device_state |= b->state;
-	    if (v && v->axisVal) {
-		axisvals = v->axisVal;
-		switch (xV->num_valuators) {
-		case 6:
-		    *(axisvals + first + 5) = xV->valuator5;
-		case 5:
-		    *(axisvals + first + 4) = xV->valuator4;
-		case 4:
-		    *(axisvals + first + 3) = xV->valuator3;
-		case 3:
-		    *(axisvals + first + 2) = xV->valuator2;
-		case 2:
-		    *(axisvals + first + 1) = xV->valuator1;
-		case 1:
-		    *(axisvals + first) = xV->valuator0;
-		case 0:
-		default:
-		    break;
-		}
-	    }
 	}
+    }
 
     if (xE->u.u.type == DeviceKeyPress) {
-        if (!k)
-            return;
-
-	modifiers = k->modifierMap[key];
-	kptr = &k->down[key >> 3];
-	if (*kptr & bit) {	/* allow ddx to generate multiple downs */
+        if (ret == IS_REPEAT) {	/* allow ddx to generate multiple downs */
+            modifiers = k->modifierMap[key];
 	    if (!modifiers) {
 		xE->u.u.type = DeviceKeyRelease;
 		ProcessOtherEvent(xE, device, count);
@@ -265,18 +407,6 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 	    }
 	    return;
 	}
-	if (device->valuator)
-	    device->valuator->motionHintWindow = NullWindow;
-	*kptr |= bit;
-	k->prev_state = k->state;
-	for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
-	    if (mask & modifiers) {
-		/* This key affects modifier "i" */
-		k->modifierKeyCount[i]++;
-		k->state |= mask;
-		modifiers &= ~mask;
-	    }
-	}
         /* XI grabs have priority */
         core = *xE;
         core.u.u.type = coretype;
@@ -287,47 +417,13 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 	    return;
 	}
     } else if (xE->u.u.type == DeviceKeyRelease) {
-        if (!k)
-            return;
-
-	kptr = &k->down[key >> 3];
-	if (!(*kptr & bit))	/* guard against duplicates */
-	    return;
-	modifiers = k->modifierMap[key];
-	if (device->valuator)
-	    device->valuator->motionHintWindow = NullWindow;
-	*kptr &= ~bit;
-	k->prev_state = k->state;
-	for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
-	    if (mask & modifiers) {
-		/* This key affects modifier "i" */
-		if (--k->modifierKeyCount[i] <= 0) {
-		    k->modifierKeyCount[i] = 0;
-		    k->state &= ~mask;
-		}
-		modifiers &= ~mask;
-	    }
-	}
-
 	if (device->deviceGrab.fromPassiveGrab &&
             (key == device->deviceGrab.activatingKey))
 	    deactivateDeviceGrab = TRUE;
     } else if (xE->u.u.type == DeviceButtonPress) {
-        if (!b)
-            return;
-
-	kptr = &b->down[key >> 3];
-	*kptr |= bit;
-	if (device->valuator)
-	    device->valuator->motionHintWindow = NullWindow;
-	b->buttonsDown++;
-	b->motionMask = DeviceButtonMotionMask;
 	xE->u.u.detail = b->map[key];
 	if (xE->u.u.detail == 0)
 	    return;
-	if (xE->u.u.detail <= 5)
-	    b->state |= (Button1Mask >> 1) << xE->u.u.detail;
-	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
         if (!grab)
         {
             core = *xE;
@@ -342,28 +438,12 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
         }
 
     } else if (xE->u.u.type == DeviceButtonRelease) {
-        if (!b)
-            return;
-
-	kptr = &b->down[key >> 3];
-	*kptr &= ~bit;
-	if (device->valuator)
-	    device->valuator->motionHintWindow = NullWindow;
-        if (b->buttonsDown >= 1 && !--b->buttonsDown)
-	    b->motionMask = 0;
 	xE->u.u.detail = b->map[key];
 	if (xE->u.u.detail == 0)
 	    return;
-	if (xE->u.u.detail <= 5)
-	    b->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
-	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
-        if (!b->state
-            && device->deviceGrab.fromPassiveGrab)
+        if (!b->state && 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)
     {


More information about the xorg-commit mailing list