app/internal/window: x11: fix issue with space not sending key.EditEvent

This is a general fix where keys with names differing from their UTF8
representation could not be sent as EditEvents.

Signed-off-by: Denis Bernard <db047h@gmail.com>
This commit is contained in:
Denis Bernard
2019-11-09 16:05:57 +01:00
committed by Elias Naur
parent c8d01d99cc
commit a0050ab79b
+38 -17
View File
@@ -225,6 +225,8 @@ func (h *x11EventHandler) handleEvents() bool {
lookup: lookup:
// Save state then clear CTRL & Shift bits in order to have // Save state then clear CTRL & Shift bits in order to have
// Xutf8LookupString return the unmodified key name in text[:l]. // Xutf8LookupString return the unmodified key name in text[:l].
// This addresses an issue on some non US keyboard layouts where
// CTRL-[0..9] do not behave consistently.
// //
// Note that this enables sending a key.Event for key combinations // Note that this enables sending a key.Event for key combinations
// like CTRL-SHIFT-/ on QWERTY layouts, but CTRL-? is completely // like CTRL-SHIFT-/ on QWERTY layouts, but CTRL-? is completely
@@ -247,24 +249,31 @@ func (h *x11EventHandler) handleEvents() bool {
w.w.Event(key.EditEvent{Text: string(h.text[:l])}) w.w.Event(key.EditEvent{Text: string(h.text[:l])})
case C.XLookupKeySym: case C.XLookupKeySym:
// Special keys. // Special keys.
if r, ok := x11SpecialKeySymToRune(h.keysym); ok { if n, m, ok := x11ConvertKeysym(h.keysym, mods); ok {
w.w.Event(key.Event{ w.w.Event(key.Event{Name: n, Modifiers: m})
Name: r,
Modifiers: mods,
})
} }
case C.XLookupBoth: case C.XLookupBoth:
if r, ok := x11SpecialKeySymToRune(h.keysym); ok { if n, m, ok := x11ConvertKeysym(h.keysym, mods); ok {
w.w.Event(key.Event{Name: r, Modifiers: mods}) w.w.Event(key.Event{Name: n, Modifiers: m})
} else { }
if r, _ := utf8.DecodeRune(h.text[:l]); r != utf8.RuneError { // Do not send EditEvent for CTRL key combinations.
w.w.Event(key.Event{Name: string(unicode.ToUpper(r)), Modifiers: mods}) if mods.Contain(key.ModCtrl) {
} break
// Send EditEvent only when not a CTRL key combination. }
if !mods.Contain(key.ModCtrl) { // Report only printable runes.
w.w.Event(key.EditEvent{Text: string(h.text[:l])}) str := h.text[:l]
for n := 0; n < len(str); {
r, s := utf8.DecodeRune(str)
if unicode.IsPrint(r) {
n += s
} else {
copy(str[n:], str[n+s:])
str = str[:len(str)-s]
} }
} }
if len(str) > 0 {
w.w.Event(key.EditEvent{Text: string(str)})
}
} }
case C.KeyRelease: case C.KeyRelease:
case C.ButtonPress, C.ButtonRelease: case C.ButtonPress, C.ButtonRelease:
@@ -349,7 +358,16 @@ func x11KeyStateToModifiers(s C.uint) key.Modifiers {
return m return m
} }
func x11SpecialKeySymToRune(s C.KeySym) (string, bool) { // x11ConvertKeysym returns the Gio special key that matches keysym s. For
// portability reasons, some keysyms might be translated and modifiers changed
// (like BackTab -> ModShift+Tab)
func x11ConvertKeysym(s C.KeySym, mods key.Modifiers) (string, key.Modifiers, bool) {
if '0' <= s && s <= '9' || 'A' <= s && s <= 'Z' {
return string(s), mods, true
}
if 'a' <= s && s <= 'z' {
return string(s - 0x20), mods, true
}
var n string var n string
switch s { switch s {
case C.XK_Escape: case C.XK_Escape:
@@ -402,14 +420,17 @@ func x11SpecialKeySymToRune(s C.KeySym) (string, bool) {
n = "F11" n = "F11"
case C.XK_F12: case C.XK_F12:
n = "F12" n = "F12"
case C.XK_ISO_Left_Tab:
mods |= key.ModShift
fallthrough
case C.XK_Tab: case C.XK_Tab:
n = key.NameTab n = key.NameTab
case 0x20, C.XK_KP_Space: case 0x20, C.XK_KP_Space:
n = "Space" n = "Space"
default: default:
return "", false return "", mods, false
} }
return n, true return n, mods, true
} }
var ( var (