~eliasnaur/gio-patches

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch

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

Details
Message ID
<20191109145123.17551-1-db047h@gmail.com>
DKIM signature
pass
Download raw message
Patch: +46 -31
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>
---
 app/internal/window/os_x11.go | 77 +++++++++++++++++++++--------------
 1 file changed, 46 insertions(+), 31 deletions(-)

diff --git a/app/internal/window/os_x11.go b/app/internal/window/os_x11.go
index c694e20..954f7ef 100644
--- a/app/internal/window/os_x11.go
+++ b/app/internal/window/os_x11.go
@@ -225,6 +225,8 @@ func (h *x11EventHandler) handleEvents() bool {
 		lookup:
 			// Save state then clear CTRL & Shift bits in order to have
 			// 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
 			// 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])})
 			case C.XLookupKeySym:
 				// Special keys.
-				if r, ok := x11SpecialKeySymToRune(h.keysym); ok {
-					w.w.Event(key.Event{
-						Name:      r,
-						Modifiers: mods,
-					})
+				if n, ok := x11ConvertKeysym(h.keysym); ok {
+					w.w.Event(key.Event{Name: n, Modifiers: mods})
 				}
 			case C.XLookupBoth:
-				if r, ok := x11SpecialKeySymToRune(h.keysym); ok {
-					w.w.Event(key.Event{Name: r, Modifiers: mods})
-				} else {
-					if r, _ := utf8.DecodeRune(h.text[:l]); r != utf8.RuneError {
-						w.w.Event(key.Event{Name: string(unicode.ToUpper(r)), Modifiers: mods})
-					}
-					// Send EditEvent only when not a CTRL key combination.
-					if !mods.Contain(key.ModCtrl) {
-						w.w.Event(key.EditEvent{Text: string(h.text[:l])})
+				if n, ok := x11ConvertKeysym(h.keysym); ok {
+					w.w.Event(key.Event{Name: n, Modifiers: mods})
+				}
+				// Do not send EditEvent for CTRL key combinations.
+				if mods.Contain(key.ModCtrl) {
+					break
+				}
+				str := h.text[:l]
+				// Report only printable runes.
+				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.ButtonPress, C.ButtonRelease:
@@ -332,24 +341,13 @@ func (h *x11EventHandler) handleEvents() bool {
 	return redraw
 }
 
-func x11KeyStateToModifiers(s C.uint) key.Modifiers {
-	var m key.Modifiers
-	if s&C.Mod1Mask != 0 {
-		m |= key.ModAlt
-	}
-	if s&C.Mod4Mask != 0 {
-		m |= key.ModSuper
+func x11ConvertKeysym(s C.KeySym) (string, bool) {
+	if '0' <= s && s <= '9' || 'A' <= s && s <= 'Z' {
+		return string(s), true
 	}
-	if s&C.ControlMask != 0 {
-		m |= key.ModCtrl
+	if 'a' <= s && s <= 'z' {
+		return string(s - 0x20), true
 	}
-	if s&C.ShiftMask != 0 {
-		m |= key.ModShift
-	}
-	return m
-}
-
-func x11SpecialKeySymToRune(s C.KeySym) (string, bool) {
 	var n string
 	switch s {
 	case C.XK_Escape:
@@ -402,7 +400,7 @@ func x11SpecialKeySymToRune(s C.KeySym) (string, bool) {
 		n = "F11"
 	case C.XK_F12:
 		n = "F12"
-	case C.XK_Tab:
+	case C.XK_Tab, C.XK_ISO_Left_Tab:
 		n = key.NameTab
 	case 0x20, C.XK_KP_Space:
 		n = "Space"
@@ -412,6 +410,23 @@ func x11SpecialKeySymToRune(s C.KeySym) (string, bool) {
 	return n, true
 }
 
+func x11KeyStateToModifiers(s C.uint) key.Modifiers {
+	var m key.Modifiers
+	if s&C.Mod1Mask != 0 {
+		m |= key.ModAlt
+	}
+	if s&C.Mod4Mask != 0 {
+		m |= key.ModSuper
+	}
+	if s&C.ControlMask != 0 {
+		m |= key.ModCtrl
+	}
+	if s&C.ShiftMask != 0 {
+		m |= key.ModShift
+	}
+	return m
+}
+
 var (
 	x11Threads sync.Once
 )
-- 
2.17.1