From e1aed88be92c27d76bff1743f35f9915dea9264f Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Tue, 28 Dec 2010 17:00:29 +0000 Subject: [PATCH 01/17] Input: Swap flags in DeviceEvents Swap flags for different-endian clients when delivering XI2 DeviceEvents. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer Reviewed-by: Chase Douglas --- Xi/extinit.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Xi/extinit.c b/Xi/extinit.c index 546ccb42e..82df7eb02 100644 --- a/Xi/extinit.c +++ b/Xi/extinit.c @@ -757,6 +757,7 @@ static void SDeviceEvent(xXIDeviceEvent *from, xXIDeviceEvent *to) swapl(&to->mods.latched_mods, n); swapl(&to->mods.locked_mods, n); swapl(&to->mods.effective_mods, n); + swapl(&to->flags, n); ptr = (char*)(&to[1]); ptr += from->buttons_len * 4; From 2592effef5f171af3f01a2b5130d9747403140f6 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Tue, 28 Dec 2010 13:42:06 +0000 Subject: [PATCH 02/17] Test: Input: Add helper function for failing EventToCore We have quite a few tests which involve checking that EventToCore fails for specific events, so refactor them into a separate function. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer Reviewed-by: Chase Douglas --- test/input.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/test/input.c b/test/input.c index 1fe228c32..c389a403a 100644 --- a/test/input.c +++ b/test/input.c @@ -256,7 +256,7 @@ static void dix_event_to_core(int type) #undef test_event } -static void dix_event_to_core_conversion(void) +static void dix_event_to_core_fail(int evtype, int expected_rc) { DeviceEvent ev; xEvent core; @@ -265,25 +265,18 @@ static void dix_event_to_core_conversion(void) ev.header = 0xFF; ev.length = sizeof(DeviceEvent); - ev.type = 0; + ev.type = evtype; rc = EventToCore((InternalEvent*)&ev, &core); - g_assert(rc == BadImplementation); + g_assert(rc == expected_rc); +} - ev.type = 1; - rc = EventToCore((InternalEvent*)&ev, &core); - g_assert(rc == BadImplementation); - - ev.type = ET_ProximityOut + 1; - rc = EventToCore((InternalEvent*)&ev, &core); - g_assert(rc == BadImplementation); - - ev.type = ET_ProximityIn; - rc = EventToCore((InternalEvent*)&ev, &core); - g_assert(rc == BadMatch); - - ev.type = ET_ProximityOut; - rc = EventToCore((InternalEvent*)&ev, &core); - g_assert(rc == BadMatch); +static void dix_event_to_core_conversion(void) +{ + dix_event_to_core_fail(0, BadImplementation); + dix_event_to_core_fail(1, BadImplementation); + dix_event_to_core_fail(ET_ProximityOut + 1, BadImplementation); + dix_event_to_core_fail(ET_ProximityIn, BadMatch); + dix_event_to_core_fail(ET_ProximityOut, BadMatch); dix_event_to_core(ET_KeyPress); dix_event_to_core(ET_KeyRelease); From a083efe8715e8b29c9bd7f4e7bb429a94620bfc4 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Tue, 28 Dec 2010 16:06:29 +0000 Subject: [PATCH 03/17] Test: Input: Check flags on DeviceEvent Add initial validation of acceptable flags for XI2 device events, and make sure they're swapped. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer Reviewed-by: Chase Douglas --- test/xi2/protocol-eventconvert.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/test/xi2/protocol-eventconvert.c b/test/xi2/protocol-eventconvert.c index 211cce6ad..0478c33fe 100644 --- a/test/xi2/protocol-eventconvert.c +++ b/test/xi2/protocol-eventconvert.c @@ -272,6 +272,7 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out, int buttons, valuators; int i; unsigned char *ptr; + uint32_t flagmask = 0; FP3232 *values; if (swap) { @@ -297,6 +298,7 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out, swapl(&out->mods.latched_mods, n); swapl(&out->mods.locked_mods, n); swapl(&out->mods.effective_mods, n); + swapl(&out->flags, n); } g_assert(out->extension == 0); /* IReqCode defaults to 0 */ @@ -308,7 +310,15 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out, g_assert(out->deviceid == in->deviceid); g_assert(out->sourceid == in->sourceid); - g_assert(out->flags == 0); /* FIXME: we don't set the flags yet */ + switch (in->type) { + case ET_KeyPress: + flagmask = XIKeyRepeat; + break; + default: + flagmask = 0; + break; + } + g_assert((out->flags & ~flagmask) == 0); g_assert(out->root == in->root); g_assert(out->event == None); /* set in FixUpEventFromWindow */ From 06a103ad1d6a0ef6146c97a8c81dc7de1c0a0083 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Tue, 28 Dec 2010 16:37:48 +0000 Subject: [PATCH 04/17] Test: Input: Test up to supported server, not protocol, events When building against a newer inputproto, the server may support fewer than XI_LASTEVENT events. We already have XI2LASTEVENT for the highest event number supported by the server, so use that instead. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer Reviewed-by: Chase Douglas --- test/xi2/protocol-xiselectevents.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/xi2/protocol-xiselectevents.c b/test/xi2/protocol-xiselectevents.c index fe1c26df8..f951a14fe 100644 --- a/test/xi2/protocol-xiselectevents.c +++ b/test/xi2/protocol-xiselectevents.c @@ -131,7 +131,7 @@ static void request_XISelectEvents_masks(xXISelectEventsReq *req) { int i, j; xXIEventMask *mask; - int nmasks = (XI_LASTEVENT + 7)/8; + int nmasks = (XI2LASTEVENT + 7)/8; unsigned char *bits; mask = (xXIEventMask*)&req[1]; @@ -150,14 +150,14 @@ static void request_XISelectEvents_masks(xXISelectEventsReq *req) request_XISelectEvent(req, Success); /* Test 1: - * mask may be larger than needed for XI_LASTEVENT. + * mask may be larger than needed for XI2LASTEVENT. * Test setting each valid mask bit, while leaving unneeded bits 0. * -> Success */ bits = (unsigned char*)&mask[1]; mask->mask_len = (nmasks + 3)/4 * 10; memset(bits, 0, mask->mask_len * 4); - for (j = 0; j <= XI_LASTEVENT; j++) + for (j = 0; j <= XI2LASTEVENT; j++) { SetBit(bits, j); request_XISelectEvent(req, Success); @@ -165,7 +165,7 @@ static void request_XISelectEvents_masks(xXISelectEventsReq *req) } /* Test 2: - * mask may be larger than needed for XI_LASTEVENT. + * mask may be larger than needed for XI2LASTEVENT. * Test setting all valid mask bits, while leaving unneeded bits 0. * -> Success */ @@ -173,21 +173,21 @@ static void request_XISelectEvents_masks(xXISelectEventsReq *req) mask->mask_len = (nmasks + 3)/4 * 10; memset(bits, 0, mask->mask_len * 4); - for (j = 0; j <= XI_LASTEVENT; j++) + for (j = 0; j <= XI2LASTEVENT; j++) { SetBit(bits, j); request_XISelectEvent(req, Success); } /* Test 3: - * mask is larger than needed for XI_LASTEVENT. If any unneeded bit + * mask is larger than needed for XI2LASTEVENT. If any unneeded bit * is set -> BadValue */ bits = (unsigned char*)&mask[1]; mask->mask_len = (nmasks + 3)/4 * 10; memset(bits, 0, mask->mask_len * 4); - for (j = XI_LASTEVENT + 1; j < mask->mask_len * 4; j++) + for (j = XI2LASTEVENT + 1; j < mask->mask_len * 4; j++) { SetBit(bits, j); request_XISelectEvent(req, BadValue); @@ -200,7 +200,7 @@ static void request_XISelectEvents_masks(xXISelectEventsReq *req) bits = (unsigned char*)&mask[1]; mask->mask_len = (nmasks + 3)/4; memset(bits, 0, mask->mask_len * 4); - for (j = 0; j <= XI_LASTEVENT; j++) + for (j = 0; j <= XI2LASTEVENT; j++) { SetBit(bits, j); request_XISelectEvent(req, Success); @@ -228,7 +228,7 @@ static void request_XISelectEvents_masks(xXISelectEventsReq *req) bits = (unsigned char*)&mask[1]; mask->mask_len = (nmasks + 3)/4; memset(bits, 0, mask->mask_len * 4); - for (j = 0; j <= XI_LASTEVENT; j++) + for (j = 0; j <= XI2LASTEVENT; j++) SetBit(bits, j); ClearBit(bits, XI_HierarchyChanged); for (j = 1; j < 6; j++) From 23c37ce1fe42e3da0609a566478e947843b05023 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Mon, 27 Dec 2010 12:48:42 +0000 Subject: [PATCH 05/17] Input: Export SpriteRec for use in public API Change its definition to be more in line with other structs, so we can use it from input.h. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer Reviewed-by: Chase Douglas --- include/input.h | 1 + include/inputstr.h | 82 +++++++++++++++++++++++----------------------- 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/include/input.h b/include/input.h index 9f3227fb0..76f646f39 100644 --- a/include/input.h +++ b/include/input.h @@ -103,6 +103,7 @@ typedef struct _OtherClients *OtherClientsPtr; typedef struct _InputClients *InputClientsPtr; typedef struct _DeviceIntRec *DeviceIntPtr; typedef struct _ClassesRec *ClassesPtr; +typedef struct _SpriteRec *SpritePtr; typedef union _GrabMask GrabMask; typedef struct _EventList { diff --git a/include/inputstr.h b/include/inputstr.h index 44de9c44a..b74ee0454 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -203,6 +203,47 @@ typedef struct _GrabRec { unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE]; } GrabRec; +/** + * Sprite information for a device. + */ +typedef struct _SpriteRec { + CursorPtr current; + BoxRec hotLimits; /* logical constraints of hot spot */ + Bool confined; /* confined to screen */ + RegionPtr hotShape; /* additional logical shape constraint */ + BoxRec physLimits; /* physical constraints of hot spot */ + WindowPtr win; /* window of logical position */ + HotSpot hot; /* logical pointer position */ + HotSpot hotPhys; /* physical pointer position */ +#ifdef PANORAMIX + ScreenPtr screen; /* all others are in Screen 0 coordinates */ + RegionRec Reg1; /* Region 1 for confining motion */ + RegionRec Reg2; /* Region 2 for confining virtual motion */ + WindowPtr windows[MAXSCREENS]; + WindowPtr confineWin; /* confine window */ +#endif + /* The window trace information is used at dix/events.c to avoid having + * to compute all the windows between the root and the current pointer + * window each time a button or key goes down. The grabs on each of those + * windows must be checked. + * spriteTraces should only be used at dix/events.c! */ + WindowPtr *spriteTrace; + int spriteTraceSize; + int spriteTraceGood; + + /* Due to delays between event generation and event processing, it is + * possible that the pointer has crossed screen boundaries between the + * time in which it begins generating events and the time when + * those events are processed. + * + * pEnqueueScreen: screen the pointer was on when the event was generated + * pDequeueScreen: screen the pointer was on when the event is processed + */ + ScreenPtr pEnqueueScreen; + ScreenPtr pDequeueScreen; + +} SpriteRec; + typedef struct _KeyClassRec { int sourceid; CARD8 down[DOWN_LENGTH]; @@ -360,47 +401,6 @@ typedef struct _ClassesRec { } ClassesRec; -/** - * Sprite information for a device. - */ -typedef struct { - CursorPtr current; - BoxRec hotLimits; /* logical constraints of hot spot */ - Bool confined; /* confined to screen */ - RegionPtr hotShape; /* additional logical shape constraint */ - BoxRec physLimits; /* physical constraints of hot spot */ - WindowPtr win; /* window of logical position */ - HotSpot hot; /* logical pointer position */ - HotSpot hotPhys; /* physical pointer position */ -#ifdef PANORAMIX - ScreenPtr screen; /* all others are in Screen 0 coordinates */ - RegionRec Reg1; /* Region 1 for confining motion */ - RegionRec Reg2; /* Region 2 for confining virtual motion */ - WindowPtr windows[MAXSCREENS]; - WindowPtr confineWin; /* confine window */ -#endif - /* The window trace information is used at dix/events.c to avoid having - * to compute all the windows between the root and the current pointer - * window each time a button or key goes down. The grabs on each of those - * windows must be checked. - * spriteTraces should only be used at dix/events.c! */ - WindowPtr *spriteTrace; - int spriteTraceSize; - int spriteTraceGood; - - /* Due to delays between event generation and event processing, it is - * possible that the pointer has crossed screen boundaries between the - * time in which it begins generating events and the time when - * those events are processed. - * - * pEnqueueScreen: screen the pointer was on when the event was generated - * pDequeueScreen: screen the pointer was on when the event is processed - */ - ScreenPtr pEnqueueScreen; - ScreenPtr pDequeueScreen; - -} SpriteRec, *SpritePtr; - /* Device properties */ typedef struct _XIPropertyValue { From 10d6c3ca103ea155488cd2f29052334b5691e680 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Mon, 27 Dec 2010 13:06:03 +0000 Subject: [PATCH 06/17] Input: Make RootWindow() take a sprite instead of device GetCurrentRootWindow already works for the device case, although not as an lvalue. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer Reviewed-by: Chase Douglas --- dix/events.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/dix/events.c b/dix/events.c index f280f9d7a..c24d77240 100644 --- a/dix/events.c +++ b/dix/events.c @@ -256,7 +256,7 @@ EventSyncInfoRec syncEvents; /** * The root window the given device is currently on. */ -#define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0] +#define RootWindow(sprite) sprite->spriteTrace[0] static xEvent* swapEvent = NULL; static int swapEventLen = 0; @@ -879,7 +879,7 @@ CheckVirtualMotion( #ifdef PANORAMIX if (noPanoramiXExtension) /* No typo. Only set the root win if disabled */ #endif - RootWindow(pDev) = pSprite->hot.pScreen->root; + RootWindow(pDev->spriteInfo->sprite) = pSprite->hot.pScreen->root; } static void @@ -1012,7 +1012,7 @@ PostNewCursor(DeviceIntPtr pDev) WindowPtr GetCurrentRootWindow(DeviceIntPtr dev) { - return RootWindow(dev); + return RootWindow(dev->spriteInfo->sprite); } /** @@ -1511,7 +1511,7 @@ DeactivatePointerGrab(DeviceIntPtr mouse) DoEnterLeaveEvents(mouse, mouse->id, grab->window, mouse->spriteInfo->sprite->win, NotifyUngrab); if (grab->confineTo) - ConfineCursorToWindow(mouse, RootWindow(mouse), FALSE, FALSE); + ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE); PostNewCursor(mouse); if (grab->cursor) FreeCursor(grab->cursor, (Cursor)0); @@ -2247,7 +2247,7 @@ FixUpEventFromWindow( event->evtype == XI_PropertyEvent) return; - event->root = RootWindow(pDev)->drawable.id; + event->root = GetCurrentRootWindow(pDev)->drawable.id; event->event = pWin->drawable.id; if (pSprite->hot.pScreen == pWin->drawable.pScreen) { @@ -2268,7 +2268,7 @@ FixUpEventFromWindow( } else { - XE_KBPTR.root = RootWindow(pDev)->drawable.id; + XE_KBPTR.root = GetCurrentRootWindow(pDev)->drawable.id; XE_KBPTR.event = pWin->drawable.id; if (pSprite->hot.pScreen == pWin->drawable.pScreen) { @@ -2564,7 +2564,7 @@ XYToWindow(DeviceIntPtr pDev, int x, int y) pSprite = pDev->spriteInfo->sprite; pSprite->spriteTraceGood = 1; /* root window still there */ - pWin = RootWindow(pDev)->firstChild; + pWin = GetCurrentRootWindow(pDev)->firstChild; while (pWin) { if ((pWin->mapped) && @@ -2737,7 +2737,8 @@ CheckMotion(DeviceEvent *ev, DeviceIntPtr pDev) if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen) { pSprite->hot.pScreen = pSprite->hotPhys.pScreen; - RootWindow(pDev) = pSprite->hot.pScreen->root; + RootWindow(pDev->spriteInfo->sprite) = + pSprite->hot.pScreen->root; } } @@ -2942,7 +2943,7 @@ InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin) FatalError("Failed to allocate spriteTrace"); pSprite->spriteTraceSize = 32; - RootWindow(pDev) = pWin; + RootWindow(pDev->spriteInfo->sprite) = pWin; pSprite->spriteTraceGood = 1; pSprite->pEnqueueScreen = pScreen; @@ -4554,7 +4555,8 @@ ProcGrabPointer(ClientPtr client) if (grab) { if (grab->confineTo && !confineTo) - ConfineCursorToWindow(device, RootWindow(device), FALSE, FALSE); + ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE, + FALSE); oldCursor = grab->cursor; } @@ -4883,7 +4885,7 @@ ProcQueryPointer(ClientPtr client) rep.mask = mouse->button ? (mouse->button->state) : 0; rep.mask |= XkbStateFieldFromRec(&keyboard->key->xkbInfo->state); rep.length = 0; - rep.root = (RootWindow(mouse))->drawable.id; + rep.root = (GetCurrentRootWindow(mouse))->drawable.id; rep.rootX = pSprite->hot.x; rep.rootY = pSprite->hot.y; rep.child = None; @@ -5042,7 +5044,7 @@ ProcSendEvent(ClientPtr client) /* If the input focus is PointerRootWin, send the event to where the pointer is if possible, then perhaps propogate up to root. */ if (inputFocus == PointerRootWin) - inputFocus = RootWindow(dev); + inputFocus = GetCurrentRootWindow(dev); if (IsParent(inputFocus, pSprite->win)) { From 07a892cd8276f8092de95f1909f2ebec6f5fdf08 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Mon, 20 Sep 2010 15:03:04 +1000 Subject: [PATCH 07/17] Input: Pass sprite instead of device to FixUpEventFromWindow Since FixUpEventFromWindow only uses the sprite trace to determine the window stack, pass in a sprite instead of hardcoding the device sprite, so we can deliver to windows other than the one currently containing the sprite. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer Reviewed-by: Chase Douglas --- Xi/exevents.c | 3 ++- dix/events.c | 43 +++++++++++++++++++++---------------------- include/input.h | 2 +- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 8615fd456..327873e29 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -1261,7 +1261,8 @@ DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, xi2event->group.effective_group = dev->key->xkbInfo->state.group; } - FixUpEventFromWindow(dev, (xEvent*)xi2event, pWin, None, FALSE); + FixUpEventFromWindow(dev->spriteInfo->sprite, (xEvent*)xi2event, pWin, + None, FALSE); DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1, GetEventFilter(dev, (xEvent*)xi2event), NullGrab); diff --git a/dix/events.c b/dix/events.c index c24d77240..df59a4e61 100644 --- a/dix/events.c +++ b/dix/events.c @@ -2181,9 +2181,8 @@ MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, return 2; } -static Window FindChildForEvent(DeviceIntPtr dev, WindowPtr event) +static Window FindChildForEvent(SpritePtr pSprite, WindowPtr event) { - SpritePtr pSprite = dev->spriteInfo->sprite; WindowPtr w = pSprite->spriteTrace[pSprite->spriteTraceGood-1]; Window child = None; @@ -2222,16 +2221,14 @@ static Window FindChildForEvent(DeviceIntPtr dev, WindowPtr event) */ void FixUpEventFromWindow( - DeviceIntPtr pDev, + SpritePtr pSprite, xEvent *xE, WindowPtr pWin, Window child, Bool calcChild) { - SpritePtr pSprite = pDev->spriteInfo->sprite; - if (calcChild) - child = FindChildForEvent(pDev, pWin); + child = FindChildForEvent(pSprite, pWin); if (XI2_EVENT(xE)) { @@ -2247,7 +2244,7 @@ FixUpEventFromWindow( event->evtype == XI_PropertyEvent) return; - event->root = GetCurrentRootWindow(pDev)->drawable.id; + event->root = RootWindow(pSprite)->drawable.id; event->event = pWin->drawable.id; if (pSprite->hot.pScreen == pWin->drawable.pScreen) { @@ -2268,7 +2265,7 @@ FixUpEventFromWindow( } else { - XE_KBPTR.root = GetCurrentRootWindow(pDev)->drawable.id; + XE_KBPTR.root = RootWindow(pSprite)->drawable.id; XE_KBPTR.event = pWin->drawable.id; if (pSprite->hot.pScreen == pWin->drawable.pScreen) { @@ -2374,6 +2371,7 @@ int DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, WindowPtr stopAt, DeviceIntPtr dev) { + SpritePtr pSprite = dev->spriteInfo->sprite; Window child = None; Mask filter; int deliveries = 0; @@ -2396,7 +2394,7 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, { /* XXX: XACE */ filter = GetEventFilter(dev, xi2); - FixUpEventFromWindow(dev, xi2, pWin, child, FALSE); + FixUpEventFromWindow(pSprite, xi2, pWin, child, FALSE); deliveries = DeliverEventsToWindow(dev, pWin, xi2, 1, filter, grab); free(xi2); @@ -2414,7 +2412,7 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, if (rc == Success) { if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count) == Success) { filter = GetEventFilter(dev, xE); - FixUpEventFromWindow(dev, xE, pWin, child, FALSE); + FixUpEventFromWindow(pSprite, xE, pWin, child, FALSE); deliveries = DeliverEventsToWindow(dev, pWin, xE, count, filter, grab); if (deliveries > 0) @@ -2432,7 +2430,7 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, if (rc == Success) { if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, &core, 1) == Success) { filter = GetEventFilter(dev, &core); - FixUpEventFromWindow(dev, &core, pWin, child, FALSE); + FixUpEventFromWindow(pSprite, &core, pWin, child, FALSE); deliveries = DeliverEventsToWindow(dev, pWin, &core, 1, filter, grab); if (deliveries > 0) @@ -3368,6 +3366,7 @@ CheckPassiveGrabsOnWindow( DeviceEvent *event, BOOL checkCore) { + SpritePtr pSprite = device->spriteInfo->sprite; GrabPtr grab = wPassiveGrabs(pWin); GrabRec tempGrab; GrabInfoPtr grabinfo; @@ -3531,7 +3530,7 @@ CheckPassiveGrabsOnWindow( if (xE) { - FixUpEventFromWindow(device, xE, grab->window, None, TRUE); + FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE); TryClientEvents(rClient(grab), device, xE, count, GetEventFilter(device, xE), @@ -3683,7 +3682,7 @@ DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window) { /* XXX: XACE */ int filter = GetEventFilter(keybd, xi2); - FixUpEventFromWindow(ptr, xi2, focus, None, FALSE); + FixUpEventFromWindow(ptr->spriteInfo->sprite, xi2, focus, None, FALSE); deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1, filter, NullGrab); if (deliveries > 0) @@ -3696,7 +3695,7 @@ DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window) if (rc == Success && XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success) { - FixUpEventFromWindow(ptr, xE, focus, None, FALSE); + FixUpEventFromWindow(ptr->spriteInfo->sprite, xE, focus, None, FALSE); deliveries = DeliverEventsToWindow(keybd, focus, xE, count, GetEventFilter(keybd, xE), NullGrab); @@ -3712,7 +3711,8 @@ DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window) rc = EventToCore(event, &core); if (rc == Success) { if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, &core, 1) == Success) { - FixUpEventFromWindow(keybd, &core, focus, None, FALSE); + FixUpEventFromWindow(keybd->spriteInfo->sprite, &core, focus, + None, FALSE); deliveries = DeliverEventsToWindow(keybd, focus, &core, 1, GetEventFilter(keybd, &core), NullGrab); @@ -3802,8 +3802,7 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev, rc = EventToCore(event, &core); if (rc == Success) { - FixUpEventFromWindow(thisDev, &core, grab->window, - None, TRUE); + FixUpEventFromWindow(pSprite, &core, grab->window, None, TRUE); if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, grab->window, &core, 1) || XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), @@ -3830,7 +3829,7 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev, grab->xi2mask[XIAllMasterDevices][evtype/8] | grab->xi2mask[thisDev->id][evtype/8]; /* try XI2 event */ - FixUpEventFromWindow(thisDev, xi2, grab->window, None, TRUE); + FixUpEventFromWindow(pSprite, xi2, grab->window, None, TRUE); /* XXX: XACE */ deliveries = TryClientEvents(rClient(grab), thisDev, xi2, 1, mask, GetEventFilter(thisDev, xi2), grab); @@ -3851,8 +3850,7 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev, else mask = grab->eventMask; - FixUpEventFromWindow(thisDev, xi, grab->window, - None, TRUE); + FixUpEventFromWindow(pSprite, xi, grab->window, None, TRUE); if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, grab->window, xi, count) || @@ -4198,7 +4196,7 @@ CoreEnterLeaveEvent( event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x; event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y; /* Counts on the same initial structure of crossing & button events! */ - FixUpEventFromWindow(mouse, &event, pWin, None, FALSE); + FixUpEventFromWindow(mouse->spriteInfo->sprite, &event, pWin, None, FALSE); /* Enter/Leave events always set child */ event.u.enterLeave.child = child; event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? @@ -4298,7 +4296,8 @@ DeviceEnterLeaveEvent( event->group.locked_group = kbd->key->xkbInfo->state.locked_group; } - FixUpEventFromWindow(mouse, (xEvent*)event, pWin, None, FALSE); + FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent*)event, pWin, + None, FALSE); filter = GetEventFilter(mouse, (xEvent*)event); diff --git a/include/input.h b/include/input.h index 76f646f39..a20f8a07a 100644 --- a/include/input.h +++ b/include/input.h @@ -528,7 +528,7 @@ extern _X_EXPORT void FreeInputAttributes(InputAttributes *attrs); /* misc event helpers */ extern Mask GetEventFilter(DeviceIntPtr dev, xEvent *event); extern Mask GetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev); -void FixUpEventFromWindow(DeviceIntPtr pDev, +void FixUpEventFromWindow(SpritePtr pSprite, xEvent *xE, WindowPtr pWin, Window child, From 690476250f58616d5156317e01ba547497f4331a Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Mon, 20 Sep 2010 15:03:05 +1000 Subject: [PATCH 08/17] Input: Pass sprite instead of device to XYToWindow, make non-static XYToWindow calculates the position of the cursor and updates the sprite trace, but does nothing else with the device. Pass a SpritePtr instead so we can update an alternate focus instead of hardcoding the device's sprite. Also make this function non-static, so we can use it elsewhere. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer Reviewed-by: Chase Douglas --- dix/events.c | 19 ++++++------------- include/input.h | 1 + 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/dix/events.c b/dix/events.c index df59a4e61..29033e2e5 100644 --- a/dix/events.c +++ b/dix/events.c @@ -332,12 +332,6 @@ IsMaster(DeviceIntPtr dev) return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD; } -static WindowPtr XYToWindow( - DeviceIntPtr pDev, - int x, - int y -); - /** * Max event opcode. */ @@ -1290,7 +1284,8 @@ ComputeFreezes(void) syncEvents.replayDev = (DeviceIntPtr)NULL; - w = XYToWindow(replayDev, event->root_x, event->root_y); + w = XYToWindow(replayDev->spriteInfo->sprite, + event->root_x, event->root_y); if (!CheckDeviceGrabs(replayDev, event, syncEvents.replayWin)) { if (replayDev->focus && !IsPointerEvent((InternalEvent*)event)) @@ -2553,16 +2548,14 @@ PointInBorderSize(WindowPtr pWin, int x, int y) * * @returns the window at the given coordinates. */ -static WindowPtr -XYToWindow(DeviceIntPtr pDev, int x, int y) +WindowPtr +XYToWindow(SpritePtr pSprite, int x, int y) { WindowPtr pWin; BoxRec box; - SpritePtr pSprite; - pSprite = pDev->spriteInfo->sprite; pSprite->spriteTraceGood = 1; /* root window still there */ - pWin = GetCurrentRootWindow(pDev)->firstChild; + pWin = RootWindow(pSprite)->firstChild; while (pWin) { if ((pWin->mapped) && @@ -2775,7 +2768,7 @@ CheckMotion(DeviceEvent *ev, DeviceIntPtr pDev) ev->root_y = pSprite->hot.y; } - newSpriteWin = XYToWindow(pDev, pSprite->hot.x, pSprite->hot.y); + newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y); if (newSpriteWin != prevSpriteWin) { diff --git a/include/input.h b/include/input.h index a20f8a07a..c1db5444f 100644 --- a/include/input.h +++ b/include/input.h @@ -533,6 +533,7 @@ void FixUpEventFromWindow(SpritePtr pSprite, WindowPtr pWin, Window child, Bool calcChild); +extern WindowPtr XYToWindow(SpritePtr pSprite, int x, int y); extern int EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win); /** From 30c8c7a86310139e79c9698caee21b3bd51936bd Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Tue, 28 Dec 2010 12:13:29 +0000 Subject: [PATCH 09/17] Input: Handle grabs with no Xi 1.x equivalent Don't try to search for an Xi 1.x grab in CheckPassiveGrabsOnWindow for events with no Xi 1.x equivalent. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer Reviewed-by: Chase Douglas --- dix/events.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dix/events.c b/dix/events.c index 29033e2e5..45d9eabea 100644 --- a/dix/events.c +++ b/dix/events.c @@ -3415,9 +3415,9 @@ CheckPassiveGrabsOnWindow( tempGrab.detail.exact = event->detail.key; if (!match) { - tempGrab.type = GetXIType((InternalEvent*)event); tempGrab.grabtype = GRABTYPE_XI; - if (GrabMatchesSecond(&tempGrab, grab, FALSE)) + if ((tempGrab.type = GetXIType((InternalEvent*)event)) && + (GrabMatchesSecond(&tempGrab, grab, FALSE))) match = XI_MATCH; } From eb5aaf5eb819f1287ce40da79edbe07bafb2b5c0 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Tue, 28 Dec 2010 12:15:28 +0000 Subject: [PATCH 10/17] Input: Export GetEventMask Make it non-static, add to headers. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer Reviewed-by: Chase Douglas --- dix/events.c | 2 +- include/input.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/dix/events.c b/dix/events.c index 45d9eabea..ff6e008ec 100644 --- a/dix/events.c +++ b/dix/events.c @@ -439,7 +439,7 @@ GetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev) (inputMasks->xi2mask[XIAllMasterDevices][evtype/8] && IsMaster(dev))); } -static Mask +Mask GetEventMask(DeviceIntPtr dev, xEvent *event, InputClients* other) { /* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */ diff --git a/include/input.h b/include/input.h index c1db5444f..56992d134 100644 --- a/include/input.h +++ b/include/input.h @@ -526,6 +526,7 @@ extern _X_EXPORT InputAttributes *DuplicateInputAttributes(InputAttributes *attr extern _X_EXPORT void FreeInputAttributes(InputAttributes *attrs); /* misc event helpers */ +extern Mask GetEventMask(DeviceIntPtr dev, xEvent* ev, InputClientsPtr clients); extern Mask GetEventFilter(DeviceIntPtr dev, xEvent *event); extern Mask GetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev); void FixUpEventFromWindow(SpritePtr pSprite, From ce74e7562dcc800306ff92b6d3c5ee885cd4763d Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Tue, 7 Dec 2010 11:48:14 +0000 Subject: [PATCH 11/17] Input: Make CheckPassiveGrabsOnWindow return grab, export Change CheckPassiveGrabsOnWindow to return the GrabPtr it used (or NULL if none) rather than a boolean, and export it. Also add an additional boolean 'activate' parameter; use TRUE for existing behaviour, or FALSE to only find the grab and then return it. This will be used in forthcoming touch patches to find the grabs, rather than open-coding same. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- dix/events.c | 30 +++++++++++++++--------------- include/dix.h | 7 +++++++ 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/dix/events.c b/dix/events.c index ff6e008ec..4daed1403 100644 --- a/dix/events.c +++ b/dix/events.c @@ -209,10 +209,6 @@ static void CheckPhysLimits(DeviceIntPtr pDev, Bool generateEvents, Bool confineToScreen, ScreenPtr pScreen); -static Bool CheckPassiveGrabsOnWindow(WindowPtr pWin, - DeviceIntPtr device, - DeviceEvent *event, - BOOL checkCore); /** Key repeat hack. Do not use but in TryClientEvents */ extern BOOL EventIsKeyRepeat(xEvent *event); @@ -2633,7 +2629,7 @@ ActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) event.deviceid = dev->id; event.sourceid = dev->id; event.detail.button = 0; - rc = CheckPassiveGrabsOnWindow(win, dev, &event, FALSE); + rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, TRUE) != NULL); if (rc) DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); return rc; @@ -2670,10 +2666,9 @@ ActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) event.deviceid = dev->id; event.sourceid = dev->id; event.detail.button = 0; - rc = CheckPassiveGrabsOnWindow(win, dev, &event, FALSE); + rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, TRUE) != NULL); if (rc) DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab); - return rc; } @@ -3344,20 +3339,23 @@ BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin) /** * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a * passive grab set on the window to be activated. - * If a passive grab is activated, the event will be delivered to the client. + * If activate is true and a passive grab is found, it will be activated, + * and the event will be delivered to the client. * * @param pWin The window that may be subject to a passive grab. * @param device Device that caused the event. * @param event The current device event. * @param checkCore Check for core grabs too. + * @param activate If a grab is found, activate it and deliver the event. */ -static Bool +GrabPtr CheckPassiveGrabsOnWindow( WindowPtr pWin, DeviceIntPtr device, DeviceEvent *event, - BOOL checkCore) + BOOL checkCore, + BOOL activate) { SpritePtr pSprite = device->spriteInfo->sprite; GrabPtr grab = wPassiveGrabs(pWin); @@ -3369,7 +3367,7 @@ CheckPassiveGrabsOnWindow( int match = 0; if (!grab) - return FALSE; + return NULL; /* Fill out the grab details, but leave the type for later before * comparing */ tempGrab.window = pWin; @@ -3483,6 +3481,8 @@ CheckPassiveGrabsOnWindow( continue; } + if (!activate) + return grab; if (match & CORE_MATCH) { @@ -3540,10 +3540,10 @@ CheckPassiveGrabsOnWindow( if (match & (XI_MATCH | XI2_MATCH)) free(xE); /* on core match xE == &core */ - return TRUE; + return grab; } } - return FALSE; + return NULL; #undef CORE_MATCH #undef XI_MATCH #undef XI2_MATCH @@ -3609,7 +3609,7 @@ CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor) for (; i < focus->traceGood; i++) { pWin = focus->trace[i]; - if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore)) + if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore, TRUE)) return TRUE; } @@ -3622,7 +3622,7 @@ CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor) for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) { pWin = device->spriteInfo->sprite->spriteTrace[i]; - if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore)) + if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore, TRUE)) return TRUE; } diff --git a/include/dix.h b/include/dix.h index 7485e8ed4..12e4b5977 100644 --- a/include/dix.h +++ b/include/dix.h @@ -372,6 +372,13 @@ extern void AllowSome( extern void ReleaseActiveGrabs( ClientPtr client); +extern GrabPtr CheckPassiveGrabsOnWindow( + WindowPtr /* pWin */, + DeviceIntPtr /* device */, + DeviceEvent * /* event */, + BOOL /* checkCore */, + BOOL /* activate */); + extern _X_EXPORT int DeliverEventsToWindow( DeviceIntPtr /* pWin */, WindowPtr /* pWin */, From 4fbadc8b17237f3c7f8c0bf56003d1139c86655e Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Thu, 6 Jan 2011 11:32:26 +1000 Subject: [PATCH 12/17] Input: Prevent MD grabs from wandering on to other MDs The code to set sync.other in DeliverGrabbedEvents is supposed to reset sync.other for a paired MD to the grab under consideration, but was rather optimistic in resetting sync.other for _all_ devices. This would fall apart given two sets of MDs (A paired with B, Y paired with Z), where both MDs were in FREEZE_BOTH_NEXT_EVENT due to being called with SyncBoth, where no event had yet triggered the grab. An event being processed on MD A would result in B, Y and Z all having sync.other set to A's grab, rather than just B. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- dix/events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dix/events.c b/dix/events.c index f280f9d7a..c1cce92d1 100644 --- a/dix/events.c +++ b/dix/events.c @@ -3889,7 +3889,7 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev, (CLIENT_BITS(grab->resource) == CLIENT_BITS(dev->deviceGrab.grab->resource))) dev->deviceGrab.sync.state = FROZEN_NO_EVENT; - else + else if (GetPairedDevice(thisDev) == dev) dev->deviceGrab.sync.other = grab; } /* fall through */ From fc6cbee772bafabf7ddd7a75043bd55bb78ad09e Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 6 Jan 2011 12:58:00 +1000 Subject: [PATCH 13/17] input: add valuator_mask_free() to free a valuator mask. Expecting the caller to free the mask requires us to keep it in a single memory block (which may be an issue lateron), aside from leaving the API asymetrical. Provide valuator_mask_free() to free the memory and reset the mask pointer to NULL. Signed-off-by: Peter Hutterer Reviewed-by: Fernando Carrijo Reviewed-by: Chase Douglas --- dix/inpututils.c | 8 ++++++++ include/input.h | 1 + test/input.c | 3 ++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/dix/inpututils.c b/dix/inpututils.c index 2877804d6..ef3142c84 100644 --- a/dix/inpututils.c +++ b/dix/inpututils.c @@ -433,6 +433,14 @@ valuator_mask_new(int num_valuators) return mask; } +void +valuator_mask_free(ValuatorMask **mask) +{ + free(*mask); + *mask = NULL; +} + + /** * Sets a range of valuators between first_valuator and num_valuators with * the data in the valuators array. All other values are set to 0. diff --git a/include/input.h b/include/input.h index 9f3227fb0..412150c0f 100644 --- a/include/input.h +++ b/include/input.h @@ -567,6 +567,7 @@ extern _X_HIDDEN void valuator_set_mode(DeviceIntPtr dev, int axis, int mode); extern Bool EnableCursor; extern _X_EXPORT ValuatorMask *valuator_mask_new(int num_valuators); +extern _X_EXPORT void valuator_mask_free(ValuatorMask **mask); extern _X_EXPORT void valuator_mask_set_range(ValuatorMask *mask, int first_valuator, int num_valuators, const int* valuators); diff --git a/test/input.c b/test/input.c index 1fe228c32..39d0badf9 100644 --- a/test/input.c +++ b/test/input.c @@ -1017,7 +1017,8 @@ static void dix_input_valuator_masks(void) g_assert(valuator_mask_get(mask, i) == valuator_mask_get(copy, i)); } - free(mask); + valuator_mask_free(&mask); + g_assert(mask == NULL); } static void dix_valuator_mode(void) From aa30a86583c3fc1a83c46e8c7583182d750edcde Mon Sep 17 00:00:00 2001 From: Tomas Carnecky Date: Sun, 1 Aug 2010 21:28:18 +0200 Subject: [PATCH 14/17] NO_PANORAMIX preprocessor symbol is nowhere defined Which makes it useless, so remove it. Signed-off-by: Tomas Carnecky Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- mi/miinitext.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/mi/miinitext.c b/mi/miinitext.c index a7441c9a8..4499f377c 100644 --- a/mi/miinitext.c +++ b/mi/miinitext.c @@ -389,9 +389,7 @@ InitExtensions(int argc, char *argv[]) if (!noGEExtension) GEExtensionInit(); #ifdef PANORAMIX -# if !defined(NO_PANORAMIX) if (!noPanoramiXExtension) PanoramiXExtensionInit(); -# endif #endif #ifdef INXQUARTZ if(!noPseudoramiXExtension) PseudoramiXExtensionInit(); From 16eb4f2a7b67ee169785973f9e0a3773e13fdea6 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 7 Jan 2011 09:53:35 +1000 Subject: [PATCH 15/17] Xi: reset remainders when warping the device. Signed-off-by: Peter Hutterer Reviewed-by: Daniel Stone Reviewed-by: Chase Douglas Reviewed-by: Simon Thum --- Xi/xiwarppointer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Xi/xiwarppointer.c b/Xi/xiwarppointer.c index 7276e6faf..c01b115f3 100644 --- a/Xi/xiwarppointer.c +++ b/Xi/xiwarppointer.c @@ -192,6 +192,8 @@ ProcXIWarpPointer(ClientPtr client) /* if we don't update the device, we get a jump next time it moves */ pDev->last.valuators[0] = x; pDev->last.valuators[1] = y; + pDev->last.remainder[0] = 0; + pDev->last.remainder[1] = 0; miPointerUpdateSprite(pDev); /* FIXME: XWarpPointer is supposed to generate an event. It doesn't do it From f1326ed2910bd985fafdb48714b1d6f38116b083 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 13 Jan 2011 09:19:28 +1000 Subject: [PATCH 16/17] xkb: Replace a few manual bitflips with SetBit & friends. Signed-off-by: Peter Hutterer Reviewed-by: Dirk Wallenstein --- xkb/XKBMisc.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/xkb/XKBMisc.c b/xkb/XKBMisc.c index efe291103..96688be18 100644 --- a/xkb/XKBMisc.c +++ b/xkb/XKBMisc.c @@ -454,11 +454,12 @@ unsigned changed,tmp; } if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) { CARD8 old; - old= xkb->ctrls->per_key_repeat[key/8]; + old= BitIsOn(xkb->ctrls->per_key_repeat, key); if (interps[0]->flags&XkbSI_AutoRepeat) - xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8)); - else xkb->ctrls->per_key_repeat[key/8]&= ~(1<<(key%8)); - if (changes && (old!=xkb->ctrls->per_key_repeat[key/8])) + SetBit(xkb->ctrls->per_key_repeat, key); + else + ClearBit(xkb->ctrls->per_key_repeat, key); + if (changes && old != BitIsOn(xkb->ctrls->per_key_repeat, key)) changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask; } } @@ -466,9 +467,9 @@ unsigned changed,tmp; if ((!found)||(interps[0]==NULL)) { if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) { CARD8 old; - old= xkb->ctrls->per_key_repeat[key/8]; - xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8)); - if (changes && (old!=xkb->ctrls->per_key_repeat[key/8])) + old = BitIsOn(xkb->ctrls->per_key_repeat, key); + SetBit(xkb->ctrls->per_key_repeat, key); + if (changes && (old != BitIsOn(xkb->ctrls->per_key_repeat, key))) changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask; } if (((explicit&XkbExplicitBehaviorMask)==0)&& From 64237697994871adfcf4905b5784e75cd7281579 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 13 Jan 2011 12:20:38 +1000 Subject: [PATCH 17/17] xkb: after making changes to the xkb ctrls, copy them back into kbdfeed. enabled_ctrls_changes nowhere near the usual event or config paths. So this condition always evaluated to false and the memcpy would thus never been hit. As a result, any modification to the XKB struct during XkbUpdateDescActions was not reflected in the kbdfeed ctrls. The flag that is set by XkbUpdateDescActions() if ctrls were changed are in enabled_ctrls. This mainly affected keyboard repeat control as XKB uses the kbdfeed ctrls, not XKB's per_key_repeats, to determine if a key needs to be repeated. Thus, adding a "repeat= False" to the XKB map of any action did not have any effect. Test case: assign Mode_switch to any key that by default repeats, e.g. the menu key. key { [ Mode_switch ] }; Then modify the Mode_switch action to not repeat the key. interpret Mode_switch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= SetGroup(group=+1); // Add this line repeat= False; }; Though the flags are correctly reflected in the description loaded in the server, the change is not handed back to the kbdfeed struct and XKB will trigger softrepeats of this key. This patch also adds two explanatory comments and an extra check, as this path may be hit before the CtrlProc for the kbdfeed struct is set. Red Hat Bug 537708 Also fixes broken auto-repeat of the backspace key in the colemak layout (mapped to CapsLock). X.Org Bug 16318 Signed-off-by: Peter Hutterer Tested-by: Dirk Wallenstein Reviewed-by: Dirk Wallenstein Reviewed-by: Daniel Stone --- xkb/xkbUtils.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c index 14dc784b8..3a56bea4c 100644 --- a/xkb/xkbUtils.c +++ b/xkb/xkbUtils.c @@ -342,15 +342,18 @@ CARD8 * repeat; xkb= xkbi->desc; repeat= xkb->ctrls->per_key_repeat; + /* before letting XKB do any changes, copy the current core values */ if (pXDev->kbdfeed) memcpy(repeat,pXDev->kbdfeed->ctrl.autoRepeats,XkbPerKeyBitArraySize); XkbUpdateDescActions(xkb,first,num,changes); if ((pXDev->kbdfeed)&& - (changes->ctrls.enabled_ctrls_changes&XkbPerKeyRepeatMask)) { - memcpy(pXDev->kbdfeed->ctrl.autoRepeats,repeat, XkbPerKeyBitArraySize); - (*pXDev->kbdfeed->CtrlProc)(pXDev, &pXDev->kbdfeed->ctrl); + (changes->ctrls.changed_ctrls&XkbPerKeyRepeatMask)) { + /* now copy the modified changes back to core */ + memcpy(pXDev->kbdfeed->ctrl.autoRepeats,repeat, XkbPerKeyBitArraySize); + if (pXDev->kbdfeed->CtrlProc) + (*pXDev->kbdfeed->CtrlProc)(pXDev, &pXDev->kbdfeed->ctrl); } return; }