diff options
-rw-r--r-- | Xi/exevents.c | 98 | ||||
-rw-r--r-- | Xi/getmmap.c | 28 | ||||
-rw-r--r-- | Xi/setmmap.c | 30 | ||||
-rw-r--r-- | dix/Makefile.am | 1 | ||||
-rw-r--r-- | dix/devices.c | 136 | ||||
-rw-r--r-- | dix/getevents.c | 43 | ||||
-rw-r--r-- | dix/inpututils.c | 239 | ||||
-rw-r--r-- | hw/xquartz/quartzKeyboard.c | 4 | ||||
-rw-r--r-- | include/exevents.h | 10 | ||||
-rw-r--r-- | include/input.h | 22 | ||||
-rw-r--r-- | include/inputstr.h | 2 | ||||
-rw-r--r-- | xkb/xkbUtils.c | 41 |
12 files changed, 335 insertions, 319 deletions
diff --git a/Xi/exevents.c b/Xi/exevents.c index 1b2c46314..824972ca5 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -201,21 +201,6 @@ CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master) memcpy(mk->modifierMap, dk->modifierMap, MAP_LENGTH); - if (dk->maxKeysPerModifier) - { - mk->modifierKeyMap = xrealloc(mk->modifierKeyMap, - 8 * dk->maxKeysPerModifier); - if (!mk->modifierKeyMap) - FatalError("[Xi] no memory for class shift.\n"); - memcpy(mk->modifierKeyMap, dk->modifierKeyMap, - (8 * dk->maxKeysPerModifier)); - } else - { - xfree(mk->modifierKeyMap); - mk->modifierKeyMap = NULL; - } - - mk->maxKeysPerModifier = dk->maxKeysPerModifier; mk->curKeySyms.minKeyCode = dk->curKeySyms.minKeyCode; mk->curKeySyms.maxKeyCode = dk->curKeySyms.maxKeyCode; SetKeySymsMap(&mk->curKeySyms, &dk->curKeySyms); @@ -498,7 +483,6 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) if (from->key) { - KeyCode *oldModKeyMap; KeySym *oldMap; struct _XkbSrvInfo *oldXkbInfo; if (!to->key) @@ -515,7 +499,6 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) classes->key = NULL; } - oldModKeyMap = to->key->modifierKeyMap; oldMap = to->key->curKeySyms.map; oldXkbInfo = to->key->xkbInfo; @@ -528,7 +511,6 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) memcpy(oldMap, from->key->curKeySyms.map, bytes); } - to->key->modifierKeyMap = oldModKeyMap; to->key->curKeySyms.map = oldMap; to->key->xkbInfo = oldXkbInfo; @@ -1664,86 +1646,6 @@ SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map) return Success; } -int -SetModifierMapping(ClientPtr client, DeviceIntPtr dev, int len, int rlen, - int numKeyPerModifier, KeyCode * inputMap, KeyClassPtr * k) -{ - KeyCode *map = NULL; - int inputMapLen; - int i; - - *k = dev->key; - if (*k == NULL) - return BadMatch; - if (len != ((numKeyPerModifier << 1) + rlen)) - return BadLength; - - inputMapLen = 8 * numKeyPerModifier; - - /* - * Now enforce the restriction that "all of the non-zero keycodes must be - * in the range specified by min-keycode and max-keycode in the - * connection setup (else a Value error)" - */ - i = inputMapLen; - while (i--) { - if (inputMap[i] - && (inputMap[i] < (*k)->curKeySyms.minKeyCode - || inputMap[i] > (*k)->curKeySyms.maxKeyCode)) { - client->errorValue = inputMap[i]; - return -1; /* BadValue collides with MappingFailed */ - } - } - - /* - * Now enforce the restriction that none of the old or new - * modifier keys may be down while we change the mapping, and - * that the DDX layer likes the choice. - */ - if (!AllModifierKeysAreUp(dev, (*k)->modifierKeyMap, - (int)(*k)->maxKeysPerModifier, inputMap, - (int)numKeyPerModifier) - || !AllModifierKeysAreUp(dev, inputMap, (int)numKeyPerModifier, - (*k)->modifierKeyMap, - (int)(*k)->maxKeysPerModifier)) { - return MappingBusy; - } else { - for (i = 0; i < inputMapLen; i++) { - if (inputMap[i] && !LegalModifier(inputMap[i], dev)) { - return MappingFailed; - } - } - } - - /* - * Now build the keyboard's modifier bitmap from the - * list of keycodes. - */ - if (inputMapLen) { - map = (KeyCode *) xalloc(inputMapLen); - if (!map) - return BadAlloc; - } - if ((*k)->modifierKeyMap) - xfree((*k)->modifierKeyMap); - if (inputMapLen) { - (*k)->modifierKeyMap = map; - memmove((char *)(*k)->modifierKeyMap, (char *)inputMap, inputMapLen); - } else - (*k)->modifierKeyMap = NULL; - - (*k)->maxKeysPerModifier = numKeyPerModifier; - for (i = 0; i < MAP_LENGTH; i++) - (*k)->modifierMap[i] = 0; - for (i = 0; i < inputMapLen; i++) - if (inputMap[i]) { - (*k)->modifierMap[inputMap[i]] - |= (1 << (i / (*k)->maxKeysPerModifier)); - } - - return (MappingSuccess); -} - void SendDeviceMappingNotify(ClientPtr client, CARD8 request, KeyCode firstKeyCode, CARD8 count, DeviceIntPtr dev) diff --git a/Xi/getmmap.c b/Xi/getmmap.c index 0ae2ccc52..ddf27a5f0 100644 --- a/Xi/getmmap.c +++ b/Xi/getmmap.c @@ -87,36 +87,34 @@ SProcXGetDeviceModifierMapping(ClientPtr client) int ProcXGetDeviceModifierMapping(ClientPtr client) { - CARD8 maxkeys; DeviceIntPtr dev; xGetDeviceModifierMappingReply rep; - KeyClassPtr kp; - int rc; + KeyCode *modkeymap = NULL; + int ret, max_keys_per_mod; REQUEST(xGetDeviceModifierMappingReq); REQUEST_SIZE_MATCH(xGetDeviceModifierMappingReq); - rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess); - if (rc != Success) - return rc; + ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess); + if (ret != Success) + return ret; - kp = dev->key; - if (kp == NULL) - return BadMatch; - - maxkeys = kp->maxKeysPerModifier; + ret = generate_modkeymap(client, dev, &modkeymap, &max_keys_per_mod); + if (ret != Success) + return ret; rep.repType = X_Reply; rep.RepType = X_GetDeviceModifierMapping; - rep.numKeyPerModifier = maxkeys; + rep.numKeyPerModifier = max_keys_per_mod; rep.sequenceNumber = client->sequence; /* length counts 4 byte quantities - there are 8 modifiers 1 byte big */ - rep.length = 2 * maxkeys; + rep.length = max_keys_per_mod << 1; WriteReplyToClient(client, sizeof(xGetDeviceModifierMappingReply), &rep); + WriteToClient(client, max_keys_per_mod * 8, (char *) modkeymap); + + xfree(modkeymap); - /* Reply with the (modified by DDX) map that SetModifierMapping passed in */ - WriteToClient(client, 8 * maxkeys, (char *)kp->modifierKeyMap); return Success; } diff --git a/Xi/setmmap.c b/Xi/setmmap.c index ddfc1bd3e..8a0ab3e81 100644 --- a/Xi/setmmap.c +++ b/Xi/setmmap.c @@ -91,33 +91,39 @@ ProcXSetDeviceModifierMapping(ClientPtr client) int ret; xSetDeviceModifierMappingReply rep; DeviceIntPtr dev; - KeyClassPtr kp; REQUEST(xSetDeviceModifierMappingReq); REQUEST_AT_LEAST_SIZE(xSetDeviceModifierMappingReq); - ret = dixLookupDevice(&dev, stuff->deviceid, client, DixManageAccess); - if (ret != Success) - return ret; + if (stuff->length != ((sizeof(xSetDeviceModifierMappingReq) >> 2) + + (stuff->numKeyPerModifier << 1))) + return BadLength; rep.repType = X_Reply; rep.RepType = X_SetDeviceModifierMapping; rep.length = 0; rep.sequenceNumber = client->sequence; - ret = SetModifierMapping(client, dev, stuff->length, - (sizeof(xSetDeviceModifierMappingReq) >> 2), - stuff->numKeyPerModifier, (BYTE *) & stuff[1], - &kp); + ret = dixLookupDevice(&dev, stuff->deviceid, client, DixManageAccess); + if (ret != Success) + return ret; + + ret = change_modmap(client, dev, (KeyCode *) &stuff[1], + stuff->numKeyPerModifier); + if (ret == Success) + ret = MappingSuccess; if (ret == MappingSuccess || ret == MappingBusy || ret == MappingFailed) { rep.success = ret; - if (ret == MappingSuccess) - SendDeviceMappingNotify(client, MappingModifier, 0, 0, dev); WriteReplyToClient(client, sizeof(xSetDeviceModifierMappingReply), &rep); - } else if (ret == -1) - return BadValue; + } + else if (ret == -1) { + return BadValue; + } + else { + return ret; + } return Success; } diff --git a/dix/Makefile.am b/dix/Makefile.am index 4c2395d82..34eeb6ddd 100644 --- a/dix/Makefile.am +++ b/dix/Makefile.am @@ -25,6 +25,7 @@ libdix_la_SOURCES = \ glyphcurs.c \ grabs.c \ initatoms.c \ + inpututils.c \ main.c \ pixmap.c \ privates.c \ diff --git a/dix/devices.c b/dix/devices.c index 6748e487d..a4ff641a0 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -620,7 +620,6 @@ FreeDeviceClass(int type, pointer *class) (*k)->xkbInfo = NULL; } xfree((*k)->curKeySyms.map); - xfree((*k)->modifierKeyMap); xfree((*k)); break; } @@ -1453,109 +1452,10 @@ BadDeviceMap(BYTE *buff, int length, unsigned low, unsigned high, XID *errval) return FALSE; } -Bool -AllModifierKeysAreUp(DeviceIntPtr dev, CARD8 *map1, int per1, - CARD8 *map2, int per2) -{ - int i, j, k; - CARD8 *down = dev->key->down; - - for (i = 8; --i >= 0; map2 += per2) - { - for (j = per1; --j >= 0; map1++) - { - if (*map1 && BitIsOn(down, *map1)) - { - for (k = per2; (--k >= 0) && (*map1 != map2[k]);) - ; - if (k < 0) - return FALSE; - } - } - } - return TRUE; -} - -static int -DoSetModifierMapping(ClientPtr client, KeyCode *inputMap, - int numKeyPerModifier, xSetModifierMappingReply *rep) -{ - DeviceIntPtr pDev = NULL; - DeviceIntPtr cp = PickKeyboard(client); /* ClientPointer keyboard */ - int rc, i = 0, inputMapLen = numKeyPerModifier * 8; - - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { - if (pDev == cp || (!pDev->isMaster && (pDev->u.master == cp) && pDev->key)) { - for (i = 0; i < inputMapLen; i++) { - /* Check that all the new modifiers fall within the advertised - * keycode range, and are okay with the DDX. */ - if (inputMap[i] && ((inputMap[i] < pDev->key->curKeySyms.minKeyCode || - inputMap[i] > pDev->key->curKeySyms.maxKeyCode) || - !LegalModifier(inputMap[i], pDev))) { - client->errorValue = inputMap[i]; - return BadValue; - } - } - - rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess); - if (rc != Success) - return rc; - - /* None of the modifiers (old or new) may be down while we change - * the map. */ - if (!AllModifierKeysAreUp(pDev, pDev->key->modifierKeyMap, - pDev->key->maxKeysPerModifier, - inputMap, numKeyPerModifier) || - !AllModifierKeysAreUp(pDev, inputMap, numKeyPerModifier, - pDev->key->modifierKeyMap, - pDev->key->maxKeysPerModifier)) { - rep->success = MappingBusy; - return Success; - } - } - } - - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { - - if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) { - bzero(pDev->key->modifierMap, MAP_LENGTH); - - /* Annoyingly, we lack a modifierKeyMap size, so we have to just free - * and re-alloc it every time. */ - if (pDev->key->modifierKeyMap) - xfree(pDev->key->modifierKeyMap); - - if (inputMapLen) { - pDev->key->modifierKeyMap = (KeyCode *) xalloc(inputMapLen); - if (!pDev->key->modifierKeyMap) - return BadAlloc; - - memcpy(pDev->key->modifierKeyMap, inputMap, inputMapLen); - pDev->key->maxKeysPerModifier = numKeyPerModifier; - - for (i = 0; i < inputMapLen; i++) { - if (inputMap[i]) { - pDev->key->modifierMap[inputMap[i]] |= - (1 << (((unsigned int)i) / numKeyPerModifier)); - } - } - } - else { - pDev->key->modifierKeyMap = NULL; - pDev->key->maxKeysPerModifier = 0; - } - } - } - - rep->success = Success; - return Success; -} - int ProcSetModifierMapping(ClientPtr client) { xSetModifierMappingReply rep; - DeviceIntPtr dev; int rc; REQUEST(xSetModifierMappingReq); REQUEST_AT_LEAST_SIZE(xSetModifierMappingReq); @@ -1568,14 +1468,16 @@ ProcSetModifierMapping(ClientPtr client) rep.length = 0; rep.sequenceNumber = client->sequence; - rc = DoSetModifierMapping(client, (KeyCode *)&stuff[1], - stuff->numKeyPerModifier, &rep); - if (rc != Success) + rc = change_modmap(client, PickKeyboard(client), (KeyCode *)&stuff[1], + stuff->numKeyPerModifier); + if (rc == MappingFailed || rc == -1) + rc = BadValue; + if (rc != Success && rc != MappingSuccess && rc != MappingFailed && + rc != MappingBusy) return rc; - for (dev = inputInfo.devices; dev; dev = dev->next) - if (dev->key && dev->coreEvents) - SendDeviceMappingNotify(client, MappingModifier, 0, 0, dev); + rep.success = rc; + WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep); return client->noClientException; } @@ -1584,26 +1486,26 @@ int ProcGetModifierMapping(ClientPtr client) { xGetModifierMappingReply rep; - DeviceIntPtr dev = PickKeyboard(client); - KeyClassPtr keyc = dev->key; - int rc; + int ret, max_keys_per_mod = 0; + KeyCode *modkeymap = NULL; REQUEST_SIZE_MATCH(xReq); - rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess); - if (rc != Success) - return rc; + ret = generate_modkeymap(client, PickKeyboard(client), &modkeymap, + &max_keys_per_mod); + if (ret != Success) + return ret; rep.type = X_Reply; - rep.numKeyPerModifier = keyc->maxKeysPerModifier; + rep.numKeyPerModifier = max_keys_per_mod; rep.sequenceNumber = client->sequence; /* length counts 4 byte quantities - there are 8 modifiers 1 byte big */ - rep.length = keyc->maxKeysPerModifier << 1; + rep.length = max_keys_per_mod << 1; WriteReplyToClient(client, sizeof(xGetModifierMappingReply), &rep); + (void)WriteToClient(client, max_keys_per_mod * 8, (char *) modkeymap); + + xfree(modkeymap); - /* Use the (modified by DDX) map that SetModifierMapping passed in */ - (void)WriteToClient(client, (int)(keyc->maxKeysPerModifier << 3), - (char *)keyc->modifierKeyMap); return client->noClientException; } diff --git a/dix/getevents.c b/dix/getevents.c index 112bb102c..81e660860 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -84,22 +84,35 @@ GetMotionHistorySize(void) return MOTION_HISTORY_SIZE; } -static void -set_key_down(DeviceIntPtr pDev, int key_code) +void +set_key_down(DeviceIntPtr pDev, int key_code, int type) { - pDev->key->postdown[key_code >> 3] |= (1 << (key_code & 7)); + if (type == KEY_PROCESSED) + pDev->key->down[key_code >> 3] |= (1 << (key_code & 7)); + else + pDev->key->postdown[key_code >> 3] |= (1 << (key_code & 7)); } -static void -set_key_up(DeviceIntPtr pDev, int key_code) +void +set_key_up(DeviceIntPtr pDev, int key_code, int type) { - pDev->key->postdown[key_code >> 3] &= ~(1 << (key_code & 7)); + if (type == KEY_PROCESSED) + pDev->key->down[key_code >> 3] &= ~(1 << (key_code & 7)); + else + pDev->key->postdown[key_code >> 3] &= ~(1 << (key_code & 7)); } -static Bool -key_is_down(DeviceIntPtr pDev, int key_code) +Bool +key_is_down(DeviceIntPtr pDev, int key_code, int type) { - return !!(pDev->key->postdown[key_code >> 3] & (1 << (key_code & 7))); + int ret = 0; + + if (type & KEY_PROCESSED) + ret |= !!(pDev->key->down[key_code >> 3] & (1 << (key_code & 7))); + else if (type & KEY_POSTED) + ret |= !!(pDev->key->postdown[key_code >> 3] & (1 << (key_code & 7))); + + return ret; } static Bool @@ -787,8 +800,6 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, int num_valuators, int *valuators) { int numEvents = 0; CARD32 ms = 0; - KeySym *map; - KeySym sym; deviceKeyButtonPointer *kbp = NULL; if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed || @@ -798,16 +809,12 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, numEvents = 1; - map = pDev->key->curKeySyms.map; - sym = map[(key_code - pDev->key->curKeySyms.minKeyCode) - * pDev->key->curKeySyms.mapWidth]; - events = updateFromMaster(events, pDev, &numEvents); numEvents += countValuatorEvents(num_valuators); /* Handle core repeating, via press/release/press/release. */ - if (type == KeyPress && key_is_down(pDev, key_code)) { + if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) { /* If autorepeating is disabled either globally or just for that key, * or we have a modifier, don't generate a repeat event. */ if (!pDev->kbdfeed->ctrl.autoRepeat || @@ -824,11 +831,11 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, kbp->detail = key_code; if (type == KeyPress) { kbp->type = DeviceKeyPress; - set_key_down(pDev, key_code); + set_key_down(pDev, key_code, KEY_POSTED); } else if (type == KeyRelease) { kbp->type = DeviceKeyRelease; - set_key_up(pDev, key_code); + set_key_up(pDev, key_code, KEY_POSTED); } events++; diff --git a/dix/inpututils.c b/dix/inpututils.c new file mode 100644 index 000000000..1adaa7888 --- /dev/null +++ b/dix/inpututils.c @@ -0,0 +1,239 @@ +/* + * Copyright © 2008 Daniel Stone + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Daniel Stone <daniel@fooishbar.org> + */ + +#ifdef HAVE_DIX_CONFIG_H +#include "dix-config.h" +#endif + +#include "exevents.h" +#include "misc.h" +#include "input.h" +#include "inputstr.h" +#include "xace.h" + +/* Check if a modifier map change is okay with the device. + * Returns -1 for BadValue, as it collides with MappingBusy; this particular + * caveat can be removed with LegalModifier, as we have no other reason to + * set MappingFailed. Sigh. */ +static int +check_modmap_change(ClientPtr client, DeviceIntPtr dev, KeyCode *modmap) +{ + int ret, i; + KeySymsPtr syms; + + ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess); + if (ret != Success) + return ret; + + if (!dev->key) + return BadMatch; + syms = &dev->key->curKeySyms; + + for (i = 0; i < MAP_LENGTH; i++) { + if (!modmap[i]) + continue; + + /* Check that all the new modifiers fall within the advertised + * keycode range. */ + if (i < syms->minKeyCode || i > syms->maxKeyCode) { + client->errorValue = i; + return -1; + } + + /* Make sure the mapping is okay with the DDX. */ + if (!LegalModifier(i, dev)) { + client->errorValue = i; + return MappingFailed; + } + + /* None of the new modifiers may be down while we change the + * map. */ + if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) { + client->errorValue = i; + return MappingBusy; + } + } + + /* None of the old modifiers may be down while we change the map, + * either. */ + for (i = syms->minKeyCode; i < syms->maxKeyCode; i++) { + if (!dev->key->modifierMap[i]) + continue; + if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) { + client->errorValue = i; + return MappingBusy; + } + } + + return Success; +} + +static int +check_modmap_change_slave(ClientPtr client, DeviceIntPtr master, + DeviceIntPtr slave, CARD8 *modmap) +{ + KeySymsPtr master_syms, slave_syms; + int i, j; + + if (!slave->key || !master->key) + return 0; + + master_syms = &master->key->curKeySyms; + slave_syms = &slave->key->curKeySyms; + + /* Ignore devices with a clearly different keymap. */ + if (slave_syms->minKeyCode != master_syms->minKeyCode || + slave_syms->maxKeyCode != master_syms->maxKeyCode) + return 0; + + for (i = 0; i < MAP_LENGTH; i++) { + if (!modmap[i]) + continue; + + /* If we have different symbols for any modifier on an + * extended keyboard, ignore the whole remap request. */ + for (j = 0; j < slave_syms->mapWidth && j < master_syms->mapWidth; j++) + if (slave_syms->map[modmap[i] * slave_syms->mapWidth + j] != + master_syms->map[modmap[i] * master_syms->mapWidth + j]) + return 0; + } + + if (check_modmap_change(client, slave, modmap) != Success) + return 0; + + return 1; +} + +/* Actually change the modifier map, and send notifications. Cannot fail. */ +static void +do_modmap_change(ClientPtr client, DeviceIntPtr dev, CARD8 *modmap) +{ + memcpy(dev->key->modifierMap, modmap, MAP_LENGTH); + SendDeviceMappingNotify(client, MappingModifier, 0, 0, dev); +} + +/* Rebuild modmap (key -> mod) from map (mod -> key). */ +static int build_modmap_from_modkeymap(CARD8 *modmap, KeyCode *modkeymap, + int max_keys_per_mod) +{ + int i, mod = 0, len = max_keys_per_mod * 8; + + memset(modmap, 0, MAP_LENGTH); + + for (i = 0; i < len; i++) { + if (!modkeymap[i]) + continue; + + if (modmap[modkeymap[i]]) + return BadValue; + + if (!(i % max_keys_per_mod)) + mod++; + modmap[modkeymap[i]] = mod; + } + + return Success; +} + +int +change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap, + int max_keys_per_mod) +{ + int ret; + CARD8 modmap[MAP_LENGTH]; + DeviceIntPtr slave; + + ret = build_modmap_from_modkeymap(modmap, modkeymap, max_keys_per_mod); + if (ret != Success) + return ret; + + /* If we can't perform the change on the requested device, bail out. */ + ret = check_modmap_change(client, dev, modmap); + if (ret != Success) + return ret; + do_modmap_change(client, dev, modmap); + + /* If we're acting on a master, change the slaves as well. */ + if (dev->isMaster) { + for (slave = inputInfo.devices; slave; slave = slave->next) { + if (slave != dev && !slave->isMaster && slave->u.master == dev) + if (check_modmap_change_slave(client, dev, slave, modmap)) + do_modmap_change(client, slave, modmap); + } + } + + return Success; +} + +int generate_modkeymap(ClientPtr client, DeviceIntPtr dev, + KeyCode **modkeymap_out, int *max_keys_per_mod_out) +{ + CARD8 keys_per_mod[8]; + int max_keys_per_mod; + KeyCode *modkeymap; + int i, j, ret; + + ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess); + if (ret != Success) + return ret; + + if (!dev->key) + return BadMatch; + + /* Count the number of keys per modifier to determine how wide we + * should make the map. */ + max_keys_per_mod = 0; + for (i = 0; i < 8; i++) + keys_per_mod[i] = 0; + for (i = 8; i < MAP_LENGTH; i++) { + for (j = 0; j < 8; j++) { + if (dev->key->modifierMap[i] & (1 << j)) { + if (++keys_per_mod[j] > max_keys_per_mod) + max_keys_per_mod = keys_per_mod[j]; + } + } + } + + modkeymap = xcalloc(max_keys_per_mod * 8, sizeof(KeyCode)); + if (!modkeymap) + return BadAlloc; + + for (i = 0; i < 8; i++) + keys_per_mod[i] = 0; + + for (i = 8; i < MAP_LENGTH; i++) { + for (j = 0; j < 8; j++) { + if (dev->key->modifierMap[i] & (1 << j)) { + modkeymap[(j * max_keys_per_mod) + keys_per_mod[j]] = i; + keys_per_mod[j]++; + } + } + } + + *max_keys_per_mod_out = max_keys_per_mod; + *modkeymap_out = modkeymap; + + return Success; +} diff --git a/hw/xquartz/quartzKeyboard.c b/hw/xquartz/quartzKeyboard.c index 72f94b443..21736d190 100644 --- a/hw/xquartz/quartzKeyboard.c +++ b/hw/xquartz/quartzKeyboard.c @@ -370,6 +370,10 @@ void DarwinKeyboardReloadHandler(int screenNum, xEventPtr xe, DeviceIntPtr pDev, KeySymsRec keySyms; DEBUG_LOG("DarwinKeyboardReloadHandler\n"); + if (pDev->key) { + if (pDev->key->curKeySyms.map) xfree(pDev->key->curKeySyms.map); + xfree(pDev->key); + } DarwinLoadKeyboardMapping(&keySyms); DarwinKeyboardSetDeviceKeyMap(&keySyms); diff --git a/include/exevents.h b/include/exevents.h index 2504baf04..8ddfbf9e8 100644 --- a/include/exevents.h +++ b/include/exevents.h @@ -31,6 +31,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #define EXEVENTS_H #include <X11/extensions/XIproto.h> +#include "inputstr.h" /** * Attached to the devPrivates of each client. Specifies the version number as @@ -136,15 +137,6 @@ extern _X_EXPORT int SetButtonMapping ( int /* nElts */, BYTE * /* map */); -extern _X_EXPORT int SetModifierMapping( - ClientPtr /* client */, - DeviceIntPtr /* dev */, - int /* len */, - int /* rlen */, - int /* numKeyPerModifier */, - KeyCode * /* inputMap */, - KeyClassPtr * /* k */); - extern _X_EXPORT void SendDeviceMappingNotify( ClientPtr /* client, */, CARD8 /* request, */, diff --git a/include/input.h b/include/input.h index db75f6c78..a38dbfac0 100644 --- a/include/input.h +++ b/include/input.h @@ -222,6 +222,15 @@ typedef struct _InputOption { struct _InputOption *next; } InputOption; +/* Key has been run through all input processing and events sent to clients. */ +#define KEY_PROCESSED 1 +/* Key has not been fully processed, no events have been sent. */ +#define KEY_POSTED 2 + +extern void set_key_down(DeviceIntPtr pDev, int key_code, int type); +extern void set_key_up(DeviceIntPtr pDev, int key_code, int type); +extern int key_is_down(DeviceIntPtr pDev, int key_code, int type); + extern _X_EXPORT void InitCoreDevices(void); extern _X_EXPORT DeviceIntPtr AddInputDevice( @@ -373,13 +382,6 @@ extern _X_EXPORT Bool BadDeviceMap( unsigned /*high*/, XID* /*errval*/); -extern _X_EXPORT Bool AllModifierKeysAreUp( - DeviceIntPtr /*device*/, - CARD8* /*map1*/, - int /*per1*/, - CARD8* /*map2*/, - int /*per2*/); - extern _X_EXPORT void NoteLedState( DeviceIntPtr /*keybd*/, int /*led*/, @@ -498,6 +500,12 @@ extern _X_EXPORT int AllocMasterDevice(ClientPtr client, extern _X_EXPORT void DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to); +/* Helper functions. */ +extern int generate_modkeymap(ClientPtr client, DeviceIntPtr dev, + KeyCode **modkeymap, int *max_keys_per_mod); +extern int change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *map, + int max_keys_per_mod); + /* Implemented by the DDX. */ extern _X_EXPORT int NewInputDeviceRequest( InputOption *options, diff --git a/include/inputstr.h b/include/inputstr.h index 7ff8dcbbb..cdd68d593 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -137,11 +137,9 @@ typedef struct _GrabRec { typedef struct _KeyClassRec { CARD8 down[DOWN_LENGTH]; CARD8 postdown[DOWN_LENGTH]; - KeyCode *modifierKeyMap; KeySymsRec curKeySyms; int modifierKeyCount[8]; CARD8 modifierMap[MAP_LENGTH]; - CARD8 maxKeysPerModifier; struct _XkbSrvInfo *xkbInfo; } KeyClassRec, *KeyClassPtr; diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c index c7a6d99d0..8960bca12 100644 --- a/xkb/xkbUtils.c +++ b/xkb/xkbUtils.c @@ -438,36 +438,7 @@ int maxNumberOfGroups; if (nGroups > maxNumberOfGroups) maxNumberOfGroups = nGroups; } - if (_XkbCoreKeycodeInRange(keyc,key)) { - if (keyc->modifierMap[key]!=0) { - register unsigned bit,i,mask; - mask= keyc->modifierMap[key]; - for (i=0,bit=1;i<XkbNumModifiers;i++,bit<<=1) { - if (mask&bit) { - keysPerMod[i]++; - if (keysPerMod[i]>maxKeysPerMod) - maxKeysPerMod= keysPerMod[i]; - } - } - } - } - } - - if (maxKeysPerMod>0) { - tmp= maxKeysPerMod*XkbNumModifiers; - if (keyc->modifierKeyMap==NULL) - keyc->modifierKeyMap= (KeyCode *)_XkbCalloc(1, tmp); - else if (keyc->maxKeysPerModifier<maxKeysPerMod) - keyc->modifierKeyMap= (KeyCode *)_XkbRealloc(keyc->modifierKeyMap,tmp); - if (keyc->modifierKeyMap==NULL) - FatalError("Couldn't allocate modifierKeyMap in UpdateCore\n"); - bzero(keyc->modifierKeyMap,tmp); } - else if ((keyc->maxKeysPerModifier>0)&&(keyc->modifierKeyMap!=NULL)) { - _XkbFree(keyc->modifierKeyMap); - keyc->modifierKeyMap= NULL; - } - keyc->maxKeysPerModifier= maxKeysPerMod; if (maxSymsPerKey>0) { /* See Section 12.4 of the XKB Protocol spec. Because of the @@ -489,7 +460,6 @@ int maxNumberOfGroups; } keyc->curKeySyms.mapWidth= maxSymsPerKey; - bzero(keysPerMod,sizeof(keysPerMod)); for (key=firstCommon;key<=lastCommon;key++) { if (keyc->curKeySyms.map!=NULL) { KeySym *pCore,*pXKB; @@ -568,17 +538,6 @@ int maxNumberOfGroups; pXKB+= XkbKeyGroupsWidth(xkb,key); } } - if (keyc->modifierMap[key]!=0) { - register unsigned bit,i,mask; - mask= keyc->modifierMap[key]; - for (i=0,bit=1;i<XkbNumModifiers;i++,bit<<=1) { - if (mask&bit) { - tmp= i*maxKeysPerMod+keysPerMod[i]; - keyc->modifierKeyMap[tmp]= key; - keysPerMod[i]++; - } - } - } } return; } |