From 51239f87ce42ad564ceee1761980391947294511 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 13 Nov 2007 11:26:16 +1030 Subject: [PATCH] dix: Send MappingNotify when keyboard maps change. If a slave device is attached to a master device, then we need to send a mapping notify to the client. Mapping notify needs to be sent if - different slave device but on same master - different master This gives you funny behaviour with the ClientPointer. When a MappingNotify is sent to the client, the client usually responds with a GetKeyboardMapping. This will retrieve the ClientPointer's keyboard mapping, regardless of which keyboard sent the last mapping notify request. So depending on the CP setting, your keyboard may change layout in each app... --- dix/getevents.c | 76 +++++++++++++++++++++++-------------------------- mi/mieq.c | 5 ++-- xkb/xkbUtils.c | 5 +++- 3 files changed, 42 insertions(+), 44 deletions(-) diff --git a/dix/getevents.c b/dix/getevents.c index d9adadf43c..b0211b61a3 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -867,63 +867,57 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, /** - * Note that pDev was the last device to send a core event. This function - * copies the complete keymap from the originating device to the core - * device, and makes sure the appropriate notifications are generated. + * pDev is the slave device that is about to send an event. If it is attached + * to a master device, then we need to send a mapping notify to the client. + * To do so, we need to remember the last master device that sent a mapping + * event. + * + * Mapping notify needs to be sent in the following cases: + * - different slave device on same master + * - different master * * Call this just before processInputProc. + * + * XXX: They way how the code is we also send a map notify if the slave device + * stays the same, but the master changes. This isn't really necessary though. + * + * XXX: this gives you funny behaviour with the ClientPointer. When a + * MappingNotify is sent to the client, the client usually responds with a + * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard + * mapping, regardless of which keyboard sent the last mapping notify request. + * So depending on the CP setting, your keyboard may change layout in each + * app... */ _X_EXPORT void SwitchCoreKeyboard(DeviceIntPtr pDev) { - KeyClassPtr ckeyc = inputInfo.keyboard->key; + static DeviceIntPtr lastMapNotifyDevice = NULL; + DeviceIntPtr master; + KeyClassPtr ckeyc; int i = 0; + BOOL sendNotify = FALSE; - if (inputInfo.keyboard->devPrivates[CoreDevicePrivatesIndex].ptr != pDev) { - memcpy(ckeyc->modifierMap, pDev->key->modifierMap, MAP_LENGTH); - if (ckeyc->modifierKeyMap) - xfree(ckeyc->modifierKeyMap); - ckeyc->modifierKeyMap = xalloc(8 * pDev->key->maxKeysPerModifier); - memcpy(ckeyc->modifierKeyMap, pDev->key->modifierKeyMap, - (8 * pDev->key->maxKeysPerModifier)); + if (pDev->isMaster || !pDev->u.master) + return; - ckeyc->maxKeysPerModifier = pDev->key->maxKeysPerModifier; - ckeyc->curKeySyms.minKeyCode = pDev->key->curKeySyms.minKeyCode; - ckeyc->curKeySyms.maxKeyCode = pDev->key->curKeySyms.maxKeyCode; - SetKeySymsMap(&ckeyc->curKeySyms, &pDev->key->curKeySyms); + master = pDev->u.master; + ckeyc = master->key; - /* - * Copy state from the extended keyboard to core. If you omit this, - * holding Ctrl on keyboard one, and pressing Q on keyboard two, will - * cause your app to quit. This feels wrong to me, hence the below - * code. - * - * XXX: If you synthesise core modifier events, the state will get - * clobbered here. You'll have to work out something sensible - * to fix that. Good luck. - */ + if (master->devPrivates[CoreDevicePrivatesIndex].ptr != pDev) { + master->devPrivates[CoreDevicePrivatesIndex].ptr = pDev; + sendNotify = TRUE; + } -#define KEYBOARD_MASK (ShiftMask | LockMask | ControlMask | Mod1Mask | \ - Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask) - ckeyc->state &= ~(KEYBOARD_MASK); - ckeyc->state |= (pDev->key->state & KEYBOARD_MASK); -#undef KEYBOARD_MASK - for (i = 0; i < 8; i++) - ckeyc->modifierKeyCount[i] = pDev->key->modifierKeyCount[i]; - -#ifdef XKB - if (!noXkbExtension && pDev->key->xkbInfo && pDev->key->xkbInfo->desc) { - if (!XkbCopyKeymap(pDev->key->xkbInfo->desc, ckeyc->xkbInfo->desc, - True)) - FatalError("Couldn't pivot keymap from device to core!\n"); - } -#endif + if (lastMapNotifyDevice != master) + sendNotify = TRUE; + if (sendNotify) + { SendMappingNotify(pDev, MappingKeyboard, ckeyc->curKeySyms.minKeyCode, (ckeyc->curKeySyms.maxKeyCode - ckeyc->curKeySyms.minKeyCode), serverClient); - inputInfo.keyboard->devPrivates[CoreDevicePrivatesIndex].ptr = pDev; + lastMapNotifyDevice = master; } } diff --git a/mi/mieq.c b/mi/mieq.c index f0af4b0ba3..11439cfac5 100644 --- a/mi/mieq.c +++ b/mi/mieq.c @@ -335,8 +335,9 @@ mieqProcessInputEvents(void) if ((e->events->event[0].u.u.type == DeviceKeyPress || e->events->event[0].u.u.type == DeviceKeyRelease || e->events->event[0].u.u.type == KeyPress || - e->events->event[0].u.u.type == KeyRelease) && - e->pDev->coreEvents) { + e->events->event[0].u.u.type == KeyRelease) && + !e->pDev->isMaster) + { SwitchCoreKeyboard(e->pDev); } diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c index e87064a42a..d49a3c63d0 100644 --- a/xkb/xkbUtils.c +++ b/xkb/xkbUtils.c @@ -935,7 +935,10 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies) xkbMapNotify mn; xkbNewKeyboardNotify nkn; - if (!src || !dst || src == dst) + if (src == dst) + return TRUE; + + if (!src || !dst) return FALSE; /* client map */