From 451d5464b4e8a2516b8a4598b3c4eb14656be90e Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 17 Apr 2007 11:17:04 +0930 Subject: [PATCH] Change enter/leave semantics for events with detail Notify{Nonlinear}Virtual. Core enter/leave events with detail Notify{Ancestor|Inferior|Nonlinear} are only sent for the first/last pointer to enter/leave. Events with detail Notify{Nonlinear}Virtual are sent at all times, but not to those windows that currently have one or more pointers inside their boundaries. --- dix/events.c | 59 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/dix/events.c b/dix/events.c index e515f107a..def209eb8 100644 --- a/dix/events.c +++ b/dix/events.c @@ -281,7 +281,7 @@ static void DoEnterLeaveEvents( WindowPtr fromWin, WindowPtr toWin, int mode -); +); static WindowPtr XYToWindow( int x, @@ -3453,6 +3453,7 @@ EnterLeaveEvent( GrabPtr devgrab = mouse->deviceGrab.grab; Mask mask; long* inWindow; /* no of sprites inside pWin */ + Bool sendevent = FALSE; deviceEnterNotify *devEnterLeave; int mskidx; @@ -3503,21 +3504,51 @@ EnterLeaveEvent( inWindow = &pWin->devPrivates[EnterLeavePrivatesIndex].val; - (type == EnterNotify) ? (*inWindow)++ : (*inWindow)--; + /* + * 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 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. + */ - if (mask & filters[type]) + if (event.u.u.detail != NotifyVirtual && + event.u.u.detail != NotifyNonlinearVirtual) { - /* only send core events for the first device to enter and the last - one to leave */ - if ((*inWindow) == (LeaveNotify - type)) - { - if (grab) - (void)TryClientEvents(rClient(grab), &event, 1, mask, - filters[type], grab); - else - (void)DeliverEventsToWindow(mouse, pWin, &event, 1, filters[type], - NullGrab, 0); - } + (type == EnterNotify) ? (*inWindow)++ : (*inWindow)--; + + if (((*inWindow) == (LeaveNotify - type))) + sendevent = TRUE; + } else + { + if (!(*inWindow)) + sendevent = TRUE; + } + + if ((mask & filters[type]) && sendevent) + { + if (grab) + (void)TryClientEvents(rClient(grab), &event, 1, mask, + filters[type], grab); + else + (void)DeliverEventsToWindow(mouse, pWin, &event, 1, filters[type], + NullGrab, 0); } devEnterLeave = (deviceEnterNotify*)&event;