[PATCH] dix: re-implement enter/leave model.
Peter Hutterer
peter.hutterer at who-t.net
Thu Dec 18 19:57:14 PST 2008
The old model was implemented based on a misunderstanding of NotifyVirtual and
NotifyNonlinearVirtual events. It became complicated and was broken in some
places [1]. This patch wipes this model completely.
A much simplified implementation is provided instead. Rather than a top-down
approach ("we have a tree of windows, which ones need to get which event")
this one uses a step-by-step approach. For each window W between A and B
determine the pointer window P as perceived by this window and determine the
event type based on this information. This is in-line with the model described
by Owen Taylor [2].
[1] http://lists.freedesktop.org/archives/xorg/2008-December/041559.html
[2] http://lists.freedesktop.org/archives/xorg/2008-August/037606.html
---
Since this patch is rather hard to review, the new enterleave.c file is
available on http://people.freedesktop.org/~whot/patches/enterleave.c
It's probably easier to just look at this file. I've tested it with one and
two mice and have yet to trip it up. There's cleanup patches following this
one but one of these is pending the implementation of the focus in/out model.
And NotifyPointer is giving me the creeps.
dix/enterleave.c | 593 +++++++++++++++++++++++++++++-------------------------
1 files changed, 315 insertions(+), 278 deletions(-)
diff --git a/dix/enterleave.c b/dix/enterleave.c
index 8176f96..2a674ca 100644
--- a/dix/enterleave.c
+++ b/dix/enterleave.c
@@ -42,71 +42,17 @@
* For a full description of the model from a window's perspective, see
* http://lists.freedesktop.org/archives/xorg/2008-August/037606.html
*
+ * Additional notes:
+ * The core protocol spec says that "In a LeaveNotify event, if a child of the
+ * event window contains the initial position of the pointer, then the child
+ * component is set to that child. Otherwise, it is None. For an EnterNotify
+ * event, if a child of the event window contains the final pointer position,
+ * then the child component is set to that child. Otherwise, it is None."
*
- * EnterNotify(Virtual, B) means EnterNotify Event, detail Virtual, child = B.
- *
- * Pointer moves from A to B, nonlinear (CoreEnterLeaveNonLinear):
- * 1. a. if A has another pointer, goto 2.
- * b. otherwise, if A has a child with a pointer in it,
- * LeaveNotify(Inferior) to A
- * LeaveNotify(Virtual) between A and child(A)
- *
- * 2. Find common ancestor X between A and B.
- * 3. Find closest pointer window P between A and X.
- * a. if P exists
- * LeaveNotify(Ancestor) to A
- * LeaveNotify(Virtual) between A and P
- * b. otherwise, if P does not exist,
- * LeaveNotify(NonLinear) to A
- * LeaveNotify(NonLinearVirtual) between A and X.
- *
- * 4. If X does not have a pointer, EnterNotify(NonLinearVirtual, B) to X.
- * 5. Find closest pointer window P between X and B.
- * a. if P exists, EnterNotify(NonLinearVirtual) between X and P
- * b. otherwise, EnterNotify(NonLinearVirtual) between X and B
- *
- * 5. a. if B has another pointer in it, finish.
- * b. otherwise, if B has a child with a pointer in it
- * LeaveNotify(Virtual) between child(B) and B.
- * EnterNotify(Inferior) to B.
- * c. otherwise, EnterNotify(NonLinear) to B.
- *
- * --------------------------------------------------------------------------
- *
- * Pointer moves from A to B, A is a parent of B (CoreEnterLeaveToDescendant):
- * 1. a. If A has another pointer, goto 2.
- * b. Otherwise, LeaveNotify(Inferior) to A.
- *
- * 2. Find highest window X that has a pointer child that is not a child of B.
- * a. if X exists, EnterNotify(Virtual, B) between A and X,
- * EnterNotify(Virtual, B) to X (if X has no pointer).
- * b. otherwise, EnterNotify(Virtual, B) between A and B.
- *
- * 3. a. if B has another pointer, finish
- * b. otherwise, if B has a child with a pointer in it,
- * LeaveNotify(Virtual, child(B)) between child(B) and B.
- * EnterNotify(Inferior, child(B)) to B.
- * c. otherwise, EnterNotify(Ancestor) to B.
- *
- * --------------------------------------------------------------------------
- *
- * Pointer moves from A to B, A is a child of B (CoreEnterLeaveToAncestor):
- * 1. a. If A has another pointer, goto 2.
- * b. Otherwise, if A has a child with a pointer in it.
- * LeaveNotify(Inferior, child(A)) to A.
- * EnterNotify(Virtual, child(A)) between A and child(A).
- * Skip to 3.
- *
- * 2. Find closest pointer window P between A and B.
- * If P does not exist, P is B.
- * LeaveNotify(Ancestor) to A.
- * LeaveNotify(Virtual, A) between A and P.
- * 3. a. If B has another pointer, finish.
- * b. otherwise, EnterNotify(Inferior) to B.
+ * By inference, this means that only NotifyVirtual or NotifyNonlinearVirtual
+ * events may have a subwindow set to other than None.
*/
-#define WID(w) ((w) ? ((w)->drawable.id) : 0)
-
/**
* Return TRUE if @win has a pointer within its boundaries, excluding child
* window.
@@ -123,109 +69,6 @@ HasPointer(WindowPtr win)
return FALSE;
}
-static BOOL
-HasOtherPointer(WindowPtr win, DeviceIntPtr dev)
-{
- int i;
-
- for (i = 0; i < sizeof(win->enterleave); i++)
- if (win->enterleave[i] &&
- !(i == dev->id/8 && win->enterleave[i] == (1 << (dev->id % 8))))
- {
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- * Set the presence flag for @dev to mark that it is now in @win.
- */
-void
-EnterWindow(DeviceIntPtr dev, WindowPtr win, int mode)
-{
- win->enterleave[dev->id/8] |= (1 << (dev->id % 8));
-}
-
-/**
- * Unset the presence flag for @dev to mark that it is not in @win anymore.
- */
-static void
-LeaveWindow(DeviceIntPtr dev, WindowPtr win, int mode)
-{
- win->enterleave[dev->id/8] &= ~(1 << (dev->id % 8));
-}
-
-
-/**
- * @return The window that is the first ancestor of both a and b.
- */
-WindowPtr
-CommonAncestor(
- WindowPtr a,
- WindowPtr b)
-{
- for (b = b->parent; b; b = b->parent)
- if (IsParent(b, a)) return b;
- return NullWindow;
-}
-
-
-/**
- * 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 dev,
- WindowPtr ancestor,
- WindowPtr child,
- int mode,
- int detail,
- BOOL core)
-{
- WindowPtr parent = child->parent;
-
- if (ancestor == parent)
- return;
- 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 windows between @child and @ancestor.
- * Events are sent running up the hierarchy.
- */
-static void
-LeaveNotifies(DeviceIntPtr dev,
- WindowPtr child,
- WindowPtr ancestor,
- int mode,
- int detail,
- BOOL core)
-{
- WindowPtr win;
-
- if (ancestor == child)
- return;
- for (win = child->parent; win != ancestor; win = win->parent)
- {
- if (core)
- CoreEnterLeaveEvent(dev, LeaveNotify, mode, detail, win,
- child->drawable.id);
- else
- DeviceEnterLeaveEvent(dev, DeviceLeaveNotify, mode, detail, win,
- child->drawable.id);
- child = win;
- }
-}
-
/**
* Search for the first window below @win that has a pointer directly within
* it's boundaries (excluding boundaries of its own descendants).
@@ -299,31 +142,168 @@ FirstPointerChild(WindowPtr win, WindowPtr exclude)
return NULL;
}
+
/**
- * Find the first parent of @win that has a pointer or has a child window with
- * a pointer. Traverses up to (and including) the root window if @stopBefore
- * is NULL, otherwise it stops at @stopBefore.
- * Neither @win nor @win's descendants nor @stopBefore are tested for having a
- * pointer.
- *
- * @return the window or NULL if @stopBefore was reached.
+ * Set the presence flag for @dev to mark that it is now in @win.
*/
-static WindowPtr
-FirstPointerAncestor(WindowPtr win, WindowPtr stopBefore)
+void
+EnterWindow(DeviceIntPtr dev, WindowPtr win, int mode)
{
- WindowPtr parent;
+ win->enterleave[dev->id/8] |= (1 << (dev->id % 8));
+}
- parent = win->parent;
+/**
+ * Unset the presence flag for @dev to mark that it is not in @win anymore.
+ */
+static void
+LeaveWindow(DeviceIntPtr dev, WindowPtr win, int mode)
+{
+ win->enterleave[dev->id/8] &= ~(1 << (dev->id % 8));
+}
+
+
+/**
+ * @return The window that is the first ancestor of both a and b.
+ */
+WindowPtr
+CommonAncestor(
+ WindowPtr a,
+ WindowPtr b)
+{
+ for (b = b->parent; b; b = b->parent)
+ if (IsParent(b, a)) return b;
+ return NullWindow;
+}
+
+
+/**
+ * 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
+DeviceEnterNotifies(DeviceIntPtr dev,
+ WindowPtr ancestor,
+ WindowPtr child,
+ int mode,
+ int detail)
+{
+ WindowPtr parent = child->parent;
+
+ if (ancestor == parent)
+ return;
+ DeviceEnterNotifies(dev, ancestor, parent, mode, detail);
+ DeviceEnterLeaveEvent(dev, DeviceEnterNotify, mode, detail, parent,
+ child->drawable.id);
+}
- while(parent && parent != stopBefore)
+/**
+ * Send enter notifies to all windows between @ancestor and @child (excluding
+ * both). Events are sent running down the window hierarchy. This function
+ * recurses.
+ */
+static void
+CoreEnterNotifies(DeviceIntPtr dev,
+ WindowPtr ancestor,
+ WindowPtr child,
+ int mode,
+ int detail)
+{
+ WindowPtr parent = child->parent;
+ if (ancestor == parent)
+ return;
+ CoreEnterNotifies(dev, ancestor, parent, mode, detail);
+
+
+ /* Case 3:
+ A is above W, B is a descendant
+
+ Classically: The move generates an EnterNotify on W with a detail of
+ Virtual or NonlinearVirtual
+
+ MPX:
+ Case 3A: There is at least one other pointer on W itself
+ P(W) doesn't change, so the event should be suppressed
+ Case 3B: Otherwise, if there is at least one other pointer in a
+ descendant
+ P(W) stays on the same descendant, or changes to a different
+ descendant. The event should be suppressed.
+ Case 3C: Otherwise:
+ P(W) moves from a window above W to a descendant. The subwindow
+ field is set to the child containing the descendant. The detail
+ may need to be changed from Virtual to NonlinearVirtual depending
+ on the previous P(W). */
+
+ if (!HasPointer(parent) && !FirstPointerChild(parent, None))
+ CoreEnterLeaveEvent(dev, EnterNotify, mode, detail, parent,
+ child->drawable.id);
+}
+
+static void
+CoreLeaveNotifies(DeviceIntPtr dev,
+ WindowPtr child,
+ WindowPtr ancestor,
+ int mode,
+ int detail)
+{
+ WindowPtr win;
+
+ if (ancestor == child)
+ return;
+
+ for (win = child->parent; win != ancestor; win = win->parent)
{
- if (HasPointer(parent) || FirstPointerChild(parent, win))
- return parent;
+ /*Case 7:
+ A is a descendant of W, B is above W
+
+ Classically: A LeaveNotify is generated on W with a detail of Virtual
+ or NonlinearVirtual.
+
+ MPX:
+ Case 3A: There is at least one other pointer on W itself
+ P(W) doesn't change, the event should be suppressed.
+ Case 3B: Otherwise, if there is at least one other pointer in a
+ descendant
+ P(W) stays on the same descendant, or changes to a different
+ descendant. The event should be suppressed.
+ Case 3C: Otherwise:
+ P(W) changes from the descendant of W to a window above W.
+ The detail may need to be changed from Virtual to NonlinearVirtual
+ or vice-versa depending on the new P(W).*/
+
+ /* If one window has a pointer or a child with a pointer, skip some
+ * work and exit. */
+ if (HasPointer(win) || FirstPointerChild(win, None))
+ return;
+
+ CoreEnterLeaveEvent(dev, LeaveNotify, mode, detail, win, child->drawable.id);
- parent = parent->parent;
+ child = win;
}
+}
- return NULL;
+/**
+ * Send leave notifies to all windows between @child and @ancestor.
+ * Events are sent running up the hierarchy.
+ */
+static void
+DeviceLeaveNotifies(DeviceIntPtr dev,
+ WindowPtr child,
+ WindowPtr ancestor,
+ int mode,
+ int detail)
+{
+ WindowPtr win;
+
+ if (ancestor == child)
+ return;
+ for (win = child->parent; win != ancestor; win = win->parent)
+ {
+ DeviceEnterLeaveEvent(dev, DeviceLeaveNotify, mode, detail, win,
+ child->drawable.id);
+ child = win;
+ }
}
/**
@@ -336,57 +316,79 @@ CoreEnterLeaveNonLinear(DeviceIntPtr dev,
WindowPtr B,
int mode)
{
- WindowPtr childA, childB, X, P;
- BOOL hasPointerA = HasPointer(A);
+ WindowPtr X = CommonAncestor(A, B);
+ /* Case 4:
+ A is W, B is above W
+
+ Classically: The move generates a LeaveNotify on W with a detail of
+ Ancestor or Nonlinear
+
+ MPX:
+ Case 3A: There is at least one other pointer on W itself
+ P(W) doesn't change, the event should be suppressed
+ Case 3B: Otherwise, if there is at least one other pointer in a
+ descendant of W
+ P(W) changes from W to a descendant of W. The subwindow field
+ is set to the child containing the new P(W), the detail field
+ is set to Inferior
+ Case 3C: Otherwise:
+ The pointer window moves from W to a window above W.
+ The detail may need to be changed from Ancestor to Nonlinear or
+ vice versa depending on the the new P(W)
+ */
- /* 2 */
- X = CommonAncestor(A, B);
-
- /* 1.a */ /* 1.b */
- if (!hasPointerA && (childA = FirstPointerChild(A, None)))
+ if (!HasPointer(A))
{
- CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyInferior, A, WID(childA));
- EnterNotifies(dev, A, childA, mode, NotifyVirtual, TRUE);
- } else {
- /* 3 */
- P = FirstPointerAncestor(A, X);
-
- if (P)
- {
- if (!hasPointerA)
- CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyAncestor, A, None);
- LeaveNotifies(dev, A, P, mode, NotifyVirtual, TRUE);
- /* 3.b */
- } else
- {
- if (!hasPointerA)
- CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyNonlinear, A, None);
- LeaveNotifies(dev, A, X, mode, NotifyNonlinearVirtual, TRUE);
- }
+ WindowPtr child = FirstPointerChild(A, None);
+ if (child)
+ CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyInferior, A, None);
+ else
+ CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyNonlinear, A, None);
}
- /* 4. */
- if (!HasPointer(X))
- CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyNonlinearVirtual, X, WID(B));
- /* 5. */
- P = FirstPointerChild(X, B);
- if (!P)
- P = B; /* 4.b */
- EnterNotifies(dev, X, P, mode, NotifyNonlinearVirtual, TRUE);
+ CoreLeaveNotifies(dev, A, X, mode, NotifyNonlinearVirtual);
- /* 5.a */
- if (!HasOtherPointer(B, dev))
- {
- /* 5.b */
- if ((childB = FirstPointerChild(B, None)))
- {
- LeaveNotifies(dev, childB, B, mode, NotifyVirtual, TRUE);
- CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyInferior, B, WID(childB));
- } else
- /* 5.c */
- CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyNonlinear, B, None);
- }
+ /*
+ Case 9:
+ A is a descendant of W, B is a descendant of W
+
+ Classically: No events are generated on W
+ MPX: The pointer window stays the same or moves to a different
+ descendant of W. No events should be generated on W.
+
+
+ Therefore, no event to X.
+ */
+
+ CoreEnterNotifies(dev, X, B, mode, NotifyNonlinearVirtual);
+
+ /* Case 2:
+ A is above W, B=W
+
+ Classically: The move generates an EnterNotify on W with a detail of
+ Ancestor or Nonlinear
+
+ MPX:
+ Case 2A: There is at least one other pointer on W itself
+ P(W) doesn't change, so the event should be suppressed
+ Case 2B: Otherwise, if there is at least one other pointer in a
+ descendant
+ P(W) moves from a descendant to W. detail is changed to Inferior,
+ subwindow is set to the child containing the previous P(W)
+ Case 2C: Otherwise:
+ P(W) changes from a window above W to W itself.
+ The detail may need to be changed from Ancestor to Nonlinear
+ or vice-versa depending on the previous P(W). */
+
+ if (!HasPointer(B))
+ {
+ WindowPtr child = FirstPointerChild(B, None);
+ if (child)
+ CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyInferior, B, None);
+ else
+ CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyNonlinear, B, None);
+ }
}
/**
@@ -398,31 +400,55 @@ CoreEnterLeaveToAncestor(DeviceIntPtr dev,
WindowPtr B,
int mode)
{
- WindowPtr childA = NULL, P;
- BOOL hasPointerA = HasPointer(A);
-
- /* 1.a */ /* 1.b */
- if (!hasPointerA && (childA = FirstPointerChild(A, None)))
+ /* Case 4:
+ A is W, B is above W
+
+ Classically: The move generates a LeaveNotify on W with a detail of
+ Ancestor or Nonlinear
+
+ MPX:
+ Case 3A: There is at least one other pointer on W itself
+ P(W) doesn't change, the event should be suppressed
+ Case 3B: Otherwise, if there is at least one other pointer in a
+ descendant of W
+ P(W) changes from W to a descendant of W. The subwindow field
+ is set to the child containing the new P(W), the detail field
+ is set to Inferior
+ Case 3C: Otherwise:
+ The pointer window moves from W to a window above W.
+ The detail may need to be changed from Ancestor to Nonlinear or
+ vice versa depending on the the new P(W)
+ */
+ if (!HasPointer(A))
{
- CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyInferior, A, WID(childA));
- EnterNotifies(dev, A, childA, mode, NotifyVirtual, TRUE);
- } else {
- /* 2 */
- P = FirstPointerAncestor(A, B);
- if (!P)
- P = B;
-
- if (!hasPointerA)
+ WindowPtr child = FirstPointerChild(A, None);
+ if (child)
+ CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyInferior, A, None);
+ else
CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyAncestor, A, None);
- LeaveNotifies(dev, A, P, mode, NotifyVirtual, TRUE);
}
- /* 3 */
- if (!HasOtherPointer(B, dev))
+ CoreLeaveNotifies(dev, A, B, mode, NotifyVirtual);
+
+ /* Case 8:
+ A is a descendant of W, B is W
+
+ Classically: A EnterNotify is generated on W with a detail of
+ NotifyInferior
+
+ MPX:
+ Case 3A: There is at least one other pointer on W itself
+ P(W) doesn't change, the event should be suppressed
+ Case 3B: Otherwise:
+ 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))
CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyInferior, B, None);
}
+
/**
* Pointer @dev moves from @A to @B and @B is a descendant of @A.
*/
@@ -432,40 +458,51 @@ CoreEnterLeaveToDescendant(DeviceIntPtr dev,
WindowPtr B,
int mode)
{
- WindowPtr X, childB, tmp;
+ /* Case 6:
+ A is W, B is a descendant of W
- /* 1 */
- if (!HasPointer(A))
- CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyInferior, A, WID(B));
+ Classically: A LeaveNotify is generated on W with a detail of
+ NotifyInferior
- /* 2 */
- X = FirstPointerAncestor(B, A);
- if (X)
- {
- /* 2.a */
- tmp = X;
- while((tmp = FirstPointerAncestor(tmp, A)))
- X = tmp;
- } else /* 2.b */
- X = B;
+ MPX:
+ Case 3A: There is at least one other pointer on W itself
+ P(W) doesn't change, the event should be suppressed
+ Case 3B: Otherwise:
+ 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 */
- EnterNotifies(dev, A, X, mode, NotifyVirtual, TRUE);
-
- if (X != B && !HasPointer(X))
- CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyVirtual, X, None);
-
- /* 3 */
- if (!HasOtherPointer(B, dev))
- {
- childB = FirstPointerChild(B, None);
- /* 3.a */
- if (childB)
- {
- LeaveNotifies(dev, childB, B, mode, NotifyVirtual, TRUE);
- CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyInferior, B, WID(childB));
- } else /* 3.c */
- CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyAncestor, B, None);
- }
+ if (!HasPointer(A))
+ CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyInferior, A, None);
+
+
+ CoreEnterNotifies(dev, A, B, mode, NotifyVirtual);
+
+ /* Case 2:
+ A is above W, B=W
+
+ Classically: The move generates an EnterNotify on W with a detail of
+ Ancestor or Nonlinear
+
+ MPX:
+ Case 2A: There is at least one other pointer on W itself
+ P(W) doesn't change, so the event should be suppressed
+ Case 2B: Otherwise, if there is at least one other pointer in a
+ descendant
+ P(W) moves from a descendant to W. detail is changed to Inferior,
+ subwindow is set to the child containing the previous P(W)
+ Case 2C: Otherwise:
+ P(W) changes from a window above W to W itself.
+ The detail may need to be changed from Ancestor to Nonlinear
+ or vice-versa depending on the previous P(W). */
+
+ if (!HasPointer(B))
+ {
+ WindowPtr child = FirstPointerChild(B, None);
+ if (child)
+ CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyInferior, B, None);
+ else
+ CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyAncestor, B, None);
+ }
}
static void
@@ -498,13 +535,13 @@ DeviceEnterLeaveEvents(DeviceIntPtr dev,
if (IsParent(from, to))
{
DeviceEnterLeaveEvent(dev, DeviceLeaveNotify, mode, NotifyInferior, from, None);
- EnterNotifies(dev, from, to, mode, NotifyVirtual, FALSE);
+ DeviceEnterNotifies(dev, from, to, mode, NotifyVirtual);
DeviceEnterLeaveEvent(dev, DeviceEnterNotify, mode, NotifyAncestor, to, None);
}
else if (IsParent(to, from))
{
DeviceEnterLeaveEvent(dev, DeviceLeaveNotify, mode, NotifyAncestor, from, None);
- LeaveNotifies(dev, from, to, mode, NotifyVirtual, FALSE);
+ DeviceLeaveNotifies(dev, from, to, mode, NotifyVirtual);
DeviceEnterLeaveEvent(dev, DeviceEnterNotify, mode, NotifyInferior, to, None);
}
else
@@ -512,8 +549,8 @@ DeviceEnterLeaveEvents(DeviceIntPtr dev,
WindowPtr common = CommonAncestor(to, from);
/* common == NullWindow ==> different screens */
DeviceEnterLeaveEvent(dev, DeviceLeaveNotify, mode, NotifyNonlinear, from, None);
- LeaveNotifies(dev, from, common, mode, NotifyNonlinearVirtual, FALSE);
- EnterNotifies(dev, common, to, mode, NotifyNonlinearVirtual, FALSE);
+ DeviceLeaveNotifies(dev, from, common, mode, NotifyNonlinearVirtual);
+ DeviceEnterNotifies(dev, common, to, mode, NotifyNonlinearVirtual);
DeviceEnterLeaveEvent(dev, DeviceEnterNotify, mode, NotifyNonlinear, to, None);
}
}
--
1.6.0.4
More information about the xorg
mailing list