Hello,
I'm using dvorak-fr keyboard layout, which uses a "dead" key as a modifier.
For example, to obtain $, I press 8, then release it, then press '.
8 is ISO_Level3_Latch
.
When connecting to a Xpra session with this layout, it works for certain keys, but not all of them.
» (8 + n) $ (8 + ') € (8 + g) ù (8 + u) <<< but ìàò work fine!! è (8 + e) £ (8 + y)
Server:
ahuillet@demo:~/xpra/src$ setxkbmap -print xkb_keymap { xkb_keycodes { include "evdev+aliases(azerty)" }; xkb_types { include "complete" }; xkb_compat { include "complete" }; xkb_symbols { include "pc+fr+inet(evdev)" }; xkb_geometry { include "pc(pc104)" }; };
Local:
arthur@Chani:~$ setxkbmap -print xkb_keymap { xkb_keycodes { include "evdev+aliases(azerty)" }; xkb_types { include "complete" }; xkb_compat { include "complete" }; xkb_symbols { include "pc+fr(dvorak)+inet(evdev)" }; xkb_geometry { include "pc(pc104)" }; };
Xmodmap outputs are attached.
xmodmap -pke on client
xmodmap -pm (local)
xmodmap -pke on server
xmodmap -pm on server
When I use "xev" to see what happens. When I press the 8 key, I get :
when I press the 8 key, here is what I get:
KeyPress event, serial 36, synthetic NO, window 0x2800001, root 0x15a, subw 0x0, time 232923257, (28,84), root:(1058,901), state 0x10, keycode 17 (keysym 0xfe04, ISO_Level3_Latch), same_screen YES, XLookupString gives 0 bytes: XmbLookupString gives 0 bytes: XFilterEvent returns: False KeyRelease event, serial 36, synthetic NO, window 0x2800001, root 0x15a, subw 0x0, time 232923449, (28,84), root:(1058,901), state 0x90, keycode 17 (keysym 0x60, grave), same_screen YES, XLookupString gives 1 bytes: (60) "`" XFilterEvent returns: False
The output is *the same* on the client and the server, so no problem here.
Now, locally, I will do ì (works on Xpra) and $ (doesn't work on Xpra) :
KeyPress event, serial 36, synthetic NO, window 0x2800001, root 0x15a, subw 0x0, time 233173178, (107,77), root:(1137,894), state 0x10, keycode 17 (keysym 0xfe04, ISO_Level3_Latch), same_screen YES, XLookupString gives 0 bytes: XmbLookupString gives 0 bytes: XFilterEvent returns: False KeyRelease event, serial 36, synthetic NO, window 0x2800001, root 0x15a, subw 0x0, time 233173306, (107,77), root:(1137,894), state 0x90, keycode 17 (keysym 0x60, grave), same_screen YES, XLookupString gives 1 bytes: (60) "`" XFilterEvent returns: False KeyPress event, serial 36, synthetic NO, window 0x2800001, root 0x15a, subw 0x0, time 233173338, (107,77), root:(1137,894), state 0x90, keycode 55 (keysym 0xec, igrave), same_screen YES, XLookupString gives 1 bytes: (ec) "ì" XmbLookupString gives 1 bytes: (ec) "ì" XFilterEvent returns: False KeyRelease event, serial 36, synthetic NO, window 0x2800001, root 0x15a, subw 0x0, time 233173418, (107,77), root:(1137,894), state 0x10, keycode 55 (keysym 0x69, i), same_screen YES, XLookupString gives 1 bytes: (69) "i" XFilterEvent returns: False KeyPress event, serial 36, synthetic NO, window 0x2800001, root 0x15a, subw 0x0, time 233173626, (107,77), root:(1137,894), state 0x10, keycode 17 (keysym 0xfe04, ISO_Level3_Latch), same_screen YES, XLookupString gives 0 bytes: XmbLookupString gives 0 bytes: XFilterEvent returns: False KeyRelease event, serial 36, synthetic NO, window 0x2800001, root 0x15a, subw 0x0, time 233173722, (107,77), root:(1137,894), state 0x90, keycode 17 (keysym 0x60, grave), same_screen YES, XLookupString gives 1 bytes: (60) "`" XFilterEvent returns: False KeyPress event, serial 36, synthetic NO, window 0x2800001, root 0x15a, subw 0x0, time 233173818, (107,77), root:(1137,894), state 0x90, keycode 25 (keysym 0x24, dollar), same_screen YES, XLookupString gives 1 bytes: (24) "$" XmbLookupString gives 1 bytes: (24) "$" XFilterEvent returns: False KeyRelease event, serial 36, synthetic NO, window 0x2800001, root 0x15a, subw 0x0, time 233173882, (107,77), root:(1137,894), state 0x10, keycode 25 (keysym 0x27, apostrophe), same_screen YES, XLookupString gives 1 bytes: (27) "'" XFilterEvent returns: False
And on the Xpra session :
KeyPress event, serial 30, synthetic NO, window 0x1400001, root 0x131, subw 0x0, time 3882373499, (87,112), root:(88,135), state 0x10, keycode 17 (keysym 0xfe04, ISO_Level3_Latch), same_screen YES, XLookupString gives 0 bytes: XmbLookupString gives 0 bytes: XFilterEvent returns: False KeyRelease event, serial 30, synthetic NO, window 0x1400001, root 0x131, subw 0x0, time 3882373606, (87,112), root:(88,135), state 0x90, keycode 17 (keysym 0x60, grave), same_screen YES, XLookupString gives 1 bytes: (60) "`" XFilterEvent returns: False KeyPress event, serial 30, synthetic NO, window 0x1400001, root 0x131, subw 0x0, time 3882373630, (87,112), root:(88,135), state 0x90, keycode 31 (keysym 0xec, igrave), same_screen YES, XLookupString gives 1 bytes: (ec) "ì" XmbLookupString gives 1 bytes: (ec) "ì" XFilterEvent returns: False KeyRelease event, serial 30, synthetic NO, window 0x1400001, root 0x131, subw 0x0, time 3882373683, (87,112), root:(88,135), state 0x10, keycode 31 (keysym 0x69, i), same_screen YES, XLookupString gives 1 bytes: (69) "i" XFilterEvent returns: False KeyPress event, serial 30, synthetic NO, window 0x1400001, root 0x131, subw 0x0, time 3882375027, (87,112), root:(88,135), state 0x10, keycode 17 (keysym 0xfe04, ISO_Level3_Latch), same_screen YES, XLookupString gives 0 bytes: XmbLookupString gives 0 bytes: XFilterEvent returns: False KeyRelease event, serial 30, synthetic NO, window 0x1400001, root 0x131, subw 0x0, time 3882375099, (87,112), root:(88,135), state 0x90, keycode 17 (keysym 0x60, grave), same_screen YES, XLookupString gives 1 bytes: (60) "`" XFilterEvent returns: False KeyPress event, serial 30, synthetic NO, window 0x1400001, root 0x131, subw 0x0, time 3882375139, (87,112), root:(88,135), state 0x90, keycode 48 (keysym 0x27, apostrophe), same_screen YES, XLookupString gives 1 bytes: (27) "'" XmbLookupString gives 1 bytes: (27) "'" XFilterEvent returns: False KeyRelease event, serial 30, synthetic NO, window 0x1400001, root 0x131, subw 0x0, time 3882375219, (87,112), root:(88,135), state 0x10, keycode 48 (keysym 0x27, apostrophe), same_screen YES, XLookupString gives 1 bytes: (27) "'" XFilterEvent returns: False
The only difference is the last-but-one event: it should be a keypress of "dollar", but is "apostrophe".
Is there actually anything wrong with Xpra? ...
Does this patch help? It should set the keyboard model on the server. (dvorak in your case)
Index: src/xpra/xkbhelper.py =================================================================== --- src/xpra/xkbhelper.py (revision 724) +++ src/xpra/xkbhelper.py (working copy) @@ -106,13 +106,17 @@ log.debug("do_set_keymap using xkbmap_print") #try to guess the layout by parsing "setxkbmap -print" try: - sym_re = re.compile("\s*xkb_symbols\s*{\s*include\s*\"([\w\+]*)") + sym_re = re.compile("\s*xkb_symbols\s*{\s*include\s*\"([\w\+]*)(\(\w*\))?") for line in xkbmap_print.splitlines(): m = sym_re.match(line) if m: layout = m.group(1) - log.info("guessing keyboard layout='%s'" % layout) - exec_keymap_command(["setxkbmap", layout]) + model = m.group(2) + log.info("guessing keyboard layout='%s', model='%s'", layout, model) + cmd = ["setxkbmap", layout] + if model: + cmd += ["-model", model] + exec_keymap_command(cmd) break except Exception, e: log.info("error setting keymap: %s" % e)
The patch, in my case, doesn't work.
What I had to do is the following:
@@ -94,7 +94,7 @@ settings[m.group(1)] = m.group(2).strip() #construct the command line arguments for setxkbmap: args = ["setxkbmap"] - for setting in ["rules", "model", "layout"]: + for setting in ["rules", "model", "layout", "variant"]:
to get variant set to dvorak... but that doesn't solve the issue.
newer patch - probably worth doing even if this doesn't solve your particular problem:
Index: src/xpra/xkbhelper.py =================================================================== --- src/xpra/xkbhelper.py (revision 724) +++ src/xpra/xkbhelper.py (working copy) @@ -106,13 +106,23 @@ log.debug("do_set_keymap using xkbmap_print") #try to guess the layout by parsing "setxkbmap -print" try: - sym_re = re.compile("\s*xkb_symbols\s*{\s*include\s*\"([\w\+]*)") + sym_re = re.compile("\s*xkb_symbols\s*{\s*include\s*\"([\w\+]*)(\((\w*)\))?((\+\w*)\((\w*)\))?") for line in xkbmap_print.splitlines(): m = sym_re.match(line) if m: layout = m.group(1) - log.info("guessing keyboard layout='%s'" % layout) - exec_keymap_command(["setxkbmap", layout]) + variant = m.group(3) + extra_layout = m.group(5) + model = m.group(6) + if extra_layout: + layout += extra_layout + log.info("guessing keyboard layout='%s', variant='%s', model='%s'", layout, variant, model) + cmd = ["setxkbmap", layout] + if variant: + cmd += ["-variant", variant[1:-1]] + if model: + cmd += ["-model", model] + exec_keymap_command(cmd) break except Exception, e: log.info("error setting keymap: %s" % e)
It doesn't solve my particular problem.
Dumping some info on the server side, for ì (working) and è (not working, producing e)
handle_key(1,1,ISO_Level3_Latch,65028,17,['mod2']) handle_key(1,0,grave,96,17,['mod2', 'mod5']) handle_key(1,1,igrave,236,31,['mod2', 'mod5']) handle_key(1,0,i,105,31,['mod2'])
handle_key(1,1,ISO_Level3_Latch,65028,17,['mod2']) handle_key(1,0,grave,96,17,['mod2', 'mod5']) handle_key(1,1,egrave,232,93,['mod2', 'mod5']) handle_key(1,0,e,101,93,['mod2'])
So the server receives correct messages in both cases.
arthur@Gurney:~$ xmodmap -pke | egrep ' (31|93) ' keycode 31 = i I i I igrave Igrave keycode 93 = e E e E egrave Egrave
This is on the Xpra session - so the key map looks good.
I have tried the following:
--- a/src/xpra/server.py +++ b/src/xpra/server.py @@ -1827,19 +1827,28 @@ class XpraServer(gobject.GObject): Does the actual press/unpress for keys Either from a packet (_process_key_action) or timeout (_key_repeat_timeout) """ - log.debug("handle_key(%s,%s,%s,%s,%s,%s)", wid, pressed, name, keyval, keycode, modifiers) + log.error("handle_key(%s,%s,%s,%s,%s,%s)", wid, pressed, name, keyval, keycode, modifiers) + xtest_fake_key(gtk.gdk.display_get_default(), 17, True) + xtest_fake_key(gtk.gdk.display_get_default(), 17, False) + xtest_fake_key(gtk.gdk.display_get_default(), 31, True) + xtest_fake_key(gtk.gdk.display_get_default(), 31, False) + xtest_fake_key(gtk.gdk.display_get_default(), 17, True) + xtest_fake_key(gtk.gdk.display_get_default(), 17, False) + xtest_fake_key(gtk.gdk.display_get_default(), 93, True) + xtest_fake_key(gtk.gdk.display_get_default(), 93, False) + return
It's stupid but should display ìè every time I press a key. I'm getting ìe. I suspect a bug in XTest. Opened a ticket at https://bugs.freedesktop.org/show_bug.cgi?id=48770
This adds a method to the native X11 bindings so we can use XSendEvent
to send keypresses instead of Xtest.
It still needs:
make_modifiers_match
we can just call this one method? really? It would save a lot of ugly code..
Index: src/wimpiggy/lowlevel/bindings.pyx =================================================================== --- src/wimpiggy/lowlevel/bindings.pyx (revision 777) +++ src/wimpiggy/lowlevel/bindings.pyx (working copy) @@ -1157,6 +1157,49 @@ _ensure_XTest_support(display_source) XTestFakeButtonEvent(get_xdisplay_for(display_source), button, is_press, 0) +def sendKeyEvent(target, root_win, modifiers_mask, keycode, is_press): + cdef Display * display + display = get_xdisplay_for(target) + cdef Window w + w = get_xwindow(target) + cdef Window root_w + root_w = get_xwindow(root_win) + cdef XKeyEvent ke + cdef XEvent e = <XEvent> e + ke.type = KeyPress + e.xany.display = display + ke.window = w + ke.root = root_w + ke.subwindow = None + ke.time = CurrentTime + ke.x = 1 + ke.y = 1 + ke.x_root = 1 + ke.y_root = 1 + ke.state = 0 + ke.same_screen = 1 + ke.keycode = keycode + ke.state = modifiers_mask + cdef Status s + cdef long event_mask + event_mask = 0 + if "shift" in modifiers_mask: + event_mask |= ShiftMask + if "lock" in modifiers_mask: + event_mask |= LockMask + if "ctrl" in modifiers_mask: + event_mask |= ControlMask + if "alt" in modifiers_mask or "meta" in modifiers_mask: + event_mask |= Mod1Mask + if is_press: + event_mask = KeyPressMask + else: + event_mask = KeyReleaseMask + s = XSendEvent(display, w, True, event_mask, &e) + if s == 0: + raise ValueError, "failed to serialize ClientMessage" + + ################################### # Extension testing ###################################
Best reference I found on using XSendEvent
to send key presses: xvkbd/events.html
Is this improved with r942? (I would not expect it to)
But at least, no worse?
Will follow up with work on #149
Please see questions above, and can you find a way for me to set the same keymap without re-configuring my X11 server? (or logging in/out or changing DE) How do you set yours? The closest I got was:
setxkbmap -rules base -model pc104 -layout fr -variant dvorak
Which gives me:
xkb_keymap { xkb_keycodes { include "xfree86+aliases(azerty)" }; xkb_types { include "complete" }; xkb_compat { include "complete" }; xkb_symbols { include "pc+fr(dvorak)" }; xkb_geometry { include "pc(pc104)" }; };
I use:
setxkbmap -layout fr -variant dvorak
Not much better...
$ setxkbmap -layout fr -variant dvorak $ setxkbmap -print xkb_keymap { xkb_keycodes { include "xfree86+aliases(azerty)" }; xkb_types { include "complete" }; xkb_compat { include "complete" }; xkb_symbols { include "pc+fr(dvorak)+inet(pc105)" }; xkb_geometry { include "pc(pc105)" }; };
vs:
$ setxkbmap -rules base -model pc104 -layout fr -variant dvorak $ setxkbmap -print xkb_keymap { xkb_keycodes { include "xfree86+aliases(azerty)" }; xkb_types { include "complete" }; xkb_compat { include "complete" }; xkb_symbols { include "pc+fr(dvorak)" }; xkb_geometry { include "pc(pc104)" }; };
When what I want is:
xkb_keymap { xkb_keycodes { include "evdev+aliases(azerty)" }; xkb_types { include "complete" }; xkb_compat { include "complete" }; xkb_symbols { include "pc+fr(dvorak)+inet(evdev)" }; xkb_geometry { include "pc(pc104)" }; };
Also, please see comment:10
I have "evdev" on my *real* X server (which runs without a xorg.conf). And on Xdummy/Xvfb?, I get xfree86 just like you.
r942 *fixes* the issues for me.
might apply to 0.3.x branch
Note: the layout printed above are for my *real* X server too.
This has caused a regression for some... see #164
this ticket has been moved to: https://github.com/Xpra-org/xpra/issues/109