I took a look at the caps lock problem in 9libs, and I think I understand what happens, or rather what _not_ happens with (at least) XFree86 version 4.1.0 on Linux. The call at 9libs-1.0/libXg/gwin.c:/XtTranslateKeycode/ should invoke a default keycode-to-sym translator that is supposed to handles shift and caps lock. Everything up to there is fine. When I examine the in data to and result from this Xt call with gdb, it handles num lock and shift, but not caps lock. Someone with a system where caps lock works could do the same test to confirm that this is the source of the problem. XtTranslateKeycode(e->xany.display, (KeyCode)e->xkey.keycode, e->xkey.state, &md, &k); e->xkey.keycode and the e->xkey.state are the inputs. md and k are the outputs. e->xkey.keycode is the code for the key on the keyboard and k should return the letter accessed on that key with the current modifier combination. e->xkey.state are the modifier bits and md returns those modifier(bit)s the translator cared for. When I try with shift it works; the shift bit is set in e->xkey and md, and k gets the upper case keysym of the key. When I try with caps lock it doesn't work; the caps lock bit is set in e->xkey, but the shift bit gets set in md (??) and k gets the lower case keysym. A similar problem -- the ctrl key is not (supposed to be) handled by the (or some) default translator -- already exists and is solved with the following code: /* Do control mapping ourselves if translator doesn't */ if((e->xkey.state&ControlMask) && !(md&ControlMask)) k &= 0x9f; So I propose the same work around for caps lock: (patch for wily 0.13.41.9libs) diff -rN -u diff-old/9libs-1.0/libXg/gwin.c diff-new/9libs-1.0/libXg/gwin.c --- diff-old/9libs-1.0/libXg/gwin.c Sat Jan 8 12:02:26 2005 +++ diff-new/9libs-1.0/libXg/gwin.c Sat Jan 8 11:57:28 2005 @@ -175,7 +175,7 @@ static int cursorctl = -1; int c, minmod; - KeySym k, mk; + KeySym k, mk, l, u; Charfunc f; Modifiers md; @@ -280,6 +280,11 @@ /* Compensate for servers that call a minus a hyphen */ if(k == XK_hyphen) k = XK_minus; + /* Do caps locking ourselves if translator doesn't */ + if ((e->xkey.state&LockMask) && !(md&LockMask)) { + XtConvertCase(e->xany.display, k, &l, &u); + k = u; + } /* Do control mapping ourselves if translator doesn't */ if((e->xkey.state&ControlMask) && !(md&ControlMask)) k &= 0x9f; -- Tommy Pettersson <ptp@xxxxxxxxxxxxxx>