xserver: Branch 'mpx'

Peter Hutterer whot at kemper.freedesktop.org
Mon Jun 18 19:03:10 PDT 2007


 dix/devices.c      |    1 
 dix/events.c       |   92 ++++++++++++++++++++++++++++++++++++++++++++++++-----
 include/dix.h      |    4 ++
 include/inputstr.h |    6 ++-
 4 files changed, 94 insertions(+), 9 deletions(-)

New commits:
diff-tree 9e257029c760883c4ea0715d4fd06476f3fe8053 (from 3e894974cdd6a75683d4601f71622d1da7ec4395)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Jun 19 11:28:07 2007 +0930

    Add implicitGrab field to GrabInfoRec.
    Is set when passive grab is implicit as result of a ButtonPress event. If this
    is the case, we need to store the XI mask as well as the core mask to ensure
    delivery of XI events during the grab's lifetime.
    
    Remove all core grabs on other devices when client issues a GrabPointer or
    GrabKeyboard request. Let's assume that the client really only wants one
    device to interact, so this seems like a reasonable solution.

diff --git a/dix/devices.c b/dix/devices.c
index 4672b2a..b56423a 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -135,6 +135,7 @@ AddInputDevice(DeviceProc deviceProc, Bo
     dev->deviceGrab.grab = NullGrab;
     dev->deviceGrab.grabTime = currentTime;
     dev->deviceGrab.fromPassiveGrab = FALSE;
+    dev->deviceGrab.implicitGrab = FALSE;
 
     dev->key = (KeyClassPtr)NULL;
     dev->valuator = (ValuatorClassPtr)NULL;
diff --git a/dix/events.c b/dix/events.c
index 4c5f5b9..f6e9021 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -209,6 +209,12 @@ static xEvent *xeviexE;
 	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
 	Mod3Mask | Mod4Mask | Mod5Mask )
 #define AllEventMasks (lastEventMask|(lastEventMask-1))
