[PATCH] dix: hack around enter/leave event issues for grabbed devices (#27804)

Peter Hutterer peter.hutterer at who-t.net
Thu Jul 15 17:08:59 PDT 2010


The current core enter/leave does not cater for device grabs during
enter/leave events. If a window W contains a pointer P1 and a client grabs a
pointer P2, this pointer will not generate enter/leave events inside this
window.

Hack around this by assuming that a grabbed device will always send
enter/leave events.

X.Org Bug 27804 <http://bugs.freedesktop.org/show_bug.cgi?id=27804>

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
This patch may have unintended side-effects so I don't think it's a good
idea for 1.9 at this stage. I've pushed this into Fedora for now to see if
there's feedback about things breaking but so far I haven't noticed any
adverse effects in single-pointer use.

The correct fix is somewhat more complicated.

 dix/enterleave.c |   27 ++++++++++++++++++---------
 1 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/dix/enterleave.c b/dix/enterleave.c
index eefa7ab..7a3ecf5 100644
--- a/dix/enterleave.c
+++ b/dix/enterleave.c
@@ -78,10 +78,19 @@ static WindowPtr FocusWindows[MAXDEVICES];
  * window.
  */
 static BOOL
-HasPointer(WindowPtr win)
+HasPointer(DeviceIntPtr dev, WindowPtr win)
 {
     int i;
 
+    /* FIXME: The enter/leave model does not cater for grabbed devices. For
+     * now, a quickfix: if the device about to send an enter/leave event to
+     * a window is grabbed, assume there is no pointer in that window.
+     * Fixes fdo 27804.
+     * There isn't enough beer in my fridge to fix this properly.
+     */
+    if (dev->deviceGrab.grab)
+        return FALSE;
+
     for (i = 0; i < MAXDEVICES; i++)
         if (PointerWindows[i] == win)
             return TRUE;
@@ -270,7 +279,7 @@ CoreEnterNotifies(DeviceIntPtr dev,
           may need to be changed from Virtual to NonlinearVirtual depending
           on the previous P(W). */
 
-    if (!HasPointer(parent) && !FirstPointerChild(parent))
+    if (!HasPointer(dev, parent) && !FirstPointerChild(parent))
             CoreEnterLeaveEvent(dev, EnterNotify, mode, detail, parent,
                                 child->drawable.id);
 }
@@ -309,7 +318,7 @@ CoreLeaveNotifies(DeviceIntPtr dev,
 
         /* If one window has a pointer or a child with a pointer, skip some
          * work and exit. */
-        if (HasPointer(win) || FirstPointerChild(win))
+        if (HasPointer(dev, win) || FirstPointerChild(win))
             return;
 
         CoreEnterLeaveEvent(dev, LeaveNotify, mode, detail, win, child->drawable.id);
@@ -373,7 +382,7 @@ CoreEnterLeaveNonLinear(DeviceIntPtr dev,
           vice versa depending on the the new P(W)
      */
 
-    if (!HasPointer(A))
+    if (!HasPointer(dev, A))
     {
         WindowPtr child = FirstPointerChild(A);
         if (child)
@@ -417,7 +426,7 @@ CoreEnterLeaveNonLinear(DeviceIntPtr dev,
           The detail may need to be changed from Ancestor to Nonlinear
           or vice-versa depending on the previous P(W). */
 
-     if (!HasPointer(B))
+     if (!HasPointer(dev, B))
      {
          WindowPtr child = FirstPointerChild(B);
          if (child)
@@ -455,7 +464,7 @@ CoreEnterLeaveToAncestor(DeviceIntPtr dev,
           The detail may need to be changed from Ancestor to Nonlinear or
           vice versa depending on the the new P(W)
      */
-    if (!HasPointer(A))
+    if (!HasPointer(dev, A))
     {
         WindowPtr child = FirstPointerChild(A);
         if (child)
@@ -479,7 +488,7 @@ CoreEnterLeaveToAncestor(DeviceIntPtr dev,
           P(W) changes from a descendant to W itself. The subwindow
           field should be set to the child containing the old P(W) <<< WRONG */
 
-    if (!HasPointer(B))
+    if (!HasPointer(dev, B))
         CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyInferior, B, None);
 
 }
@@ -507,7 +516,7 @@ CoreEnterLeaveToDescendant(DeviceIntPtr dev,
           P(W) changes from W to a descendant of W. The subwindow field
           is set to the child containing the new P(W) <<< THIS IS WRONG */
 
-    if (!HasPointer(A))
+    if (!HasPointer(dev, A))
         CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyInferior, A, None);
 
 
@@ -531,7 +540,7 @@ CoreEnterLeaveToDescendant(DeviceIntPtr dev,
           The detail may need to be changed from Ancestor to Nonlinear
           or vice-versa depending on the previous P(W). */
 
-     if (!HasPointer(B))
+     if (!HasPointer(dev, B))
      {
          WindowPtr child = FirstPointerChild(B);
          if (child)
-- 
1.7.1



More information about the xorg-devel mailing list