Xpra: Ticket #661: Hard to switch keyboard layout using hot keys; "Keyboard" menu has no effect

0.14.2: I need to type email using alternative keyboard layout. Previously in 0.13.* there were no problems with that whatsoever as Desktop Environment (KDE) hot-key combination (Alt+Shift) worked in Xpra session. Now not only it doesn't work at all (ignored?) but even switching layout using new "Keyboard" menu in Xpra does nothing.

Client Xpra logs "new keyboard layout selected" but in fact everything is typed using "us" layout. I couldn't find a way to switch layout in xpra session at all... :(



Sat, 23 Aug 2014 20:56:45 GMT - onlyjob: priority changed

Not sure what's happened but after I upgraded to version 0.14.3 and restarted client and server I can switch keyboard layouts using hotkeys but still not from Xpra "keyboard" menu (which is not working) -- hence I'm lowering severity of this bug...


Sat, 23 Aug 2014 20:58:34 GMT - onlyjob: summary changed


Sat, 23 Aug 2014 22:20:11 GMT - onlyjob:

Related to #86


Sun, 24 Aug 2014 04:33:42 GMT - Antoine Martin: owner changed

The answer... is not simple. When is it ever?

First, assuming that you can reproduce it, please be aware of the changes in 0.14.x relating to input methods: #634. The default should be unchanged: none is the default and disables all input methods server side. But I may have missed something. The differences are easy to spot as this change only affects the environment variables exposed to start-child X11 clients on the server (see #634 for the list of variables affected). Comparing with an older versions should just be a matter of comparing the environment, and verifying the status of whatever dbus daemon / input settings / input method daemons are relevant..


