xkb/gkve: copy XKB map, not pointer-assign
Write a new function to copy an XKB map (does everything but geometry at the moment), and use that instead of nasty pointer assignments.
This commit is contained in:
parent
a56b98bb04
commit
8f8487ff99
|
@ -260,16 +260,6 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEVICE_CLOSE:
|
case DEVICE_CLOSE:
|
||||||
/* This, uh, probably requires some explanation.
|
|
||||||
* Press a key on another keyboard.
|
|
||||||
* Watch its xkbInfo get pivoted into core's.
|
|
||||||
* Kill the server.
|
|
||||||
* Watch the first device's xkbInfo get freed.
|
|
||||||
* Try to free ours, which points to same.
|
|
||||||
*
|
|
||||||
* ... yeah.
|
|
||||||
*/
|
|
||||||
pDev->key->xkbInfo = NULL;
|
|
||||||
pDev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
|
pDev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
10
dix/events.c
10
dix/events.c
|
@ -4802,14 +4802,8 @@ int GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type,
|
||||||
mn.virtualMods = ~0; /* ??? */
|
mn.virtualMods = ~0; /* ??? */
|
||||||
mn.changed = XkbAllMapComponentsMask;
|
mn.changed = XkbAllMapComponentsMask;
|
||||||
|
|
||||||
/* If this is still the map we set at DEVICE_INIT, free it so
|
if (!XkbCopyKeymap(pDev->key->xkbInfo, ckeyc->xkbInfo))
|
||||||
* it doesn't just get lost. (Shameful hack, sorry.) */
|
FatalError("Couldn't pivot keymap from device to core!\n");
|
||||||
if (!inputInfo.keyboard->devPrivates[CoreDevicePrivatesIndex].ptr &&
|
|
||||||
ckeyc->xkbInfo)
|
|
||||||
XkbFreeInfo(ckeyc->xkbInfo);
|
|
||||||
/* FIXME we really need a map copy here. */
|
|
||||||
ckeyc->xkbInfo = pDev->key->xkbInfo;
|
|
||||||
XkbSendMapNotify(inputInfo.keyboard, &mn);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
SendMappingNotify(MappingKeyboard, ckeyc->curKeySyms.minKeyCode,
|
SendMappingNotify(MappingKeyboard, ckeyc->curKeySyms.minKeyCode,
|
||||||
|
|
|
@ -72,3 +72,7 @@ extern Bool XkbDDXCompileKeymapByNames(
|
||||||
unsigned need,
|
unsigned need,
|
||||||
char * nameRtrn,
|
char * nameRtrn,
|
||||||
int nameRtrnLen);
|
int nameRtrnLen);
|
||||||
|
|
||||||
|
extern Bool XkbCopyKeymap(
|
||||||
|
XkbDescPtr src,
|
||||||
|
XkbDescPtr dst);
|
||||||
|
|
404
xkb/xkbUtils.c
404
xkb/xkbUtils.c
|
@ -969,3 +969,407 @@ XkbConvertCase(register KeySym sym, KeySym *lower, KeySym *upper)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy an XKB map from src to dst, reallocating when necessary: if some
|
||||||
|
* map components are present in one, but not in the other, the destination
|
||||||
|
* components will be allocated or freed as necessary.
|
||||||
|
*
|
||||||
|
* Basic map consistency is assumed on both sides, so maps with random
|
||||||
|
* uninitialised data (e.g. names->radio_grous == NULL, names->num_rg == 19)
|
||||||
|
* _will_ cause failures. You've been warned.
|
||||||
|
*
|
||||||
|
* Returns TRUE on success, or FALSE on failure. If this function fails,
|
||||||
|
* dst may be in an inconsistent state: all its pointers are guaranteed
|
||||||
|
* to remain valid, but part of the map may be from src and part from dst.
|
||||||
|
*/
|
||||||
|
Bool
|
||||||
|
XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst)
|
||||||
|
{
|
||||||
|
int i = 0, j = 0;
|
||||||
|
void *tmp = NULL;
|
||||||
|
XkbKeyTypePtr stype = NULL, dtype = NULL;
|
||||||
|
|
||||||
|
if (!src || !dst)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* client map */
|
||||||
|
if (src->map) {
|
||||||
|
if (!dst->map) {
|
||||||
|
tmp = xcalloc(1, sizeof(XkbClientMapRec));
|
||||||
|
if (!tmp)
|
||||||
|
return FALSE;
|
||||||
|
dst->map = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->map->syms) {
|
||||||
|
if (src->map->size_syms != dst->map->size_syms) {
|
||||||
|
if (dst->map->syms)
|
||||||
|
tmp = xrealloc(dst->map->syms, src->map->size_syms);
|
||||||
|
else
|
||||||
|
tmp = xalloc(src->map->size_syms);
|
||||||
|
if (!tmp)
|
||||||
|
return FALSE;
|
||||||
|
dst->map->syms = tmp;
|
||||||
|
}
|
||||||
|
memcpy(dst->map->syms, src->map->syms, src->map->size_syms);
|
||||||
|
memcpy(dst->map->key_sym_map, src->map->key_sym_map,
|
||||||
|
src->map->size_syms);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->map->syms) {
|
||||||
|
xfree(dst->map->syms);
|
||||||
|
dst->map->syms = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dst->map->num_syms = src->map->num_syms;
|
||||||
|
dst->map->size_syms = src->map->size_syms;
|
||||||
|
|
||||||
|
if (src->map->types) {
|
||||||
|
if (src->map->size_types != dst->map->size_types) {
|
||||||
|
XkbKeyTypePtr stype = src->map->types;
|
||||||
|
|
||||||
|
if (dst->map->types)
|
||||||
|
tmp = xrealloc(dst->map->types, src->map->size_types);
|
||||||
|
else
|
||||||
|
tmp = xalloc(src->map->size_types);
|
||||||
|
if (!tmp)
|
||||||
|
return FALSE;
|
||||||
|
dst->map->types = tmp;
|
||||||
|
}
|
||||||
|
memcpy(dst->map->types, src->map->types, src->map->size_types);
|
||||||
|
|
||||||
|
stype = src->map->types;
|
||||||
|
dtype = dst->map->types;
|
||||||
|
for (i = 0; i < dst->map->num_types; i++, dtype++, stype++) {
|
||||||
|
dtype->level_names = xalloc(dtype->num_levels * sizeof(Atom));
|
||||||
|
if (!dtype->level_names)
|
||||||
|
continue; /* don't return FALSE here, try to whack all the
|
||||||
|
pointers we can, so we don't double-free when
|
||||||
|
going down. */
|
||||||
|
memcpy(dtype->level_names, stype->level_names,
|
||||||
|
dtype->num_levels * sizeof(Atom));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->map->types) {
|
||||||
|
for (i = 0, dtype = dst->map->types; i < dst->map->num_types;
|
||||||
|
i++, dtype++)
|
||||||
|
xfree(dtype->level_names);
|
||||||
|
xfree(dst->map->types);
|
||||||
|
dst->map->types = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dst->map->size_types = src->map->size_types;
|
||||||
|
dst->map->num_types = src->map->num_types;
|
||||||
|
|
||||||
|
if (src->map->modmap) {
|
||||||
|
if (src->max_key_code != dst->max_key_code) {
|
||||||
|
if (dst->map->modmap)
|
||||||
|
tmp = xrealloc(dst->map->modmap, src->max_key_code + 1);
|
||||||
|
else
|
||||||
|
tmp = xalloc(src->max_key_code + 1);
|
||||||
|
if (!tmp)
|
||||||
|
return FALSE;
|
||||||
|
dst->map->syms = tmp;
|
||||||
|
}
|
||||||
|
memcpy(dst->map->modmap, src->map->modmap, src->max_key_code + 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->map->modmap) {
|
||||||
|
xfree(dst->map->modmap);
|
||||||
|
dst->map->modmap = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->map)
|
||||||
|
XkbFreeClientMap(dst, XkbAllClientInfoMask, True);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* server map */
|
||||||
|
if (src->server) {
|
||||||
|
if (!dst->server) {
|
||||||
|
tmp = xcalloc(1, sizeof(XkbServerMapRec));
|
||||||
|
if (!tmp)
|
||||||
|
return FALSE;
|
||||||
|
dst->server = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->server->explicit) {
|
||||||
|
if (src->max_key_code != dst->max_key_code) {
|
||||||
|
if (dst->server->explicit)
|
||||||
|
tmp = xrealloc(dst->server->explicit, src->max_key_code + 1);
|
||||||
|
else
|
||||||
|
tmp = xalloc(src->max_key_code + 1);
|
||||||
|
if (!tmp)
|
||||||
|
return FALSE;
|
||||||
|
dst->server->explicit = tmp;
|
||||||
|
}
|
||||||
|
memcpy(dst->server->explicit, src->server->explicit,
|
||||||
|
src->max_key_code + 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->server->explicit) {
|
||||||
|
xfree(dst->server->explicit);
|
||||||
|
dst->server->explicit = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->server->acts) {
|
||||||
|
if (src->server->size_acts != dst->server->size_acts) {
|
||||||
|
if (dst->server->acts)
|
||||||
|
tmp = xrealloc(dst->server->acts, src->server->size_acts);
|
||||||
|
else
|
||||||
|
tmp = xalloc(src->server->size_acts);
|
||||||
|
if (!tmp)
|
||||||
|
return FALSE;
|
||||||
|
dst->server->acts = tmp;
|
||||||
|
}
|
||||||
|
memcpy(dst->server->acts, src->server->acts,
|
||||||
|
src->server->size_acts);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->server->acts) {
|
||||||
|
xfree(dst->server->acts);
|
||||||
|
dst->server->acts = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dst->server->size_acts = src->server->size_acts;
|
||||||
|
|
||||||
|
if (src->server->key_acts) {
|
||||||
|
if (src->max_key_code != dst->max_key_code) {
|
||||||
|
if (dst->server->key_acts)
|
||||||
|
tmp = xrealloc(dst->server->key_acts, src->max_key_code + 1);
|
||||||
|
else
|
||||||
|
tmp = xalloc(src->max_key_code + 1);
|
||||||
|
if (!tmp)
|
||||||
|
return FALSE;
|
||||||
|
dst->server->key_acts = tmp;
|
||||||
|
}
|
||||||
|
memcpy(dst->server->key_acts, src->server->key_acts,
|
||||||
|
src->max_key_code + 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->server->key_acts) {
|
||||||
|
xfree(dst->server->key_acts);
|
||||||
|
dst->server->key_acts = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->server->behaviors) {
|
||||||
|
if (src->max_key_code != dst->max_key_code) {
|
||||||
|
if (dst->server->behaviors)
|
||||||
|
tmp = xrealloc(dst->server->behaviors,
|
||||||
|
(src->max_key_code + 1) *
|
||||||
|
sizeof(XkbBehavior));
|
||||||
|
else
|
||||||
|
tmp = xalloc((src->max_key_code + 1) *
|
||||||
|
sizeof(XkbBehavior));
|
||||||
|
if (!tmp)
|
||||||
|
return FALSE;
|
||||||
|
dst->server->behaviors = tmp;
|
||||||
|
}
|
||||||
|
memcpy(dst->server->behaviors, src->server->behaviors,
|
||||||
|
(src->max_key_code + 1) * sizeof(XkbBehavior));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->server->behaviors) {
|
||||||
|
xfree(dst->server->behaviors);
|
||||||
|
dst->server->behaviors = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->server->vmodmap) {
|
||||||
|
if (src->max_key_code != dst->max_key_code) {
|
||||||
|
if (dst->server->vmodmap)
|
||||||
|
tmp = xrealloc(dst->server->vmodmap,
|
||||||
|
src->max_key_code + 1);
|
||||||
|
else
|
||||||
|
tmp = xalloc(src->max_key_code + 1);
|
||||||
|
if (!tmp)
|
||||||
|
return FALSE;
|
||||||
|
dst->server->vmodmap = tmp;
|
||||||
|
}
|
||||||
|
memcpy(dst->server->vmodmap, src->server->vmodmap,
|
||||||
|
src->max_key_code + 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->server->vmodmap) {
|
||||||
|
xfree(dst->server->vmodmap);
|
||||||
|
dst->server->vmodmap = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->server)
|
||||||
|
XkbFreeServerMap(dst, XkbAllServerInfoMask, True);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* indicators */
|
||||||
|
if (src->indicators) {
|
||||||
|
if (!dst->indicators) {
|
||||||
|
dst->indicators = xalloc(sizeof(XkbIndicatorRec));
|
||||||
|
if (!dst->indicators)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
memcpy(dst->indicators, src->indicators, sizeof(XkbIndicatorRec));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->indicators) {
|
||||||
|
xfree(dst->indicators);
|
||||||
|
dst->indicators = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* controls */
|
||||||
|
if (src->ctrls) {
|
||||||
|
if (!dst->ctrls) {
|
||||||
|
dst->ctrls = xalloc(sizeof(XkbControlsRec));
|
||||||
|
if (!dst->ctrls)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
memcpy(dst->ctrls, src->ctrls, sizeof(XkbControlsRec));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->ctrls) {
|
||||||
|
xfree(dst->ctrls);
|
||||||
|
dst->ctrls = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* names */
|
||||||
|
if (src->names) {
|
||||||
|
if (!dst->names) {
|
||||||
|
dst->names = xcalloc(1, sizeof(XkbNamesRec));
|
||||||
|
if (!dst->names)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->names->keys) {
|
||||||
|
if (src->max_key_code != dst->max_key_code) {
|
||||||
|
if (dst->names->keys)
|
||||||
|
tmp = xrealloc(dst->names->keys, (src->max_key_code + 1) *
|
||||||
|
sizeof(XkbKeyNameRec));
|
||||||
|
else
|
||||||
|
tmp = xalloc((src->max_key_code + 1) *
|
||||||
|
sizeof(XkbKeyNameRec));
|
||||||
|
if (!tmp)
|
||||||
|
return FALSE;
|
||||||
|
dst->names->keys = tmp;
|
||||||
|
}
|
||||||
|
memcpy(dst->names->keys, src->names->keys,
|
||||||
|
(src->max_key_code + 1) * sizeof(XkbKeyNameRec));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->names->keys) {
|
||||||
|
xfree(dst->names->keys);
|
||||||
|
dst->names->keys = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->names->num_key_aliases) {
|
||||||
|
if (src->names->num_key_aliases != dst->names->num_key_aliases) {
|
||||||
|
if (dst->names->key_aliases)
|
||||||
|
tmp = xrealloc(dst->names->key_aliases,
|
||||||
|
src->names->num_key_aliases *
|
||||||
|
sizeof(XkbKeyAliasRec));
|
||||||
|
else
|
||||||
|
tmp = xalloc(src->names->num_key_aliases *
|
||||||
|
sizeof(XkbKeyAliasRec));
|
||||||
|
if (!tmp)
|
||||||
|
return FALSE;
|
||||||
|
dst->names->key_aliases = tmp;
|
||||||
|
}
|
||||||
|
memcpy(dst->names->key_aliases, src->names->key_aliases,
|
||||||
|
src->names->num_key_aliases * sizeof(XkbKeyAliasRec));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->names->key_aliases) {
|
||||||
|
xfree(dst->names->key_aliases);
|
||||||
|
dst->names->key_aliases = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dst->names->num_key_aliases = src->names->num_key_aliases;
|
||||||
|
|
||||||
|
if (src->names->num_rg) {
|
||||||
|
if (src->names->num_rg != dst->names->num_rg) {
|
||||||
|
if (dst->names->radio_groups)
|
||||||
|
tmp = xrealloc(dst->names->radio_groups,
|
||||||
|
src->names->num_rg * sizeof(Atom));
|
||||||
|
else
|
||||||
|
tmp = xalloc(src->names->num_rg * sizeof(Atom));
|
||||||
|
if (!tmp)
|
||||||
|
return FALSE;
|
||||||
|
dst->names->radio_groups = tmp;
|
||||||
|
}
|
||||||
|
memcpy(dst->names->radio_groups, src->names->radio_groups,
|
||||||
|
src->names->num_rg * sizeof(Atom));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->names->radio_groups)
|
||||||
|
xfree(dst->names->radio_groups);
|
||||||
|
}
|
||||||
|
dst->names->num_rg = src->names->num_rg;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->names)
|
||||||
|
XkbFreeNames(dst, XkbAllNamesMask, True);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compat */
|
||||||
|
if (src->compat) {
|
||||||
|
if (src->compat->sym_interpret) {
|
||||||
|
if (src->compat->num_si != dst->compat->num_si) {
|
||||||
|
if (dst->compat->sym_interpret)
|
||||||
|
tmp = xrealloc(dst->compat->sym_interpret,
|
||||||
|
src->compat->num_si *
|
||||||
|
sizeof(XkbSymInterpretRec));
|
||||||
|
else
|
||||||
|
tmp = xalloc(src->compat->num_si *
|
||||||
|
sizeof(XkbSymInterpretRec));
|
||||||
|
if (!tmp)
|
||||||
|
return FALSE;
|
||||||
|
dst->compat->sym_interpret = tmp;
|
||||||
|
}
|
||||||
|
memcpy(dst->compat->sym_interpret, src->compat->sym_interpret,
|
||||||
|
src->compat->num_si * sizeof(XkbSymInterpretRec));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->compat->sym_interpret) {
|
||||||
|
xfree(dst->compat->sym_interpret);
|
||||||
|
dst->compat->sym_interpret = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dst->compat->num_si = src->compat->num_si;
|
||||||
|
|
||||||
|
memcpy(dst->compat->groups, src->compat->groups,
|
||||||
|
XkbNumKbdGroups * sizeof(XkbModsRec));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->compat)
|
||||||
|
XkbFreeCompatMap(dst, XkbAllCompatMask, True);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* geometry */
|
||||||
|
if (src->geom) {
|
||||||
|
/* properties */
|
||||||
|
/* colors */
|
||||||
|
/* shapes */
|
||||||
|
/* sections */
|
||||||
|
/* doodads */
|
||||||
|
/* key aliases */
|
||||||
|
/* font?!? */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dst->geom) {
|
||||||
|
XkbFreeGeometry(dst->geom, XkbGeomAllMask, True);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dst->min_key_code = src->min_key_code;
|
||||||
|
dst->max_key_code = src->max_key_code;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user