Bug 23202

Summary: MappingNotify does not get sent to all clients after using xmodmap(1)
Product: xorg Reporter: Michael Stapelberg <michael+freedesktop>
Component: Server/Input/CoreAssignee: Xorg Project Team <xorg-team>
Status: RESOLVED MOVED QA Contact: Xorg Project Team <xorg-team>
Severity: normal    
Priority: medium CC: daniel, gatis.paeglis, mitya57, peter.hutterer, psychon, tiagomatos
Version: 7.4 (2008.09)   
Hardware: Other   
OS: All   
Whiteboard:
i915 platform: i915 features:
Attachments:
Description Flags
test program using Xlib
none
test program using XKB
none
test program using XCB
none
(fixed for current stuff) test program using XCB
none
XCB test for generated mapping events
none
xserver: set initial mapNotifyMask none

Description Michael Stapelberg 2009-08-07 08:56:15 UTC
Created attachment 28424 [details]
test program using Xlib

I noticed that, using XCB, I do not get a mapping_notify event when I change the keyboard mapping using xmodmap, only when using setxkbmap. I then wrote several test programs (attached to this bug) and noticed the following:

When manually selecting XkbMapNotify events using XKB, I get events on setxkbmap and xmodmap.
When using Xlib and calling XKeysymToKeycode at least once (so that it gets the keyboard mapping) I get events for setxkbmap and xmodmap. Xlib seems to generate these events from XkbMapNotify, though, see lib/X11/XKBUse.c:318.
When using XCB and calling XKeysymToKeycode at least once, I still only get events for setxkbmap.

Is this a bug in the X server itself? Or are programs supposed to use XKB for getting all kinds of mapping_notify events?
Comment 1 Michael Stapelberg 2009-08-07 08:56:40 UTC
Created attachment 28425 [details]
test program using XKB
Comment 2 Michael Stapelberg 2009-08-07 08:56:56 UTC
Created attachment 28426 [details]
test program using XCB
Comment 3 Julien Cristau 2009-08-07 09:16:46 UTC
CC:ing Peter.

According to the xcb@ thread where this came up, it looks like older servers do send the MappingNotify event.
Comment 4 Peter Hutterer 2009-08-17 21:20:42 UTC
testing these with setxkbmap:
Xlib program: events
xcb program: events
xkb program: no events

for the xkb program I had to add XkbNewKeyboardNotifyMask to receive any events from setxkbmap. 

running xmodmap -e "keycode 65 = s" yields an event off all three test programs.
What exactly am I supposed to do with this again?
Comment 5 Michael Stapelberg 2009-08-18 04:51:49 UTC
Hi Peter,

thanks for testing. Are you definitely sure that you used the xcb program and did not confuse the source code? If yes, that makes it even more interesting. I still do not receive any events in the xcb one when running xmodmap -e "keycode 65 = s", as you suggested.

The versions on my system are:
ii  xserver-xorg                                            1:7.4+3                                the X.Org X server
ii  xserver-xorg-core                                       2:1.6.2-1                              Xorg X server - core server
ii  xserver-xorg-dev                                        2:1.6.2-1                              Xorg X server - development files
ii  xserver-xorg-input-evdev                                1:2.2.4-1                              X.Org X server -- evdev input driver
ii  xserver-xorg-video-intel                                2:2.8.0-0                              X.Org X server -- Intel i8xx, i9xx display d

libxcb is version 1.4, xcb-util is version 0.3.5

Best regards,
Michael
Comment 6 Peter Hutterer 2009-08-18 15:36:34 UTC
verified. Can reproduce the issue with server 1.6 but not with git.

Unfortunately, 1.6 and 1.7 have quite different input systems and finding the fix will be time-consuming.