Now for the new keyboard menu entry... it doesn't do what you think it does. It only changes the layout exposed to X11 applications via the X11 root window property. The actual individual key mapping still comes from the client's keymap and is applied on top of that. Mostly.. Because it is impossible to use the core X11 keyboard API to set the exact keymap we have detected (and that we don't even have an X11 keymap on non-X11 platforms..)

So, with X11 clients, it is only really useful for two things:

The keys the client sends remain the same, so if your client is configured to use us and you set the server to fr, the keys received should still be us. Mostly..


Suggestions on how to improve this, present it better or change it in any way would be most welcome.

I hope one day to get around to #371 and use xkbcommon to provide exact keyboard mapping between X11 clients and X11 servers.


Mon, 01 Sep 2014 12:24:59 GMT - onlyjob: priority changed

I've been hit hard by this issue again on 0.14.4 however this time restarting client and server did not help. I can't switch keyboard layout so the problem is reproduced... What's next? Why client do not send non-us layout any more? I've never ever had such problem on 0.13.* and earlier...

I do not start applications using "--start-child" and I don't see any environment variables related to input methods on my system...

Server started as xpra start :22 --use-display to reuse previous session (I had to "kill -9 xpra" after yet another hang on pulseaudio...).

I can't switch keyboard layout even if I start xpra server as usual (without "--use-display").

Also purpose of "Keyboard" menu escapes me entirely... What is it good for? (Probably an example could help me to understand). Thanks.


Thu, 04 Sep 2014 09:54:42 GMT - onlyjob: summary changed

The essence of this regression from 0.13.* is that to switch layout in 0.13 I had to press "Alt+Shift". With 0.14 it is possible to switch layout but it is much more difficult as I have to press "Alt+Shift+Shift+Shift" (that is "Alt" held, "Shift" pressed three(!) times). Reproduced by temporary downgrading client to 0.13.9.


Thu, 04 Sep 2014 13:47:23 GMT - Antoine Martin:

Why client do not send non-us layout any more?


On "Auto" mode, things were meant to be unchanged, but maybe it isn't working as it should? Please provide -d keyboard logs.

Does this make any difference (should more or less revert to v0.13.x behaviour I believe):

--- trunk/src/xpra/client/gtk_base/gtk_tray_menu_base.py	(revision 7502)
+++ trunk/src/xpra/client/gtk_base/gtk_tray_menu_base.py	(working copy)
@@ -779,7 +779,7 @@
             return c.lower()+l.lower()
         layout,layouts,variant,variants = self.client.keyboard_helper.keyboard.get_layout_spec()
         full_layout_list = False
-        if len(layouts)>1:
+        if False and len(layouts)>1:
             log.info("keyboard layouts: %s", ",".join(layouts))
             auto = kbitem("Auto", "Auto", "", True)
             self.layout_submenu.append(auto)


I do not start applications using "--start-child" ..


Then just be aware that the environment variables will all be unset, and the input method behaviour will vary.


.. --use-display ...


FYI: we don't pass any input method settings to the X11 server. So whether the X11 server is started already or not should not matter.


Also purpose of "Keyboard" menu escapes me entirely... What is it good for?


See comment:4. If you only use the same version of Linux at both ends, you probably don't need it.

The essence of this regression from 0.13.* is that to switch layout in 0.13 I had to press "Alt+Shift".


This keyboard layout toggle is done using the setxkbmap option: -option grp:alt_shift_toggle. It is possible that somehow we end up stripping it when overriding the keyboard layout. (that would be a bug) Log samples would clarify this.


Sun, 14 Sep 2014 14:50:31 GMT - onlyjob:

I upgraded (server and client) to 0.14.6 and couldn't switch keyboard layout at all, no matter how hard I tried. Naturally I tried the patch but it didn't change a thing. Finally I downgraded client to 0.13.9 and immediately after attaching to session I could switch keyboard layout effortlessly. Then I installed 0.14.6 again and to my surprise I could change keyboard layout this time, although I needed to press Alt+Shift twice while in 0.13.9 only one keypress was sufficient. I realise it may seem strange but observation is accurate even though I don't have a slightest idea what is going on... Unfortunately I've forgotten to pass -d keyboard to client. I'll post logs when keyboard switching stop working again...


Tue, 16 Sep 2014 02:41:18 GMT - onlyjob: attachment set


Tue, 16 Sep 2014 02:41:25 GMT - onlyjob: attachment set


Tue, 16 Sep 2014 02:49:49 GMT - onlyjob:

Here are client -d keyboard logs. In the attached "0.14.6-fail.log.xz I'm trying to switch to alternative keyboard layout by pressing "Alt+Shift" and typing "qwe" to see if it works. All attempts fail so I couldn't switch.

Then I downgraded to 0.13.9 (see attached "0.13.9-ok.log.xz​") where I type "qwe", then switch to alternative layout with "Alt+Shift" from first attempt, type "йцу" and switch back English.

Just like in previous incident to fix situation it was enough to attach with 0.13.9 once, then even if re-attached with 0.14.6 again keyboard switching worked.

Problem manifested after complete server restart. Please help.


Sun, 21 Sep 2014 13:20:28 GMT - Antoine Martin:

The two log samples have just the key events, and client side only, so there is nothing there to compare. We want the setup phase, server side. With optional key events separately.

I am still quite unclear on which version at which end is causing the problem, and since I don't have the faintest idea how to setup a system to reproduce this, I am extremely unlikely to find the problem.

I don't see how the changes in 0.14 can have this effect, or at least, I don't understand why disabling the client-side tray menu changes doesn't revert to 0.13.x behaviour. This is similar to the patch in comment:7, but more brutal:

--- src/xpra/client/gtk_base/gtk_tray_menu_base.py	(revision 7712)
+++ src/xpra/client/gtk_base/gtk_tray_menu_base.py	(working copy)
@@ -231,7 +231,8 @@
         if SHOW_COMPRESSION_MENU:
             menu.append(self.make_compressionmenu())
         if not self.client.readonly and self.client.keyboard_helper:
-            menu.append(self.make_layoutsmenuitem())
+            pass
+            #menu.append(self.make_layoutsmenuitem())
         if self.client.windows_enabled and not self.client.readonly:
             menu.append(self.make_keyboardsyncmenuitem())
         if self.client.windows_enabled:

Please re-assign tickets to me when you want me to take a look.


Thu, 02 Oct 2014 15:11:40 GMT - onlyjob: owner changed

I wish I had better understanding of this situation. This bug unfortunately is very persistent, and way too easy to reproduce form so I've hit it many many times...

Here is server-side log of 0.14.8 with -d keyboard:

2014-10-03 00:57:35,915 get_keycode(24, q, ()) native keymap, using unmodified keycode: 24
2014-10-03 00:57:35,915 handle_key(3,True,q,113,24,()) keyboard_sync=False
2014-10-03 00:57:35,915 is_modifier(24) not found
2014-10-03 00:57:35,915 handle keycode pressing 24: key q
2014-10-03 00:57:35,916 fake_key(24, True)
2014-10-03 00:57:35,916 handle keycode unpressing 24: key q
2014-10-03 00:57:35,916 fake_key(24, False)
2014-10-03 00:57:36,018 get_keycode(24, q, ()) native keymap, using unmodified keycode: 24
2014-10-03 00:57:36,018 handle_key(3,False,q,113,24,()) keyboard_sync=False
2014-10-03 00:57:36,018 is_modifier(24) not found
2014-10-03 00:57:36,018 handle keycode 24: key q was already unpressed, ignoring
2014-10-03 00:57:36,163 get_keycode(25, w, ()) native keymap, using unmodified keycode: 25
2014-10-03 00:57:36,163 handle_key(3,True,w,119,25,()) keyboard_sync=False
2014-10-03 00:57:36,163 is_modifier(25) not found
2014-10-03 00:57:36,163 handle keycode pressing 25: key w
2014-10-03 00:57:36,163 fake_key(25, True)
2014-10-03 00:57:36,164 handle keycode unpressing 25: key w
2014-10-03 00:57:36,164 fake_key(25, False)
2014-10-03 00:57:36,250 get_keycode(25, w, ()) native keymap, using unmodified keycode: 25
2014-10-03 00:57:36,250 handle_key(3,False,w,119,25,()) keyboard_sync=False
2014-10-03 00:57:36,250 is_modifier(25) not found
2014-10-03 00:57:36,250 handle keycode 25: key w was already unpressed, ignoring
2014-10-03 00:57:36,410 get_keycode(26, e, ()) native keymap, using unmodified keycode: 26
2014-10-03 00:57:36,410 handle_key(3,True,e,101,26,()) keyboard_sync=False
2014-10-03 00:57:36,410 is_modifier(26) not found
2014-10-03 00:57:36,410 handle keycode pressing 26: key e
2014-10-03 00:57:36,410 fake_key(26, True)
2014-10-03 00:57:36,411 handle keycode unpressing 26: key e
2014-10-03 00:57:36,411 fake_key(26, False)
2014-10-03 00:57:36,482 get_keycode(26, e, ()) native keymap, using unmodified keycode: 26
2014-10-03 00:57:36,482 handle_key(3,False,e,101,26,()) keyboard_sync=False
2014-10-03 00:57:36,482 is_modifier(26) not found
2014-10-03 00:57:36,482 handle keycode 26: key e was already unpressed, ignoring
2014-10-03 00:57:38,858 get_keycode(64, Alt_L, ()) native keymap, using unmodified keycode: 64
2014-10-03 00:57:38,859 handle_key(3,True,Alt_L,65513,64,()) keyboard_sync=False
2014-10-03 00:57:38,859 handle keycode pressing 64: key Alt_L
2014-10-03 00:57:38,859 fake_key(64, True)
2014-10-03 00:57:39,179 get_keycode(50, ISO_Next_Group, ('mod1',)) native keymap, using unmodified keycode: 50
2014-10-03 00:57:39,180 handle_key(3,True,ISO_Next_Group,65032,50,('mod1',)) keyboard_sync=False
2014-10-03 00:57:39,180 is_modifier(50) found modifier: Shift_L
2014-10-03 00:57:39,180 handle keycode pressing 50: key ISO_Next_Group
2014-10-03 00:57:39,180 fake_key(50, True)
2014-10-03 00:57:39,290 get_keycode(64, Alt_L, ('mod1',)) native keymap, using unmodified keycode: 64
2014-10-03 00:57:39,290 make_keymask_match(('mod1',)) current mask: set(['mod1', 'shift']), wanted: set(['mod1']), ignoring=64/['Alt_L'], keys_pressed={64: 'Alt_L', 50: 'ISO_Next_Group'}
2014-10-03 00:57:39,290 is_ignored(shift, set(['Shift_L', 'Shift_R']))=set([])
2014-10-03 00:57:39,290 keynames(shift)=set(['Shift_L', 'Shift_R']), keycodes=[50, 62], nuisance=False
2014-10-03 00:57:39,290 make_keymask_match(remove) ('mod1',) modifier shift using 50, success: True
2014-10-03 00:57:39,291 handle_key(3,False,Alt_L,65513,64,('mod1',)) keyboard_sync=False
2014-10-03 00:57:39,291 handle keycode unpressing 64: key Alt_L
2014-10-03 00:57:39,291 fake_key(64, False)
2014-10-03 00:57:39,306 get_keycode(50, Shift_L, ()) native keymap, using unmodified keycode: 50
2014-10-03 00:57:39,306 handle_key(3,False,Shift_L,65505,50,()) keyboard_sync=False
2014-10-03 00:57:39,306 handle keycode unpressing 50: key Shift_L
2014-10-03 00:57:39,306 fake_key(50, False)
2014-10-03 00:57:42,362 get_keycode(24, Cyrillic_shorti, ()) native keymap, using unmodified keycode: 24
2014-10-03 00:57:42,362 handle_key(3,True,Cyrillic_shorti,1738,24,()) keyboard_sync=False
2014-10-03 00:57:42,362 is_modifier(24) not found
2014-10-03 00:57:42,363 handle keycode pressing 24: key Cyrillic_shorti
2014-10-03 00:57:42,363 fake_key(24, True)
2014-10-03 00:57:42,363 handle keycode unpressing 24: key Cyrillic_shorti
2014-10-03 00:57:42,363 fake_key(24, False)
2014-10-03 00:57:42,473 get_keycode(24, Cyrillic_shorti, ()) native keymap, using unmodified keycode: 24
2014-10-03 00:57:42,474 handle_key(3,False,Cyrillic_shorti,1738,24,()) keyboard_sync=False
2014-10-03 00:57:42,474 is_modifier(24) not found
2014-10-03 00:57:42,474 handle keycode 24: key Cyrillic_shorti was already unpressed, ignoring
2014-10-03 00:57:42,970 get_keycode(25, Cyrillic_tse, ()) native keymap, using unmodified keycode: 25
2014-10-03 00:57:42,970 handle_key(3,True,Cyrillic_tse,1731,25,()) keyboard_sync=False
2014-10-03 00:57:42,970 is_modifier(25) not found
2014-10-03 00:57:42,971 handle keycode pressing 25: key Cyrillic_tse
2014-10-03 00:57:42,971 fake_key(25, True)
2014-10-03 00:57:42,971 handle keycode unpressing 25: key Cyrillic_tse
2014-10-03 00:57:42,971 fake_key(25, False)
2014-10-03 00:57:43,073 get_keycode(25, Cyrillic_tse, ()) native keymap, using unmodified keycode: 25
2014-10-03 00:57:43,074 handle_key(3,False,Cyrillic_tse,1731,25,()) keyboard_sync=False
2014-10-03 00:57:43,074 is_modifier(25) not found
2014-10-03 00:57:43,074 handle keycode 25: key Cyrillic_tse was already unpressed, ignoring
2014-10-03 00:57:43,450 get_keycode(26, Cyrillic_u, ()) native keymap, using unmodified keycode: 26
2014-10-03 00:57:43,450 handle_key(3,True,Cyrillic_u,1749,26,()) keyboard_sync=False
2014-10-03 00:57:43,451 is_modifier(26) not found
2014-10-03 00:57:43,451 handle keycode pressing 26: key Cyrillic_u
2014-10-03 00:57:43,451 fake_key(26, True)
2014-10-03 00:57:43,452 handle keycode unpressing 26: key Cyrillic_u
2014-10-03 00:57:43,452 fake_key(26, False)
2014-10-03 00:57:43,538 get_keycode(26, Cyrillic_u, ()) native keymap, using unmodified keycode: 26
2014-10-03 00:57:43,539 handle_key(3,False,Cyrillic_u,1749,26,()) keyboard_sync=False
2014-10-03 00:57:43,539 is_modifier(26) not found
2014-10-03 00:57:43,539 handle keycode 26: key Cyrillic_u was already unpressed, ignoring
2014-10-03 00:57:44,762 get_keycode(64, Alt_L, ()) native keymap, using unmodified keycode: 64
2014-10-03 00:57:44,763 handle_key(3,True,Alt_L,65513,64,()) keyboard_sync=False
2014-10-03 00:57:44,763 handle keycode pressing 64: key Alt_L
2014-10-03 00:57:44,763 fake_key(64, True)
2014-10-03 00:57:44,963 get_keycode(50, ISO_Next_Group, ('mod1',)) native keymap, using unmodified keycode: 50
2014-10-03 00:57:44,963 handle_key(3,True,ISO_Next_Group,65032,50,('mod1',)) keyboard_sync=False
2014-10-03 00:57:44,963 is_modifier(50) found modifier: Shift_L
2014-10-03 00:57:44,963 handle keycode pressing 50: key ISO_Next_Group
2014-10-03 00:57:44,963 fake_key(50, True)
2014-10-03 00:57:45,050 get_keycode(64, Alt_L, ('mod1',)) native keymap, using unmodified keycode: 64
2014-10-03 00:57:45,050 make_keymask_match(('mod1',)) current mask: set(['mod1', 'shift']), wanted: set(['mod1']), ignoring=64/['Alt_L'], keys_pressed={64: 'Alt_L', 50: 'ISO_Next_Group'}
2014-10-03 00:57:45,050 is_ignored(shift, set(['Shift_L', 'Shift_R']))=set([])
2014-10-03 00:57:45,050 keynames(shift)=set(['Shift_L', 'Shift_R']), keycodes=[50, 62], nuisance=False
2014-10-03 00:57:45,050 make_keymask_match(remove) ('mod1',) modifier shift using 50, success: True
2014-10-03 00:57:45,050 handle_key(3,False,Alt_L,65513,64,('mod1',)) keyboard_sync=False
2014-10-03 00:57:45,051 handle keycode unpressing 64: key Alt_L
2014-10-03 00:57:45,051 fake_key(64, False)
2014-10-03 00:57:45,089 get_keycode(50, Shift_L, ()) native keymap, using unmodified keycode: 50
2014-10-03 00:57:45,090 handle_key(3,False,Shift_L,65505,50,()) keyboard_sync=False
2014-10-03 00:57:45,090 handle keycode unpressing 50: key Shift_L
2014-10-03 00:57:45,090 fake_key(50, False)
2014-10-03 00:57:46,011 _clear_keys_pressed()

As previously I press "qwe" following by "Alt+Shift" to switch keyboard layout then type "qwe" buttons once again (this time I expect to see national characters)". In application "qwe" appears for the second time, which is a problem. I tried pressing Alt+Shift combinations many many times with no result whatsoever.

Now the interesting part begins: I downgrade Xpra to version 0.13.9 on client and try the above procedure again:

2014-10-03 01:03:52,282 get_keycode(24, q, ()) native keymap, using unmodified keycode: 24
2014-10-03 01:03:52,725 handle_key(3,True,q,113,24,()) keyboard_sync=False
2014-10-03 01:03:52,725 is_modifier(24) not found
2014-10-03 01:03:52,725 handle keycode pressing 24: key q
2014-10-03 01:03:52,725 fake_key(24, True)
2014-10-03 01:03:52,726 handle keycode unpressing 24: key q
2014-10-03 01:03:52,726 fake_key(24, False)
2014-10-03 01:03:52,733 get_keycode(24, q, ()) native keymap, using unmodified keycode: 24
2014-10-03 01:03:52,734 handle_key(3,False,q,113,24,()) keyboard_sync=False
2014-10-03 01:03:52,734 is_modifier(24) not found
2014-10-03 01:03:52,734 handle keycode 24: key q was already unpressed, ignoring
2014-10-03 01:03:52,734 get_keycode(25, w, ()) native keymap, using unmodified keycode: 25
2014-10-03 01:03:52,734 handle_key(3,True,w,119,25,()) keyboard_sync=False
2014-10-03 01:03:52,734 is_modifier(25) not found
2014-10-03 01:03:52,734 handle keycode pressing 25: key w
2014-10-03 01:03:52,734 fake_key(25, True)
2014-10-03 01:03:52,734 handle keycode unpressing 25: key w
2014-10-03 01:03:52,734 fake_key(25, False)
2014-10-03 01:03:52,735 get_keycode(25, w, ()) native keymap, using unmodified keycode: 25
2014-10-03 01:03:52,735 handle_key(3,False,w,119,25,()) keyboard_sync=False
2014-10-03 01:03:52,735 is_modifier(25) not found
2014-10-03 01:03:52,735 handle keycode 25: key w was already unpressed, ignoring
2014-10-03 01:03:52,850 get_keycode(26, e, ()) native keymap, using unmodified keycode: 26
2014-10-03 01:03:52,850 handle_key(3,True,e,101,26,()) keyboard_sync=False
2014-10-03 01:03:52,850 is_modifier(26) not found
2014-10-03 01:03:52,850 handle keycode pressing 26: key e
2014-10-03 01:03:52,851 fake_key(26, True)
2014-10-03 01:03:52,851 handle keycode unpressing 26: key e
2014-10-03 01:03:52,851 fake_key(26, False)
2014-10-03 01:03:52,937 get_keycode(26, e, ()) native keymap, using unmodified keycode: 26
2014-10-03 01:03:52,938 handle_key(3,False,e,101,26,()) keyboard_sync=False
2014-10-03 01:03:52,938 is_modifier(26) not found
2014-10-03 01:03:52,938 handle keycode 26: key e was already unpressed, ignoring
2014-10-03 01:03:54,762 get_keycode(64, Alt_L, ()) native keymap, using unmodified keycode: 64
2014-10-03 01:03:54,763 handle_key(3,True,Alt_L,65513,64,()) keyboard_sync=False
2014-10-03 01:03:54,763 handle keycode pressing 64: key Alt_L
2014-10-03 01:03:54,763 fake_key(64, True)
2014-10-03 01:03:55,067 get_keycode(50, ISO_Next_Group, ('mod1',)) native keymap, using unmodified keycode: 50
2014-10-03 01:03:55,067 handle_key(3,True,ISO_Next_Group,65032,50,('mod1',)) keyboard_sync=False
2014-10-03 01:03:55,067 is_modifier(50) found modifier: Shift_L
2014-10-03 01:03:55,068 handle keycode pressing 50: key ISO_Next_Group
2014-10-03 01:03:55,068 fake_key(50, True)
2014-10-03 01:03:55,169 get_keycode(64, Alt_L, ('mod1',)) native keymap, using unmodified keycode: 64
2014-10-03 01:03:55,170 handle_key(3,False,Alt_L,65513,64,('mod1',)) keyboard_sync=False
2014-10-03 01:03:55,170 handle keycode unpressing 64: key Alt_L
2014-10-03 01:03:55,170 fake_key(64, False)
2014-10-03 01:03:55,201 get_keycode(50, Shift_L, ()) native keymap, using unmodified keycode: 50
2014-10-03 01:03:55,202 handle_key(3,False,Shift_L,65505,50,()) keyboard_sync=False
2014-10-03 01:03:55,202 handle keycode unpressing 50: key Shift_L
2014-10-03 01:03:55,202 fake_key(50, False)
2014-10-03 01:03:56,393 get_keycode(24, Cyrillic_shorti, ()) native keymap, using unmodified keycode: 24
2014-10-03 01:03:56,394 handle_key(3,True,Cyrillic_shorti,1738,24,()) keyboard_sync=False
2014-10-03 01:03:56,394 is_modifier(24) not found
2014-10-03 01:03:56,394 handle keycode pressing 24: key Cyrillic_shorti
2014-10-03 01:03:56,394 fake_key(24, True)
2014-10-03 01:03:56,395 handle keycode unpressing 24: key Cyrillic_shorti
2014-10-03 01:03:56,395 fake_key(24, False)
2014-10-03 01:03:56,513 get_keycode(24, Cyrillic_shorti, ()) native keymap, using unmodified keycode: 24
2014-10-03 01:03:56,514 handle_key(3,False,Cyrillic_shorti,1738,24,()) keyboard_sync=False
2014-10-03 01:03:56,514 is_modifier(24) not found
2014-10-03 01:03:56,514 handle keycode 24: key Cyrillic_shorti was already unpressed, ignoring
2014-10-03 01:03:56,610 get_keycode(25, Cyrillic_tse, ()) native keymap, using unmodified keycode: 25
2014-10-03 01:03:56,610 handle_key(3,True,Cyrillic_tse,1731,25,()) keyboard_sync=False
2014-10-03 01:03:56,610 is_modifier(25) not found
2014-10-03 01:03:56,610 handle keycode pressing 25: key Cyrillic_tse
2014-10-03 01:03:56,610 fake_key(25, True)
2014-10-03 01:03:56,610 handle keycode unpressing 25: key Cyrillic_tse
2014-10-03 01:03:56,610 fake_key(25, False)
2014-10-03 01:03:56,697 get_keycode(25, Cyrillic_tse, ()) native keymap, using unmodified keycode: 25
2014-10-03 01:03:56,698 handle_key(3,False,Cyrillic_tse,1731,25,()) keyboard_sync=False
2014-10-03 01:03:56,698 is_modifier(25) not found
2014-10-03 01:03:56,698 handle keycode 25: key Cyrillic_tse was already unpressed, ignoring
2014-10-03 01:03:56,834 get_keycode(26, Cyrillic_u, ()) native keymap, using unmodified keycode: 26
2014-10-03 01:03:56,834 handle_key(3,True,Cyrillic_u,1749,26,()) keyboard_sync=False
2014-10-03 01:03:56,834 is_modifier(26) not found
2014-10-03 01:03:56,834 handle keycode pressing 26: key Cyrillic_u
2014-10-03 01:03:56,834 fake_key(26, True)
2014-10-03 01:03:56,834 handle keycode unpressing 26: key Cyrillic_u
2014-10-03 01:03:56,835 fake_key(26, False)
2014-10-03 01:03:56,937 get_keycode(26, Cyrillic_u, ()) native keymap, using unmodified keycode: 26
2014-10-03 01:03:56,938 handle_key(3,False,Cyrillic_u,1749,26,()) keyboard_sync=False
2014-10-03 01:03:56,938 is_modifier(26) not found
2014-10-03 01:03:56,938 handle keycode 26: key Cyrillic_u was already unpressed, ignoring
2014-10-03 01:04:07,076 _clear_keys_pressed()
2014-10-03 01:04:14,991 _clear_keys_pressed()
2014-10-03 01:04:15,710 Connection lost
2014-10-03 01:04:15,711 xpra client disconnected.
2014-10-03 01:04:15,711 _clear_keys_pressed()

This time typing "qwe" after Alt+Shift produced "йцу" as expected. Now I'm installing 0.14.8 on client and repeat:

2014-10-03 01:06:51,474 get_keycode(24, q, ()) native keymap, using unmodified keycode: 24
2014-10-03 01:06:51,475 handle_key(3,True,q,113,24,()) keyboard_sync=False
2014-10-03 01:06:51,475 is_modifier(24) not found
2014-10-03 01:06:51,475 handle keycode pressing 24: key q
2014-10-03 01:06:51,475 fake_key(24, True)
2014-10-03 01:06:51,476 handle keycode unpressing 24: key q
2014-10-03 01:06:51,476 fake_key(24, False)
2014-10-03 01:06:51,570 get_keycode(24, q, ()) native keymap, using unmodified keycode: 24
2014-10-03 01:06:51,570 handle_key(3,False,q,113,24,()) keyboard_sync=False
2014-10-03 01:06:51,571 is_modifier(24) not found
2014-10-03 01:06:51,571 handle keycode 24: key q was already unpressed, ignoring
2014-10-03 01:06:51,771 get_keycode(25, w, ()) native keymap, using unmodified keycode: 25
2014-10-03 01:06:51,771 handle_key(3,True,w,119,25,()) keyboard_sync=False
2014-10-03 01:06:51,771 is_modifier(25) not found
2014-10-03 01:06:51,771 handle keycode pressing 25: key w
2014-10-03 01:06:51,772 fake_key(25, True)
2014-10-03 01:06:51,772 handle keycode unpressing 25: key w
2014-10-03 01:06:51,772 fake_key(25, False)
2014-10-03 01:06:51,874 get_keycode(25, w, ()) native keymap, using unmodified keycode: 25
2014-10-03 01:06:51,874 handle_key(3,False,w,119,25,()) keyboard_sync=False
2014-10-03 01:06:51,874 is_modifier(25) not found
2014-10-03 01:06:51,875 handle keycode 25: key w was already unpressed, ignoring
2014-10-03 01:06:52,019 get_keycode(26, e, ()) native keymap, using unmodified keycode: 26
2014-10-03 01:06:52,019 handle_key(3,True,e,101,26,()) keyboard_sync=False
2014-10-03 01:06:52,019 is_modifier(26) not found
2014-10-03 01:06:52,019 handle keycode pressing 26: key e
2014-10-03 01:06:52,019 fake_key(26, True)
2014-10-03 01:06:52,019 handle keycode unpressing 26: key e
2014-10-03 01:06:52,020 fake_key(26, False)
2014-10-03 01:06:52,098 get_keycode(26, e, ()) native keymap, using unmodified keycode: 26
2014-10-03 01:06:52,098 handle_key(3,False,e,101,26,()) keyboard_sync=False
2014-10-03 01:06:52,098 is_modifier(26) not found
2014-10-03 01:06:52,098 handle keycode 26: key e was already unpressed, ignoring
2014-10-03 01:06:52,618 get_keycode(64, Alt_L, ()) native keymap, using unmodified keycode: 64
2014-10-03 01:06:52,619 handle_key(3,True,Alt_L,65513,64,()) keyboard_sync=False
2014-10-03 01:06:52,619 handle keycode pressing 64: key Alt_L
2014-10-03 01:06:52,619 fake_key(64, True)
2014-10-03 01:06:52,964 get_keycode(50, ISO_Next_Group, ('mod1',)) native keymap, using unmodified keycode: 50
2014-10-03 01:06:52,965 handle_key(3,True,ISO_Next_Group,65032,50,('mod1',)) keyboard_sync=False
2014-10-03 01:06:52,965 is_modifier(50) found modifier: Shift_L
2014-10-03 01:06:52,965 handle keycode pressing 50: key ISO_Next_Group
2014-10-03 01:06:52,965 fake_key(50, True)
2014-10-03 01:06:53,058 get_keycode(64, Alt_L, ('mod1',)) native keymap, using unmodified keycode: 64
2014-10-03 01:06:53,058 handle_key(3,False,Alt_L,65513,64,('mod1',)) keyboard_sync=False
2014-10-03 01:06:53,058 handle keycode unpressing 64: key Alt_L
2014-10-03 01:06:53,059 fake_key(64, False)
2014-10-03 01:06:53,090 get_keycode(50, Shift_L, ()) native keymap, using unmodified keycode: 50
2014-10-03 01:06:53,090 handle_key(3,False,Shift_L,65505,50,()) keyboard_sync=False
2014-10-03 01:06:53,090 handle keycode unpressing 50: key Shift_L
2014-10-03 01:06:53,090 fake_key(50, False)
2014-10-03 01:06:53,843 get_keycode(24, Cyrillic_shorti, ()) native keymap, using unmodified keycode: 24
2014-10-03 01:06:53,843 handle_key(3,True,Cyrillic_shorti,1738,24,()) keyboard_sync=False
2014-10-03 01:06:53,843 is_modifier(24) not found
2014-10-03 01:06:53,844 handle keycode pressing 24: key Cyrillic_shorti
2014-10-03 01:06:53,844 fake_key(24, True)
2014-10-03 01:06:53,844 handle keycode unpressing 24: key Cyrillic_shorti
2014-10-03 01:06:53,844 fake_key(24, False)
2014-10-03 01:06:54,002 get_keycode(24, Cyrillic_shorti, ()) native keymap, using unmodified keycode: 24
2014-10-03 01:06:54,002 handle_key(3,False,Cyrillic_shorti,1738,24,()) keyboard_sync=False
2014-10-03 01:06:54,002 is_modifier(24) not found
2014-10-03 01:06:54,002 handle keycode 24: key Cyrillic_shorti was already unpressed, ignoring
2014-10-03 01:06:55,058 get_keycode(25, Cyrillic_tse, ()) native keymap, using unmodified keycode: 25
2014-10-03 01:06:55,059 handle_key(3,True,Cyrillic_tse,1731,25,()) keyboard_sync=False
2014-10-03 01:06:55,059 is_modifier(25) not found
2014-10-03 01:06:55,059 handle keycode pressing 25: key Cyrillic_tse
2014-10-03 01:06:55,060 fake_key(25, True)
2014-10-03 01:06:55,060 handle keycode unpressing 25: key Cyrillic_tse
2014-10-03 01:06:55,060 fake_key(25, False)
2014-10-03 01:06:55,138 get_keycode(25, Cyrillic_tse, ()) native keymap, using unmodified keycode: 25
2014-10-03 01:06:55,138 handle_key(3,False,Cyrillic_tse,1731,25,()) keyboard_sync=False
2014-10-03 01:06:55,138 is_modifier(25) not found
2014-10-03 01:06:55,138 handle keycode 25: key Cyrillic_tse was already unpressed, ignoring
2014-10-03 01:06:55,266 get_keycode(26, Cyrillic_u, ()) native keymap, using unmodified keycode: 26
2014-10-03 01:06:55,266 handle_key(3,True,Cyrillic_u,1749,26,()) keyboard_sync=False
2014-10-03 01:06:55,266 is_modifier(26) not found
2014-10-03 01:06:55,266 handle keycode pressing 26: key Cyrillic_u
2014-10-03 01:06:55,267 fake_key(26, True)
2014-10-03 01:06:55,267 handle keycode unpressing 26: key Cyrillic_u
2014-10-03 01:06:55,267 fake_key(26, False)
2014-10-03 01:06:55,337 get_keycode(26, Cyrillic_u, ()) native keymap, using unmodified keycode: 26
2014-10-03 01:06:55,338 handle_key(3,False,Cyrillic_u,1749,26,()) keyboard_sync=False
2014-10-03 01:06:55,338 is_modifier(26) not found
2014-10-03 01:06:55,338 handle keycode 26: key Cyrillic_u was already unpressed, ignoring
2014-10-03 01:06:55,658 get_keycode(64, Alt_L, ()) native keymap, using unmodified keycode: 64
2014-10-03 01:06:55,658 handle_key(3,True,Alt_L,65513,64,()) keyboard_sync=False
2014-10-03 01:06:55,659 handle keycode pressing 64: key Alt_L
2014-10-03 01:06:55,659 fake_key(64, True)
2014-10-03 01:06:55,859 get_keycode(50, ISO_Next_Group, ('mod1',)) native keymap, using unmodified keycode: 50
2014-10-03 01:06:55,860 handle_key(3,True,ISO_Next_Group,65032,50,('mod1',)) keyboard_sync=False
2014-10-03 01:06:55,860 is_modifier(50) found modifier: Shift_L
2014-10-03 01:06:55,860 handle keycode pressing 50: key ISO_Next_Group
2014-10-03 01:06:55,860 fake_key(50, True)
2014-10-03 01:06:55,946 get_keycode(64, Alt_L, ('mod1',)) native keymap, using unmodified keycode: 64
2014-10-03 01:06:55,946 handle_key(3,False,Alt_L,65513,64,('mod1',)) keyboard_sync=False
2014-10-03 01:06:55,947 handle keycode unpressing 64: key Alt_L
2014-10-03 01:06:55,947 fake_key(64, False)
2014-10-03 01:06:55,978 get_keycode(50, Shift_L, ()) native keymap, using unmodified keycode: 50
2014-10-03 01:06:55,978 handle_key(3,False,Shift_L,65505,50,()) keyboard_sync=False
2014-10-03 01:06:55,978 handle keycode unpressing 50: key Shift_L
2014-10-03 01:06:55,978 fake_key(50, False)
2014-10-03 01:06:56,242 get_keycode(24, q, ()) native keymap, using unmodified keycode: 24
2014-10-03 01:06:56,242 handle_key(3,True,q,113,24,()) keyboard_sync=False
2014-10-03 01:06:56,242 is_modifier(24) not found
2014-10-03 01:06:56,243 handle keycode pressing 24: key q
2014-10-03 01:06:56,243 fake_key(24, True)
2014-10-03 01:06:56,243 handle keycode unpressing 24: key q
2014-10-03 01:06:56,243 fake_key(24, False)
2014-10-03 01:06:56,337 get_keycode(24, q, ()) native keymap, using unmodified keycode: 24
2014-10-03 01:06:56,338 handle_key(3,False,q,113,24,()) keyboard_sync=False
2014-10-03 01:06:56,338 is_modifier(24) not found
2014-10-03 01:06:56,338 handle keycode 24: key q was already unpressed, ignoring
2014-10-03 01:06:56,434 get_keycode(25, w, ()) native keymap, using unmodified keycode: 25
2014-10-03 01:06:56,434 handle_key(3,True,w,119,25,()) keyboard_sync=False
2014-10-03 01:06:56,435 is_modifier(25) not found
2014-10-03 01:06:56,435 handle keycode pressing 25: key w
2014-10-03 01:06:56,435 fake_key(25, True)
2014-10-03 01:06:56,436 handle keycode unpressing 25: key w
2014-10-03 01:06:56,436 fake_key(25, False)
2014-10-03 01:06:56,521 get_keycode(25, w, ()) native keymap, using unmodified keycode: 25
2014-10-03 01:06:56,522 handle_key(3,False,w,119,25,()) keyboard_sync=False
2014-10-03 01:06:56,522 is_modifier(25) not found
2014-10-03 01:06:56,522 handle keycode 25: key w was already unpressed, ignoring
2014-10-03 01:06:56,634 get_keycode(26, e, ()) native keymap, using unmodified keycode: 26
2014-10-03 01:06:56,634 handle_key(3,True,e,101,26,()) keyboard_sync=False
2014-10-03 01:06:56,634 is_modifier(26) not found
2014-10-03 01:06:56,634 handle keycode pressing 26: key e
2014-10-03 01:06:56,634 fake_key(26, True)
2014-10-03 01:06:56,635 handle keycode unpressing 26: key e
2014-10-03 01:06:56,635 fake_key(26, False)
2014-10-03 01:06:56,722 get_keycode(26, e, ()) native keymap, using unmodified keycode: 26
2014-10-03 01:06:56,722 handle_key(3,False,e,101,26,()) keyboard_sync=False
2014-10-03 01:06:56,722 is_modifier(26) not found
2014-10-03 01:06:56,723 handle keycode 26: key e was already unpressed, ignoring
2014-10-03 01:07:08,145 _clear_keys_pressed()

This time 0.14.8 works although I had to press "Alt+Shift" twice.

Basically I can't switch keyboard layout in 0.14 at all, unless I connect using old 0.13.9 client once(!) which somehow fixes the problem until server restart.

This is with patch from comment:10 on top of 0.14.8. I'm willing to try anything to fix this, hopefully soon...


Thu, 02 Oct 2014 15:49:29 GMT - Antoine Martin:

Wow, that's weird.

I've just gone through the full diff of src/client between v0.13.x and v0.14.x (assuming the code is not in the x11 bits.. which it might be!), and the only things related to the keyboard code are:

This one, I think we can avoid all of the new code with just this trivial change:

--- src/xpra/client/keyboard_helper.py	(revision 7831)
+++ src/xpra/client/keyboard_helper.py	(working copy)
@@ -247,6 +247,7 @@
     def query_xkbmap(self):
         self.xkbmap_layout, _, self.xkbmap_variant, self.xkbmap_variants = self.keyboard.get_layout_spec()
         self.xkbmap_print, self.xkbmap_query, self.xkbmap_query_struct = self.keyboard.get_keymap_spec()
+        self.xkbmap_query_struct = {}
         self.xkbmap_keycodes = self.get_full_keymap()
         self.xkbmap_x11_keycodes = self.keyboard.get_x11_keymap()
         self.xkbmap_mod_meanings, self.xkbmap_mod_managed, self.xkbmap_mod_pointermissing = self.keyboard.get_keymap_modifiers()

This should be a minimal revert for it:

--- src/xpra/client/gtk_base/gtk_keyboard_helper.py	(revision 7831)
+++ src/xpra/client/gtk_base/gtk_keyboard_helper.py	(working copy)
@@ -42,13 +42,14 @@
             self._keymap_changing = False
             if self.locked:
                 #automatic changes not allowed!
-                log.info("ignoring keymap change: layout is locked to '%s'", self.layout_str())
-                return
+                log.info("NOT ignoring keymap change: layout is locked to '%s'", self.layout_str())
+                pass
             if self.update():
-                log.info("keymap has been changed to '%s', sending updated mappings to the server", self.layout_str())
-                if self.xkbmap_layout:
-                    self.send_layout()
-                self.send_keymap()
+                pass
+            log.info("keymap is set to '%s', sending mappings to the server", self.layout_str())
+            if self.xkbmap_layout:
+                self.send_layout()
+            self.send_keymap()
         gobject.timeout_add(500, do_keys_changed)
     def update(self):

This one looks really innocuous but who knows.. You can just swap this function for the old one if you also re-add the definition for nn somewhere in that file (anywhere will do):

def nn(x):
    if x is None:
        return  ""
    return x

Does any of those reverts make any difference?


Thu, 02 Oct 2014 16:21:49 GMT - Antoine Martin:

Wait, wait, wait. I see:

keyboard_sync=False

You have keyboard sync turned off and you never mentioned it until now!?? That's an absolutely essential piece of information. Have you tried turning that on again? I am not saying that it will solve things, but it might, and definitely makes a huge difference on the keyboard code and my debugging of it.


Now, as for the log, both the working and non-working case show the same stuff, simplified as:

handle_key(3,True,Alt_L,65513,64,()) keyboard_sync=False
handle keycode pressing 64: key Alt_L
handle_key(3,True,ISO_Next_Group,65032,50,('mod1',)) keyboard_sync=False
is_modifier(50) found modifier: Shift_L
handle keycode pressing 50: key ISO_Next_Group
handle_key(3,False,Alt_L,65513,64,('mod1',)) keyboard_sync=False
handle keycode unpressing 64: key Alt_L
handle_key(3,False,Shift_L,65505,50,()) keyboard_sync=False
handle keycode unpressing 50: key Shift_L
handle_key(3,True,Cyrillic_shorti,1738,24,()) keyboard_sync=False
handle keycode pressing 24: key Cyrillic_shorti

Basically:

The clients are sending exactly the same thing, and the server is pressing exactly the same keycodes. So the next thing (which should have been the first thing in this ticket really..) would be to compare xpra info | grep "^keyboard" between the two cases to see if there are any differences.


Thu, 02 Oct 2014 20:31:36 GMT - onlyjob:

Of course I tried keyboard sync -- it didn't change a thing so perhaps that's why I've forgotten to mention it. I usually set keyboard-sync = no in ~/.xpra/xpra.conf to avoid occasional keyboard ghosting (i.e. when one keypress produces more than one letter).

I tried first two patches from comment:12 with 0.14.8 (no difference), third one seems to be reverting something to 0.14.8 and the forth one I did not understand.

I also tried re-building 0.13.9 in exactly the same environment as 0.14.8 is built and again there were no difference in behaviour: when I connect to server 0.14.8 using client 0.13.9 I can switch keyboard layout effortlessly. When attached with client 0.14.8 I can't switch layout at all.

I'm attaching the output of xpra info | grep "^keyboard" on server:

1) 0.14.8a.txt.xz 2) 0.13.9.txt.xz 3) 0.14.8b.txt.xz

