diff --git a/Xi/exevents.c b/Xi/exevents.c index da10040da..623f71036 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -205,41 +205,20 @@ XIGetDevice(xEvent* xE) static void CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master) { - static DeviceIntPtr lastMapNotifyDevice = NULL; - KeyClassPtr mk, dk; /* master, device */ + KeyClassPtr mk = master->key; + KeyClassPtr dk = device->key; int i; if (device == master) return; - dk = device->key; - mk = master->key; - - mk->curKeySyms.minKeyCode = dk->curKeySyms.minKeyCode; - mk->curKeySyms.maxKeyCode = dk->curKeySyms.maxKeyCode; SetKeySymsMap(&mk->curKeySyms, &dk->curKeySyms); for (i = 0; i < 8; i++) mk->modifierKeyCount[i] = dk->modifierKeyCount[i]; - if (!XkbCopyKeymap(dk->xkbInfo->desc, mk->xkbInfo->desc, True)) + if (!XkbCopyDeviceKeymap(master, device)) FatalError("Couldn't pivot keymap from device to core!\n"); - - /* Copy the state here. This means we'll only have consistency - * between state and active keymap, rather than between state and - * keycodes pressed, but there's pretty much no way to win here, - * so might as well go for the one that would seem to give the - * least nonsensical result. */ - mk->xkbInfo->state = dk->xkbInfo->state; - - if (lastMapNotifyDevice != master) { - SendMappingNotify(master, MappingKeyboard, - mk->curKeySyms.minKeyCode, - (mk->curKeySyms.maxKeyCode - - mk->curKeySyms.minKeyCode), - serverClient); - lastMapNotifyDevice = master; - } } /** @@ -1661,23 +1640,15 @@ SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map) } void -SendDeviceMappingNotify(ClientPtr client, CARD8 request, - KeyCode firstKeyCode, CARD8 count, DeviceIntPtr dev) +SendDevicePointerMappingNotify(ClientPtr client, DeviceIntPtr dev) { xEvent event; deviceMappingNotify *ev = (deviceMappingNotify *) & event; ev->type = DeviceMappingNotify; - ev->request = request; + ev->request = MappingPointer; ev->deviceid = dev->id; ev->time = currentTime.milliseconds; - if (request == MappingKeyboard) { - ev->firstKeyCode = firstKeyCode; - ev->count = count; - } - - if (request == MappingKeyboard || request == MappingModifier) - XkbApplyMappingChange(dev, request, firstKeyCode, count, client); SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) ev, 1); } @@ -1712,9 +1683,10 @@ ChangeKeyMapping(ClientPtr client, keysyms.maxKeyCode = firstKeyCode + keyCodes - 1; keysyms.mapWidth = keySymsPerKeyCode; keysyms.map = map; - if (!SetKeySymsMap(&k->curKeySyms, &keysyms)) - return BadAlloc; - SendDeviceMappingNotify(client, MappingKeyboard, firstKeyCode, keyCodes, dev); + + XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL, + serverClient); + return client->noClientException; } diff --git a/Xi/setbmap.c b/Xi/setbmap.c index 3c293c0db..0bcfbb8eb 100644 --- a/Xi/setbmap.c +++ b/Xi/setbmap.c @@ -121,7 +121,8 @@ ProcXSetDeviceButtonMapping(ClientPtr client) } if (ret != MappingBusy) - SendDeviceMappingNotify(client, MappingPointer, 0, 0, dev); + SendDevicePointerMappingNotify(client, dev); + return Success; } diff --git a/dix/devices.c b/dix/devices.c index a4ff641a0..33f149ce4 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -1013,19 +1013,20 @@ QueryMinMaxKeyCodes(KeyCode *minCode, KeyCode *maxCode) } } +/* Notably, this function does not expand the destination's keycode range, or + * notify clients. */ Bool SetKeySymsMap(KeySymsPtr dst, KeySymsPtr src) { int i, j; + KeySym *tmp; int rowDif = src->minKeyCode - dst->minKeyCode; /* if keysym map size changes, grow map first */ - if (src->mapWidth < dst->mapWidth) - { - for (i = src->minKeyCode; i <= src->maxKeyCode; i++) - { -#define SI(r, c) (((r-src->minKeyCode)*src->mapWidth) + (c)) -#define DI(r, c) (((r - dst->minKeyCode)*dst->mapWidth) + (c)) + if (src->mapWidth < dst->mapWidth) { + for (i = src->minKeyCode; i <= src->maxKeyCode; i++) { +#define SI(r, c) (((r - src->minKeyCode) * src->mapWidth) + (c)) +#define DI(r, c) (((r - dst->minKeyCode) * dst->mapWidth) + (c)) for (j = 0; j < src->mapWidth; j++) dst->map[DI(i, j)] = src->map[SI(i, j)]; for (j = src->mapWidth; j < dst->mapWidth; j++) @@ -1035,39 +1036,37 @@ SetKeySymsMap(KeySymsPtr dst, KeySymsPtr src) } return TRUE; } - else if (src->mapWidth > dst->mapWidth) - { - KeySym *map; - int bytes = sizeof(KeySym) * src->mapWidth * - (dst->maxKeyCode - dst->minKeyCode + 1); - map = (KeySym *)xcalloc(1, bytes); - if (!map) - return FALSE; - if (dst->map) - { - for (i = 0; i <= dst->maxKeyCode-dst->minKeyCode; i++) - memmove((char *)&map[i*src->mapWidth], - (char *)&dst->map[i*dst->mapWidth], - dst->mapWidth * sizeof(KeySym)); - xfree(dst->map); - } - dst->mapWidth = src->mapWidth; - dst->map = map; - } else if (!dst->map) - { - KeySym *map; - int bytes = sizeof(KeySym) * src->mapWidth * - (dst->maxKeyCode - dst->minKeyCode + 1); - map = (KeySym *)xcalloc(1, bytes); - if (!map) + else if (src->mapWidth > dst->mapWidth) { + i = sizeof(KeySym) * src->mapWidth * + (dst->maxKeyCode - dst->minKeyCode + 1); + tmp = xcalloc(sizeof(KeySym), i); + if (!tmp) return FALSE; - dst->map = map; + + if (dst->map) { + for (i = 0; i <= dst->maxKeyCode-dst->minKeyCode; i++) + memmove(&tmp[i * src->mapWidth], &dst->map[i * dst->mapWidth], + dst->mapWidth * sizeof(KeySym)); + xfree(dst->map); + } + dst->mapWidth = src->mapWidth; + dst->map = tmp; + } + else if (!dst->map) { + i = sizeof(KeySym) * src->mapWidth * + (dst->maxKeyCode - dst->minKeyCode + 1); + tmp = xcalloc(sizeof(KeySym), i); + if (!tmp) + return FALSE; + + dst->map = tmp; dst->mapWidth = src->mapWidth; } - memmove((char *)&dst->map[rowDif * dst->mapWidth], - (char *)src->map, - (int)(src->maxKeyCode - src->minKeyCode + 1) * - dst->mapWidth * sizeof(KeySym)); + + memmove(&dst->map[rowDif * dst->mapWidth], src->map, + (src->maxKeyCode - src->minKeyCode + 1) * + dst->mapWidth * sizeof(KeySym)); + return TRUE; } @@ -1398,34 +1397,24 @@ InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, } _X_EXPORT void -SendMappingNotify(DeviceIntPtr pDev, unsigned request, unsigned firstKeyCode, - unsigned count, ClientPtr client) +SendPointerMappingNotify(DeviceIntPtr pDev, ClientPtr client) { int i; xEvent event; - event.u.u.type = MappingNotify; - event.u.mappingNotify.request = request; - if (request == MappingKeyboard) - { - event.u.mappingNotify.firstKeyCode = firstKeyCode; - event.u.mappingNotify.count = count; - } - if (request == MappingKeyboard || request == MappingModifier) - XkbApplyMappingChange(pDev,request,firstKeyCode,count, client); + /* 0 is the server client. */ + for (i = 1; i < currentMaxClients; i++) { + /* Don't send irrelevant events to naïve clients. */ + if (PickPointer(clients[i]) != pDev) + continue; - /* 0 is the server client */ - for (i=1; iclientState == ClientStateRunning) - { - if (request == MappingKeyboard && - clients[i]->xkbClientFlags != 0 && - (clients[i]->mapNotifyMask & XkbKeySymsMask)) - continue; - event.u.u.sequenceNumber = clients[i]->sequence; - WriteEventsToClient(clients[i], 1, &event); - } + if (clients[i] && clients[i]->clientState == ClientStateRunning) { + event.u.u.type = MappingNotify; + event.u.u.sequenceNumber = clients[i]->sequence; + event.u.mappingNotify.request = MappingPointer; + + WriteEventsToClient(clients[i], 1, &event); + } } } @@ -1516,7 +1505,7 @@ ProcChangeKeyboardMapping(ClientPtr client) unsigned len; KeySymsRec keysyms; KeySymsPtr curKeySyms = &PickKeyboard(client)->key->curKeySyms; - DeviceIntPtr pDev = NULL; + DeviceIntPtr pDev, tmp; int rc; REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq); @@ -1536,28 +1525,30 @@ ProcChangeKeyboardMapping(ClientPtr client) return BadValue; } - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { - if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) { - rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess); - if (rc != Success) - return rc; - } - } - keysyms.minKeyCode = stuff->firstKeyCode; keysyms.maxKeyCode = stuff->firstKeyCode + stuff->keyCodes - 1; keysyms.mapWidth = stuff->keySymsPerKeyCode; - keysyms.map = (KeySym *)&stuff[1]; - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) - if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) - if (!SetKeySymsMap(&pDev->key->curKeySyms, &keysyms)) - return BadAlloc; + keysyms.map = (KeySym *) &stuff[1]; - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) - if (pDev->key && pDev->coreEvents) - SendDeviceMappingNotify(client, MappingKeyboard, - stuff->firstKeyCode, stuff->keyCodes, - pDev); + pDev = PickKeyboard(client); + rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess); + if (rc != Success) + return rc; + + XkbApplyMappingChange(pDev, &keysyms, stuff->firstKeyCode, + stuff->keyCodes, NULL, client); + + for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { + if (tmp->isMaster || tmp->u.master != pDev) + continue; + + rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess); + if (rc != Success) + continue; + + XkbApplyMappingChange(tmp, &keysyms, stuff->firstKeyCode, + stuff->keyCodes, NULL, client); + } return client->noClientException; } @@ -1639,7 +1630,8 @@ ProcSetPointerMapping(ClientPtr client) return Success; } - SendMappingNotify(ptr, MappingPointer, 0, 0, client); + /* FIXME: Send mapping notifies for masters/slaves as well. */ + SendPointerMappingNotify(ptr, client); WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep); return Success; } diff --git a/dix/inpututils.c b/dix/inpututils.c index 1b6458f45..309ef516d 100644 --- a/dix/inpututils.c +++ b/dix/inpututils.c @@ -132,8 +132,7 @@ check_modmap_change_slave(ClientPtr client, DeviceIntPtr master, static void do_modmap_change(ClientPtr client, DeviceIntPtr dev, CARD8 *modmap) { - memcpy(dev->key->xkbInfo->desc->map->modmap, modmap, MAP_LENGTH); - SendDeviceMappingNotify(client, MappingModifier, 0, 0, dev); + XkbApplyMappingChange(dev, NULL, 0, 0, modmap, serverClient); } /* Rebuild modmap (key -> mod) from map (mod -> key). */ @@ -165,7 +164,7 @@ change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap, { int ret; CARD8 modmap[MAP_LENGTH]; - DeviceIntPtr slave; + DeviceIntPtr tmp; ret = build_modmap_from_modkeymap(modmap, modkeymap, max_keys_per_mod); if (ret != Success) @@ -177,12 +176,21 @@ change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap, return ret; do_modmap_change(client, dev, modmap); - /* If we're acting on a master, change the slaves as well. */ + /* Change any attached masters/slaves. */ 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); + for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { + if (!tmp->isMaster && tmp->u.master == dev) + if (check_modmap_change_slave(client, dev, tmp, modmap)) + do_modmap_change(client, tmp, modmap); + } + } + else { + for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { + if (tmp->isMaster && tmp->u.lastSlave == dev) { + /* If this fails, expect the results to be weird. */ + if (check_modmap_change(client, tmp, modmap)) + do_modmap_change(client, tmp, modmap); + } } } diff --git a/hw/xquartz/quartzKeyboard.c b/hw/xquartz/quartzKeyboard.c index 9e8da8be9..020b6a6ab 100644 --- a/hw/xquartz/quartzKeyboard.c +++ b/hw/xquartz/quartzKeyboard.c @@ -293,26 +293,15 @@ static void DarwinLoadKeyboardMapping(KeySymsRec *keySyms) { * DarwinKeyboardSetDeviceKeyMap * Load a keymap into the keyboard device */ -static void DarwinKeyboardSetDeviceKeyMap(KeySymsRec *keySyms) { +static void DarwinKeyboardSetDeviceKeyMap(KeySymsRec *keySyms, CARD8 *modmap) { DeviceIntPtr pDev; - /* From ProcSetModifierMapping */ - SendMappingNotify(darwinKeyboard, MappingModifier, 0, 0, serverClient); - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) - if (pDev->key && pDev->coreEvents) - SendDeviceMappingNotify(serverClient, MappingModifier, 0, 0, pDev); - - /* From ProcChangeKeyboardMapping */ for (pDev = inputInfo.devices; pDev; pDev = pDev->next) if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) - assert(SetKeySymsMap(&pDev->key->curKeySyms, keySyms)); - - SendMappingNotify(darwinKeyboard, MappingKeyboard, keySyms->minKeyCode, - keySyms->maxKeyCode - keySyms->minKeyCode + 1, serverClient); - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) - if (pDev->key && pDev->coreEvents) - SendDeviceMappingNotify(serverClient, MappingKeyboard, keySyms->minKeyCode, - keySyms->maxKeyCode - keySyms->minKeyCode + 1, pDev); + XkbApplyMappingChange(pDev, XkbKeySymsMask | XkbModifierMapMask, + keysyms, keysyms.minKeyCode, + keysyms.maxKeyCode - keysyms.minKeyCode + 1, + modmap, serverClient); } /* @@ -340,14 +329,11 @@ void DarwinKeyboardInit(DeviceIntPtr pDev) { //XkbSetRulesDflts("base", "pc105", "us", NULL, NULL); pthread_mutex_lock(&keyInfo_mutex); - assert(XkbInitKeyboardDeviceStruct(pDev, &names, &keySyms, keyInfo.modMap, - QuartzBell, DarwinChangeKeyboardControl)); - assert(pDev->key->xkbInfo->desc->map->modmap!=NULL); - memcpy(pDev->key->xkbInfo->desc->map->modmap, keyInfo.modMap, sizeof(keyInfo.modMap)); + assert(XkbInitKeyboardDeviceStruct(pDev, &names, &keySyms, QuartzBell, + DarwinChangeKeyboardControl)); + assert(keyInfo.modMap!=NULL); pthread_mutex_unlock(&keyInfo_mutex); - QuartzXkbUpdate(pDev); -#else pthread_mutex_lock(&keyInfo_mutex); assert( InitKeyboardDeviceStruct( (DevicePtr)pDev, &keySyms, QuartzBell, @@ -373,7 +359,7 @@ void DarwinKeyboardInit(DeviceIntPtr pDev) { XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOn); } - DarwinKeyboardSetDeviceKeyMap(&keySyms); + DarwinKeyboardSetDeviceKeyMap(&keySyms, keyInfo.modMap); } void DarwinKeyboardReloadHandler(int screenNum, xEventPtr xe, DeviceIntPtr pDev, int nevents) { diff --git a/include/exevents.h b/include/exevents.h index abe1a5f23..46df009a4 100644 --- a/include/exevents.h +++ b/include/exevents.h @@ -137,11 +137,8 @@ extern _X_EXPORT int SetButtonMapping ( int /* nElts */, BYTE * /* map */); -extern _X_EXPORT void SendDeviceMappingNotify( +extern _X_EXPORT void SendDevicePointerMappingNotify( ClientPtr /* client, */, - CARD8 /* request, */, - KeyCode /* firstKeyCode */, - CARD8 /* count */, DeviceIntPtr /* dev */); extern _X_EXPORT int ChangeKeyMapping( diff --git a/include/input.h b/include/input.h index a38dbfac0..8a774c963 100644 --- a/include/input.h +++ b/include/input.h @@ -368,11 +368,8 @@ extern _X_EXPORT Bool InitKeyboardDeviceStruct( BellProcPtr /*bellProc*/, KbdCtrlProcPtr /*controlProc*/); -extern _X_EXPORT void SendMappingNotify( +extern _X_EXPORT void SendPointerMappingNotify( DeviceIntPtr /* pDev */, - unsigned int /*request*/, - unsigned int /*firstKeyCode*/, - unsigned int /*count*/, ClientPtr /* client */); extern _X_EXPORT Bool BadDeviceMap( diff --git a/include/xkbsrv.h b/include/xkbsrv.h index b2b173627..54010eb0b 100644 --- a/include/xkbsrv.h +++ b/include/xkbsrv.h @@ -538,9 +538,10 @@ extern _X_EXPORT void XkbUpdateCoreDescription( extern _X_EXPORT void XkbApplyMappingChange( DeviceIntPtr /* pXDev */, - CARD8 /* request */, - KeyCode /* firstKey */, - CARD8 /* num */, + KeySymsPtr /* map */, + KeyCode /* firstKey */, + CARD8 /* num */, + CARD8 * /* modmap */, ClientPtr /* client */ ); @@ -955,8 +956,11 @@ extern _X_EXPORT void XkbSendNewKeyboardNotify( extern Bool XkbCopyKeymap( XkbDescPtr /* dst */, - XkbDescPtr /* src */, - Bool /* sendNotifies */); + XkbDescPtr /* src */); + +extern Bool XkbCopyDeviceKeymap( + DeviceIntPtr /* dst */, + DeviceIntPtr /* src */); #include "xkbfile.h" #include diff --git a/xkb/xkb.c b/xkb/xkb.c index b99b261e9..722141ca5 100644 --- a/xkb/xkb.c +++ b/xkb/xkb.c @@ -5837,8 +5837,7 @@ ProcXkbGetKbdByName(ClientPtr client) (dev->id == inputInfo.keyboard->id && tmpd->key && tmpd->coreEvents)) { if (tmpd != dev) - XkbCopyKeymap(dev->key->xkbInfo->desc, - tmpd->key->xkbInfo->desc, True); + XkbCopyDeviceKeymap(tmpd, dev); XkbUpdateCoreDescription(tmpd, True); if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) { diff --git a/xkb/xkbEvents.c b/xkb/xkbEvents.c index ed80b047c..6c2d32d75 100644 --- a/xkb/xkbEvents.c +++ b/xkb/xkbEvents.c @@ -35,6 +35,8 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include "inputstr.h" +#include "exevents.h" +#include "exglobals.h" #include "windowstr.h" #include "exevents.h" #include @@ -42,58 +44,151 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE. /***====================================================================***/ +/* + * This function sends out two kinds of notification: + * - Core mapping notify events sent to clients for whom kbd is the + * current core ('picked') keyboard _and_ have not explicitly + * selected for XKB mapping notify events; + * - Xi mapping events, sent unconditionally to all clients who have + * explicitly selected for them (including those who have explicitly + * selected for XKB mapping notify events!). + */ +static void +XkbSendLegacyMapNotify(DeviceIntPtr kbd, CARD16 xkb_event, CARD16 changed, + int first_key, int num_keys) +{ + int i; + int keymap_changed = 0; + int modmap_changed = 0; + xEvent core_mn; + deviceMappingNotify xi_mn; + CARD32 time = GetTimeInMillis(); + + if (xkb_event == XkbNewKeyboardNotify) { + if (changed & XkbNKN_KeycodesMask) { + keymap_changed = 1; + modmap_changed = 1; + } + } + else if (xkb_event == XkbMapNotify) { + if (changed & XkbKeySymsMask) + keymap_changed = 1; + if (changed & XkbModifierMapMask) + modmap_changed = 1; + } + if (!keymap_changed && !modmap_changed) + return; + + core_mn.u.u.type = MappingNotify; + xi_mn.type = DeviceMappingNotify; + xi_mn.deviceid = kbd->id; + xi_mn.time = time; + + /* 0 is serverClient. */ + for (i = 1; i < currentMaxClients; i++) { + if (!clients[i] || clients[i]->clientState != ClientStateRunning) + continue; + + /* Ignore clients which will have already received this. + * Inconsistent with themselves, but consistent with previous + * behaviour.*/ + if (xkb_event == XkbMapNotify && (clients[i]->mapNotifyMask & changed)) + continue; + if (xkb_event == XkbNewKeyboardNotify && + (clients[i]->xkbClientFlags & _XkbClientInitialized)) + continue; + + /* Don't send core events to clients who don't know about us. */ + if (!XIShouldNotify(clients[i], kbd)) + continue; + + core_mn.u.u.sequenceNumber = clients[i]->sequence; + if (keymap_changed) { + core_mn.u.mappingNotify.request = MappingKeyboard; + + /* Clip the keycode range to what the client knows about, so it + * doesn't freak out. */ + if (first_key >= clients[i]->minKC) + core_mn.u.mappingNotify.firstKeyCode = first_key; + else + core_mn.u.mappingNotify.firstKeyCode = clients[i]->minKC; + if (first_key + num_keys - 1 <= clients[i]->maxKC) + core_mn.u.mappingNotify.count = num_keys; + else + core_mn.u.mappingNotify.count = clients[i]->maxKC - + clients[i]->minKC + 1; + + WriteEventsToClient(clients[i], 1, &core_mn); + } + if (modmap_changed) { + core_mn.u.mappingNotify.request = MappingModifier; + core_mn.u.mappingNotify.firstKeyCode = 0; + core_mn.u.mappingNotify.count = 0; + WriteEventsToClient(clients[i], 1, &core_mn); + } + } + + /* Hmm, maybe we can accidentally generate Xi events for core devices + * here? Clients might be upset, but that seems better than the + * alternative of stale keymaps. -ds */ + if (keymap_changed) { + xi_mn.request = MappingKeyboard; + xi_mn.firstKeyCode = first_key; + xi_mn.count = num_keys; + SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn, + 1); + } + if (modmap_changed) { + xi_mn.request = MappingModifier; + xi_mn.firstKeyCode = 0; + xi_mn.count = 0; + SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn, + 1); + } +} + +/***====================================================================***/ + void XkbSendNewKeyboardNotify(DeviceIntPtr kbd,xkbNewKeyboardNotify *pNKN) -{ -register int i; -Time time; -CARD16 changed; +{ + int i; + Time time = GetTimeInMillis(); + CARD16 changed = pNKN->changed; pNKN->type = XkbEventCode + XkbEventBase; pNKN->xkbType = XkbNewKeyboardNotify; - pNKN->time = time = GetTimeInMillis(); - changed = pNKN->changed; for (i=1; iclientGone || - (clients[i]->requestVector==InitialVector)) { - continue; - } + if (!clients[i] || clients[i]->clientState != ClientStateRunning) + continue; - if (clients[i]->xkbClientFlags&_XkbClientInitialized) { - if (clients[i]->newKeyboardNotifyMask&changed) { - pNKN->sequenceNumber = clients[i]->sequence; - pNKN->time = time; - pNKN->changed = changed; - if ( clients[i]->swapped ) { - register int n; - swaps(&pNKN->sequenceNumber,n); - swapl(&pNKN->time,n); - swaps(&pNKN->changed,n); - } - WriteToClient(clients[i],sizeof(xEvent),(char *)pNKN); - if (changed&XkbNKN_KeycodesMask) { - clients[i]->minKC= pNKN->minKeyCode; - clients[i]->maxKC= pNKN->maxKeyCode; - } - } - } - else if (changed&XkbNKN_KeycodesMask) { - xEvent event; - event.u.u.type= MappingNotify; - event.u.mappingNotify.request= MappingKeyboard; - event.u.mappingNotify.firstKeyCode= clients[i]->minKC; - event.u.mappingNotify.count= clients[i]->maxKC-clients[i]->minKC+1; - event.u.u.sequenceNumber= clients[i]->sequence; - if (clients[i]->swapped) { - int n; - swaps(&event.u.u.sequenceNumber,n); - } - WriteToClient(clients[i],SIZEOF(xEvent), (char *)&event); - event.u.mappingNotify.request= MappingModifier; - WriteToClient(clients[i],SIZEOF(xEvent), (char *)&event); - } + if (!(clients[i]->newKeyboardNotifyMask & changed)) + continue; + + if (!XIShouldNotify(clients[i], kbd)) + continue; + + pNKN->sequenceNumber = clients[i]->sequence; + pNKN->time = time; + pNKN->changed = changed; + if (clients[i]->swapped) { + int n; + swaps(&pNKN->sequenceNumber,n); + swapl(&pNKN->time,n); + swaps(&pNKN->changed,n); + } + WriteToClient(clients[i], sizeof(xEvent), pNKN); + + if (changed & XkbNKN_KeycodesMask) { + clients[i]->minKC = pNKN->minKeyCode; + clients[i]->maxKC = pNKN->maxKeyCode; + } } + + XkbSendLegacyMapNotify(kbd, XkbNewKeyboardNotify, changed, pNKN->minKeyCode, + pNKN->maxKeyCode - pNKN->minKeyCode + 1); + return; } @@ -139,7 +234,8 @@ register CARD16 changed,bState; if ((!interest->client->clientGone) && (interest->client->requestVector != InitialVector) && (interest->client->xkbClientFlags&_XkbClientInitialized) && - (interest->stateNotifyMask&changed)) { + (interest->stateNotifyMask&changed) && + XIShouldNotify(interest->client,kbd)) { pSN->sequenceNumber = interest->client->sequence; pSN->time = time; pSN->changed = changed; @@ -160,49 +256,50 @@ register CARD16 changed,bState; /***====================================================================***/ +/* + * This function sends out XKB mapping notify events to clients which + * have explicitly selected for them. Core and Xi events are handled by + * XkbSendLegacyMapNotify. */ void -XkbSendMapNotify(DeviceIntPtr kbd,xkbMapNotify *pMN) +XkbSendMapNotify(DeviceIntPtr kbd, xkbMapNotify *pMN) { -int i; -XkbSrvInfoPtr xkbi; -unsigned time = 0,initialized; -CARD16 changed; + int i; + CARD32 time = GetTimeInMillis(); + CARD16 changed = pMN->changed; + XkbSrvInfoPtr xkbi = kbd->key->xkbInfo; - if (!kbd->key || !kbd->key->xkbInfo) - return; + pMN->minKeyCode = xkbi->desc->min_key_code; + pMN->maxKeyCode = xkbi->desc->max_key_code; + pMN->type = XkbEventCode + XkbEventBase; + pMN->xkbType = XkbMapNotify; + pMN->deviceID = kbd->id; - xkbi = kbd->key->xkbInfo; - initialized= 0; + /* 0 is serverClient. */ + for (i = 1; i < currentMaxClients; i++) { + if (!clients[i] || clients[i]->clientState != ClientStateRunning) + continue; - changed = pMN->changed; - pMN->minKeyCode= xkbi->desc->min_key_code; - pMN->maxKeyCode= xkbi->desc->max_key_code; - for (i=1; iclientGone && - (clients[i]->requestVector != InitialVector) && - (clients[i]->xkbClientFlags&_XkbClientInitialized) && - (clients[i]->mapNotifyMask&changed)) - { - if (!initialized) { - pMN->type = XkbEventCode + XkbEventBase; - pMN->xkbType = XkbMapNotify; - pMN->deviceID = kbd->id; - time = GetTimeInMillis(); - initialized= 1; - } - pMN->time= time; - pMN->sequenceNumber = clients[i]->sequence; - pMN->changed = changed; - if ( clients[i]->swapped ) { - register int n; - swaps(&pMN->sequenceNumber,n); - swapl(&pMN->time,n); - swaps(&pMN->changed,n); - } - WriteToClient(clients[i],sizeof(xEvent),(char *)pMN); - } + if (!(clients[i]->mapNotifyMask & changed)) + continue; + + if (!XIShouldNotify(clients[i], kbd)) + continue; + + pMN->time = time; + pMN->sequenceNumber = clients[i]->sequence; + pMN->changed = changed; + + if (clients[i]->swapped) { + int n; + swaps(&pMN->sequenceNumber, n); + swapl(&pMN->time, n); + swaps(&pMN->changed, n); + } + WriteToClient(clients[i], sizeof(xEvent), pMN); } - return; + + XkbSendLegacyMapNotify(kbd, XkbMapNotify, changed, pMN->firstKeySym, + pMN->nKeySyms); } int @@ -306,7 +403,8 @@ Time time = 0; if ((!interest->client->clientGone) && (interest->client->requestVector != InitialVector) && (interest->client->xkbClientFlags&_XkbClientInitialized) && - (interest->ctrlsNotifyMask&changedControls)) { + (interest->ctrlsNotifyMask&changedControls) && + XIShouldNotify(interest->client, kbd)) { if (!initialized) { pCN->type = XkbEventCode + XkbEventBase; pCN->xkbType = XkbControlsNotify; @@ -354,6 +452,7 @@ CARD32 state,changed; if ((!interest->client->clientGone) && (interest->client->requestVector != InitialVector) && (interest->client->xkbClientFlags&_XkbClientInitialized) && + XIShouldNotify(interest->client, kbd) && (((xkbType==XkbIndicatorStateNotify)&& (interest->iStateNotifyMask&changed))|| ((xkbType==XkbIndicatorMapNotify)&& @@ -437,7 +536,8 @@ XID winID = 0; if ((!interest->client->clientGone) && (interest->client->requestVector != InitialVector) && (interest->client->xkbClientFlags&_XkbClientInitialized) && - (interest->bellNotifyMask)) { + (interest->bellNotifyMask) && + XIShouldNotify(interest->client,kbd)) { if (!initialized) { time = GetTimeInMillis(); bn.type = XkbEventCode + XkbEventBase; @@ -491,7 +591,8 @@ CARD16 sk_delay,db_delay; if ((!interest->client->clientGone) && (interest->client->requestVector != InitialVector) && (interest->client->xkbClientFlags&_XkbClientInitialized) && - (interest->accessXNotifyMask&(1<detail))) { + (interest->accessXNotifyMask&(1<detail)) && + XIShouldNotify(interest->client, kbd)) { if (!initialized) { pEv->type = XkbEventCode + XkbEventBase; pEv->xkbType = XkbAccessXNotify; @@ -538,7 +639,8 @@ CARD32 changedIndicators; if ((!interest->client->clientGone) && (interest->client->requestVector != InitialVector) && (interest->client->xkbClientFlags&_XkbClientInitialized) && - (interest->namesNotifyMask&pEv->changed)) { + (interest->namesNotifyMask&pEv->changed) && + XIShouldNotify(interest->client, kbd)) { if (!initialized) { pEv->type = XkbEventCode + XkbEventBase; pEv->xkbType = XkbNamesNotify; @@ -583,7 +685,8 @@ CARD16 firstSI = 0, nSI = 0, nTotalSI = 0; if ((!interest->client->clientGone) && (interest->client->requestVector != InitialVector) && (interest->client->xkbClientFlags&_XkbClientInitialized) && - (interest->compatNotifyMask)) { + (interest->compatNotifyMask) && + XIShouldNotify(interest->client, kbd)) { if (!initialized) { pEv->type = XkbEventCode + XkbEventBase; pEv->xkbType = XkbCompatMapNotify; @@ -635,7 +738,8 @@ Time time = 0; if ((!interest->client->clientGone) && (interest->client->requestVector != InitialVector) && (interest->client->xkbClientFlags&_XkbClientInitialized) && - (interest->actionMessageMask)) { + (interest->actionMessageMask) && + XIShouldNotify(interest->client, kbd)) { if (!initialized) { pEv->type = XkbEventCode + XkbEventBase; pEv->xkbType = XkbActionMessage; @@ -681,7 +785,8 @@ CARD16 reason; if ((!interest->client->clientGone) && (interest->client->requestVector != InitialVector) && (interest->client->xkbClientFlags&_XkbClientInitialized) && - (interest->extDevNotifyMask&reason)) { + (interest->extDevNotifyMask&reason) && + XIShouldNotify(interest->client, dev)) { if (!initialized) { pEv->type = XkbEventCode + XkbEventBase; pEv->xkbType = XkbExtensionDeviceNotify; diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c index b07dceb80..89d38251f 100644 --- a/xkb/xkbUtils.c +++ b/xkb/xkbUtils.c @@ -563,41 +563,52 @@ XkbSetRepeatKeys(DeviceIntPtr pXDev,int key,int onoff) return; } +/* Applies a change to a single device, does not traverse the device tree. */ void -XkbApplyMappingChange( DeviceIntPtr kbd, - CARD8 request, - KeyCode firstKey, - CARD8 num, - ClientPtr client) +XkbApplyMappingChange(DeviceIntPtr kbd, KeySymsPtr map, KeyCode first_key, + CARD8 num_keys, CARD8 *modmap, ClientPtr client) { -XkbEventCauseRec cause; -XkbChangesRec changes; -unsigned check; + XkbDescPtr xkb = kbd->key->xkbInfo->desc; + XkbEventCauseRec cause; + XkbChangesRec changes; + unsigned int check; - bzero(&changes,sizeof(XkbChangesRec)); - check= 0; - if (request==MappingKeyboard) { - XkbSetCauseCoreReq(&cause,X_ChangeKeyboardMapping,client); - XkbUpdateKeyTypesFromCore(kbd,firstKey,num,&changes); - XkbUpdateActions(kbd,firstKey,num,&changes,&check,&cause); - if (check) - XkbCheckSecondaryEffects(kbd->key->xkbInfo,check,&changes,&cause); - } - else if (request==MappingModifier) { - XkbDescPtr xkb= kbd->key->xkbInfo->desc; + memset(&changes, 0, sizeof(changes)); + memset(&cause, 0, sizeof(cause)); - XkbSetCauseCoreReq(&cause,X_SetModifierMapping,client); - num = xkb->max_key_code-xkb->min_key_code+1; - changes.map.changed|= XkbModifierMapMask; - changes.map.first_modmap_key= xkb->min_key_code; - changes.map.num_modmap_keys= num; - XkbUpdateActions(kbd,xkb->min_key_code,num,&changes,&check,&cause); - if (check) - XkbCheckSecondaryEffects(kbd->key->xkbInfo,check,&changes,&cause); + if (map && first_key && num_keys) { + check = 0; + XkbSetCauseCoreReq(&cause, X_ChangeKeyboardMapping, client); + + if (!SetKeySymsMap(&kbd->key->curKeySyms, map)) + FatalError("XkbApplyMappingChange: failed to copy core keymap!\n"); + XkbUpdateKeyTypesFromCore(kbd, first_key, num_keys, &changes); + XkbUpdateActions(kbd, first_key, num_keys, &changes, &check, &cause); + + if (check) + XkbCheckSecondaryEffects(kbd->key->xkbInfo, 1, &changes, &cause); } - /* 3/26/94 (ef) -- XXX! Doesn't deal with input extension requests */ - XkbSendNotification(kbd,&changes,&cause); - return; + + if (modmap) { + /* A keymap change can imply a modmap change, se we prefer the + * former. */ + if (!cause.mjr) + XkbSetCauseCoreReq(&cause,X_SetModifierMapping,client); + + check = 0; + num_keys = xkb->max_key_code - xkb->min_key_code + 1; + changes.map.changed |= XkbModifierMapMask; + changes.map.first_modmap_key = xkb->min_key_code; + changes.map.num_modmap_keys = num_keys; + memcpy(kbd->key->xkbInfo->desc->map->modmap, modmap, MAP_LENGTH); + XkbUpdateActions(kbd, xkb->min_key_code, num_keys, &changes, &check, + &cause); + + if (check) + XkbCheckSecondaryEffects(kbd->key->xkbInfo, 1, &changes, &cause); + } + + XkbSendNotification(kbd, &changes, &cause); } void @@ -2062,17 +2073,8 @@ _XkbCopyControls(XkbDescPtr src, XkbDescPtr dst) */ Bool -XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies) +XkbCopyKeymap(XkbDescPtr dst, XkbDescPtr src) { - DeviceIntPtr pDev = NULL, tmpDev = NULL; - xkbMapNotify mn; - xkbNewKeyboardNotify nkn; - XkbEventCauseRec cause; - XkbChangesRec changes; - unsigned int check = 0; - - memset(&changes, 0, sizeof(changes)); - memset(&cause, 0, sizeof(cause)); if (!src || !dst) { DebugF("XkbCopyKeymap: src (%p) or dst (%p) is NULL\n", src, dst); @@ -2111,79 +2113,36 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies) return FALSE; } - for (tmpDev = inputInfo.devices; tmpDev && !pDev; tmpDev = tmpDev->next) { - if (tmpDev->key && tmpDev->key->xkbInfo && - tmpDev->key->xkbInfo->desc == dst) { - pDev = tmpDev; - break; - } - } - for (tmpDev = inputInfo.off_devices; tmpDev && !pDev; - tmpDev = tmpDev->next) { - if (tmpDev->key && tmpDev->key->xkbInfo && - tmpDev->key->xkbInfo->desc == dst) { - pDev = tmpDev; - break; - } - } - - if (sendNotifies) { - if (!pDev) { - ErrorF("[xkb] XkbCopyKeymap: asked for notifies, but can't find device!\n"); - } - else { - /* send NewKeyboardNotify if the keycode range changed, else - * just MapNotify. we also need to send NKN if the geometry - * changed (obviously ...). */ - if ((src->min_key_code != dst->min_key_code || - src->max_key_code != dst->max_key_code)) { - nkn.oldMinKeyCode = dst->min_key_code; - nkn.oldMaxKeyCode = dst->max_key_code; - nkn.deviceID = nkn.oldDeviceID = pDev->id; - nkn.minKeyCode = src->min_key_code; - nkn.maxKeyCode = src->max_key_code; - nkn.requestMajor = XkbReqCode; - nkn.requestMinor = X_kbSetMap; /* XXX bare-faced lie */ - nkn.changed = XkbAllNewKeyboardEventsMask; - XkbSendNewKeyboardNotify(pDev, &nkn); - } else - { - mn.deviceID = pDev->id; - mn.minKeyCode = src->min_key_code; - mn.maxKeyCode = src->max_key_code; - mn.firstType = 0; - mn.nTypes = src->map->num_types; - mn.firstKeySym = src->min_key_code; - mn.nKeySyms = XkbNumKeys(src); - mn.firstKeyAct = src->min_key_code; - mn.nKeyActs = XkbNumKeys(src); - /* Cargo-culted from ProcXkbGetMap. */ - mn.firstKeyBehavior = src->min_key_code; - mn.nKeyBehaviors = XkbNumKeys(src); - mn.firstKeyExplicit = src->min_key_code; - mn.nKeyExplicit = XkbNumKeys(src); - mn.firstModMapKey = src->min_key_code; - mn.nModMapKeys = XkbNumKeys(src); - mn.firstVModMapKey = src->min_key_code; - mn.nVModMapKeys = XkbNumKeys(src); - mn.virtualMods = ~0; /* ??? */ - mn.changed = XkbAllMapComponentsMask; - XkbSendMapNotify(pDev, &mn); - } - - XkbUpdateActions(pDev, dst->min_key_code, - XkbNumKeys(pDev->key->xkbInfo->desc), &changes, - &check, &cause); - if (check) - XkbCheckSecondaryEffects(pDev->key->xkbInfo, check, &changes, - &cause); - memcpy(pDev->kbdfeed->ctrl.autoRepeats, dst->ctrls->per_key_repeat, - XkbPerKeyBitArraySize); - } - } - dst->min_key_code = src->min_key_code; dst->max_key_code = src->max_key_code; return TRUE; } + +Bool +XkbCopyDeviceKeymap(DeviceIntPtr dst, DeviceIntPtr src) +{ + xkbNewKeyboardNotify nkn; + Bool ret; + + if (!dst->key || !src->key) + return FALSE; + + nkn.oldMinKeyCode = dst->key->xkbInfo->desc->min_key_code; + nkn.oldMaxKeyCode = dst->key->xkbInfo->desc->max_key_code; + nkn.deviceID = dst->id; + nkn.oldDeviceID = dst->id; /* maybe src->id? */ + nkn.minKeyCode = src->key->xkbInfo->desc->min_key_code; + nkn.maxKeyCode = src->key->xkbInfo->desc->max_key_code; + nkn.requestMajor = XkbReqCode; + nkn.requestMinor = X_kbSetMap; /* Near enough's good enough. */ + nkn.changed = XkbNKN_KeycodesMask; + if (src->key->xkbInfo->desc->geom) + nkn.changed |= XkbNKN_GeometryMask; + + ret = XkbCopyKeymap(dst->key->xkbInfo->desc, src->key->xkbInfo->desc); + if (ret) + XkbSendNewKeyboardNotify(dst, &nkn); + + return ret; +}