xserver: Branch 'mpx'

Peter Hutterer whot at kemper.freedesktop.org
Tue Apr 17 10:23:41 EEST 2007


 dix/events.c        |   92 ++++++++++++++++++++++++++++++++++++++++------------
 dix/window.c        |   15 ++++++--
 include/inputstr.h  |    1 
 include/windowstr.h |   10 +++++
 4 files changed, 92 insertions(+), 26 deletions(-)

New commits:
diff-tree b6aec7f6f906a18d13586d63afabf1ee4fbb11c3 (from 451d5464b4e8a2516b8a4598b3c4eb14656be90e)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 17 16:51:16 2007 +0930

    Change FocusIn/Out semantics to match Enter/Leave semantics.

diff --git a/dix/events.c b/dix/events.c
index def209e..1733e2d 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2272,7 +2272,7 @@ DefineInitialRootWindow(WindowPtr win)
         if (DevHasCursor(pDev))
         {
             InitializeSprite(pDev, win);
-            win->devPrivates[EnterLeavePrivatesIndex].val++;
+            win->devPrivates[FocusPrivatesIndex].val++;
         }
         pDev = pDev->next;
     }
@@ -3452,7 +3452,7 @@ EnterLeaveEvent(
     GrabPtr	        grab = mouse->coreGrab.grab;
     GrabPtr	        devgrab = mouse->deviceGrab.grab;
     Mask		mask;
-    long*               inWindow; /* no of sprites inside pWin */
+    int*                inWindow; /* no of sprites inside pWin */
     Bool                sendevent = FALSE;        
 
     deviceEnterNotify   *devEnterLeave;
@@ -3502,7 +3502,7 @@ EnterLeaveEvent(
              IsParent(focus, pWin)))
         event.u.enterLeave.flags |= ELFlagFocus;
 
-    inWindow = &pWin->devPrivates[EnterLeavePrivatesIndex].val;
+    inWindow = &((FocusSemaphoresPtr)pWin->devPrivates[FocusPrivatesIndex].ptr)->enterleave;
 
     /*
      * Sending multiple core enter/leave events to the same window confuse the
@@ -3665,28 +3665,80 @@ static void
 FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
 {
     xEvent event;
+    int* numFoci; /* no of foci the window has already */
+    Bool sendevent = FALSE;
+    FocusSemaphoresPtr focus;
 
     if (dev != inputInfo.keyboard)
 	DeviceFocusEvent(dev, type, mode, detail, pWin);
-    event.u.focus.mode = mode;
-    event.u.u.type = type;
-    event.u.u.detail = detail;
-    event.u.focus.window = pWin->drawable.id;
-    (void)DeliverEventsToWindow(dev, pWin, &event, 1, filters[type], NullGrab,
-                                0);
-    if ((type == FocusIn) &&
-	((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
+
+    /*
+     * Same procedure as for Enter/Leave events.
+     *
+     * Sending multiple core FocusIn/Out events to the same window may confuse
+     * the client.  
+     * We can send multiple events that have detail NotifyVirtual,
+     * NotifyNonlinearVirtual, NotifyPointerRoot, NotifyDetailNone or
+     * NotifyPointer however.
+     *
+     * For standard events (NotifyAncestor, NotifyInferior, NotifyNonlinear)
+     * we only send an FocusIn event for the first kbd to set the focus. A
+     * FocusOut event is sent for the last kbd to set the focus away from the
+     * window.. 
+     *
+     * For events with Virtual detail, we send them only to a window that does
+     * not have a focus from another keyboard.
+     *
+     * For a window tree in the form of 
+     *
+     * A -> Bf -> C -> D 
+     *  \               (where B and E have focus)
+     *    -> Ef         
+     *    
+     * If the focus changes from E into D, a FocusOut is sent to E, a
+     * FocusIn is sent to D, a FocusIn with detail
+     * NotifyNonlinearVirtual to C and nothing to B.
+     */
+
+    numFoci =
+        &((FocusSemaphoresPtr)pWin->devPrivates[FocusPrivatesIndex].ptr)->focusinout;
+    if (detail != NotifyVirtual && 
+            detail != NotifyNonlinearVirtual && 
+            detail != NotifyPointer &&
+            detail != NotifyPointerRoot &&
+            detail != NotifyDetailNone)
     {
-	xKeymapEvent ke;
-	ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)];
-	if (XaceHook(XACE_DEVICE_ACCESS, client, dev, FALSE))
-	    memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
-	else
-	    bzero((char *)&ke.map[0], 31);
+        (type == FocusIn) ? (*numFoci)++ : (*numFoci)--;
+        if (((*numFoci) == (FocusOut - type)))
+            sendevent = TRUE;
+    } else
+    {
+        if (!(*numFoci))
+            sendevent = TRUE;
+    }
 
-	ke.type = KeymapNotify;
-	(void)DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1,
-				    KeymapStateMask, NullGrab, 0);
+    if (sendevent)
+    {
+        event.u.focus.mode = mode;
+        event.u.u.type = type;
+        event.u.u.detail = detail;
+        event.u.focus.window = pWin->drawable.id;
+        (void)DeliverEventsToWindow(dev, pWin, &event, 1, filters[type], NullGrab,
+                                    0);
+        if ((type == FocusIn) &&
+                ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
+        {
+            xKeymapEvent ke;
+            ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)];
+            if (XaceHook(XACE_DEVICE_ACCESS, client, dev, FALSE))
+                memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
+            else
+                bzero((char *)&ke.map[0], 31);
+
+            ke.type = KeymapNotify;
+            (void)DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1,
+                                        KeymapStateMask, NullGrab, 0);
+        }
     }
 }
 
