From a85696d5e07d8906b0bebeb3f4947281a23b4db4 Mon Sep 17 00:00:00 2001 From: Dmytro Maluka Date: Mon, 10 Jun 2024 02:30:55 +0200 Subject: [PATCH] Don't use tcell's Rune() for non-KeyRune events According to tcell documentation, Rune() should only be used for KeyRune events. Otherwise its return value is not guaranteed and should not be relied upon. This fixes issue #2947: Esc key not working on Windows, since tcell sends lone Esc key event with rune == 0 on Unix but with rune == 27 (the keycode) on Windows. --- internal/action/bindings.go | 13 ------------- internal/action/bufpane.go | 4 +++- internal/action/events.go | 11 +++++++---- internal/action/infopane.go | 4 +++- internal/action/termpane.go | 4 +++- 5 files changed, 16 insertions(+), 20 deletions(-) diff --git a/internal/action/bindings.go b/internal/action/bindings.go index 0b940ebf..01ea7845 100644 --- a/internal/action/bindings.go +++ b/internal/action/bindings.go @@ -176,31 +176,18 @@ modSearch: // see if the key is in bindingKeys with the Ctrl prefix. k = string(unicode.ToUpper(rune(k[0]))) + k[1:] if code, ok := keyEvents["Ctrl"+k]; ok { - var r tcell.Key - // Special case for escape, for some reason tcell doesn't send it with the esc character - if code < 256 && code != 27 { - r = code - } - // It is, we're done. return KeyEvent{ code: code, mod: modifiers, - r: rune(r), }, true } } // See if we can find the key in bindingKeys if code, ok := keyEvents[k]; ok { - var r tcell.Key - // Special case for escape, for some reason tcell doesn't send it with the esc character - if code < 256 && code != 27 { - r = code - } return KeyEvent{ code: code, mod: modifiers, - r: rune(r), }, true } diff --git a/internal/action/bufpane.go b/internal/action/bufpane.go index 7b348b79..369749f5 100644 --- a/internal/action/bufpane.go +++ b/internal/action/bufpane.go @@ -472,7 +472,9 @@ func (h *BufPane) HandleEvent(event tcell.Event) { ke := KeyEvent{ code: e.Key(), mod: metaToAlt(e.Modifiers()), - r: e.Rune(), + } + if e.Key() == tcell.KeyRune { + ke.r = e.Rune() } done := h.DoKeyEvent(ke) diff --git a/internal/action/events.go b/internal/action/events.go index 4addf1b5..c0d5b7be 100644 --- a/internal/action/events.go +++ b/internal/action/events.go @@ -68,7 +68,7 @@ func (k KeyEvent) Name() string { if k.code == tcell.KeyRune { s = string(k.r) } else { - s = fmt.Sprintf("Key[%d,%d]", k.code, int(k.r)) + s = fmt.Sprintf("Key[%d]", k.code) } } if len(m) != 0 { @@ -155,11 +155,14 @@ func (m MouseEvent) Name() string { func ConstructEvent(event tcell.Event) (Event, error) { switch e := event.(type) { case *tcell.EventKey: - return KeyEvent{ + ke := KeyEvent{ code: e.Key(), mod: metaToAlt(e.Modifiers()), - r: e.Rune(), - }, nil + } + if e.Key() == tcell.KeyRune { + ke.r = e.Rune() + } + return ke, nil case *tcell.EventRaw: return RawEvent{ esc: e.EscSeq(), diff --git a/internal/action/infopane.go b/internal/action/infopane.go index d3f30fd4..8f13c184 100644 --- a/internal/action/infopane.go +++ b/internal/action/infopane.go @@ -89,7 +89,9 @@ func (h *InfoPane) HandleEvent(event tcell.Event) { ke := KeyEvent{ code: e.Key(), mod: metaToAlt(e.Modifiers()), - r: e.Rune(), + } + if e.Key() == tcell.KeyRune { + ke.r = e.Rune() } done := h.DoKeyEvent(ke) diff --git a/internal/action/termpane.go b/internal/action/termpane.go index f440f0cd..0cb50706 100644 --- a/internal/action/termpane.go +++ b/internal/action/termpane.go @@ -128,7 +128,9 @@ func (t *TermPane) HandleEvent(event tcell.Event) { ke := KeyEvent{ code: e.Key(), mod: metaToAlt(e.Modifiers()), - r: e.Rune(), + } + if e.Key() == tcell.KeyRune { + ke.r = e.Rune() } action, more := TermBindings.NextEvent(ke, nil)