diff options
author | Daniel Stone <daniel@fooishbar.org> | 2011-07-13 12:08:04 +0100 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2011-07-15 15:44:19 +1000 |
commit | 82f5521a6d91ebcd2a4400f6c221ad625edc99a1 (patch) | |
tree | e88df47cd8b6f974e2819cdd53a14eacf7c2c3be /xkb | |
parent | c177a5bcaa170d24a784540460906cc04ac5c752 (diff) |
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: Daniel Stone <daniel@fooishbar.org>
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Diffstat (limited to 'xkb')
-rw-r--r-- | xkb/xkb.c | 19 | ||||
-rw-r--r-- | xkb/xkmread.c | 31 |
2 files changed, 46 insertions, 4 deletions
@@ -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; } diff --git a/xkb/xkmread.c b/xkb/xkmread.c index e8b97dcda..a5c1ecfff 100644 --- a/xkb/xkmread.c +++ b/xkb/xkmread.c @@ -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; |