+
+/**
+ * Used to indicate a implicit passive grab created by a ButtonPress event.
+ * See DeliverEventsToWindow().
+ */
+#define ImplicitGrabMask (1 << 7)
 /*
  * The following relies on the fact that the Button<n>MotionMasks are equal
  * to the corresponding Button<n>Masks from the current modifier/button state.
@@ -1238,6 +1244,14 @@ PlayReleasedEvents(void)
     } 
 }
 
+/**
+ * Freeze or thaw the given devices. The device's processing proc is
+ * switched to either the real processing proc (in case of thawing) or an
+ * enqueuing processing proc (usually EnqueueEvent()).
+ *
+ * @param dev The device to freeze/thaw
+ * @param frozen True to freeze or false to thaw.
+ */
 static void
 FreezeThaw(DeviceIntPtr dev, Bool frozen)
 {
@@ -1248,6 +1262,14 @@ FreezeThaw(DeviceIntPtr dev, Bool frozen
 	dev->public.processInputProc = dev->public.realInputProc;
 }
 
+/**
+ * Unfreeze devices and replay all events to the respective clients.
+ *
+ * ComputeFreezes takes the first event in the device's frozen event queue. It
+ * runs up the sprite tree (spriteTrace) and searches for the window to replay
+ * the events from. If it is found, it checks for passive grabs one down from
+ * the window or delivers the events.
+ */
 void
 ComputeFreezes(void)
 {
@@ -1394,7 +1416,8 @@ CheckGrabForSyncs(DeviceIntPtr thisDev, 
  * on, but core events will be sent to other clients.
  * Can cause the cursor to change if a grab cursor is set.
  * 
- * Extension devices are set up for ActivateKeyboardGrab().
+ * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab
+ * is an implicit grab caused by a ButtonPress event.
  * 
  * @param mouse The device to grab.
  * @param grab The grab structure, needs to be setup.
@@ -1428,7 +1451,8 @@ ActivatePointerGrab(DeviceIntPtr mouse, 
 	grab->cursor->refcnt++;
     grabinfo->activeGrab = *grab;
     grabinfo->grab = &grabinfo->activeGrab;
-    grabinfo->fromPassiveGrab = autoGrab;
+    grabinfo->fromPassiveGrab = autoGrab & ~ImplicitGrabMask;
+    grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
     PostNewCursor(mouse);
     CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
 }
@@ -1987,7 +2011,8 @@ DeliverEventsToWindow(DeviceIntPtr pDev,
 
         tempGrab.genericMasks = NULL;
 	(*inputInfo.pointer->deviceGrab.ActivateGrab)(pDev, &tempGrab,
-					   currentTime, TRUE);
+					   currentTime, 
+                                           TRUE | ImplicitGrabMask);
     }
     else if ((type == MotionNotify) && deliveries)
 	pDev->valuator->motionHintWindow = pWin;
@@ -3243,13 +3268,19 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIn
             } else 
             {
                 Mask mask = grab->eventMask;
-                if (grabinfo->fromPassiveGrab && (xE->u.u.type &
-                            EXTENSION_EVENT_BASE))
+                if (grabinfo->fromPassiveGrab  &&
+                        grabinfo->implicitGrab && 
+                        (xE->u.u.type & EXTENSION_EVENT_BASE))
                     mask = grab->deviceMask;
 
                 FixUpEventFromWindow(thisDev, xE, grab->window, None, TRUE);
-                deliveries = TryClientEvents(rClient(grab), xE, count,
-                        mask, filters[xE->u.u.type], grab);
+
+                if (!(!(xE->u.u.type & EXTENSION_EVENT_BASE) &&
+                        IsInterferingGrab(rClient(grab), thisDev, xE)))
+                {
+                    deliveries = TryClientEvents(rClient(grab), xE, count,
+                            mask, filters[xE->u.u.type], grab);
+                }
             }
             if (deliveries && (xE->u.u.type == MotionNotify
 #ifdef XINPUT
@@ -4629,6 +4660,8 @@ ProcGrabPointer(ClientPtr client)
 	if (oldCursor)
 	    FreeCursor (oldCursor, (Cursor)0);
 	rep.status = GrabSuccess;
+
+        RemoveOtherCoreGrabs(client, device);
     }
     WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
     return Success;
@@ -4798,6 +4831,47 @@ GrabDevice(ClientPtr client, DeviceIntPt
 }
 
 /**
+ * Deactivate any core grabs on the given client except the given device.
+ *
+ * This fixes race conditions where clients deal with implicit passive grabs
+ * on one device, but then actively grab their client pointer, which is
+ * another device.
+ *
+ * Grabs are only removed if the other device matches the type of device. If
+ * dev is a pointer device, only other pointer grabs are removed. Likewise, if
+ * dev is a keyboard device, only keyboard grabs are removed.
+ * 
+ * If dev doesn't have a grab, do nothing and go for a beer.
+ *
+ * @param client The client that is to be limited.
+ * @param dev The only device allowed to have a grab on the client.
+ */
+
+_X_EXPORT void
+RemoveOtherCoreGrabs(ClientPtr client, DeviceIntPtr dev)
+{
+    if (!dev || !dev->deviceGrab.grab)
+        return;
+
+    DeviceIntPtr it = inputInfo.devices;
+    for (; it; it = it->next)
+    {
+        if (it == dev)
+            continue;
+        /* check for IsPointer Device */
+
+        if (it->deviceGrab.grab &&
+                it->deviceGrab.grab->coreGrab &&
+                SameClient(it->deviceGrab.grab, client))
+        {
+            if ((IsPointerDevice(dev) && IsPointerDevice(it)) ||
+                    (IsKeyboardDevice(dev) && IsKeyboardDevice(it)))
+                (*it->deviceGrab.DeactivateGrab)(it);
+        }
+    }
+}
+
+/**
  * Server-side protocol handling for GrabKeyboard request.
  *
  * Grabs the client's keyboard and returns success status to client.
@@ -4813,10 +4887,13 @@ ProcGrabKeyboard(ClientPtr client)
     REQUEST_SIZE_MATCH(xGrabKeyboardReq);
 
     if (XaceHook(XACE_DEVICE_ACCESS, client, keyboard, TRUE))
+    {
 	result = GrabDevice(client, keyboard, stuff->keyboardMode,
 			    stuff->pointerMode, stuff->grabWindow,
 			    stuff->ownerEvents, stuff->time,
 			    KeyPressMask | KeyReleaseMask, &rep.status, TRUE);
+        RemoveOtherCoreGrabs(client, keyboard);
+    }
     else {
 	result = Success;
 	rep.status = AlreadyGrabbed;
@@ -5857,3 +5934,4 @@ ExtUngrabDevice(ClientPtr client, Device
 }
 
 
+
diff --git a/include/dix.h b/include/dix.h
index f0e2f2a..be1cb95 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -494,6 +494,10 @@ extern int GrabDevice(
     CARD8 * /* status */,
     Bool /* coreGrab */);
 
+extern void RemoveOtherCoreGrabs(
+    ClientPtr /* client */,
+    DeviceIntPtr /* dev */);
+
 extern void InitEvents(void);
 extern void InitSprite(
         DeviceIntPtr /* pDev */, 
diff --git a/include/inputstr.h b/include/inputstr.h
index 986232c..d9128cc 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -333,9 +333,11 @@ typedef struct {
 #define FROZEN_NO_EVENT		5
 #define FROZEN_WITH_EVENT	6
 #define THAW_OTHERS		7
+
 typedef struct _GrabInfoRec {
-    TimeStamp	    grabTime;
-    Bool            fromPassiveGrab;
+    TimeStamp	    grabTime;           
+    Bool            fromPassiveGrab;    /* true if from passive grab */
+    Bool            implicitGrab;       /* implicit from ButtonPress */
     GrabRec         activeGrab;
     GrabPtr         grab;
     CARD8           activatingKey;


More information about the xorg-commit mailing list