Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

keyboard problems with dead keys and dvorak layout #109

Closed
totaam opened this issue Apr 16, 2012 · 20 comments
Closed

keyboard problems with dead keys and dvorak layout #109

totaam opened this issue Apr 16, 2012 · 20 comments

Comments

@totaam
Copy link
Collaborator

totaam commented Apr 16, 2012

Issue migrated from trac ticket # 109

component: core | priority: major | resolution: fixed | keywords: keyboard

2012-04-16 09:37:53: ahuillet created the issue


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.

@totaam
Copy link
Collaborator Author

totaam commented Apr 16, 2012

2012-04-16 09:38:12: ahuillet uploaded file local_xmodmap_pke.txt (10.3 KiB)

xmodmap -pke on client

@totaam
Copy link
Collaborator Author

totaam commented Apr 16, 2012

2012-04-16 09:38:23: ahuillet uploaded file local_xmodmap_pm.txt (0.4 KiB)

xmodmap -pm (local)

@totaam
Copy link
Collaborator Author

totaam commented Apr 16, 2012

2012-04-16 09:39:04: ahuillet uploaded file server_xmodmap_pke.txt (15.3 KiB)

xmodmap -pke on server

@totaam
Copy link
Collaborator Author

totaam commented Apr 16, 2012

2012-04-16 09:39:14: ahuillet uploaded file server_xmodmap_pm.txt (0.4 KiB)

xmodmap -pm on server

@totaam
Copy link
Collaborator Author

totaam commented Apr 16, 2012

2012-04-16 09:48:29: ahuillet commented


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

@totaam
Copy link
Collaborator Author

totaam commented Apr 16, 2012

2012-04-16 11:20:47: antoine commented


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)

@totaam
Copy link
Collaborator Author

totaam commented Apr 16, 2012

2012-04-16 11:40:45: ahuillet commented


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.

@totaam
Copy link
Collaborator Author

totaam commented Apr 16, 2012

2012-04-16 12:16:15: antoine commented


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)

@totaam
Copy link
Collaborator Author

totaam commented Apr 16, 2012

2012-04-16 13:31:55: ahuillet commented


It doesn't solve my particular problem.

@totaam
Copy link
Collaborator Author

totaam commented Apr 16, 2012

2012-04-16 13:53:40: ahuillet commented


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.

@totaam
Copy link
Collaborator Author

totaam commented Apr 16, 2012

2012-04-16 14:00:38: ahuillet commented


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

@totaam
Copy link
Collaborator Author

totaam commented May 4, 2012

2012-05-04 11:09:01: antoine commented


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

@totaam
Copy link
Collaborator Author

totaam commented Jun 22, 2012

2012-06-22 11:16:45: antoine commented


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

But at least, no worse?

Will follow up with work on #149

@totaam
Copy link
Collaborator Author

totaam commented Jun 24, 2012

2012-06-24 07:14:35: antoine commented


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

@totaam
Copy link
Collaborator Author

totaam commented Jun 24, 2012

2012-06-24 17:38:34: ahuillet commented


I use:

setxkbmap -layout fr -variant dvorak

@totaam
Copy link
Collaborator Author

totaam commented Jun 24, 2012

2012-06-24 17:42:53: antoine commented


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

@totaam
Copy link
Collaborator Author

totaam commented Jun 24, 2012

2012-06-24 17:47:52: ahuillet commented


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.

@totaam
Copy link
Collaborator Author

totaam commented Jun 24, 2012

2012-06-24 17:51:20: antoine changed title from Keyboard problems to keyboard problems with dead keys and dvorak layout

@totaam
Copy link
Collaborator Author

totaam commented Jun 24, 2012

2012-06-24 17:51:20: antoine commented


might apply to 0.3.x branch

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

@totaam totaam closed this as completed Jun 24, 2012
@totaam
Copy link
Collaborator Author

totaam commented Jul 12, 2012

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant