After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 565540 - Metacity's keybindings fail to update when XKB keyboard layout changes
Metacity's keybindings fail to update when XKB keyboard layout changes
Status: RESOLVED FIXED
Product: metacity
Classification: Other
Component: general
2.25.x
Other All
: Normal normal
: ---
Assigned To: Metacity maintainers list
Metacity maintainers list
: 164082 562120 562922 590032 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2008-12-24 07:15 UTC by Derek Poon
Modified: 2010-11-22 21:00 UTC
See Also:
GNOME target: ---
GNOME version: 2.25/2.26


Attachments
Bugfix for metacity 2.24.0 (1.77 KB, patch)
2008-12-24 07:16 UTC, Derek Poon
none Details | Review
Bugfix for metacity 2.25.55 (1.77 KB, patch)
2008-12-24 07:20 UTC, Derek Poon
reviewed Details | Review
Derek's patch, in git format, against current metacity, with slight tweaking (2.76 KB, patch)
2010-05-02 15:38 UTC, Thomas Thurman
reviewed Details | Review
Unify the three branches of the keymap-reloading code (2.28 KB, patch)
2010-05-02 15:39 UTC, Thomas Thurman
needs-work Details | Review
Update keybindings when XKB keyboard layout changes (3.06 KB, patch)
2010-11-22 19:16 UTC, Owen Taylor
none Details | Review
Update keybindings when XKB keyboard layout changes (3.02 KB, patch)
2010-11-22 19:23 UTC, Owen Taylor
committed Details | Review
Unify keymap-reloading code branches (2.63 KB, patch)
2010-11-22 20:37 UTC, Owen Taylor
committed Details | Review

Description Derek Poon 2008-12-24 07:15:02 UTC
Metacity's keybinding table becomes out of date when the keyboard layout changes via XKB.  This is likely to be a problem when starting a Gnome session, as there is a race condition with gnome-settings-manager, and metacity is likely to configure its keybindings based on the system-wide keyboard layout rather than the layout selected by the user in gnome-keyboard-properties.

To reproduce:
0) Assuming the system-wide keyboard layout is U.S. English...
1) Launch gnome-keybinding-properties
2) Set the "Toggle fullscreen" shortcut to Ctrl+;
3) Press Ctrl+; and verify that toggle fullscreen works
4) setxkbmap fr
5) Press Ctrl+; again (on the French layout, the semicolon is where the comma would be on a U.S. English layout) and see that toggle fullscreen fails
6) metacity-message restart
7) Press Ctrl+; (using French layout) and see that toggle fullscreen works again

Cross-references:
This might be the cause of http://bugzilla.gnome.org/show_bug.cgi?id=164082
Comment 1 Derek Poon 2008-12-24 07:16:51 UTC
Created attachment 125259 [details] [review]
Bugfix for metacity 2.24.0
Comment 2 Derek Poon 2008-12-24 07:20:11 UTC
Created attachment 125260 [details] [review]
Bugfix for metacity 2.25.55

Same patch as for 2.24.0, with different line numbers
Comment 3 Daniel Svensson 2009-01-16 07:38:07 UTC
Is this why I every morning when I get to work and plugin my external keyboard have to do:

1. Open "System -> Preferences -> Keyboard"
2. Select "Layouts" tab.
2.1 Notice that "Sweden Dvorak" is chosen, but external keyboard is qwerty
3. Open "Layout Options"
3.1 Notice that "Ctrl key position" is "Swap Ctrl and CapsLock" but  Ctrl and CapsLock isn't swapped.
4. Set "Ctrl key position" to "Default" and click "Close"
5. Open "Layout Options"
6. Set "Ctrl key position" to "Swap Ctrl and CapsLock" and click "Close"
7. Close "Keyboard Preferences"
8. Open up a terminal and write "setxkbmap se dvorak"
9. Finally, my external keyboard matches the keyboard on my laptop.

Possibly worth mentioning is that my external keyboard is found by ev input and not the oldskool way:


(II) config/hal: Adding input device Microsoft Natural? Ergonomic Keyboard 4000
(**) Microsoft Natural? Ergonomic Keyboard 4000: always reports core events
(**) Microsoft Natural? Ergonomic Keyboard 4000: Device: "/dev/input/event2"
(II) Microsoft Natural? Ergonomic Keyboard 4000: Found 1 mouse buttons
(II) Microsoft Natural? Ergonomic Keyboard 4000: Found keys
(II) Microsoft Natural? Ergonomic Keyboard 4000: Configuring as keyboard
(**) Microsoft Natural? Ergonomic Keyboard 4000: YAxisMapping: buttons 4 and 5
(**) Microsoft Natural? Ergonomic Keyboard 4000: EmulateWheelButton: 4, EmulateWheelInertia: 10, EmulateWheelTimeout: 200
(II) XINPUT: Adding extended input device "Microsoft Natural? Ergonomic Keyboard 4000" (type: KEYBOARD)
(**) Option "xkb_rules" "evdev"
(**) Microsoft Natural? Ergonomic Keyboard 4000: xkb_rules: "evdev"
(**) Option "xkb_model" "evdev"
(**) Microsoft Natural? Ergonomic Keyboard 4000: xkb_model: "evdev"
(**) Option "xkb_layout" "us"
(**) Microsoft Natural? Ergonomic Keyboard 4000: xkb_layout: "us"


