提交 842e443d 编写于 作者: J Jonathan Little

macOS delay on incomplete escape sequences to avoid spurious escape keypress detection #132

上级 aa4a75b1
......@@ -8,6 +8,7 @@ import "os"
import "os/signal"
import "syscall"
import "runtime"
import "time"
// public API
......@@ -253,8 +254,8 @@ func CellBuffer() []Cell {
// NOTE: This API is experimental and may change in future.
func ParseEvent(data []byte) Event {
event := Event{Type: EventKey}
ok := extract_event(data, &event)
if !ok {
status := extract_event(data, &event, false)
if status != event_extracted {
return Event{Type: EventNone, N: event.N}
}
return event
......@@ -303,34 +304,65 @@ func PollRawEvent(data []byte) Event {
// Wait for an event and return it. This is a blocking function call.
func PollEvent() Event {
// Constant governing macOS specific behavior. See https://github.com/nsf/termbox-go/issues/132
// This is an arbitrary delay which hopefully will be enough time for any lagging
// partial escape sequences to come through.
const esc_wait_delay = 50 * time.Millisecond
var event Event
var esc_wait_timer *time.Timer
var esc_timeout <-chan time.Time
// try to extract event from input buffer, return on success
event.Type = EventKey
ok := extract_event(inbuf, &event)
status := extract_event(inbuf, &event, true)
if event.N != 0 {
copy(inbuf, inbuf[event.N:])
inbuf = inbuf[:len(inbuf)-event.N]
}
if ok {
if status == event_extracted {
return event
} else if status == esc_wait {
esc_wait_timer = time.NewTimer(esc_wait_delay)
esc_timeout = esc_wait_timer.C
}
for {
select {
case ev := <-input_comm:
if esc_wait_timer != nil {
if !esc_wait_timer.Stop() {
<-esc_wait_timer.C
}
esc_wait_timer = nil
}
if ev.err != nil {
return Event{Type: EventError, Err: ev.err}
}
inbuf = append(inbuf, ev.data...)
input_comm <- ev
ok := extract_event(inbuf, &event)
status := extract_event(inbuf, &event, true)
if event.N != 0 {
copy(inbuf, inbuf[event.N:])
inbuf = inbuf[:len(inbuf)-event.N]
}
if status == event_extracted {
return event
} else if status == esc_wait {
esc_wait_timer = time.NewTimer(esc_wait_delay)
esc_timeout = esc_wait_timer.C
}
case <-esc_timeout:
esc_wait_timer = nil
status := extract_event(inbuf, &event, false)
if event.N != 0 {
copy(inbuf, inbuf[event.N:])
inbuf = inbuf[:len(inbuf)-event.N]
}
if ok {
if status == event_extracted {
return event
}
case <-interrupt_comm:
......
// +build !darwin
package termbox
// On all systems other than macOS, disable behavior which will wait before
// deciding that the escape key was pressed, to account for partially send
// escape sequences, especially with regard to lengthy mouse sequences.
// See https://github.com/nsf/termbox-go/issues/132
func enable_wait_for_escape_sequence() bool {
return false
}
package termbox
// On macOS, enable behavior which will wait before deciding that the escape
// key was pressed, to account for partially send escape sequences, especially
// with regard to lengthy mouse sequences.
// See https://github.com/nsf/termbox-go/issues/132
func enable_wait_for_escape_sequence() bool {
return true
}
......@@ -41,6 +41,14 @@ type input_event struct {
err error
}
type extract_event_res int
const (
event_not_extracted extract_event_res = iota
event_extracted
esc_wait
)
var (
// term specific sequences
keys []string
......@@ -440,17 +448,27 @@ func extract_raw_event(data []byte, event *Event) bool {
return true
}
func extract_event(inbuf []byte, event *Event) bool {
func extract_event(inbuf []byte, event *Event, allow_esc_wait bool) extract_event_res {
if len(inbuf) == 0 {
event.N = 0
return false
return event_not_extracted
}
if inbuf[0] == '\033' {
// possible escape sequence
if n, ok := parse_escape_sequence(event, inbuf); n != 0 {
event.N = n
return ok
if ok {
return event_extracted
} else {
return event_not_extracted
}
}
// possible partially read escape sequence; trigger a wait if appropriate
if enable_wait_for_escape_sequence() && allow_esc_wait {
event.N = 0
return esc_wait
}
// it's not escape sequence, then it's Alt or Esc, check input_mode
......@@ -461,17 +479,17 @@ func extract_event(inbuf []byte, event *Event) bool {
event.Key = KeyEsc
event.Mod = 0
event.N = 1
return true
return event_extracted
case input_mode&InputAlt != 0:
// if we're in alt mode, set Alt modifier to event and redo parsing
event.Mod = ModAlt
ok := extract_event(inbuf[1:], event)
if ok {
status := extract_event(inbuf[1:], event, false)
if status == event_extracted {
event.N++
} else {
event.N = 0
}
return ok
return status
default:
panic("unreachable")
}
......@@ -486,7 +504,7 @@ func extract_event(inbuf []byte, event *Event) bool {
event.Ch = 0
event.Key = Key(inbuf[0])
event.N = 1
return true
return event_extracted
}
// the only possible option is utf8 rune
......@@ -494,10 +512,10 @@ func extract_event(inbuf []byte, event *Event) bool {
event.Ch = r
event.Key = 0
event.N = n
return true
return event_extracted
}
return false
return event_not_extracted
}
func fcntl(fd int, cmd int, arg int) (val int, err error) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册