I am acting as an intermediate for Christophe. He has filed a bug in the Debian BTS, that follows: When doing something like xkbcomp $DISPLAY /tmp/xkb <edit /tmp/xkb to change key autorepeat state> xkbcomp /tmp/xkb $DISPLAY to change some keys' autorepeat state as viewed by the X server, the autorepeat states are silently unchanged. I believe that this is because the code which would be responsible for changing the state is commented out: #ifdef NOTYET ... #endif in XkbWriteToServer in srvmisc.c. My IBM X40 Thinkpad has two keys which I would like to turn into Hyper and Super modifiers; however, their default state is to autorepeat, and I can't turn this off using xkbcomp. (Using xset -r <keycode> works, however, as does generating an XkbSetControls request manually). I'd be happy to provide more information or provide sample files if that would help.
I forgot to say that the URL to the bug is http://bugs.debian.org/407189.
Sorry about the phenomenal bug spam, guys. Adding xorg-team@ to the QA contact so bugs don't get lost in future.
Indeed, xkbcomp used XkbWriteToServer from libxkbfile, but XkbWriteToServer has the call "XkbSetControls" ifdef-ed out. To the per-key-repeat array (which is part of the XkbControls) is not updated in the server. I can't guess why it's commented out like this, I will have to try it.
I am told by others that this bug 9796 is related to https://bugs.freedesktop.org/show_bug.cgi?id=78661 and https://bugs.freedesktop.org/show_bug.cgi?id=78180 What can I do to help fix it here?
Ok, so I built a patched libxkbfile1_1.0.8-1_amd64.deb on Ubuntu 14.04 where NOTYET was removed: //#ifdef NOTYET if (!XkbSetControls(dpy,XkbAllControlsMask,xkb)) return False; //#endif This still didn't help fix #78661. However, using xset r 111 xset r 116 however did fix the autorepeat setting for the keys described in #78661. Please take this with a grain of salt. I'm not particularily good with .deb building and may have made a mistake with patching this.
Created attachment 99162 [details] Steps to try to reproduce Thanks for trying Hanno. I wanted to try it, but actually when I'm trying your example from bug #78661, I cannot reproduce the problem. Please see the attached file for the steps I took. It seems like the server does receive the repeat=Yes and the Ctrl+Alt+Up does repeat. Can you please read the steps and try them, and see if there's any diff showing at the end?
Just to clarify: I tried the steps on the latest vanilla releases of xkbcomp, libxkbfile, etc. without the change discussed above.
That's weird. Are you using Linux and if so, which distribution? (I'm using Xubuntu with their binaries of X.org here.)
...and the current Xubuntu I'm using here comes with xkbcomp 1.2.4 libxkbfile1 1.0.8-1 xorg 1:7.7+1ubuntu8
Indeed, I tried your script and it works. However, when I put my changes into /usr/share/X11/xkb/ to make sure that the change is system-wide, it doesn't. What's the difference?
Errr. I just tried to prepare a reproducible test case for you and now it works on my side. I'm confused and will test further before reporting back.
Weird. I'm now in a state where repeat is lost, again. So now the bug is back but I don't know what's different. Will investigate this further. Anyway, if you want to try, here's what I did on a vanilla Xubuntu 14.04 system. // put this in /usr/share/X11/xkb/types/pc type "CTRL+ALT_FOUR_LEVEL" { modifiers = Control+Alt; map[None] = Level1; map[Control] = Level2; map[Alt] = Level3; map[Control+Alt] = Level4; level_name[Level1] = "Base"; level_name[Level2] = "Ctrl"; level_name[Level3] = "Alt"; level_name[Level4] = "Ctrl+Alt"; }; // put this in /usr/share/X11/xkb/symbols/inet // Chromebook keyboards // (work in progress, some keys missing) partial alphanumeric_keys xkb_symbols "chromebook" { key <FK01> { type="CTRL+ALT_FOUR_LEVEL", repeat=yes, symbols[Group1] = [ XF86Back, XF86ApplicationLeft, XF86Back, XF86AudioPrev ] }; key <FK02> { type="CTRL+ALT_FOUR_LEVEL", repeat=yes, symbols[Group1] = [ XF86Forward, XF86ApplicationRight, XF86Forward, XF86AudioNext ] }; key <FK03> { type="CTRL+ALT_FOUR_LEVEL", repeat=yes, symbols[Group1] = [ XF86Refresh, XF86Refresh, XF86Refresh, XF86AudioPlay ] }; key <FK04> { type="CTRL+ALT_FOUR_LEVEL", repeat=yes, symbols[Group1] = [ XF86View, XF86Display, XF86Display, XF86Music ] }; key <FK05> { type="CTRL+ALT_FOUR_LEVEL", repeat=yes, symbols[Group1] = [ XF86LaunchA, Print, XF86LaunchA, XF86Video ], actions[Group1] = [ NoAction(), RedirectKey(key=<PRSC>, clearmods=Control), NoAction(), NoAction() ] }; key <FK06> { type="CTRL+ALT_FOUR_LEVEL", repeat=yes, symbols[Group1] = [ XF86MonBrightnessDown, XF86MonBrightnessDown, XF86KbdBrightnessDown, XF86ZoomOut ] }; key <FK07> { type="CTRL+ALT_FOUR_LEVEL", repeat=yes, symbols[Group1] = [ XF86MonBrightnessUp, XF86MonBrightnessUp, XF86KbdBrightnessUp, XF86ZoomIn ] }; key <FK08> { [ XF86AudioMute ] }; key <FK09> { [ XF86AudioLowerVolume ] }; key <FK10> { [ XF86AudioRaiseVolume ] }; key <BKSP> { type="CTRL+ALT_FOUR_LEVEL", repeat=yes, symbols[Group1] = [ BackSpace, BackSpace, Delete, BackSpace ], actions[Group1] = [ NoAction(), NoAction(), RedirectKey(key=<DELE>, clearmods=Alt), NoAction() ] }; key <UP> { type="CTRL+ALT_FOUR_LEVEL", repeat=yes, symbols[Group1] = [ Up, Up, Prior, Home ], actions[Group1] = [ NoAction(), NoAction(), RedirectKey(key=<PGUP>, clearmods=Alt), RedirectKey(key=<HOME>, clearmods=Control+Alt) ] }; key <DOWN> { type="CTRL+ALT_FOUR_LEVEL", repeat=yes, symbols[Group1] = [ Down, Down, Next, End ], actions[Group1] = [ NoAction(), NoAction(), RedirectKey(key=<PGDN>, clearmods=Alt), RedirectKey(key=<END>, clearmods=Control+Alt) ] }; }; // put this at the end of /usr/share/X11/xkb/rules/evdev ! model = symbols chromebook = +inet(chromebook) // change this in /etc/default/keyboard // (German user here) XKBMODEL="chromebook" XKBLAYOUT="de" XKBVARIANT="" XKBOPTIONS="" // finally... rm /var/lib/xkb/server-* reboot xkbcomp :0 -xkb - | less -S // this will result in an entry such as this: key <BKSP> { type= "CTRL+ALT_FOUR_LEVEL", repeat= No, symbols[Group1]= [ BackSpace, BackSpace, Delete, BackSpace ], actions[Group1]= [ NoAction(), NoAction(), RedirectKey(key=<DELE>,clearMods= Alt), NoAction() ] };
Created attachment 99572 [details] New script to reproduce the problem
Hi Ran, ok, now I can reproduce the problem for you. And found something interesting. Please see the attached script. Somewhere on the path from the xkb file to the X server, the repeat bits get messed up and overwritten with their old values. As a result, it appears that this happens: - when there is a "repeat=" setting in the key definition - the X server will change the repeat setting for that key - but NOT to the repeat value defined in the xkb file - but to the repeat value that the X server had stored for this key BEFORE the new definition So as shown by the attached script... xset r 111 xkb input to X: "repeat= yes" or "repeat= no" xkb output from X: "repeat= yes" xset -r 111 xkb input to X: "repeat= yes" or "repeat= no" xkb output from X: "repeat= no" xset r 111 or xset -r 111 xkb input to X: repeat not mentioned xkb output from X: repeat not mentioned This would also explain why you could not reproduce the problem while it occurs to me after a clean reboot. You tried your script on a system that was up and running and thus had the repeat bit for key 111 set already. But I tried after a reboot when (apparently) the repeat bit for key 111 wasn't set, yet. This diagnosis is still guesswork, so forgive me if this is incorrect.
Hi Hanno, thanks for investigating. Until I feel like looking at it, I can at least give you some details that might help pinpoint the issue. There are two things at play here: core X input (let's call it "Core") and the XKB extension. The core input provides the original X11 requests, and is very simple. XKB provides many more capabilities. Both Core and XKB provide requests for changing the key-repeat settings. For Core there is the ChangeKeyboardControl request: http://www.x.org/releases/X11R7.7/doc/xproto/x11protocol.html#requests:ChangeKeyboardControl And for XKB there is the XkbSetControls request: http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Querying_and_Changing_Keyboard_Controls http://www.x.org/releases/current/doc/kbproto/xkbproto.html#The_RepeatKeys_Control (In fact it's also possible to change keyboard controls using the XInput1 extension, but that's equivalent to Core here). Assuming that XKB is enabled, the key-repeat settings between Core and XKB are supposed to be synchronized; that is, if you use one of the above requests it should be recognized by the other. (One place where this shows is the fact in XKB the key-repeat setting is for the entire *key* rather then per key-group or even key-group-level, which is more sensible. But due to backward compatibility with Core [I'm guessing] they left it per-key). Now I'll describe what happens in the various cases. 1. Server start up. The server itself reads your config values from xorg.conf ("RMLVO" - rules/model/layout/variant/options). It looks at the "rules" files to translate the RMLVO (well, it already used the "R" part) to a "KCCGST" (keycodes/types/compat/symbols/geometry) which is the format of the XKB keymaps. It then forks xkbcomp to compile the KCCGST for it. xkbcomp processes all of the needed xkeyboard-config files and then serializes the compiled keymap back to the server over a pipe in a (pretty bad and in some rare cases lossy) format called "XKM". Server deserializes this format and then it has its initial keymap, more or less. 2. xkbcomp $DISPLAY out.xkb to download the active keymap. xkbcomp in this case uses various functions from libX11, like XkbGetMap and XkbGetControls, which use an XKB request of the same name to get all the parts of the keymap. Then it uses the libxkbfile library to convert the keymap struct to text and print it. 3. xkbcomp out.xkb $DISPLAY to upload a keymap to the server. In this case xkbcomp reads the given file and compiles it to a keymap struct itself. Then it uses the XkbWriteToServer() function from libxkbfile to write the new keymap to the server. XkbWriteToServer calls various functions from libX11 like XkbSetMap which use the XKB requests of the same name. (Here though XkbSetControls is commented out with NOTYET as pointed out in this bug). Note that these request modify the active keymap in the server in-place, as opposed to (1) which *creates* a keymap. 4. xset +/-r <keycode>. This just uses the Core ChangeKeyboardControl request (through a wrapper in libX11). Internally in the server all changes to key-repeat settings are supposed to percolate to the dev->kbdfeed->ctrl.autoRepeats array of each keyboard device, which is a simple bitmap with repeat/no-repeat for each key. So as you can see there are a lot of places where things can go wrong. One seemingly obvious culprit seemed to be the mysterious NOTYET on XkbSetControls but you say removing it doesn't help. So other problems can be in the Core/XKB interaction (which can be buggy), or maybe one of the functions along the way ignores/overrides the perKeyRepeat array, or just some coding error. One final note: you may wonder if the perKeyRepeat array is a bitmap, how come xkbcomp only shows Repeat=True/False for keys where you've set it explicitly? Well fittingly enough the keymap contains an "explicit" array which says among other things if each key has an explicit key-repeat setting. If there isn't libxkbfile doesn't print it to the keymap file. Well that was a lot to write just to avoid looking at old XKB code :)
Thanks! Will go hunt for clues in the source code of the various packages. Please try patching the NOTYET section yourself. I'm not sure if things were done right that right when I tried that. Thanks for the write-up. Looking at the source of the various packages, there appear to be several duplicated implementations of XKB file parsing. One wonders why these haven't been merged to one library so that when things go wrong, it's just one place to look at. I'm not much into X source and thus still guess what the code does. But the problem might be in XkbUpdateActions in xkb/xkbUtils.c where there is some back and forth memcpy copying of repeat bits going on.
I was able to reproduce the problem using your scripts. Indeed with a patched libxkbfile (which I think is required in any case), the problem still occurs. I can see that libxkbfile calls XkbSetControls with key 111's repeat bit is 1 and explicit-repeat bit also 1: -#ifdef NOTYET + printf("111 r is: %d\n", xkb->ctrls->per_key_repeat[111/8] & (1 << (111 % 8))); + printf("111 exp is: %d\n", xkb->server->explicit[111] & XkbExplicitAutoRepeatMask); if (!XkbSetControls(dpy, XkbAllControlsMask, xkb)) return False; -#endif Since libX11's XkbSetControls function seems fine to me, I think the XkbSetControls request is also sent properly to the server. So if we look at the "in -> server -> out" path, besides the NOTYET problem in the "in" part there is a problem somewhere in the "server -> out" parts. In the "server" part the XkbSetControls is handled in src/xkb.c. It calls XkbDDDChangeControls which shuffles around 3 perKeyRepeat arrays, it might be worth checking if there's a problem there maybe. However testing modified X servers is a bit difficult for me now, so I'll leave it to you or another time.
Typo: should be XkbDDXChangeControls.
-- GitLab Migration Automatic Message -- This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/xorg/lib/libxkbfile/issues/2.
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.