diff options
author | Peter Hutterer <peter.hutterer@redhat.com> | 2008-11-14 15:37:35 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@redhat.com> | 2008-11-25 09:21:45 +1000 |
commit | 6bdc963cdabb4a2e77de7f00a1d062aa2b873f9b (patch) | |
tree | 3caff5be1c52f70b819941d3141a67a503f4c87f /dix | |
parent | 5e48f5e2dd2dec7cfd1fa40b61e25123dfca515e (diff) |
dix: split enter/leave event handling into core and device handling.
Device events always need to be delivered, core events only in some cases.
Let's keep them completely separate so we can adjust core event delivery.
Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
Diffstat (limited to 'dix')
-rw-r--r-- | dix/enterleave.c | 76 | ||||
-rw-r--r-- | dix/enterleave.h | 13 | ||||
-rw-r--r-- | dix/events.c | 159 |
3 files changed, 125 insertions, 123 deletions
diff --git a/dix/enterleave.c b/dix/enterleave.c index 941aa528a..11929c6fe 100644 --- a/dix/enterleave.c +++ b/dix/enterleave.c @@ -30,6 +30,7 @@ #include <X11/X.h> #include "windowstr.h" +#include "exglobals.h" #include "enterleave.h" /** @@ -47,46 +48,57 @@ CommonAncestor( /** - * Send enter notifies to all parent windows up to ancestor. - * This function recurses. + * 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 pDev, +EnterNotifies(DeviceIntPtr dev, WindowPtr ancestor, WindowPtr child, int mode, - int detail) + int detail, + BOOL core) { WindowPtr parent = child->parent; if (ancestor == parent) return; - EnterNotifies(pDev, ancestor, parent, mode, detail); - EnterLeaveEvent(pDev, EnterNotify, mode, detail, parent, - child->drawable.id); + 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 parent windows up to ancestor. - * This function recurses. + * Send leave notifies to all windows between @child and @ancestor. + * Events are sent running up the hierarchy. */ static void -LeaveNotifies(DeviceIntPtr pDev, +LeaveNotifies(DeviceIntPtr dev, WindowPtr child, WindowPtr ancestor, int mode, - int detail) + int detail, + BOOL core) { - WindowPtr pWin; + WindowPtr win; if (ancestor == child) return; - for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent) + for (win = child->parent; win != ancestor; win = win->parent) { - EnterLeaveEvent(pDev, LeaveNotify, mode, detail, pWin, - child->drawable.id); - child = pWin; + if (core) + CoreEnterLeaveEvent(dev, LeaveNotify, mode, detail, win, + child->drawable.id); + else + DeviceEnterLeaveEvent(dev, DeviceLeaveNotify, mode, detail, win, + child->drawable.id); + child = win; } } @@ -108,31 +120,7 @@ DoEnterLeaveEvents(DeviceIntPtr pDev, if (fromWin == toWin) return; - if (IsParent(fromWin, toWin)) - { - EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyInferior, fromWin, - None); - EnterNotifies(pDev, fromWin, toWin, mode, - NotifyVirtual); - EnterLeaveEvent(pDev, EnterNotify, mode, NotifyAncestor, toWin, None); - } - else if (IsParent(toWin, fromWin)) - { - EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyAncestor, fromWin, - None); - LeaveNotifies(pDev, fromWin, toWin, mode, NotifyVirtual); - EnterLeaveEvent(pDev, EnterNotify, mode, NotifyInferior, toWin, None); - } - else - { /* neither fromWin nor toWin is descendent of the other */ - WindowPtr common = CommonAncestor(toWin, fromWin); - /* common == NullWindow ==> different screens */ - EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyNonlinear, fromWin, - None); - LeaveNotifies(pDev, fromWin, common, mode, NotifyNonlinearVirtual); - EnterNotifies(pDev, common, toWin, mode, NotifyNonlinearVirtual); - EnterLeaveEvent(pDev, EnterNotify, mode, NotifyNonlinear, toWin, - None); - } -} + CoreEnterLeaveEvents(pDev, fromWin, toWin, mode); + DeviceEnterLeaveEvents(pDev, fromWin, toWin, mode); +} diff --git a/dix/enterleave.h b/dix/enterleave.h index c1bfc3ada..6e062260e 100644 --- a/dix/enterleave.h +++ b/dix/enterleave.h @@ -50,4 +50,17 @@ extern WindowPtr CommonAncestor( WindowPtr a, WindowPtr b); +extern void CoreEnterLeaveEvent(DeviceIntPtr mouse, + int type, + int mode, + int detail, + WindowPtr pWin, + Window child); +extern void DeviceEnterLeaveEvent(DeviceIntPtr mouse, + int type, + int mode, + int detail, + WindowPtr pWin, + Window child); + #endif /* _ENTERLEAVE_H_ */ diff --git a/dix/events.c b/dix/events.c index 0f63ca3be..bfc84948d 100644 --- a/dix/events.c +++ b/dix/events.c @@ -4184,7 +4184,7 @@ EventSuppressForWindow(WindowPtr pWin, ClientPtr client, * Uses the paired keyboard to get some additional information. */ void -EnterLeaveEvent( +CoreEnterLeaveEvent( DeviceIntPtr mouse, int type, int mode, @@ -4197,12 +4197,6 @@ EnterLeaveEvent( DeviceIntPtr keybd; GrabPtr grab = mouse->deviceGrab.grab; Mask mask; - int inWindow; /* zero if no sprites are in window */ - Bool sendevent = FALSE; - - deviceEnterNotify *devEnterLeave; - int mskidx; - OtherInputMasks *inputMasks; keybd = GetPairedDevice(mouse); @@ -4250,44 +4244,7 @@ EnterLeaveEvent( IsParent(focus, pWin))) event.u.enterLeave.flags |= ELFlagFocus; - - /* - * 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 most clients anyway. - * - * 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. - */ - - /* Clear bit for device, but don't worry about SDs. */ - if (mouse->isMaster && type == LeaveNotify && - (detail != NotifyVirtual && detail != NotifyNonlinearVirtual)) - if (mode != NotifyUngrab) - ENTER_LEAVE_SEMAPHORE_UNSET(pWin, mouse); - - inWindow = EnterLeaveSemaphoresIsset(pWin); - - if(!inWindow || mode == NotifyGrab || mode == NotifyUngrab) - sendevent = TRUE; - - - if ((mask & filters[mouse->id][type]) && sendevent) + if ((mask & filters[mouse->id][type])) { if (grab) TryClientEvents(rClient(grab), mouse, &event, 1, mask, @@ -4297,18 +4254,81 @@ EnterLeaveEvent( filters[mouse->id][type], NullGrab, 0); } - if (mouse->isMaster && type == EnterNotify && - (detail != NotifyVirtual && detail != NotifyNonlinearVirtual)) - if (mode != NotifyGrab) - ENTER_LEAVE_SEMAPHORE_SET(pWin, mouse); + if ((type == EnterNotify) && (mask & KeymapStateMask)) + { + xKeymapEvent ke; + ClientPtr client = grab ? rClient(grab) + : clients[CLIENT_ID(pWin->drawable.id)]; + if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess)) + bzero((char *)&ke.map[0], 31); + else + memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31); + + ke.type = KeymapNotify; + if (grab) + TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1, + mask, KeymapStateMask, grab); + else + DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } +} + +void +DeviceEnterLeaveEvent( + DeviceIntPtr mouse, + int type, + int mode, + int detail, + WindowPtr pWin, + Window child) +{ + xEvent event; + GrabPtr grab = mouse->deviceGrab.grab; + deviceEnterNotify *devEnterLeave; + int mskidx; + OtherInputMasks *inputMasks; + Mask mask; + DeviceIntPtr keybd = GetPairedDevice(mouse); + BOOL sameScreen; + + if (grab) { + mask = (pWin == grab->window) ? grab->eventMask : 0; + if (grab->ownerEvents) + mask |= EventMaskForClient(pWin, rClient(grab)); + } else { + mask = pWin->eventMask | wOtherEventMasks(pWin); + } /* we don't have enough bytes, so we squash flags and mode into one byte, and use the last byte for the deviceid. */ - devEnterLeave = (deviceEnterNotify*)&event; - devEnterLeave->type = (type == EnterNotify) ? DeviceEnterNotify : - DeviceLeaveNotify; - devEnterLeave->mode |= (event.u.enterLeave.flags << 4); + devEnterLeave = (deviceEnterNotify*)&event; + devEnterLeave->detail = detail; + devEnterLeave->time = currentTime.milliseconds; + devEnterLeave->rootX = mouse->spriteInfo->sprite->hot.x; + devEnterLeave->rootY = mouse->spriteInfo->sprite->hot.y; + FixUpEventFromWindow(mouse, &event, pWin, None, FALSE); + sameScreen = event.u.keyButtonPointer.sameScreen; + + devEnterLeave->child = child; + devEnterLeave->type = type; devEnterLeave->deviceid = mouse->id; + devEnterLeave->mode = mode; + devEnterLeave->mode |= (sameScreen ? (ELFlagSameScreen << 4) : 0); + +#ifdef XKB + if (!noXkbExtension) { + devEnterLeave->state = mouse->button->state & 0x1f00; + if (keybd) + devEnterLeave->state |= + XkbGrabStateFromRec(&keybd->key->xkbInfo->state); + } else +#endif + { + devEnterLeave->state = (keybd) ? keybd->key->state : 0; + devEnterLeave->state |= mouse->button->state; + } + mskidx = mouse->id; inputMasks = wOtherInputMasks(pWin); if (inputMasks && @@ -4316,34 +4336,15 @@ EnterLeaveEvent( inputMasks->deliverableEvents[mskidx])) { if (grab) - (void)TryClientEvents(rClient(grab), mouse, - (xEvent*)devEnterLeave, 1, - mask, filters[mouse->id][devEnterLeave->type], - grab); - else - (void)DeliverEventsToWindow(mouse, pWin, (xEvent*)devEnterLeave, - 1, filters[mouse->id][devEnterLeave->type], - NullGrab, mouse->id); + TryClientEvents(rClient(grab), mouse, + (xEvent*)devEnterLeave, 1, mask, + filters[mouse->id][devEnterLeave->type], grab); + else + DeliverEventsToWindow(mouse, pWin, (xEvent*)devEnterLeave, 1, + filters[mouse->id][devEnterLeave->type], + NullGrab, mouse->id); } - if ((type == EnterNotify) && (mask & KeymapStateMask)) - { - xKeymapEvent ke; - ClientPtr client = grab ? rClient(grab) - : clients[CLIENT_ID(pWin->drawable.id)]; - if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess)) - bzero((char *)&ke.map[0], 31); - else - memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31); - - ke.type = KeymapNotify; - if (grab) - (void)TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1, - mask, KeymapStateMask, grab); - else - (void)DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1, - KeymapStateMask, NullGrab, 0); - } } static void |