[PATCH 3/7] dix: split enter/leave event handling into core and device handling.

peter.hutterer at who-t.net peter.hutterer at who-t.net
Fri Nov 14 02:51:12 PST 2008


From: Peter Hutterer <peter.hutterer at redhat.com>

Device events always need to be delivered, core events only in some cases.
Let's keep them completely separate so we can adjust core event delivery.

Signed-off-by: Peter Hutterer <peter.hutterer at redhat.com>
---
 dix/enterleave.c |   76 +++++++++++---------------
 dix/enterleave.h |   13 +++++
 dix/events.c     |  159 +++++++++++++++++++++++++++---------------------------
 3 files changed, 125 insertions(+), 123 deletions(-)

diff --git a/dix/enterleave.c b/dix/enterleave.c
index 941aa52..11929c6 100644
--- a/dix/enterleave.c
+++ b/dix/enterleave.c
@@ -30,6 +30,7 @@
 
 #include <X11/X.h>
 #include "windowstr.h"
+#include "exglobals.h"
 #include "enterleave.h"
 
 /**
@@ -47,46 +48,57 @@ CommonAncestor(
 
 
 /**
- * Send enter notifies to all parent windows up to ancestor.
- * This function recurses.
+ * Send enter notifies to all windows between @ancestor and @child (excluding
+ * both). Events are sent running up the window hierarchy. This function
+ * recurses.
+ * If @core is TRUE, core events are sent, otherwise XI events will be sent.
  */
 static void
-EnterNotifies(DeviceIntPtr pDev,
+EnterNotifies(DeviceIntPtr dev,
               WindowPtr ancestor,
               WindowPtr child,
               int mode,
-              int detail)
+              int detail,
+              BOOL core)
 {
     WindowPtr	parent = child->parent;
 
     if (ancestor == parent)
 	return;
-    EnterNotifies(pDev, ancestor, parent, mode, detail);
-    EnterLeaveEvent(pDev, EnterNotify, mode, detail, parent,
-                    child->drawable.id);
+    EnterNotifies(dev, ancestor, parent, mode, detail, core);
+    if (core)
+        CoreEnterLeaveEvent(dev, EnterNotify, mode, detail, parent,
+                            child->drawable.id);
+    else
+        DeviceEnterLeaveEvent(dev, DeviceEnterNotify, mode, detail, parent,
+                              child->drawable.id);
 }
 
-
 /**
- * Send leave notifies to all parent windows up to ancestor.
- * This function recurses.
+ * Send leave notifies to all windows between @child and @ancestor.
+ * Events are sent running up the hierarchy.
  */
 static void
-LeaveNotifies(DeviceIntPtr pDev,
+LeaveNotifies(DeviceIntPtr dev,
               WindowPtr child,
               WindowPtr ancestor,
               int mode,
-              int detail)
+              int detail,
+              BOOL core)
 {
-    WindowPtr  pWin;
+    WindowPtr  win;
 
     if (ancestor == child)
 	return;
-    for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent)
+    for (win = child->parent; win != ancestor; win = win->parent)
     {
-        EnterLeaveEvent(pDev, LeaveNotify, mode, detail, pWin,
-                        child->drawable.id);
-        child = pWin;
+        if (core)
+            CoreEnterLeaveEvent(dev, LeaveNotify, mode, detail, win,
+                            child->drawable.id);
+        else
+            DeviceEnterLeaveEvent(dev, DeviceLeaveNotify, mode, detail, win,
+                                  child->drawable.id);
+        child = win;
     }
 }
 
@@ -108,31 +120,7 @@ DoEnterLeaveEvents(DeviceIntPtr pDev,
 
     if (fromWin == toWin)
 	return;
-    if (IsParent(fromWin, toWin))
-    {
-        EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyInferior, fromWin,
-                        None);
-        EnterNotifies(pDev, fromWin, toWin, mode,
-                      NotifyVirtual);
-        EnterLeaveEvent(pDev, EnterNotify, mode, NotifyAncestor, toWin, None);
-    }
-    else if (IsParent(toWin, fromWin))
-    {
-	EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyAncestor, fromWin,
-                        None);
-	LeaveNotifies(pDev, fromWin, toWin, mode, NotifyVirtual);
-	EnterLeaveEvent(pDev, EnterNotify, mode, NotifyInferior, toWin, None);
-    }
-    else
-    { /* neither fromWin nor toWin is descendent of the other */
-	WindowPtr common = CommonAncestor(toWin, fromWin);
-	/* common == NullWindow ==> different screens */
-        EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyNonlinear, fromWin,
-                        None);
-        LeaveNotifies(pDev, fromWin, common, mode, NotifyNonlinearVirtual);
-	EnterNotifies(pDev, common, toWin, mode, NotifyNonlinearVirtual);
-        EnterLeaveEvent(pDev, EnterNotify, mode, NotifyNonlinear, toWin,
-                        None);
-    }
-}
 
