Input: Remove modifierKeyMap
Since modifierKeyMap is generated from modifierMap, just remove it, and only generate it when we need to send the modifier map to the client. Signed-off-by: Daniel Stone <daniel@fooishbar.org> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
cf6a2fc2bd
commit
f062e90a95
|
@ -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)
|
||||
|
|
28
Xi/getmmap.c
28
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;
|
||||
}
|
||||
|
||||
|
|
30
Xi/setmmap.c
30
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;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ libdix_la_SOURCES = \
|
|||
glyphcurs.c \
|
||||
grabs.c \
|
||||
initatoms.c \
|
||||
inpututils.c \
|
||||
main.c \
|
||||
pixmap.c \
|
||||
privates.c \
|
||||
|
|
136
dix/devices.c
136
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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++;
|
||||
|
|
239
dix/inpututils.c
Normal file
239
dix/inpututils.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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, */,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -438,37 +438,8 @@ 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
|
||||
* single-group distribution for multi-group keyboards, we have to
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user