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

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 forcing grabbed devices to 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@who-t.net>
Reviewed-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
Peter Hutterer 2010-07-15 13:24:14 +10:00
parent a2c13f0d65
commit c54f81ba7a

View File

@ -78,10 +78,19 @@ static WindowPtr FocusWindows[MAXDEVICES];
* window. * window.
*/ */
static BOOL static BOOL
HasPointer(WindowPtr win) HasPointer(DeviceIntPtr dev, WindowPtr win)
{ {
int i; 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++) for (i = 0; i < MAXDEVICES; i++)
if (PointerWindows[i] == win) if (PointerWindows[i] == win)
return TRUE; return TRUE;
@ -270,7 +279,7 @@ CoreEnterNotifies(DeviceIntPtr dev,
may need to be changed from Virtual to NonlinearVirtual depending may need to be changed from Virtual to NonlinearVirtual depending
on the previous P(W). */ on the previous P(W). */
if (!HasPointer(parent) && !FirstPointerChild(parent)) if (!HasPointer(dev, parent) && !FirstPointerChild(parent))
CoreEnterLeaveEvent(dev, EnterNotify, mode, detail, parent, CoreEnterLeaveEvent(dev, EnterNotify, mode, detail, parent,
child->drawable.id); child->drawable.id);
} }
@ -309,7 +318,7 @@ CoreLeaveNotifies(DeviceIntPtr dev,
/* If one window has a pointer or a child with a pointer, skip some /* If one window has a pointer or a child with a pointer, skip some
* work and exit. */ * work and exit. */
if (HasPointer(win) || FirstPointerChild(win)) if (HasPointer(dev, win) || FirstPointerChild(win))
return; return;
CoreEnterLeaveEvent(dev, LeaveNotify, mode, detail, win, child->drawable.id); 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) vice versa depending on the the new P(W)
*/ */
if (!HasPointer(A)) if (!HasPointer(dev, A))
{ {
WindowPtr child = FirstPointerChild(A); WindowPtr child = FirstPointerChild(A);
if (child) if (child)
@ -417,7 +426,7 @@ CoreEnterLeaveNonLinear(DeviceIntPtr dev,
The detail may need to be changed from Ancestor to Nonlinear The detail may need to be changed from Ancestor to Nonlinear
or vice-versa depending on the previous P(W). */ or vice-versa depending on the previous P(W). */
if (!HasPointer(B)) if (!HasPointer(dev, B))
{ {
WindowPtr child = FirstPointerChild(B); WindowPtr child = FirstPointerChild(B);
if (child) if (child)
@ -455,7 +464,7 @@ CoreEnterLeaveToAncestor(DeviceIntPtr dev,
The detail may need to be changed from Ancestor to Nonlinear or The detail may need to be changed from Ancestor to Nonlinear or
vice versa depending on the the new P(W) vice versa depending on the the new P(W)
*/ */
if (!HasPointer(A)) if (!HasPointer(dev, A))
{ {
WindowPtr child = FirstPointerChild(A); WindowPtr child = FirstPointerChild(A);
if (child) if (child)
@ -479,7 +488,7 @@ CoreEnterLeaveToAncestor(DeviceIntPtr dev,
P(W) changes from a descendant to W itself. The subwindow P(W) changes from a descendant to W itself. The subwindow
field should be set to the child containing the old P(W) <<< WRONG */ 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); 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 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 */ 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); 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 The detail may need to be changed from Ancestor to Nonlinear
or vice-versa depending on the previous P(W). */ or vice-versa depending on the previous P(W). */
if (!HasPointer(B)) if (!HasPointer(dev, B))
{ {
WindowPtr child = FirstPointerChild(B); WindowPtr child = FirstPointerChild(B);
if (child) if (child)