summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Xi/exevents.c98
-rw-r--r--Xi/getmmap.c28
-rw-r--r--Xi/setmmap.c30
-rw-r--r--dix/Makefile.am1
-rw-r--r--dix/devices.c136
-rw-r--r--dix/getevents.c43
-rw-r--r--dix/inpututils.c239
-rw-r--r--hw/xquartz/quartzKeyboard.c4
-rw-r--r--include/exevents.h10
-rw-r--r--include/input.h22
-rw-r--r--include/inputstr.h2
-rw-r--r--xkb/xkbUtils.c41
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;
}