Input: Clean up keymap change notifications

Keyboard map notifications are always generated from within XKB code,
which also takes care of copying the keysyms, etc.  If you need to
mangle the keymap yourself, generate a new core keymap/modmap, and pass
it to XkbApplyMappingChange.

SendMappingNotify is renamed to SendPointerMappingNotify (and ditto its
Device variants), which still only _sends_ the notifications, as opposed
to also doing the copying a la XkbApplyMappingChange.

Also have the modmap change code traverse the device hierachy, rather
than just going off the core keyboard.

Signed-off-by: Daniel Stone <daniel@fooishbar.org>
This commit is contained in:
Daniel Stone 2008-10-18 20:59:30 +01:00
parent 1d1a0f67ee
commit f06a9d2e05
11 changed files with 382 additions and 362 deletions

View File

@ -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;
}

View File

@ -121,7 +121,8 @@ ProcXSetDeviceButtonMapping(ClientPtr client)
}
if (ret != MappingBusy)
SendDeviceMappingNotify(client, MappingPointer, 0, 0, dev);
SendDevicePointerMappingNotify(client, dev);
return Success;
}

View File

@ -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; i<currentMaxClients; i++)
{
if (clients[i] && clients[i]->clientState == 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;
}

View File

@ -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);
}
}
}

View File

@ -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) {

View File

@ -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(

View File

@ -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(

View File

@ -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 <X11/extensions/XKMformat.h>

View File

@ -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) {

View File

@ -35,6 +35,8 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <X11/extensions/XI.h>
#include <X11/extensions/XIproto.h>
#include "inputstr.h"
#include "exevents.h"
#include "exglobals.h"
#include "windowstr.h"
#include "exevents.h"
#include <xkbsrv.h>
@ -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; i<currentMaxClients; i++) {
if ((!clients[i]) || clients[i]->clientGone ||
(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; i<currentMaxClients; i++) {
if (clients[i] && ! clients[i]->clientGone &&
(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<<pEv->detail))) {
(interest->accessXNotifyMask&(1<<pEv->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;

View File

@ -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;
}