Commit 82f5521a authored by Daniel Stone's avatar Daniel Stone Committed by Peter Hutterer

XKB: Work around broken interps from old xkbcomp

Bugfix for broken xkbcomp: if we encounter an XFree86Private action with
Any+AnyOfOrNone(All), then we skip the interp as broken.  Versions of
xkbcomp below 1.2.2 had a bug where they would interpret a symbol that
couldn't be found in an interpret as Any.  So, an
XF86LogWindowTree+AnyOfOrNone(All) interp that triggered the PrWins
action would make every key without an action trigger PrWins if libX11
didn't yet know about the XF86LogWindowTree keysym.  None too useful.

We only do this for XFree86 actions, as the current XKB dataset relies
on Any+AnyOfOrNone(All) -> SetMods for Ctrl in particular.

See xkbcomp commits 2a473b906943ffd807ad81960c47530ee7ae9a60 and
3caab5aa37decb7b5dc1642a0452efc3e1f5100e for more details.
Signed-off-by: 's avatarDaniel Stone <daniel@fooishbar.org>
Acked-by: 's avatarPeter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: 's avatarPeter Hutterer <peter.hutterer@who-t.net>
parent c177a5bc
......@@ -2786,6 +2786,7 @@ _XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
if (req->nSI>0) {
xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data;
XkbSymInterpretPtr sym;
unsigned int skipped = 0;
if ((unsigned)(req->firstSI+req->nSI)>compat->num_si) {
compat->num_si= req->firstSI+req->nSI;
compat->sym_interpret= realloc(compat->sym_interpret,
......@@ -2799,11 +2800,19 @@ _XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
compat->num_si = req->firstSI+req->nSI;
}
sym = &compat->sym_interpret[req->firstSI];
for (i=0;i<req->nSI;i++,wire++,sym++) {
for (i=0;i<req->nSI;i++,wire++) {
if (client->swapped) {
int n;
swapl(&wire->sym,n);
}
if (wire->sym == NoSymbol && wire->match == XkbSI_AnyOfOrNone &&
(wire->mods & 0xff) == 0xff &&
wire->act.type == XkbSA_XFree86Private) {
ErrorF("XKB: Skipping broken Any+AnyOfOrNone(All) -> Private "
"action from client\n");
skipped++;
continue;
}
sym->sym= wire->sym;
sym->mods= wire->mods;
sym->match= wire->match;
......@@ -2811,6 +2820,14 @@ _XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
sym->virtual_mod= wire->virtualMod;
memcpy((char *)&sym->act,(char *)&wire->act,
SIZEOF(xkbActionWireDesc));
sym++;
}
if (skipped) {
if (req->firstSI + req->nSI < compat->num_si)
memmove(sym, sym + skipped,
(compat->num_si - req->firstSI - req->nSI) *
sizeof(*sym));
compat->num_si -= skipped;
}
data = (char *)wire;
}
......
......@@ -425,9 +425,9 @@ XkbAction *act;
if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_si)!=Success)
return -1;
compat= xkb->compat;
compat->num_si= num_si;
compat->num_si= 0;
interp= compat->sym_interpret;
for (i=0;i<num_si;i++,interp++) {
for (i=0;i<num_si;i++) {
tmp= fread(&wire,SIZEOF(xkmSymInterpretDesc),1,file);
nRead+= tmp*SIZEOF(xkmSymInterpretDesc);
interp->sym= wire.sym;
......@@ -520,6 +520,29 @@ XkbAction *act;
break;
case XkbSA_XFree86Private:
/*
* Bugfix for broken xkbcomp: if we encounter an XFree86Private
* action with Any+AnyOfOrNone(All), then we skip the interp as
* broken. Versions of xkbcomp below 1.2.2 had a bug where they
* would interpret a symbol that couldn't be found in an interpret
* as Any. So, an XF86LogWindowTree+AnyOfOrNone(All) interp that
* triggered the PrWins action would make every key without an
* action trigger PrWins if libX11 didn't yet know about the
* XF86LogWindowTree keysym. None too useful.
*
* We only do this for XFree86 actions, as the current XKB
* dataset relies on Any+AnyOfOrNone(All) -> SetMods for Ctrl in
* particular.
*
* See xkbcomp commits 2a473b906943ffd807ad81960c47530ee7ae9a60 and
* 3caab5aa37decb7b5dc1642a0452efc3e1f5100e for more details.
*/
if (interp->sym == NoSymbol && interp->match == XkbSI_AnyOfOrNone &&
(interp->mods & 0xff) == 0xff) {
ErrorF("XKB: Skipping broken Any+AnyOfOrNone(All) -> Private "
"action from compiled keymap\n");
continue;
}
/* copy the kind of action */
memcpy(act->any.data, wire.actionData, XkbAnyActionDataSize);
break ;
......@@ -531,10 +554,12 @@ XkbAction *act;
/* unsupported. */
break;
}
interp++;
compat->num_si++;
}
if ((num_si>0)&&(changes)) {
changes->compat.first_si= 0;
changes->compat.num_si= num_si;
changes->compat.num_si= compat->num_si;
}
if (groups) {
register unsigned bit;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment