xpra icon
Bug tracker and wiki

Opened 7 years ago

Closed 6 years ago

Last modified 6 years ago

#109 closed defect (fixed)

keyboard problems with dead keys and dvorak layout

Reported by: ahuillet Owned by: ahuillet
Priority: major Milestone: 0.3
Component: core Version: 0.1.0
Keywords: keyboard Cc:

Description (last modified by Antoine Martin)

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.

  • normal keys (unmodified) all work
  • normal keys with shift all work fine
  • symbols that are obtained with the dead key work, except for:

» (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.

Attachments (4)

local_xmodmap_pke.txt (10.3 KB) - added by ahuillet 7 years ago.
xmodmap -pke on client
local_xmodmap_pm.txt (399 bytes) - added by ahuillet 7 years ago.
xmodmap -pm (local)
server_xmodmap_pke.txt (15.3 KB) - added by ahuillet 7 years ago.
xmodmap -pke on server
server_xmodmap_pm.txt (414 bytes) - added by ahuillet 7 years ago.
xmodmap -pm on server

Download all attachments as: .zip

Change History (21)

Changed 7 years ago by ahuillet

Attachment: local_xmodmap_pke.txt added

xmodmap -pke on client

Changed 7 years ago by ahuillet

Attachment: local_xmodmap_pm.txt added

xmodmap -pm (local)

Changed 7 years ago by ahuillet

Attachment: server_xmodmap_pke.txt added

xmodmap -pke on server

Changed 7 years ago by ahuillet

Attachment: server_xmodmap_pm.txt added

xmodmap -pm on server

comment:1 Changed 7 years ago by ahuillet

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? ...

Last edited 7 years ago by ahuillet (previous) (diff)

comment:2 Changed 7 years ago by Antoine Martin

Status: newaccepted

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)

comment:3 Changed 7 years ago by ahuillet

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.

comment:4 Changed 7 years ago by Antoine Martin

Description: modified (diff)

comment:5 Changed 7 years ago by Antoine Martin

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)

comment:6 Changed 7 years ago by ahuillet

It doesn't solve my particular problem.

comment:7 Changed 7 years ago by ahuillet

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.

Last edited 7 years ago by ahuillet (previous) (diff)

comment:8 Changed 7 years ago by ahuillet

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

Last edited 7 years ago by ahuillet (previous) (diff)

comment:9 Changed 6 years ago by Antoine Martin

This adds a method to the native X11 bindings so we can use XSendEvent to send keypresses instead of Xtest.
It still needs:

  • instead of calling make_modifiers_match we can just call this one method? really? It would save a lot of ugly code..
  • hooking up with our knowledge of the modifiers: mod1 is not always "meta", etc... we have a client supplied mapping so we need to use it. (but maybe we can test this proof of concept with only shift and caps for now)
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

Last edited 6 years ago by Antoine Martin (previous) (diff)

comment:10 Changed 6 years ago by Antoine Martin

Is this improved with r942? (I would not expect it to)

But at least, no worse?

Will follow up with work on #149

Last edited 6 years ago by Antoine Martin (previous) (diff)

comment:11 Changed 6 years ago by Antoine Martin

Owner: changed from Antoine Martin to ahuillet
Status: acceptedassigned

comment:12 Changed 6 years ago by Antoine Martin

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)"	};
};

comment:13 Changed 6 years ago by ahuillet

I use:

setxkbmap -layout fr -variant dvorak

comment:14 Changed 6 years ago by Antoine Martin

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

comment:15 Changed 6 years ago by ahuillet

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.

comment:16 Changed 6 years ago by Antoine Martin

Keywords: keyboard added
Resolution: fixed
Status: assignedclosed
Summary: Keyboard problemskeyboard problems with dead keys and dvorak layout

might apply to 0.3.x branch

Note: the layout printed above are for my *real* X server too.

comment:17 Changed 6 years ago by Antoine Martin

This has caused a regression for some... see #164

Note: See TracTickets for help on using tickets.