Bug 9796 - libxkbfile1: does not change key autorepeat state
Summary: libxkbfile1: does not change key autorepeat state
Status: RESOLVED MOVED
Alias: None
Product: xorg
Classification: Unclassified
Component: Lib/libxkb* (show other bugs)
Version: 7.1 (2006.05)
Hardware: x86 (IA32) Linux (All)
: medium minor
Assignee: Xorg Project Team
QA Contact: Xorg Project Team
URL:
Whiteboard: 2011BRB_Reviewed
Keywords:
Depends on:
Blocks:
 
Reported: 2007-01-29 03:30 UTC by David Martínez Moreno
Modified: 2018-08-10 20:20 UTC (History)
3 users (show)

See Also:
i915 platform:
i915 features:


Attachments
Steps to try to reproduce (1.56 KB, text/plain)
2014-05-16 14:43 UTC, Ran Benita
no flags Details
New script to reproduce the problem (2.77 KB, text/plain)
2014-05-22 09:07 UTC, Hanno Zulla
no flags Details

Description David Martínez Moreno 2007-01-29 03:30:19 UTC
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.
Comment 1 David Martínez Moreno 2007-01-30 12:03:39 UTC
I forgot to say that the URL to the bug is http://bugs.debian.org/407189.
Comment 2 Daniel Stone 2007-02-27 01:36:00 UTC
Sorry about the phenomenal bug spam, guys.  Adding xorg-team@ to the QA contact so bugs don't get lost in future.
Comment 3 Ran Benita 2014-05-13 20:49:03 UTC
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.
Comment 4 Hanno Zulla 2014-05-16 08:56:47 UTC
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?
Comment 5 Hanno Zulla 2014-05-16 10:11:44 UTC
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.
Comment 6 Ran Benita 2014-05-16 14:43:16 UTC
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?
Comment 7 Ran Benita 2014-05-16 14:48:40 UTC
Just to clarify: I tried the steps on the latest vanilla releases of xkbcomp, libxkbfile, etc. without the change discussed above.
Comment 8 Hanno Zulla 2014-05-17 21:46:41 UTC
That's weird. Are you using Linux and if so, which distribution? (I'm using Xubuntu with their binaries of X.org here.)
Comment 9 Hanno Zulla 2014-05-17 21:51:06 UTC
...and the current Xubuntu I'm using here comes with

xkbcomp 1.2.4
libxkbfile1 1.0.8-1
xorg 1:7.7+1ubuntu8
Comment 10 Hanno Zulla 2014-05-17 22:06:55 UTC
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?
Comment 11 Hanno Zulla 2014-05-20 13:16:55 UTC
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.
Comment 12 Hanno Zulla 2014-05-20 20:51:24 UTC
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() ]
    };
Comment 13 Hanno Zulla 2014-05-22 09:07:39 UTC
Created attachment 99572 [details]
New script to reproduce the problem
Comment 14 Hanno Zulla 2014-05-22 09:22:10 UTC
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.
Comment 15 Ran Benita 2014-05-22 10:28:17 UTC
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 :)
Comment 16 Hanno Zulla 2014-05-22 10:47:36 UTC
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.
Comment 17 Ran Benita 2014-05-22 12:17:48 UTC
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.
Comment 18 Ran Benita 2014-05-22 12:19:41 UTC
Typo: should be XkbDDXChangeControls.
Comment 19 GitLab Migration User 2018-08-10 20:20:57 UTC
-- 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.