diff --git a/dix/window.c b/dix/window.c
index 5a03642..4846939 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -155,7 +155,7 @@ _X_EXPORT int screenIsSaved = SCREEN_SAV
 
 _X_EXPORT ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
 
-_X_EXPORT int EnterLeavePrivatesIndex = -1;
+_X_EXPORT int FocusPrivatesIndex = -1;
 
 #if 0
 extern void DeleteWindowFromAnyEvents();
@@ -312,6 +312,12 @@ SetWindowToDefaults(WindowPtr pWin)
 #ifdef COMPOSITE
     pWin->redirectDraw = 0;
 #endif
+
+    ((FocusSemaphoresPtr)
+     pWin->devPrivates[FocusPrivatesIndex].ptr)->enterleave = 0;
+    ((FocusSemaphoresPtr)
+     pWin->devPrivates[FocusPrivatesIndex].ptr)->focusinout = 0;
+
 }
 
 static void
@@ -3981,10 +3987,11 @@ WindowParentHasDeviceCursor(WindowPtr pW
 _X_EXPORT Bool
 InitWindowPrivates(ScreenPtr screen)
 {
-    if (EnterLeavePrivatesIndex == -1)
-        EnterLeavePrivatesIndex = AllocateWindowPrivateIndex();
+    if (FocusPrivatesIndex == -1)
+        FocusPrivatesIndex = AllocateWindowPrivateIndex();
 
-    return AllocateWindowPrivate(screen, EnterLeavePrivatesIndex, 0);
+    return AllocateWindowPrivate(screen, FocusPrivatesIndex, 
+            sizeof(FocusSemaphoresRec));
 }
 
 #ifndef NOLOGOHACK
diff --git a/include/inputstr.h b/include/inputstr.h
index d8d12d7..bdb7518 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -391,5 +391,4 @@ typedef struct _QdEvent {
     int			evcount;
 } QdEventRec;    
 
-#define MPXDBG(...) ErrorF("MPX: " __VA_ARGS__ )
 #endif /* INPUTSTRUCT_H */
diff --git a/include/windowstr.h b/include/windowstr.h
index 4683abe..87158b2 100644
--- a/include/windowstr.h
+++ b/include/windowstr.h
@@ -216,7 +216,15 @@ typedef struct _ScreenSaverStuff {
 
 extern int screenIsSaved;
 extern ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
-extern int EnterLeavePrivatesIndex;
+extern int FocusPrivatesIndex;
+
+/* Used to maintain semantics of core protocol for Enter/LeaveNotifies and
+ * FocusIn/Out events for multiple pointers/keyboards. 
+ */ 
+typedef struct _FocusSemaphores {
+    int                 enterleave;
+    int                 focusinout;
+} FocusSemaphoresRec, *FocusSemaphoresPtr;
 
 /*
  * this is the configuration parameter "NO_BACK_SAVE"



More information about the xorg-commit mailing list