diff options
Diffstat (limited to 'dix/events.c')
-rw-r--r-- | dix/events.c | 286 |
1 files changed, 81 insertions, 205 deletions
diff --git a/dix/events.c b/dix/events.c index 27601b7e3..bfc84948d 100644 --- a/dix/events.c +++ b/dix/events.c @@ -164,6 +164,8 @@ typedef const char *string; #include "geext.h" #include "geint.h" +#include "enterleave.h" + /** * Extension events type numbering starts at EXTENSION_EVENT_BASE. */ @@ -326,13 +328,6 @@ IsKeyboardDevice(DeviceIntPtr dev) return (dev->key && dev->kbdfeed) && !IsPointerDevice(dev); } -static void DoEnterLeaveEvents( - DeviceIntPtr pDev, - WindowPtr fromWin, - WindowPtr toWin, - int mode -); - static WindowPtr XYToWindow( DeviceIntPtr pDev, int x, @@ -4185,24 +4180,11 @@ EventSuppressForWindow(WindowPtr pWin, ClientPtr client, } /** - * @return The window that is the first ancestor of both a and b. - */ -static WindowPtr -CommonAncestor( - WindowPtr a, - WindowPtr b) -{ - for (b = b->parent; b; b = b->parent) - if (IsParent(b, a)) return b; - return NullWindow; -} - -/** * Assembles an EnterNotify or LeaveNotify and sends it event to the client. * Uses the paired keyboard to get some additional information. */ -static void -EnterLeaveEvent( +void +CoreEnterLeaveEvent( DeviceIntPtr mouse, int type, int mode, @@ -4215,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); @@ -4268,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, @@ -4315,145 +4254,97 @@ 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); - - /* 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->deviceid = mouse->id; - mskidx = mouse->id; - inputMasks = wOtherInputMasks(pWin); - if (inputMasks && - (filters[mouse->id][devEnterLeave->type] & - 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); - } - 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); + 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); + 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); } } -/** - * Send enter notifies to all parent windows up to ancestor. - * This function recurses. - */ -static void -EnterNotifies(DeviceIntPtr pDev, - WindowPtr ancestor, - WindowPtr child, - int mode, - int detail) -{ - WindowPtr parent = child->parent; - - if (ancestor == parent) - return; - EnterNotifies(pDev, ancestor, parent, mode, detail); - EnterLeaveEvent(pDev, EnterNotify, mode, detail, parent, - child->drawable.id); -} - - -/** - * Send leave notifies to all parent windows up to ancestor. - * This function recurses. - */ -static void -LeaveNotifies(DeviceIntPtr pDev, - WindowPtr child, - WindowPtr ancestor, - int mode, - int detail) +void +DeviceEnterLeaveEvent( + DeviceIntPtr mouse, + int type, + int mode, + int detail, + WindowPtr pWin, + Window child) { - WindowPtr pWin; - - if (ancestor == child) - return; - for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent) - { - EnterLeaveEvent(pDev, LeaveNotify, mode, detail, pWin, - child->drawable.id); - child = pWin; + 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->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; -/** - * Figure out if enter/leave events are necessary and send them to the - * appropriate windows. - * - * @param fromWin Window the sprite moved out of. - * @param toWin Window the sprite moved into. - */ -static void -DoEnterLeaveEvents(DeviceIntPtr pDev, - WindowPtr fromWin, - WindowPtr toWin, - int mode) -{ - if (!IsPointerDevice(pDev)) - return; + devEnterLeave->child = child; + devEnterLeave->type = type; + devEnterLeave->deviceid = mouse->id; + devEnterLeave->mode = mode; + devEnterLeave->mode |= (sameScreen ? (ELFlagSameScreen << 4) : 0); - if (fromWin == toWin) - return; - if (IsParent(fromWin, toWin)) +#ifdef XKB + if (!noXkbExtension) { + devEnterLeave->state = mouse->button->state & 0x1f00; + if (keybd) + devEnterLeave->state |= + XkbGrabStateFromRec(&keybd->key->xkbInfo->state); + } else +#endif { - EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyInferior, fromWin, - None); - EnterNotifies(pDev, fromWin, toWin, mode, - NotifyVirtual); - EnterLeaveEvent(pDev, EnterNotify, mode, NotifyAncestor, toWin, None); + devEnterLeave->state = (keybd) ? keybd->key->state : 0; + devEnterLeave->state |= mouse->button->state; } - else if (IsParent(toWin, fromWin)) + + mskidx = mouse->id; + inputMasks = wOtherInputMasks(pWin); + if (inputMasks && + (filters[mouse->id][devEnterLeave->type] & + inputMasks->deliverableEvents[mskidx])) { - 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); + if (grab) + 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); } + } static void @@ -6259,21 +6150,6 @@ ExtGrabDevice(ClientPtr client, } /* - * @return Zero if no device is currently in window, non-zero otherwise. - */ -int -EnterLeaveSemaphoresIsset(WindowPtr win) -{ - int set = 0; - int i; - - for (i = 0; i < (MAXDEVICES + 7)/8; i++) - set += win->enterleave[i]; - - return set; -} - -/* * @return Zero if no devices has focus on the window, non-zero otherwise. */ int |