The above logs represent changes when 0.14.8 is first connected to the new session (can't switch layout); then when client 0.13.9 is attached (switching layout works); then with 0.14.8 attached again (switching layout works).


Thu, 02 Oct 2014 20:31:54 GMT - onlyjob: attachment set


Thu, 02 Oct 2014 20:32:03 GMT - onlyjob: attachment set


Thu, 02 Oct 2014 20:32:12 GMT - onlyjob: attachment set


Fri, 03 Oct 2014 16:59:41 GMT - Antoine Martin:

The diff between 0.13.9 and 0.14.8b has nothing in it (just some new info added in 0.14.x):

1153a1154
> keyboard.layout=us
1200d1200
< keyboard.print=xkb_keymap {\n	xkb_keycodes  { include "evdev+aliases(qwerty)"	};\n	xkb_types     { include "complete"	};\n	xkb_compat    { include "complete+ledscroll(group_lock)"	};\n	xkb_symbols   { include "pc+us+ru:2+inet(evdev)+group(alt_shift_toggle)"	};\n	xkb_geometry  { include "pc(pc101)"	};\n};\n

And between 0.14.8a and 0.14.8b shows very little:

164d163
< keyboard.keycode.Meta_R=113
172,173c171,172
< keyboard.keycode.Page_Down=105
< keyboard.keycode.Page_Up=99
---
> keyboard.keycode.Page_Down=117
> keyboard.keycode.Page_Up=112
270,271d268
< keyboard.keycode.XF86Standby=223
< keyboard.keycode.XF86Stop=232
964d960
< keyboard.keysym.Meta_R=113
972,973c968,969
< keyboard.keysym.Page_Down=105
< keyboard.keysym.Page_Up=99
---
> keyboard.keysym.Page_Down=117
> keyboard.keysym.Page_Up=112
1070,1071d1065
< keyboard.keysym.XF86Standby=223
< keyboard.keysym.XF86Stop=232

The difference is quite small, and I don't understand why we would care about those keys, you're using Alt_L, not Meta_R. But at least that is something to look into.

Please post the client log when connecting with both 0.13.9 and 0.14.8, with -d keyboard. It should show us what it is sending to the server, and there must be something different in there.

A shot in the dark, does this help (you will need r7873 to fix a bug that fires with this change applied):

--- src/xpra/platform/xposix/keyboard.py	(revision 7873)
+++ src/xpra/platform/xposix/keyboard.py	(working copy)
@@ -17,7 +17,7 @@
     keyboard_bindings = X11KeyboardBindings()
 except Exception as e:
     log.warn("failed load posix keyboard bindings: %s", e)
-    keyboard_bindings = None
+keyboard_bindings = None
 class Keyboard(KeyboardBase):

If so, then the debug log from above should tell us what the bindings are doing "wrong" or different anyway.


Sat, 04 Oct 2014 07:31:10 GMT - onlyjob:

That was perhaps the most effective "shot in the dark" that I've seen: it helped and keyboard layout switching works perfectly when 0.14.8 patched as follows:

--- a/xpra/platform/xposix/keyboard.py
+++ b/xpra/platform/xposix/keyboard.py
@@ -16,9 +16,9 @@
     from xpra.x11.bindings.keyboard_bindings import X11KeyboardBindings   #@UnresolvedImport
     keyboard_bindings = X11KeyboardBindings()
 except Exception, e:
     log.warn("failed load posix keyboard bindings: %s", e)
-    keyboard_bindings = None
+keyboard_bindings = None
 class Keyboard(KeyboardBase):
@@ -87,8 +87,10 @@
         if xkbmap_query is None and xkbmap_print is not None:
             log.error("the server will try to guess your keyboard mapping, which works reasonably well in most cases")
             log.error("however, upgrading 'setxkbmap' to a version that supports the '-query' parameter is preferred")
             xkbmap_query_struct = parse_xkbmap_query(xkbmap_query)
+        else:
+            xkbmap_query_struct = {}
         return xkbmap_print, xkbmap_query, xkbmap_query_struct
     def get_keymap_spec_from_xkb(self):
         log("get_keymap_spec_from_xkb() keyboard_bindings=%s", keyboard_bindings)

Thank you very much.

I'm attaching attach_0.14.8.log and attach_0.13.9.log (taken in this order). To aid comparison I filtered both files to drop timestamps, gtk.gdk.KeymapX11 prefix and identical "get_entries_for_keycode" lines.


Sat, 04 Oct 2014 07:31:26 GMT - onlyjob: attachment set


Sat, 04 Oct 2014 07:31:34 GMT - onlyjob: attachment set


Sat, 04 Oct 2014 15:59:39 GMT - Antoine Martin: owner changed

Well, we should have started there, it sticks out like a sore thumb:

detected keyboard: rules=evdev, model=pc101, layout=us,ru

vs

detected keyboard: rules=evdev, model=pc101, layout=us

You cannot get the 'ru' layout if it isn't defined to begin with!

I believe that the fix is just r7877. Works for me with dual gb,us layout. Please confirm so I can backport.

(btw, added your screen resolution in r7875)


Sat, 04 Oct 2014 18:24:49 GMT - onlyjob:

No, unfortunately r7877 on top of 0.14.8 did not help even though on attach it prints

detected keyboard: rules=evdev, model=pc101, layout=us,ru

instead of

detected keyboard: rules=evdev, model=pc101, layout=us

I've noticed that now "Keyboard" menu have four entries:

Previously "us,ru" was not there. Thanks for harvesting screen resolutions even though my current layout is made of three different size monitors. :)


