On Fri, Dec 09, 2005 at 11:22:30PM +0200, Simo Kauppi wrote: > On Thu, Dec 08, 2005 at 09:34:26PM +0100, Almut Behrens wrote: > > On Wed, Dec 07, 2005 at 02:16:09PM +0200, Simo Kauppi wrote: > > > Is there a way to compile keyboard definitions for X and save them > > > somewhere, where XServer can read them, when it starts? > > > > $ xkbcomp -xkm :0 keymap.xkm > > Then, simply transfer the resulting keymap.xkm to your thinclient, > > where you can make the X server load it upon startup using the option > > "-xkbmap keymap.xkm". > > Thanks a lot, I hadn't figured this one out. Unfortunately, if I start X > with -xkbmap keymap.xkm, it says it doesn't like it! > > If I start X with -xkbdb keymap.xkm, it doesn't complain, but the > keyboard doesn't behave properly :(
Not too surprising. That option's value is assigned to some variable XkbDB (in xc/programs/Xserver/xkb/xkbInit.c) which isn't used anywhere else beyond this assignment, in the entire X sources. Whatever that's supposed to do, it isn't implemented yet ;) The fact that -xkbmap doesn't work as advertised, isn't too surprising either, 'cos I was telling rubbish (yeah, next time, Almut reminds herself to actually verify the stuff she's claiming...) Well actually, this option does work, kind of, but not in a manner as straightforward as on might expect. However, I knew for sure I once had it working already, so I've played around with it some more... Well, found lots of weird things. But don't worry, I won't bore you with the details. Just a brief description of how I finally got it working, after lots of strace'ing and poking around in the X sources. All in all, I can't help getting the impression, that Simo and me are to the only two people in this world who have ever tried to make use of this -xkbmap option :) My main observations: * you can't keep the X server from wanting to call xkbcomp, even in the presence of a perfectly valid compiled xkbmap. At least, I dunno how. * even though the output of the xkbcomp run isn't really used in this case (AFAICT), it is good to have it succeed, superficially. In case of any failures in this step, a couple of other things are being tried which eventually lead to a complete failure of the whole shebang. * you are expected to specify the bare name of the keymap (without the .xkm extension); the X server looks for the map in certain predefined directories (which do vary depending on which UID the server is started as) * unless you have a dot in the keymap name, the X server deletes the map before reading it. No kidding. This seems to be because the path of the temporary output file (created during the useless run of xkbcomp) is being set to where the real keymap is expected to be found. And tempfile cleanup happens before the actual "-xkbmap"-related code gets a chance to read it... Luckily, there's some odd "sanitizing" being applied to the tempfile name (replacing '.' by '_'). That allows us to play tricks here: 1: 6929 execve("/usr/bin/X11/XFree86", ["/usr/X11R6/bin/X", ":1", "-xkbmap", "default.map"], [/* 14 vars */]) = 0 2: 6930 execve("/usr/X11R6/lib/X11/xkb/xkbcomp", ["/usr/X11R6/lib/X11/xkb/xkbcomp", "-w", "1", "-R/usr/X11R6/lib/X11/xkb", "-xkm", "-em1", "The XKEYBOARD keymap compiler (x"..., "-emp", "> ", "-eml", "Errors from xkbcomp are not fata"..., "keymap/default.map", "compiled/default_map.xkm"], [/* 14 vars */]) = 0 3: 6931 lstat64("/usr/X11R6/lib/X11/xkb/compiled/default_map.xkm", 0xbffffa1c) = -1 ENOENT (No such file or directory) 4: 6931 stat64("/usr/X11R6/lib/X11/xkb/keymap/default.map", {st_mode=S_IFREG|0644, st_size=7804, ...}) = 0 5: 6931 open("/usr/X11R6/lib/X11/xkb/keymap/default.map", O_RDONLY|O_LARGEFILE) = 6 6: 6931 open("/usr/X11R6/lib/X11/xkb/compiled/default_map.xkm", O_WRONLY|O_CREAT|O_LARGEFILE, 0100644) = 7 7: 6929 open("/usr/X11R6/lib/X11/xkb/compiled/default_map.xkm", O_RDONLY) = 6 8: 6929 unlink("/usr/X11R6/lib/X11/xkb/compiled/default_map.xkm") = 0 9: 6929 open("/usr/X11R6/lib/X11/xkb/compiled/default.map.xkm", O_RDONLY) = 6 These are the relevant lines from the strace output when running X with "-xbkmap default.map" (line numbers prepended). As you can see, for some calls it uses "default_map" in place of "default.map". The open() in line 9 apparently is what finally makes things work. The open() of the tempfile in line 7 has to succeed, too, or else weird things happen, and the real open() in line 9 never takes place. Line 8 shows that tempfile cleanup now is no longer deleting the real file. So, to summarize, here's what I did: * moved away the original /usr/X11R6/lib/X11/xkb directory (a link to /etc/X11/xkb, normally), preventing X from accessing anything in there. * uncommented all 'Option "Xkb*"' entries in XF86Config-4/xorg.conf. * created a dummy replacement for xkbcomp. This is just a simple script which copies the precompiled keymap to the tempfile location where X is expecting to find it -- hereby simulating a successful compile run: #!/usr/bin/perl $base = "/usr/X11R6/lib/X11/xkb/"; $dest = pop @ARGV; # of the 12 args that xkbcomp is called $src = $base . pop @ARGV; # with, the last two are of interest... $dest = "$base$dest" if $dest !~ m|^/|; system 'cp', $src, $dest; # create expected output exit 0 # always succeed (If you want your thinclient to be really thin, i.e. without perl, you could of course rewrite this in shell, or even replace it with just a single cp call. Once you've figured out where the files are supposed to be placed, you no longer need the flexibility of the script...) * created a new xkb directory, containing just the following: -rwxr-xr-x root/root 313 /usr/X11R6/lib/X11/xkb/xkbcomp drwxr-xr-x root/root 0 /usr/X11R6/lib/X11/xkb/keymap/ -rw-r--r-- root/root 7804 /usr/X11R6/lib/X11/xkb/keymap/default.map drwxr-xr-x root/root 0 /usr/X11R6/lib/X11/xkb/compiled/ lrwxrwxrwx root/root 0 /usr/X11R6/lib/X11/xkb/compiled/default.map.xkm -> /usr/X11R6/lib/X11/xkb/keymap/default.map lrwxrwxrwx root/root 0 /var/tmp/default.map.xkm -> /usr/X11R6/lib/X11/xkb/keymap/default.map (xkbcomp is the above script. default.map is the compiled keymap. The map in /var/tmp/ is used when X is run as a regular user.) That's it. I created a new clean user account, and started the "thin" X with "-xkbmap default.map". No more error messages from X, and my usual german keyboard layout (which I had previously extracted using "xkbcomp -xkm :0 default.map") works without a hitch -- to my surprise even all my specially xmodmap'ed windows and "web" keys... I'm not saying this is way to do it -- just that it worked for me :) Tried with various versions of X from woody's XFree86 to Xorg-6.8.2. Let me know whether it works for you, too, Simo. I'm afraid I won't be able to help, if not, though -- just out of curiosity... Almut (...and I said, I wouldn't bore you with details... Well.) -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]