or is this a separate bug?
Comment 4 Jens Petersen 2009-08-25 03:25:03 UTC
This is not a metacity bug - not even sure it is a bug at all.
Comment 5 Daniel Svensson 2009-08-25 05:42:37 UTC
It surely can't be the expected behavior?
Comment 6 Jens Petersen 2009-08-26 03:09:09 UTC
Sorry you can probably ignore comment 4, I guess I didn't read the description carefully enough.
Comment 7 Owen Taylor 2009-11-20 21:34:50 UTC
*** Bug 590032 has been marked as a duplicate of this bug. ***
Comment 8 Owen Taylor 2009-11-20 21:42:57 UTC
*** Bug 562120 has been marked as a duplicate of this bug. ***
Comment 9 Owen Taylor 2009-11-20 21:44:45 UTC
*** Bug 164082 has been marked as a duplicate of this bug. ***
Comment 10 Owen Taylor 2009-11-20 21:47:28 UTC
*** Bug 562922 has been marked as a duplicate of this bug. ***
Comment 11 Owen Taylor 2009-11-20 22:28:09 UTC
Review of attachment 125260 [details] [review]:

This basically looks like a good fix to me. The key ingredient in why it is necessary (which needs to be described in a comment somewhere) is that *GTK+* selects for Xkb keyboard and mapping notify events when gdk_display_open() is called and delivery of MappingNotify events is disabled when a client has selected for Xkb events. E.g., comment in xserver/xkb/xkbEvents.c is:

 * This function [XkbSendLegacyMapNotify] sends out  two kinds of notification
 *   - Core mapping notify events sent to clients for whom kbd is the
 *     current core ('picked') keyboard _and_ have not explicitly
 *     selected for XKB mapping notify events;

(Presumably also in the docs somewhere)

Some detailed comments about the patch below; the patch also needs to be updated to current Metacity, since the code it is changing has been moved around and changed a bit.

There's a separate and much harder issue here that the grabbing code in Metacity is unable to handle the complexities of the XKB model of keyboards. (And in fact, XGrabKey really isn't up to it either.) Problems include:

 - Multiple installed layouts with the same keys in different positions (bug 103331)
 - Key symbols that are duplicated multiple places on the keyboard (https://bugzilla.redhat.com/show_bug.cgi?id=449908)

But that shouldn't block a fix like this one going in.

::: metacity-2.25.55/src/core/display.c.xkb
@@ +515,3 @@
+      
+      rebuild_window_binding_table (display);
+      rebuild_screen_binding_table (display);

I think these calls are not really right. For comparison, they don't occur in the MappingNotify versions of this code. I think you needed to add them because of a bug in reload_keycodes() - it reads:

          if (display->key_bindings[i].keycode == 0)
              display->key_bindings[i].keycode = XKeysymToKeycode (
                      display->xdisplay, display->key_bindings[i].keysym);

Which isn't going to work when keycode has already been initialized. Instead it should read:

          if (display->key_bindings[i].keysym != 0)

(That is, the binding is on a keysym not a keycode)

It probably makes sense to unify all three branches here with some boolean variables 'modifiers_changed' 'keycodes_changed' or something like that; otherwise only the XKB branch will ever be debugged.

@@ +614,3 @@
+  /* meta_display_init_keys() should have already called XkbQueryExtension() */
+  if (-1 == display->xkb_base_event_type ||
+      False == XkbSelectEvents (display->xdisplay, XkbUseCoreKbd,

The reversed conditionals here aren't in accordance to the Metacity style (GCC will catch an assignment used as a conditional anyways, so the trick isn't needed to deal with that.)

Also, I don't think it's worth checking the return valur for XkbSelectEvents - it's not a round trip to the server and can't fail for any interesting reason. The return value is documented as:

       True           The XkbSelectEvents function returns True if the Xkb extension has been initilialized.
       False          The XkbSelectEvents function returns False if the Xkb extension has not been initilialized.

@@ +618,3 @@
+                                XkbNewKeyboardNotifyMask | XkbMapNotifyMask))
+      meta_topic (META_DEBUG_KEYBINDINGS,
+                  "Unable to respond to XKB keyboard mapping changes");

If we don't have XKB, then the MappingNotify branches will work, so this comment, while true, is a bit deceptive.
Comment 12 Thomas Thurman 2010-01-20 20:02:00 UTC
Reporter: want to put something together addressing Owen's points, or shall I do it?
Comment 13 Thomas Thurman 2010-05-02 15:36:48 UTC
Review of attachment 125260 [details] [review]:

Setting patch to reviewed, since Owen reviewed it
Comment 14 Thomas Thurman 2010-05-02 15:38:35 UTC
Created attachment 160146 [details] [review]
Derek's patch, in git format, against current metacity, with slight tweaking

I am taking matters into my own hands and updating the patch.  Owen, if you have a moment, could you verify that this answers your issues raised in the review?

Another patch follows in a moment to unify the three branches of the keymap-updating code.
Comment 15 Thomas Thurman 2010-05-02 15:39:04 UTC
Created attachment 160147 [details] [review]
Unify the three branches of the keymap-reloading code

As before.
Comment 16 Owen Taylor 2010-11-22 19:08:33 UTC
Review of attachment 160146 [details] [review]:

Just one comment. I'll attach a fixed up version of the patch. Need to push something to Mutter in this area so I can write another patch that modifies reload_keycodes.

::: src/core/keybindings.c
@@ +618,3 @@
+    {
+      meta_topic (META_DEBUG_KEYBINDINGS,
+                  "Unable to respond to XKB keyboard mapping changes");

Comment I made on the original patch still applies here.

if display->xkb_base_event_type == -1 then we don't have XKB and we'll get MappingNotify events, so this message is deceptive.
if display->xkb_base_event_type != -1 then the XkbSelectEvents call can't fail.

So there's no reason for a message here.
Comment 17 Owen Taylor 2010-11-22 19:16:06 UTC
Created attachment 175063 [details] [review]
Update keybindings when XKB keyboard layout changes

Here's my version of Derek's patch. Removed the deceptive warning
message and added a useful commit message.
Comment 18 Owen Taylor 2010-11-22 19:23:13 UTC
Created attachment 175065 [details] [review]
Update keybindings when XKB keyboard layout changes

Also with fix so it actually compiles against current Metacity.
Comment 19 Owen Taylor 2010-11-22 19:34:19 UTC
Review of attachment 160147 [details] [review]:

::: src/core/keybindings.c
@@ +517,3 @@
                   "XKB mapping changed, will redo keybindings\n");
 
+      redo_keybindings = TRUE;

Don't see the point in this as compared to writing (redo_keycodes || redo_modifiers) below.

@@ +545,1 @@
       reload_keymap (display);

This wasn't called before in the MappingModifier case.

@@ +553,3 @@
+      if (redo_modifiers)
+        {
+          reload_modifiers (display);

It looks like a bug to me that this wasn't called in the MappingKeyboard case. MappingKeyboard requires reload_modmap() because that depends on key symbols. And when the loaded modifier map changes the modifiers in bindings can change.
Comment 20 Owen Taylor 2010-11-22 19:37:09 UTC
Review of attachment 160147 [details] [review]:

::: src/core/keybindings.c
@@ +536,3 @@
                   "Received MappingKeyboard event, will reload keycodes and redo keybindings\n");
 
+      redo_keybindings = TRUE;

Also, this needs to set redo_keycodes
Comment 21 Owen Taylor 2010-11-22 20:37:03 UTC
Created attachment 175067 [details] [review]
Unify keymap-reloading code branches

Simplify the keymap loading logic by unifying the different
branches; in the reorganization this patch fixes a bug where when
we got a MappingKeyboard event we wouldn't update virtual modifiers
correctly.

Based on a patch by Thomas Thurman <tthurman@gnome.org>
Comment 22 Dan Winship 2010-11-22 20:47:07 UTC
Comment on attachment 175065 [details] [review]
Update keybindings when XKB keyboard layout changes

looks right
Comment 23 Dan Winship 2010-11-22 20:50:44 UTC
Comment on attachment 175067 [details] [review]
Unify keymap-reloading code branches

seems right
Comment 24 Owen Taylor 2010-11-22 21:00:08 UTC
Patches pushed with my fixes and Dan's review. Sorry for the slow response
at reviewing the last versions; lost track that it this was
blocking on me.

The one thing I'm left uncertain here is a paragraph in the XKB docs:

 The X Keyboard Extension uses XkbMapNotify and XkbNewKeyboardNotify
 events to track changes to the keyboard mapping. When an Xkb-aware
 client receives either event, it should call
 XkbRefreshKeyboardMapping to update the keyboard description used
 internally by the X library. To avoid duplicate events, the X server
 does not send core protocol MappingNotify events to a client that has
 selected for XkbMapNotify events.

We don't do that in this patch, yet the patch seems to work. Reading the
code in Xlib didn't immediately enlighten me. If we find additional
problems in this area, that is probably that. (Actually, GTK+ would
need to be doing that, since it's already selecting for XkbMapNotify
before Metacity gets into the picture, but it doesn't seem to do that
either.)
Attachment 175065 [details] pushed as c262e3d - Update keybindings when XKB keyboard layout changes
Attachment 175067 [details] pushed as ba2e5f7 - Unify keymap-reloading code branches