Sat, 04 Oct 2014 18:34:58 GMT - onlyjob: owner changed

Interesting behaviour: with r7877 I could not switch keyboard layout on first attach but after disconnect switching worked like if session was "fixed" by attaching using 0.13 client.

With patch from comment:16 (alone) it is possible to switch keyboard layout in first attach to new session.


Sat, 04 Oct 2014 18:45:59 GMT - onlyjob:

Please disregard comment:19 -- second re-attach was made with Xpra patched as per comment:16. Sorry. I tried attaching with just r7877 applied and could not swith keyboard layout at all in first or subsequent attaches.


Sun, 05 Oct 2014 06:50:06 GMT - Antoine Martin: owner changed

I believe the faulty function was get_keymap_spec_from_xkb, and if any emergency fix should be applied, it is probably this one, definitely NOT what is in comment:16:

--- src/xpra/platform/xposix/keyboard.py	(revision 7882)
+++ src/xpra/platform/xposix/keyboard.py	(working copy)
@@ -100,7 +100,7 @@
         return "", _query, _query_struct
     def get_keymap_spec(self):
-        v = self.get_keymap_spec_from_xkb()
+        v = None    #self.get_keymap_spec_from_xkb()
         if not v:
             v = self.get_keymap_spec_using_setxkbmap()
         from xpra.util import nonl

