several fixes for XKB
[email protected] (Michal Maruška)
| Newsgroups | gmane.comp.xfree86.devel |
|---|---|
| Message-ID | <[email protected]> |
hello fellow _xfree86_ hackers! In order to provide to my friends, and maybe one day customers, a way to type differently, as described at http://maruska.dyndns.org/wiki/forkExtension.html ... i would like to donate a necessary infrastructure to xfree86 project, to be distributed under the xfree86 version 1.1 licence. I also provide patches exclusively under this license. I'm working on the documentation (and final patches), which i will send here as several emails, you can see a pre-version at: http://maruska.dyndns.org/wiki/x-plugin In this email, I provide some patches(against CVS)/fixes for XKB: * memory allocation in file lib/X11/XKBMAlloc.c ** off-by-one errors. bzero-ing wrong regions. This is only triggered by a keyboard driver, which (at start) registers <256 keycodes. It is also impossible to change the interval of *core* valid keycodes. I have hacked a (probably unacceptable) workaround, by updating ConnectionInfo (from DIX). A part of my work is a new keyboard driver ( http://maruska.dyndns.org/wiki/medved ), and if this workaround is not accepted (nor easily corrected), i'll just force registering of all 256 keycodes. ** growing tables w/o never shrinking. table of XKB actions and keysyms. (i provide comments in the patch) * client requests for info lib/X11/XKBGetMap.c various vmodmap vs. modmap "incomplete cut-n-paste" bugs * client request to change XKB configuration failing (ProcXkbSetMap) programs/Xserver/xkb/xkb.c if the client request does not specify (XKB) types, the request fails. * notify event processing in lib/X11/XKBUse.c If number of XKB types changes (by calling apropriate functions), the XKB-unaware applications (eg. xterm) don't notice it! In other words (client side) synthesized core X events were not sufficiently informative. Next patches (some against the same files) will not contain these modifications (i hope).
xkb.patch
(text/x-patch, 16.3 KB)
--- /linux/13/x/xfree86/xc/lib/X11/XKBGetMap.c 2003-11-17 23:20:09.000000000 +0100
+++ lib/X11/XKBGetMap.c 2005-04-12 22:13:22.000000000 +0200
@@ -150,6 +150,7 @@
register int i;
XkbClientMapPtr map;
+ if ( rep->totalSyms>0 ) { /* mmc: */
map= xkb->map;
if (map->key_sym_map==NULL) {
register int offset;
@@ -236,6 +237,7 @@
oldMap->width = newMap->width;
}
}
+ }
return Success;
}
@@ -263,8 +265,16 @@
ret = BadLength;
goto done;
}
+#if 0
+ /* mmc: this probably should check that the number of actions & keysyms is the same for each keycode.
+ * But for now it doesn't, so i disable it. */
symMap = &info->map->key_sym_map[rep->firstKeyAct];
- for (i=0;i<(int)rep->nKeyActs;i++,symMap++) {
+#endif
+ for (i=0;i<(int)rep->nKeyActs;i++
+#if 0
+ ,symMap++
+#endif
+ ) {
if (numDesc[i]==0) {
info->server->key_acts[i+rep->firstKeyAct]= 0;
}
@@ -478,7 +488,7 @@
}
extraData= (int)(rep->length*4);
extraData-= (SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply));
- if (rep->length) {
+ if (extraData) {
XkbReadBufferRec buf;
int left;
if (_XkbInitReadBuffer(dpy,&buf,extraData)) {
@@ -683,6 +693,8 @@
req = _XkbGetGetMapReq(dpy, xkb);
req->virtualMods = which;
+ /* mmc: we want this information, so the mask must be set! */
+ req->partial = XkbVirtualModsMask;
status= _XkbHandleGetMapReply(dpy, xkb);
UnlockDisplay(dpy);
@@ -740,6 +752,7 @@
req = _XkbGetGetMapReq(dpy, xkb);
req->firstModMapKey = first;
req->nModMapKeys = num;
+ req->partial = XkbModifierMapMask; /* mmc: once again (see above) */
if ((xkb!=NULL) && (xkb->map!=NULL) && (xkb->map->modmap!=NULL)) {
if ((num>0)&&(first>=xkb->min_key_code)&&(first+num<=xkb->max_key_code))
bzero(&xkb->map->modmap[first],num);
@@ -767,9 +780,10 @@
LockDisplay(dpy);
req = _XkbGetGetMapReq(dpy, xkb);
+ req->partial = XkbVirtualModMapMask;
req->firstVModMapKey = first;
req->nVModMapKeys = num;
- if ((xkb!=NULL) && (xkb->map!=NULL) && (xkb->map->modmap!=NULL)) {
+ if ((xkb!=NULL) && (xkb->server!=NULL) && (xkb->server->vmodmap!=NULL)) {
if ((num>0)&&(first>=xkb->min_key_code)&&(first+num<=xkb->max_key_code))
bzero(&xkb->server->vmodmap[first],num*sizeof(unsigned short));
}
--- /linux/13/x/xfree86/xc/lib/X11/XKBMAlloc.c 2003-11-17 23:20:09.000000000 +0100
+++ lib/X11/XKBMAlloc.c 2005-06-02 16:01:39.000000000 +0200
@@ -363,7 +363,7 @@
Status
XkbResizeKeyType( XkbDescPtr xkb,
int type_ndx,
- int map_count,
+ int map_count, /* number of mappings: modifier-set -> level */
Bool want_preserve,
int new_num_lvls)
{
@@ -596,6 +596,7 @@
int nCopy;
nCopy= nKeySyms= XkbKeyNumSyms(xkb,i);
+ /* i could invert these following 2 IFs: */
if ((nKeySyms==0)&&(i!=key))
continue;
if (i==key)
@@ -610,6 +611,22 @@
_XkbFree(xkb->map->syms);
xkb->map->syms = newSyms;
xkb->map->num_syms = nSyms;
+
+
+ /* mmc: we grow the table when needed, and never shrink it. So i decided to test & shrink here: */
+
+ if (xkb->map->size_syms > 2 * xkb->map->num_syms + 64)
+ {
+#ifdef XKB_IN_SERVER
+#ifdef DEBUG
+ ErrorF("%s: reduction! %d ->%d\n", __FUNCTION__, xkb->map->size_syms, 2 * xkb->map->num_syms + 64);
+#endif
+#endif
+ xkb->map->size_syms = 2 * xkb->map->num_syms + 64;
+ /* xkb->map->num_syms remains! */
+ /* todo: if this fails....!! hopefully never, we just shrink. */
+ xkb->map->syms = _XkbTypedRealloc(xkb->map->syms, xkb->map->size_syms, KeySym);
+ }
return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
}
@@ -702,7 +719,7 @@
if (changes) {
changes->map.changed= _ExtendRange(changes->map.changed,
XkbVirtualModMapMask,minKC,
- &changes->map.first_modmap_key,
+ &changes->map.first_vmodmap_key,
&changes->map.num_vmodmap_keys);
}
}
@@ -732,7 +749,7 @@
_XkbFree(prev_key_sym_map);
return BadAlloc;
}
- bzero((char *)&xkb->map->key_sym_map[xkb->max_key_code],
+ bzero((char *)&xkb->map->key_sym_map[xkb->max_key_code+1],
tmp*sizeof(XkbSymMapRec));
if (changes) {
changes->map.changed= _ExtendRange(changes->map.changed,
@@ -750,7 +767,7 @@
_XkbFree(prev_modmap);
return BadAlloc;
}
- bzero((char *)&xkb->map->modmap[xkb->max_key_code],tmp);
+ bzero((char *)&xkb->map->modmap[xkb->max_key_code + 1],tmp);
if (changes) {
changes->map.changed= _ExtendRange(changes->map.changed,
XkbModifierMapMask,maxKC,
@@ -769,7 +786,7 @@
_XkbFree(prev_behaviors);
return BadAlloc;
}
- bzero((char *)&xkb->server->behaviors[xkb->max_key_code],
+ bzero((char *)&xkb->server->behaviors[xkb->max_key_code +1],
tmp*sizeof(XkbBehavior));
if (changes) {
changes->map.changed= _ExtendRange(changes->map.changed,
@@ -787,7 +804,7 @@
_XkbFree(prev_key_acts);
return BadAlloc;
}
- bzero((char *)&xkb->server->key_acts[xkb->max_key_code],
+ bzero((char *)&xkb->server->key_acts[xkb->max_key_code + 1],
tmp*sizeof(unsigned short));
if (changes) {
changes->map.changed= _ExtendRange(changes->map.changed,
@@ -805,15 +822,34 @@
_XkbFree(prev_vmodmap);
return BadAlloc;
}
- bzero((char *)&xkb->server->vmodmap[xkb->max_key_code],
+ bzero((char *)&xkb->server->vmodmap[xkb->max_key_code + 1],
tmp*sizeof(unsigned short));
if (changes) {
changes->map.changed= _ExtendRange(changes->map.changed,
XkbVirtualModMapMask,maxKC,
- &changes->map.first_modmap_key,
+ &changes->map.first_vmodmap_key,
&changes->map.num_vmodmap_keys);
}
}
+ /* mmc: we have to resize server->explicit too. */
+ if (xkb->server->explicit) {
+ unsigned short *prev_explicit = xkb->server->explicit;
+ xkb->server->explicit= _XkbTypedRealloc(xkb->server->explicit,
+ (maxKC+1),unsigned char);
+ if (!xkb->server->explicit) {
+ _XkbFree(prev_explicit);
+ return BadAlloc;
+ }
+ bzero((char *)&xkb->server->explicit[xkb->max_key_code + 1],
+ tmp*sizeof(unsigned char));
+ if (changes) {
+ changes->map.changed= _ExtendRange(changes->map.changed,
+ XkbExplicitComponentsMask,maxKC,
+ /* ???? */
+ &changes->map.first_key_explicit,
+ &changes->map.num_key_explicit);
+ }
+ }
}
if ((xkb->names)&&(xkb->names->keys)) {
XkbKeyNameRec *prev_keys = xkb->names->keys;
@@ -824,7 +860,7 @@
_XkbFree(prev_keys);
return BadAlloc;
}
- bzero((char *)&xkb->names->keys[xkb->max_key_code],
+ bzero((char *)&xkb->names->keys[xkb->max_key_code +1],
tmp*sizeof(XkbKeyNameRec));
if (changes) {
changes->names.changed= _ExtendRange(changes->names.changed,
@@ -885,6 +921,21 @@
_XkbFree(xkb->server->acts);
xkb->server->acts = newActs;
xkb->server->num_acts= nActs;
+
+ /* mmc: again (see above for keysyms), we grow the table when needed, and never shrink it. So i decided to test & shrink here: */
+ if (xkb->server->size_acts > 2 * xkb->server->num_acts + 64)
+ {
+#ifdef XKB_IN_SERVER
+#ifdef DEBUG
+ ErrorF("%s: reduction! %d ->%d\n", __FUNCTION__, xkb->server->size_acts, 2 * xkb->server->num_acts + 64);
+#endif
+#endif
+ xkb->server->size_acts = 2 * xkb->server->num_acts + 64;
+
+ /* xkb->server->num_acts remains! */
+ /* fixme: if this fails....! */
+ xkb->server->acts = _XkbTypedRealloc(xkb->server->acts, xkb->server->size_acts, XkbAction);
+ }
return &xkb->server->acts[xkb->server->key_acts[key]];
}
--- /linux/13/x/xfree86/xc/lib/X11/XKBUse.c 2003-11-17 23:20:10.000000000 +0100
+++ lib/X11/XKBUse.c 2005-04-11 00:30:36.000000000 +0200
@@ -204,6 +204,8 @@
return;
}
+/* mmc: rewrite xbk event, possibly to a core X event.
+ * EVENT is on wire (xkb event). RE is where we transfer to (X event). */
static Bool
wire_to_event(Display *dpy,XEvent *re,xEvent *event)
{
@@ -305,7 +307,8 @@
ev->count = mn->nKeySyms;
_XkbNoteCoreMapChanges(&xkbi->changes,ev,XKB_XLIB_MAP_MASK);
if (xkbi->changes.changed)
- xkbi->flags|= XkbMapPending;
+ /* if types change, we need to reload all, othewise, _maybe_ only ... */
+ xkbi->flags|= XkbMapPending | (mn->nTypes != 0)?0:XkbXlibNewKeyboard;
return True;
}
}
--- /linux/13/x/xfree86/xc/programs/Xserver/xkb/xkb.c 2005-03-28 04:51:13.000000000 +0200
+++ programs/Xserver/xkb/xkb.c 2005-06-02 16:22:16.000000000 +0200
@@ -1514,10 +1514,12 @@
*nMapsRtrn = xkb->map->num_types;
for (i=0;i<xkb->map->num_types;i++) {
mapWidthRtrn[i] = xkb->map->types[i].num_levels;
+ /* mmc: mapWidthRtrn is allocated for max keycodes. is the same limit valid for # of levels of Types???*/
}
return 1;
}
+ /* copy the unaffected interval: */
for (i=0;i<req->firstType;i++) {
mapWidthRtrn[i] = xkb->map->types[i].num_levels;
}
@@ -1610,14 +1612,30 @@
xkbSymMapWireDesc ** wireRtrn,
int * errorRtrn)
{
+ /* mmc:
+ * Checks consistency of the data:
+ * - types inside an interval
+ * - number of syms must be = width * ngroups
+ * AND
+ * constructs the symsPerKey mapping keycode->number. This will be used by the caller for checking n. of actions!
+ * uses mapWidths for that(?)
+ */
unsigned i;
XkbSymMapPtr map;
xkbSymMapWireDesc* wire = *wireRtrn;
- if (!(XkbKeySymsMask&req->present))
+#if 0
+ if (!(XkbKeySymsMask&req->present)) /* mmc: is this correct? symsPerKey would not be computed! */
return 1;
+#endif
+
CHK_REQ_KEY_RANGE2(0x11,req->firstKeySym,req->nKeySyms,req,(*errorRtrn),0);
map = &xkb->map->key_sym_map[xkb->min_key_code];
+
+ /* mmc: this checks if the keycodes `below' (think this ordering:
+ * min_keycode----req->firstKeySym --- (req->firstKeySym + req->nKeySyms) --- max_keycode)
+ * have types above the nTypes. If so -> error.
+ */
for (i=xkb->min_key_code;i<(unsigned)req->firstKeySym;i++,map++) {
int g,ng,w;
ng= XkbNumGroups(map->group_info);
@@ -1629,6 +1647,8 @@
if (mapWidths[map->kt_index[g]]>w)
w= mapWidths[map->kt_index[g]];
}
+ /* mmc: now w is the maximum of widths, and
+ * the caller is interested in this info: */
symsPerKey[i] = w*ng;
}
for (i=0;i<req->nKeySyms;i++) {
@@ -1637,6 +1657,7 @@
if (client->swapped) {
swaps(&wire->nSyms,nG);
}
+ /* mmc: checking the Nodes: 1/ good group information? */
nG = XkbNumGroups(wire->groupInfo);
if (nG>XkbNumKbdGroups) {
*errorRtrn = _XkbErrCode3(0x14,i+req->firstKeySym,nG);
@@ -1668,12 +1689,16 @@
*errorRtrn = _XkbErrCode3(0x17,i+req->firstKeySym,wire->nSyms);
return 0;
}
+ /* go to next? skip the record & following syms!*/
pSyms = (KeySym *)&wire[1];
wire = (xkbSymMapWireDesc *)&pSyms[wire->nSyms];
}
+ /* mmc:
+ * keycodes after affected ones:
+ */
map = &xkb->map->key_sym_map[i];
- for (;i<=(unsigned)xkb->max_key_code;i++,map++) {
+ for (i= req->nKeySyms + req->firstKeySym ;i<=(unsigned)xkb->max_key_code;i++,map++) { /* mmc: bug was here */
int g,nG,w;
nG= XkbKeyNumGroups(xkb,i);
for (w=g=0;g<nG;g++) {
@@ -2088,6 +2113,7 @@
if (changes->map.changed&XkbKeyActionsMask) {
int oldLast;
oldLast= changes->map.first_key_act+changes->map.num_key_acts-1;
+ /* mmc: isn't there a function to enlarge an interval to include 2 points? (inverse of CLAMP)*/
if (changes->map.first_key_act<first)
first= changes->map.first_key_act;
if (oldLast>last)
@@ -2320,13 +2346,14 @@
}
tmp = (char *)&stuff[1];
- if ((stuff->present&XkbKeyTypesMask)&&
+ /* bug: we need `mapWidths' which is calculated in CheckKeyTypes. */
+ if ( /* (stuff->present&XkbKeyTypesMask)&& */
(!CheckKeyTypes(client,xkb,stuff,(xkbKeyTypeWireDesc **)&tmp,
&nTypes,mapWidths))) {
client->errorValue = nTypes;
return BadValue;
}
- if ((stuff->present&XkbKeySymsMask)&&
+ if ( /* (stuff->present&XkbKeySymsMask)&& */ /* symsPerKey is used later*/
(!CheckKeySyms(client,xkb,stuff,nTypes,mapWidths,symsPerKey,
(xkbSymMapWireDesc **)&tmp,&error))) {
client->errorValue = error;
@@ -2718,7 +2745,9 @@
&cause);
if (check)
XkbCheckSecondaryEffects(xkbi,check,&change,&cause);
- XkbUpdateCoreDescription(dev,False);
+ XkbUpdateCoreDescription(dev,True); /* mmc: was False. I think there will be problems,
+ * but i want to discover them. Besides, this function probably
+ * does not resize the XKB map */
XkbSendNotification(dev,&change,&cause);
}
return client->noClientException;
--- /linux/13/x/xfree86/xc/programs/Xserver/xkb/xkbUtils.c 2005-04-14 14:31:58.000000000 +0200
+++ programs/Xserver/xkb/xkbUtils.c 2005-06-02 16:58:43.000000000 +0200
@@ -372,6 +372,8 @@
return;
}
+extern char* ConnectionInfo; /* mmc: i think it's a precomputed byte array to send to clients on connection. */
+
void
XkbUpdateCoreDescription(DeviceIntPtr keybd,Bool resize)
{
@@ -388,6 +390,11 @@
keyc= keybd->key;
maxSymsPerKey= maxKeysPerMod= 0;
bzero(keysPerMod,sizeof(keysPerMod));
+
+ /* mmc:
+ * 1/ does it start w/ keycode 0? or min?
+ * 2/ modifierMap is always 256
+ * xkb->max_key_code might be > keyc->curKeySyms.maxKeyCode */
memcpy(keyc->modifierMap,xkb->map->modmap,xkb->max_key_code+1);
if ((xkb->min_key_code==keyc->curKeySyms.minKeyCode)&&
(xkb->max_key_code==keyc->curKeySyms.maxKeyCode)) {
@@ -403,6 +410,12 @@
FatalError("Couldn't allocate keysyms\n");
first= firstCommon= xkb->min_key_code;
last= lastCommon= xkb->max_key_code;
+
+ /* mmc: i should recompute: ConnectionInfo in dix/main.c !! */
+#if 1
+ ((xConnSetup*) ConnectionInfo)->minKeyCode = xkb->min_key_code;
+ ((xConnSetup*) ConnectionInfo)->maxKeyCode = xkb->max_key_code;
+#endif
}
else {
if (xkb->min_key_code<keyc->curKeySyms.minKeyCode) {
@@ -410,6 +423,7 @@
firstCommon= keyc->curKeySyms.minKeyCode;
}
else {
+ /* mmc: core (partly) superset of xkb? */
firstCommon= xkb->min_key_code;
first= keyc->curKeySyms.minKeyCode;
}
@@ -423,7 +437,9 @@
}
}
- /* determine sizes */
+ /* determine sizes: maxSymsPerKey and maxKeysPerMod:
+ * minimum 2 ! Sum of group1 & group2 ?
+ */
for (key=first;key<=last;key++) {
if (XkbKeycodeInRange(xkb,key)) {
int nGroups;
@@ -441,6 +457,7 @@
tmp+= 2;
else tmp+= w;
} else {
+ /* group 1 provides more than 2: */
if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup2Index))>2)
tmp+= w - 2;
}
@@ -483,7 +500,8 @@
}
keyc->maxKeysPerModifier= maxKeysPerMod;
- if (maxSymsPerKey>0) {
+ /* now, that we have the `maxSymsPerKey' */
+ if (maxSymsPerKey>0) { /* mmc: this could fail if ... xkb keycode range is disjoint from the core range? */
tmp= maxSymsPerKey*_XkbCoreNumKeys(keyc);
keyc->curKeySyms.map= _XkbTypedRealloc(keyc->curKeySyms.map,tmp,KeySym);
if (keyc->curKeySyms.map==NULL)
@@ -495,6 +513,8 @@
}
keyc->curKeySyms.mapWidth= maxSymsPerKey;
+ if (maxSymsPerKey>0){ /* mmc! */
+ /* what use in core for keysPerMod ? 8 numbers-- count of keycodes associtated w/ the modifier bit. */
bzero(keysPerMod,sizeof(keysPerMod));
for (key=firstCommon;key<=lastCommon;key++) {
if (keyc->curKeySyms.map!=NULL) {
@@ -507,12 +527,13 @@
bzero(pCore,maxSymsPerKey*sizeof(KeySym));
pXKB= XkbKeySymsPtr(xkb,key);
nOut= 2;
+ /* copy the initial keysyms? */
if (nGroups>0) {
groupWidth= XkbKeyGroupWidth(xkb,key,XkbGroup1Index);
if (groupWidth>0) pCore[0]= pXKB[0];
if (groupWidth>1) pCore[1]= pXKB[1];
for (n=2;n<groupWidth;n++) {
- pCore[2+n]= pXKB[n];
+ pCore[2+n]= pXKB[n]; /* mmc: why the 2+ skip? --- b/c below (on 2,3) we put from group2 !*/
}
if (groupWidth>2)
nOut= groupWidth;
@@ -556,6 +577,7 @@
}
}
}
+ }
#ifdef MODE_SWITCH
/* Fix up any of the KME stuff if we changed the core description.
*/