diff options
-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 |