It would have been pretty obvious if we had collected the keyboard debug information in detail to begin with (as per wiki/Keyboard). Instead, much time was spent inspecting the UI and whatnot.

You can see by diffing the two logs:

diff -u attach_0.13.9.log attach_0.14.8.log | \
    egrep -v "get_gtk_keymap|XpraClient.send|hash|update_modifier_map|^ "

(the egrep cleanup is just trimming things that are identical but for pointers, r7880 and r7881 make this redundant) That there is one crucial bit of configuration missing: options: grp:alt_shift_toggle,grp_led:scroll.

This should be fixed in r7883. r7877 is still needed, even if things may "look" like they work without it.

An easy way to verify is to run this both inside and outside xpra:

setxkbmap -query | grep toggle

(it should be identical)


Sun, 05 Oct 2014 07:11:10 GMT - onlyjob:

I'm getting

  File "/usr/lib/python2.7/dist-packages/xpra/platform/xposix/keyboard.py", line 91, in get_keymap_spec_using_setxkbmap
    return xkbmap_print, xkbmap_query, xkbmap_query_struct
UnboundLocalError: local variable 'xkbmap_query_struct' referenced before assignment

Sun, 05 Oct 2014 08:14:18 GMT - Antoine Martin:

UnboundLocalError: local variable 'xkbmap_query_struct' referenced before assignment


