diff options
Diffstat (limited to 'dix/events.c')
-rw-r--r-- | dix/events.c | 251 |
1 files changed, 167 insertions, 84 deletions
diff --git a/dix/events.c b/dix/events.c index 87d2ef746..bb5520af9 100644 --- a/dix/events.c +++ b/dix/events.c @@ -117,7 +117,6 @@ of the copyright holder. #endif #include <X11/X.h> -#include <X11/keysym.h> #include "misc.h" #include "resource.h" #include <X11/Xproto.h> @@ -135,9 +134,6 @@ of the copyright holder. #include <X11/extensions/XKBproto.h> #include "xkbsrv.h" -/* XKB FIXME: why is this here? */ -extern Bool XkbFilterEvents(ClientPtr, int, xEvent *); - #include "xace.h" #ifdef XSERVER_DTRACE @@ -167,6 +163,7 @@ typedef const char *string; #include "geext.h" #include "geint.h" +#include "eventstr.h" #include "enterleave.h" #include "eventconvert.h" @@ -233,6 +230,9 @@ static Bool CheckPassiveGrabsOnWindow(WindowPtr pWin, DeviceEvent *event, BOOL checkCore); +/** Key repeat hack. Do not use but in TryClientEvents */ +extern BOOL EventIsKeyRepeat(xEvent *event); + /** * Main input device struct. * inputInfo.pointer @@ -1551,7 +1551,8 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, Bool isPassive = autoGrab & ~ImplicitGrabMask; /* slave devices need to float for the duration of the grab. */ - if (!(autoGrab & ImplicitGrabMask) && !IsMaster(mouse)) + if (grab->grabtype == GRABTYPE_XI2 && + !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse)) DetachFromMaster(mouse); if (grab->confineTo) @@ -1562,7 +1563,7 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, mouse->spriteInfo->sprite->hotPhys.y = 0; ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE); } - DoEnterLeaveEvents(mouse, oldWin, grab->window, NotifyGrab); + DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab); mouse->valuator->motionHintWindow = NullWindow; if (syncEvents.playingEvents) grabinfo->grabTime = syncEvents.time; @@ -1601,7 +1602,7 @@ DeactivatePointerGrab(DeviceIntPtr mouse) if (dev->deviceGrab.sync.other == grab) dev->deviceGrab.sync.other = NullGrab; } - DoEnterLeaveEvents(mouse, grab->window, + DoEnterLeaveEvents(mouse, mouse->id, grab->window, mouse->spriteInfo->sprite->win, NotifyUngrab); if (grab->confineTo) ConfineCursorToWindow(mouse, RootWindow(mouse), FALSE, FALSE); @@ -1609,7 +1610,7 @@ DeactivatePointerGrab(DeviceIntPtr mouse) if (grab->cursor) FreeCursor(grab->cursor, (Cursor)0); - if (!wasImplicit) + if (!wasImplicit && grab->grabtype == GRABTYPE_XI2) ReattachToOldMaster(mouse); ComputeFreezes(); @@ -1627,7 +1628,9 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool pass WindowPtr oldWin; /* slave devices need to float for the duration of the grab. */ - if (!(passive & ImplicitGrabMask) && !IsMaster(keybd)) + if (grab->grabtype == GRABTYPE_XI2 && + !(passive & ImplicitGrabMask) && + !IsMaster(keybd)) DetachFromMaster(keybd); if (grabinfo->grab) @@ -1680,7 +1683,7 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd) } DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); - if (!wasImplicit) + if (!wasImplicit && grab->grabtype == GRABTYPE_XI2) ReattachToOldMaster(keybd); ComputeFreezes(); @@ -1924,70 +1927,124 @@ TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents, int type; #ifdef DEBUG_EVENTS - ErrorF("[dix] Event([%d, %d], mask=0x%x), client=%d", - pEvents->u.u.type, pEvents->u.u.detail, mask, client->index); + ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s", + pEvents->u.u.type, pEvents->u.u.detail, mask, + client ? client->index : -1, + (client && client->clientGone) ? " (gone)" : ""); #endif - if ((client) && (client != serverClient) && (!client->clientGone) && - ((filter == CantBeFiltered) || (mask & filter))) - { - if (grab && !SameClient(grab, client)) - return -1; /* don't send, but notify caller */ - type = pEvents->u.u.type; - if (type == MotionNotify) - { - if (mask & PointerMotionHintMask) - { - if (WID(dev->valuator->motionHintWindow) == - pEvents->u.keyButtonPointer.event) - { + + if (!client || client == serverClient || client->clientGone) { #ifdef DEBUG_EVENTS - ErrorF("[dix] \n"); - ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n"); + ErrorF(" not delivered to fake/dead client\n"); #endif - return 1; /* don't send, but pretend we did */ - } - pEvents->u.u.detail = NotifyHint; - } - else - { - pEvents->u.u.detail = NotifyNormal; - } - } - else - { - if ((type == DeviceMotionNotify) && - MaybeSendDeviceMotionNotifyHint - ((deviceKeyButtonPointer*)pEvents, mask) != 0) - return 1; - } - type &= 0177; - if (type != KeymapNotify) - { - /* all extension events must have a sequence number */ - for (i = 0; i < count; i++) - pEvents[i].u.u.sequenceNumber = client->sequence; - } + return 0; + } - if (BitIsOn(criticalEvents, type)) - { - if (client->smart_priority < SMART_MAX_PRIORITY) - client->smart_priority++; - SetCriticalOutputPending(); - } + if (filter != CantBeFiltered && !(mask & filter)) + { + #ifdef DEBUG_EVENTS + ErrorF(" filtered\n"); + #endif + return 0; + } - WriteEventsToClient(client, count, pEvents); + if (grab && !SameClient(grab, client)) + { #ifdef DEBUG_EVENTS - ErrorF("[dix] delivered\n"); + ErrorF(" not delivered due to grab\n"); #endif - return 1; + return -1; /* don't send, but notify caller */ } - else + + type = pEvents->u.u.type; + if (type == MotionNotify) { + if (mask & PointerMotionHintMask) + { + if (WID(dev->valuator->motionHintWindow) == + pEvents->u.keyButtonPointer.event) + { #ifdef DEBUG_EVENTS - ErrorF("[dix] \n"); + ErrorF("[dix] \n"); + ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n"); #endif - return 0; + return 1; /* don't send, but pretend we did */ + } + pEvents->u.u.detail = NotifyHint; + } + else + { + pEvents->u.u.detail = NotifyNormal; + } } + else if (type == DeviceMotionNotify) + { + if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer*)pEvents, + mask) != 0) + return 1; + } else if (type == KeyPress) + { + if (EventIsKeyRepeat(pEvents)) + { + if (!_XkbWantsDetectableAutoRepeat(client)) + { + xEvent release = *pEvents; + release.u.u.type = KeyRelease; + release.u.u.sequenceNumber = client->sequence; + WriteEventsToClient(client, 1, &release); +#ifdef DEBUG_EVENTS + ErrorF(" (plus fake core release for repeat)"); +#endif + } else + { +#ifdef DEBUG_EVENTS + ErrorF(" (detectable autorepeat for core)"); +#endif + } + } + + } else if (type == DeviceKeyPress) + { + if (EventIsKeyRepeat(pEvents)) + { + if (!_XkbWantsDetectableAutoRepeat(client)) + { + deviceKeyButtonPointer release = *(deviceKeyButtonPointer *)pEvents; + release.type = DeviceKeyRelease; + release.sequenceNumber = client->sequence; +#ifdef DEBUG_EVENTS + ErrorF(" (plus fake xi1 release for repeat)"); +#endif + WriteEventsToClient(client, 1, (xEvent *) &release); + } + else { +#ifdef DEBUG_EVENTS + ErrorF(" (detectable autorepeat for core)"); +#endif + } + } + } + + type &= 0177; + if (type != KeymapNotify) + { + /* all extension events must have a sequence number */ + for (i = 0; i < count; i++) + pEvents[i].u.u.sequenceNumber = client->sequence; + } + + if (BitIsOn(criticalEvents, type)) + { + if (client->smart_priority < SMART_MAX_PRIORITY) + client->smart_priority++; + SetCriticalOutputPending(); + } + + WriteEventsToClient(client, count, pEvents); +#ifdef DEBUG_EVENTS + ErrorF("[dix] delivered\n"); +#endif + return 1; } @@ -2288,7 +2345,14 @@ FixUpEventFromWindow( { xXIDeviceEvent* event = (xXIDeviceEvent*)xE; - if (event->evtype == XI_RawEvent) + if (event->evtype == XI_RawKeyPress || + event->evtype == XI_RawKeyRelease || + event->evtype == XI_RawButtonPress || + event->evtype == XI_RawButtonRelease || + event->evtype == XI_RawMotion || + event->evtype == XI_DeviceChanged || + event->evtype == XI_HierarchyChanged || + event->evtype == XI_PropertyEvent) return; event->root = RootWindow(pDev)->drawable.id; @@ -2740,7 +2804,7 @@ ActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) if (dev->deviceGrab.grab->window == win || IsParent(dev->deviceGrab.grab->window, win)) return FALSE; - DoEnterLeaveEvents(dev, old, win, XINotifyPassiveUngrab); + DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); (*dev->deviceGrab.DeactivateGrab)(dev); } @@ -2757,7 +2821,7 @@ ActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) event.detail.button = 0; rc = CheckPassiveGrabsOnWindow(win, dev, &event, FALSE); if (rc) - DoEnterLeaveEvents(dev, old, win, XINotifyPassiveUngrab); + DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); return rc; } @@ -2780,7 +2844,7 @@ ActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) if (dev->deviceGrab.grab->window == win || IsParent(dev->deviceGrab.grab->window, win)) return FALSE; - DoEnterLeaveEvents(dev, old, win, XINotifyPassiveUngrab); + DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); (*dev->deviceGrab.DeactivateGrab)(dev); } @@ -2794,7 +2858,7 @@ ActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) event.detail.button = 0; rc = CheckPassiveGrabsOnWindow(win, dev, &event, FALSE); if (rc) - DoEnterLeaveEvents(dev, old, win, XINotifyPassiveGrab); + DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab); return rc; } @@ -2909,12 +2973,16 @@ CheckMotion(DeviceEvent *ev, DeviceIntPtr pDev) if (newSpriteWin != prevSpriteWin) { - if (!ev) + int sourceid; + if (!ev) { UpdateCurrentTimeIf(); + sourceid = pDev->id; /* when from WindowsRestructured */ + } else + sourceid = ev->sourceid; if (prevSpriteWin != NullWindow) { if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin)) - DoEnterLeaveEvents(pDev, prevSpriteWin, + DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin, newSpriteWin, NotifyNormal); } /* set pSprite->win after ActivateEnterGrab, otherwise @@ -2937,7 +3005,7 @@ WindowsRestructured(void) DeviceIntPtr pDev = inputInfo.devices; while(pDev) { - if (DevHasCursor(pDev)) + if (IsMaster(pDev) || !pDev->u.master) CheckMotion(NULL, pDev); pDev = pDev->next; } @@ -3543,6 +3611,7 @@ CheckPassiveGrabsOnWindow( { DeviceIntPtr gdev; XkbSrvInfoPtr xkbi = NULL; + Mask mask = 0; gdev= grab->modifierDevice; if (grab->grabtype == GRABTYPE_CORE) @@ -3570,8 +3639,6 @@ CheckPassiveGrabsOnWindow( /* Check for XI2 and XI grabs first */ tempGrab.type = GetXI2Type((InternalEvent*)event); tempGrab.grabtype = GRABTYPE_XI2; - if (event->type == ET_KeyPress) - tempGrab.detail.exact = XkbGetKeysym(device, event); if (GrabMatchesSecond(&tempGrab, grab, FALSE)) match = XI2_MATCH; @@ -3659,6 +3726,7 @@ CheckPassiveGrabsOnWindow( } xE = &core; count = 1; + mask = grab->eventMask; } else if (match & XI2_MATCH) { rc = EventToXI2((InternalEvent*)event, &xE); @@ -3670,6 +3738,16 @@ CheckPassiveGrabsOnWindow( continue; } count = 1; + + /* FIXME: EventToXI2 returns NULL for enter events, so + * dereferencing the event is bad. Internal event types are + * aligned with core events, so the else clause is valid. + * long-term we should use internal events for enter/focus + * as well */ + if (xE) + mask = grab->xi2mask[device->id][((xGenericEvent*)xE)->evtype/8]; + else if (event->type == XI_Enter || event->type == XI_FocusIn) + mask = grab->xi2mask[device->id][event->type/8]; } else { rc = EventToXI((InternalEvent*)event, &xE, &count); @@ -3680,6 +3758,7 @@ CheckPassiveGrabsOnWindow( "(%d, %d).\n", device->name, event->type, rc); continue; } + mask = grab->eventMask; } (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE); @@ -3688,8 +3767,7 @@ CheckPassiveGrabsOnWindow( { FixUpEventFromWindow(device, xE, grab->window, None, TRUE); - TryClientEvents(rClient(grab), device, xE, count, - GetEventFilter(device, xE), + TryClientEvents(rClient(grab), device, xE, count, mask, GetEventFilter(device, xE), grab); } @@ -4404,6 +4482,7 @@ CoreEnterLeaveEvent( void DeviceEnterLeaveEvent( DeviceIntPtr mouse, + int sourceid, int type, int mode, int detail, @@ -4420,8 +4499,8 @@ DeviceEnterLeaveEvent( (mode == XINotifyPassiveUngrab && type == XI_Enter)) return; - btlen = (mouse->button) ? (mouse->button->numButtons + 7)/8 : 0; - btlen = (btlen + 3)/4; + btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0; + btlen = bytes_to_int32(btlen); len = sizeof(xXIEnterEvent) + btlen * 4; event = xcalloc(1, len); @@ -4433,7 +4512,7 @@ DeviceEnterLeaveEvent( event->detail = detail; event->time = currentTime.milliseconds; event->deviceid = mouse->id; - event->sourceid = 0; /*XXX */ + event->sourceid = sourceid; event->mode = mode; event->root_x = FP1616(mouse->spriteInfo->sprite->hot.x, 0); event->root_y = FP1616(mouse->spriteInfo->sprite->hot.y, 0); @@ -5261,7 +5340,7 @@ ProcUngrabKey(ClientPtr client) int rc; REQUEST_SIZE_MATCH(xUngrabKeyReq); - rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess); + rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess); if (rc != Success) return rc; @@ -5729,8 +5808,8 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events) int i, eventlength = sizeof(xEvent); - if (!XkbFilterEvents(pClient, count, events)) - return; + /* Let XKB rewrite the state, as it depends on client preferences. */ + XkbFilterEvents(pClient, count, events); #ifdef PANORAMIX if(!noPanoramiXExtension && @@ -5842,21 +5921,25 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events) * PickPointer()). * If a keyboard is needed, the first keyboard paired with the CP is used. */ -Bool +int SetClientPointer(ClientPtr client, DeviceIntPtr device) { + int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess); + if (rc != Success) + return rc; + if (!IsMaster(device)) { ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n"); - return FALSE; + return BadDevice; } else if (!device->spriteInfo->spriteOwner) { ErrorF("[dix] Device %d does not have a sprite. " "Cannot be ClientPointer\n", device->id); - return FALSE; + return BadDevice; } client->clientPtr = device; - return TRUE; + return Success; } /* PickPointer will pick an appropriate pointer for the given client. |