+    CoreEnterLeaveEvents(pDev, fromWin, toWin, mode);
+    DeviceEnterLeaveEvents(pDev, fromWin, toWin, mode);
+}
diff --git a/dix/enterleave.h b/dix/enterleave.h
index c1bfc3a..6e06226 100644
--- a/dix/enterleave.h
+++ b/dix/enterleave.h
@@ -50,4 +50,17 @@ extern WindowPtr CommonAncestor(
     WindowPtr a,
     WindowPtr b);
 
+extern void CoreEnterLeaveEvent(DeviceIntPtr mouse,
+                                int type,
+                                int mode,
+                                int detail,
+                                WindowPtr pWin,
+                                Window child);
+extern void DeviceEnterLeaveEvent(DeviceIntPtr mouse,
+                                  int type,
+                                  int mode,
+                                  int detail,
+                                  WindowPtr pWin,
+                                  Window child);
+
 #endif /* _ENTERLEAVE_H_ */
diff --git a/dix/events.c b/dix/events.c
index eff7eeb..047ec60 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4184,7 +4184,7 @@ EventSuppressForWindow(WindowPtr pWin, ClientPtr client,
  * Uses the paired keyboard to get some additional information.
  */
 void
-EnterLeaveEvent(
+CoreEnterLeaveEvent(
     DeviceIntPtr mouse,
     int type,
     int mode,
@@ -4197,12 +4197,6 @@ EnterLeaveEvent(
     DeviceIntPtr        keybd;
     GrabPtr	        grab = mouse->deviceGrab.grab;
     Mask		mask;
-    int                 inWindow; /* zero if no sprites are in window */
-    Bool                sendevent = FALSE;
-
-    deviceEnterNotify   *devEnterLeave;
-    int                 mskidx;
-    OtherInputMasks     *inputMasks;
 
     keybd = GetPairedDevice(mouse);
 
@@ -4250,44 +4244,7 @@ EnterLeaveEvent(
              IsParent(focus, pWin)))
         event.u.enterLeave.flags |= ELFlagFocus;
 
-
-    /*
-     * Sending multiple core enter/leave events to the same window confuse the
-     * client.
-     * We can send multiple events that have detail NotifyVirtual or
-     * NotifyNonlinearVirtual however. For most clients anyway.
-     *
-     * For standard events (NotifyAncestor, NotifyInferior, NotifyNonlinear)
-     * we only send an enter event for the first pointer to enter. A leave
-     * event is sent for the last pointer to leave.
-     *
-     * For events with Virtual detail, we send them only to a window that does
-     * not have a pointer inside.
-     *
-     * For a window tree in the form of
-     *
-     * A -> Bp -> C -> D
-     *  \               (where B and E have pointers)
-     *    -> Ep
-     *
-     * If the pointer moves from E into D, a LeaveNotify is sent to E, an
-     * EnterNotify is sent to D, an EnterNotify with detail
-     * NotifyNonlinearVirtual to C and nothing to B.
-     */
-
-    /* Clear bit for device, but don't worry about SDs. */
-    if (mouse->isMaster && type == LeaveNotify &&
-            (detail != NotifyVirtual && detail != NotifyNonlinearVirtual))
-        if (mode != NotifyUngrab)
-            ENTER_LEAVE_SEMAPHORE_UNSET(pWin, mouse);
-
-    inWindow = EnterLeaveSemaphoresIsset(pWin);
-
-    if(!inWindow || mode == NotifyGrab || mode == NotifyUngrab)
-        sendevent = TRUE;
-
-
-    if ((mask & filters[mouse->id][type]) && sendevent)
+    if ((mask & filters[mouse->id][type]))
     {
         if (grab)
             TryClientEvents(rClient(grab), mouse, &event, 1, mask,
@@ -4297,18 +4254,81 @@ EnterLeaveEvent(
                                   filters[mouse->id][type], NullGrab, 0);
     }
 
-    if (mouse->isMaster && type == EnterNotify &&
-            (detail != NotifyVirtual && detail != NotifyNonlinearVirtual))
-        if (mode != NotifyGrab)
-            ENTER_LEAVE_SEMAPHORE_SET(pWin, mouse);
+    if ((type == EnterNotify) && (mask & KeymapStateMask))
+    {
+        xKeymapEvent ke;
+        ClientPtr client = grab ? rClient(grab)
+            : clients[CLIENT_ID(pWin->drawable.id)];
+        if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess))
+            bzero((char *)&ke.map[0], 31);
+        else
+            memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31);
+
+        ke.type = KeymapNotify;
+        if (grab)
+            TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1,
+                            mask, KeymapStateMask, grab);
+        else
+            DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1,
+                                  KeymapStateMask, NullGrab, 0);
+    }
+}
+
+void
+DeviceEnterLeaveEvent(
+    DeviceIntPtr mouse,
+    int type,
+    int mode,
+    int detail,
+    WindowPtr pWin,
+    Window child)
+{
+    xEvent              event;
+    GrabPtr             grab = mouse->deviceGrab.grab;
+    deviceEnterNotify   *devEnterLeave;
+    int                 mskidx;
+    OtherInputMasks     *inputMasks;
+    Mask                mask;
+    DeviceIntPtr        keybd = GetPairedDevice(mouse);
+    BOOL                sameScreen;
+
+    if (grab) {
+        mask = (pWin == grab->window) ? grab->eventMask : 0;
+        if (grab->ownerEvents)
+            mask |= EventMaskForClient(pWin, rClient(grab));
+    } else {
+        mask = pWin->eventMask | wOtherEventMasks(pWin);
+    }
 
     /* we don't have enough bytes, so we squash flags and mode into
        one byte, and use the last byte for the deviceid. */
-    devEnterLeave = (deviceEnterNotify*)&event;
-    devEnterLeave->type = (type == EnterNotify) ? DeviceEnterNotify :
-        DeviceLeaveNotify;
-    devEnterLeave->mode |= (event.u.enterLeave.flags << 4);
+    devEnterLeave           = (deviceEnterNotify*)&event;
+    devEnterLeave->detail   = detail;
+    devEnterLeave->time     = currentTime.milliseconds;
+    devEnterLeave->rootX    = mouse->spriteInfo->sprite->hot.x;
+    devEnterLeave->rootY    = mouse->spriteInfo->sprite->hot.y;
+    FixUpEventFromWindow(mouse, &event, pWin, None, FALSE);
+    sameScreen = event.u.keyButtonPointer.sameScreen;
+
+    devEnterLeave->child    = child;
+    devEnterLeave->type     = type;
     devEnterLeave->deviceid = mouse->id;
+    devEnterLeave->mode     = mode;
+    devEnterLeave->mode    |= (sameScreen ?  (ELFlagSameScreen << 4) : 0);
+
+#ifdef XKB
+    if (!noXkbExtension) {
+        devEnterLeave->state = mouse->button->state & 0x1f00;
+        if (keybd)
+            devEnterLeave->state |=
+                XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
+    } else
+#endif
+    {
+        devEnterLeave->state = (keybd) ? keybd->key->state : 0;
+        devEnterLeave->state |= mouse->button->state;
+    }
+
     mskidx = mouse->id;
     inputMasks = wOtherInputMasks(pWin);
     if (inputMasks &&
@@ -4316,34 +4336,15 @@ EnterLeaveEvent(
             inputMasks->deliverableEvents[mskidx]))
     {
         if (grab)
-            (void)TryClientEvents(rClient(grab), mouse,
-                                (xEvent*)devEnterLeave, 1,
-                                mask, filters[mouse->id][devEnterLeave->type],
-                                grab);
-	else
-	    (void)DeliverEventsToWindow(mouse, pWin, (xEvent*)devEnterLeave,
-                                   1, filters[mouse->id][devEnterLeave->type],
-                                   NullGrab, mouse->id);
+            TryClientEvents(rClient(grab), mouse,
+                            (xEvent*)devEnterLeave, 1, mask,
+                            filters[mouse->id][devEnterLeave->type], grab);
+        else
+            DeliverEventsToWindow(mouse, pWin, (xEvent*)devEnterLeave, 1,
+                                  filters[mouse->id][devEnterLeave->type],
+                                  NullGrab, mouse->id);
     }
 
-    if ((type == EnterNotify) && (mask & KeymapStateMask))
-    {
-	xKeymapEvent ke;
-	ClientPtr client = grab ? rClient(grab)
-				: clients[CLIENT_ID(pWin->drawable.id)];
-	if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess))
-	    bzero((char *)&ke.map[0], 31);
-	else
-	    memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31);
-
-	ke.type = KeymapNotify;
-	if (grab)
-	    (void)TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1,
-                                  mask, KeymapStateMask, grab);
-	else
-	    (void)DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1,
-					KeymapStateMask, NullGrab, 0);
-    }
 }
 
 static void
-- 
1.6.0.3




More information about the xorg mailing list