See r7873 or comment:16 - note: again, this isn't really a proper fix, this is done to isolate the problem (down from one whole file to just one function).


Assuming that r7883 + r7877 works, that's the change that will be backported.


What's up with comment:22? Looks empty.


Sun, 05 Oct 2014 10:36:05 GMT - onlyjob:

Assuming that r7883 + r7877 works, that's the change that will be backported.


It does not work.


What's up with comment:22? Looks empty.


I was just trying to edit it to correct 7883 to r7883.


Sun, 05 Oct 2014 10:42:11 GMT - Antoine Martin:

It does not work.


OK

I was just trying to edit it to correct 7883 to r7883.


Comment deleted, also edited the original comment.

I believe the faulty function was get_keymap_spec_from_xkb ...


So.. is it? (as per comment:21)

An easy way to verify is to run this both inside and outside xpra:...


Does it not match?


Sun, 05 Oct 2014 10:53:46 GMT - Antoine Martin:

Very important: I've just noticed that many of the comments pointed to r7783 instead of r7883 as being the important fix. I hope that's not the changeset you tested... as that one is a cosmetic change to do with icon logging! (also that change is 11 days old..) Sorry about that.


Sun, 05 Oct 2014 19:44:12 GMT - onlyjob:

Thanks for clarifying which commits to apply. I guessed that r7783 is unrelated and checked recent commits where I found r7883. Second hunk of the latter did not apply to 0.14.8 so I modified it as follows:

--- a/xpra/x11/bindings/keyboard_bindings.pyx
+++ b/xpra/x11/bindings/keyboard_bindings.pyx
@@ -224,9 +224,9 @@
         if vd.layout:
             v["layout"] = vd.layout[:]
             XFree(vd.layout)
         if vd.options!=NULL:
-            v["options"] = vd.options.split("\0")
+            v["options"] = vd.options[:]
             XFree(vd.options)
         #log("vd.num_extra=%s", vd.num_extra)
         if vd.extra_names:
             #no idea how to use this!

Unfortunately only after comment:27 it occur to me to try r7883 and r7877 together. This combination fixed the problem. Thank you very much.

Now I've noticed one little difference from 0.13.9: the latter needs only one press of Alt+Shift to switch to secondary keyboard layout. 0.14.8 patched with r7883 and r7877 needs Alt+Shift to be pressed twice to switch to secondary keyboard layout (and only once to switch back). This is a minor issue and I can live with that of course. I just want to note that comment:16 works slightly better as it needs Alt+Shift to be pressed only once. Hopefully you may have some ideas how to address that (I will be happy to test).


Mon, 06 Oct 2014 03:47:15 GMT - Antoine Martin: owner, status changed

Now I've noticed one little difference from 0.13.9: the latter needs only one press of Alt+Shift to switch to secondary keyboard layout. 0.14.8 patched with r7883 and r7877 needs Alt+Shift to be pressed twice


