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.
This commit is contained in:
parent
ea27b09d3a
commit
451d5464b4
59
dix/events.c
59
dix/events.c
|
@ -281,7 +281,7 @@ static void DoEnterLeaveEvents(
|
||||||
WindowPtr fromWin,
|
WindowPtr fromWin,
|
||||||
WindowPtr toWin,
|
WindowPtr toWin,
|
||||||
int mode
|
int mode
|
||||||
);
|
);
|
||||||
|
|
||||||
static WindowPtr XYToWindow(
|
static WindowPtr XYToWindow(
|
||||||
int x,
|
int x,
|
||||||
|
@ -3453,6 +3453,7 @@ EnterLeaveEvent(
|
||||||
GrabPtr devgrab = mouse->deviceGrab.grab;
|
GrabPtr devgrab = mouse->deviceGrab.grab;
|
||||||
Mask mask;
|
Mask mask;
|
||||||
long* inWindow; /* no of sprites inside pWin */
|
long* inWindow; /* no of sprites inside pWin */
|
||||||
|
Bool sendevent = FALSE;
|
||||||
|
|
||||||
deviceEnterNotify *devEnterLeave;
|
deviceEnterNotify *devEnterLeave;
|
||||||
int mskidx;
|
int mskidx;
|
||||||
|
@ -3503,21 +3504,51 @@ EnterLeaveEvent(
|
||||||
|
|
||||||
inWindow = &pWin->devPrivates[EnterLeavePrivatesIndex].val;
|
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
|
(type == EnterNotify) ? (*inWindow)++ : (*inWindow)--;
|
||||||
one to leave */
|
|
||||||
if ((*inWindow) == (LeaveNotify - type))
|
if (((*inWindow) == (LeaveNotify - type)))
|
||||||
{
|
sendevent = TRUE;
|
||||||
if (grab)
|
} else
|
||||||
(void)TryClientEvents(rClient(grab), &event, 1, mask,
|
{
|
||||||
filters[type], grab);
|
if (!(*inWindow))
|
||||||
else
|
sendevent = TRUE;
|
||||||
(void)DeliverEventsToWindow(mouse, pWin, &event, 1, filters[type],
|
}
|
||||||
NullGrab, 0);
|
|
||||||
}
|
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;
|
devEnterLeave = (deviceEnterNotify*)&event;
|
||||||
|
|
Loading…
Reference in New Issue