CC'ing daniel, maybe he can think of where to start looking.
Comment 7 Gatis Paeglis 2013-04-29 10:26:31 UTC
Still an issue. As a workaround i add a call to XKeysymToKeycode after initializing xlib display:

    Display *dpy = XOpenDisplay(m_displayName.constData());
    if (dpy) {
        m_primaryScreen = DefaultScreen(dpy);
        m_connection = XGetXCBConnection(dpy);
        XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
        XSetErrorHandler(nullErrorHandler);
        m_xlib_display = dpy;
        (void)XKeysymToKeycode(dpy, 0x0047); // LATIN CAPITAL LETTER G

This way Xlib can setup whatever it needs to setup to make this work.
Comment 8 Uli Schlachter 2013-04-29 15:31:15 UTC
Created attachment 78604 [details]
(fixed for current stuff) test program using XCB

I can't reproduce this bug. Attached is a new version of the notify.c from earlier. I removed the useless and pointless Xlib Display and made it pure xcb and it works as expected here on server 1.12.4 (debian testing).

However, xlibn.c breaks here if I remove the call to XKeysymToKeycode(). This seems to be an Xlib issue, because it enables XKB (XKEYBOARD UseExtension request), but doesn't request any events. As my XCB-example shows, the server seems to do the right thing if the client doesn't touch XKEYBOARD. (tested with xtrace)

Could someone with some more clue about XKEYBOARD get out xtrace and figure out what exactly the different test cases are doing and which part exactly is supposed to be a server bug?
Comment 9 Gatis Paeglis 2013-05-02 14:11:01 UTC
Yes, with a pure xcb application this works as expected. This must be an issue somewhere in Xlib's code. If somebody is going to look into this issue i have provided a xlib-xcb test application in https://bugreports.qt-project.org/browse/QTBUG-30911.
Comment 10 Ran Benita 2013-07-18 17:57:17 UTC
I tried some of this as well (with just XCB), here are a few observations.

1. 'setxkbmap -layout us,de'  (different layout)
   -> 5 XkbNewKeyboardNotify events.

2. 'xkbcomp out.xkb $DISPLAY'
   -> 10 XkbMapNotify events, 1 core MappingNotify event, 5 XkbNewKeyboardNotify events.

3. 'xmodmap -e "keycode 65 = s"'
   -> 5 XkbMapNotify events, 1 core MappingNotify event.

Note that the XKB proto spec says that in some situations if you select the NewKeyboardNotify event, it doesn't send some other XKB events. But it doesn't make a difference here to the other events (at least in the above cases).

I'll look at it some more later.
Comment 11 Ran Benita 2013-07-18 17:59:00 UTC
Created attachment 82623 [details]
XCB test for generated mapping events

Oh, here's my quick test file.
Comment 12 Gatis Paeglis 2013-07-25 08:52:51 UTC
The workaround what i mentioned in the "Comment 7" works for xmodmap and for xkbcomp, but not for setxkbmap. This is problematic since MAPPING_NOTIFY is pretty important event, it signals when its time to update my local key mappings.. And updating (re-compiling) keymap on every KEYMAP_NOTIFY probably isn't a good idea.
Comment 13 Rui Tiago Matos 2013-09-13 17:31:55 UTC
(In reply to comment #12)
> The workaround what i mentioned in the "Comment 7" works for xmodmap and for
> xkbcomp, but not for setxkbmap. This is problematic since MAPPING_NOTIFY is
> pretty important event, it signals when its time to update my local key
> mappings.. And updating (re-compiling) keymap on every KEYMAP_NOTIFY
> probably isn't a good idea.

You really should handle XkbNewKeyboardNotify which you are not currently, if I'm reading qxcbconnection.cpp correctly.
Comment 14 Gatis Paeglis 2013-12-03 11:39:02 UTC
Rui, this has nothing to do with the XkbNewKeyboardNotify event. 

From XKB proto:

"XKB supports the XkbNewKeyboardNotify event, which reports a change in key-
board geometry or the range of supported keycodes. The server can generate an
XkbNewKeyboardNotify event when it detects a new keyboard, or in response to
an XkbGetKeyboardByName request (see section 16.3.12) which loads a new key-
board description."
Comment 15 Rui Tiago Matos 2014-03-13 10:20:34 UTC
(In reply to comment #14)
> or in response to
> an XkbGetKeyboardByName request (see section 16.3.12) which loads a new key-
> board description."

Right, so if there's a new keyboard description Qt isn't (or wasn't, I didn't check again) doing anything with it.
Comment 16 Daniel Stone 2014-03-13 10:52:38 UTC
Hi,

(In reply to comment #15)
> Right, so if there's a new keyboard description Qt isn't (or wasn't, I
> didn't check again) doing anything with it.

Just as a side note - yes, you should reload the keymap on either XkbMapNotify or XkbNewKeyboardNotify.

The code to send MappingNotify events is here:
http://cgit.freedesktop.org/xorg/xserver/tree/xkb/xkbEvents.c#n46

This is probably the smoking gun:
        /* XKB allows clients to restrict the MappingNotify events sent to
         * them.  This was broken for three years.  Sorry. */
        if (xkb_event == XkbMapNotify &&
            (clients[i]->xkbClientFlags & _XkbClientInitialized) &&
            !(clients[i]->mapNotifyMask & changed))
            continue;

For three years previous, the test was inverted: clients would only receive events they did _not_ select for.  This is affected by calling XkbSelectEvents with affectWhich including XkbMapNotifyMask, and then the affectMap and map bits.

We could probably fix this by setting the initial mapNotifyMask for clients to include XkbKeySymsMask and XkbModifierMapMask; I believe this is technically a spec break, but it seems to be the most useful compromise.

In the meantime, having toolkits (etc) update mapNotifyMask as above would work around the issue, except it would break on old servers (between commits f06a9d and 323196).
Comment 17 Daniel Stone 2014-03-13 10:53:41 UTC
Created attachment 95707 [details] [review]
xserver: set initial mapNotifyMask

Set an initial mapNotifyMask for XKB-using clients, in the hope that they'll get core MappingNotify events delivered when xmodmap (rather than setxkbmap) is used.
Comment 18 Daniel Stone 2014-03-13 10:55:01 UTC
Oh, as a side note, you shouldn't actually be getting MappingNotify from setxkbmap.  That should be generating an XkbNewKeyboardNotify event, and according to the spec, clients must never receive a MappingNotify event from a NewKeyboardNotify.  There is code in the server to guard against this; I believe Xlib fakes a MappingNotify event, but not sure how the event arrives when you're using XCB ... ?
Comment 19 Dmitry Shachnev 2014-03-21 05:26:13 UTC
Daniel: I tested your patch and unfortunately it doesn't fix the issues for Qt 5 applications.
Comment 20 GitLab Migration User 2018-12-17 17:27:10 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/xserver/issues/573.

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.