Damn.

I just want to note that comment:16 works slightly better as it needs Alt+Shift to be pressed only once


That narrows it down quite a bit.


Interestingly, I was in the process of debugging something completely unrelated and I've just noticed that switching layouts with Alt + Shift causes this property change on our window client side (but only if we have focus):

<gtk.gdk.Event at 0x2ed2bc0: GDK_PROPERTY_NOTIFY atom=XKLAVIER_STATE>) : XKLAVIER_STATE

So r7886 adds keyboard debug logging for this, and we see those cryptic values now instead (with -d keyboard):

property_changed(...) : XKLAVIER_STATE
XKLAVIER_STATE=['0x0', '0x42930600']

I cannot find any shred of documentation on what XKLAVIER_STATE actually means to us or how to interpret those values. I was hoping that we could somehow detect those keyboard layout changes client side and propagate them ourselves, out of band, to the server so that the keyboard layout state would match without relying on not missing any key events. This would mean stripping the grp:alt_shift_toggle (and maybe more) from the keymap option on the server side if the client advertises that it will take care of notifying the server of layout switching explicitly instead. This would be cleaner, and also more compatible with other non-X11 platforms which may have other means of switching keyboard layouts.


Mon, 06 Oct 2014 04:36:59 GMT - Antoine Martin:

What is strange is that it takes only one press the first time to toggle to the secondary layout, always just one press to toggle back to the first layout, but two presses the second time around onwards to toggle the secondary layout!

Note: with the disabled bindings as per comment:16, I can switch layouts with Shift + Alt, but not with Alt + Shift. That's probably a side effect of the lack of bindings, giving us a sub-par keyboard mapping detection.


Mon, 06 Oct 2014 05:31:04 GMT - Antoine Martin: owner, status changed

The need to press twice should be fixed in r7889. Will also backport if confirmed (it is small).

I don't really understand how all of this works: why / how this is fixed, and I am not particularly optimistic that xkbcommon (#371) will necessarily improve things much (there's bound to be new issues with supporting non-X11 clients...). But I've already spent so much time on this, that I'm going to have to leave it at that for now.


Mon, 06 Oct 2014 06:35:42 GMT - onlyjob:

Tried r7889, it works perfectly. Please backport. I have the same feeling that some issues take too much time and push everything else back. However this problem seems to be fixed very well and that matters. Thanks very much.


Mon, 27 Oct 2014 17:36:13 GMT - Antoine Martin: status changed; resolution set

Backport was in r7892. Closing.


Sat, 23 Jan 2021 05:02:16 GMT - migration script:

this ticket has been moved to: https://github.com/Xpra-org/xpra/issues/661