Skip to content

Commit

Permalink
refactor: windows: clean up, tidy and improve windows key handling (#…
Browse files Browse the repository at this point in the history
…1163)

This fixes a bunch of issues on Windows bringing improvements and
reliability to the implementation. It replaces the existing key events
hack with a key state that keeps track of previous key events to parse
the incoming ANSI escape sequences. It also decodes unicode utf16 pairs
at the parser level instead of the driver level.

Related: #1126

TODO:
- [x] Windows API tests
  - [x] Key events
  - [x] Mouse events
  - [x] Resize events
  - [x] Focus events
  • Loading branch information
aymanbagabas authored Oct 16, 2024
2 parents fb09ffd + bde5d1b commit 5d08fe9
Show file tree
Hide file tree
Showing 8 changed files with 713 additions and 605 deletions.
27 changes: 20 additions & 7 deletions driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,23 @@ import (
"github.com/muesli/cancelreader"
)

// win32InputState is a state machine for parsing key events from the Windows
// Console API into escape sequences and utf8 runes, and keeps track of the last
// control key state to determine modifier key changes. It also keeps track of
// the last mouse button state and window size changes to determine which mouse
// buttons were released and to prevent multiple size events from firing.
//
//nolint:unused
type win32InputState struct {
ansiBuf [256]byte
ansiIdx int
utf16Buf [2]rune
utf16Half bool
lastCks uint32 // the last control key state for the previous event
lastMouseBtns uint32 // the last mouse button state for the previous event
lastWinsizeX, lastWinsizeY int16 // the last window size for the previous event to prevent multiple size events from firing
}

// driver represents an ANSI terminal input driver.
// It reads input events and parses ANSI sequences from the terminal input
// buffer.
Expand All @@ -23,13 +40,9 @@ type driver struct {

buf [256]byte // do we need a larger buffer?

// prevMouseState keeps track of the previous mouse state to determine mouse
// up button events.
prevMouseState uint32 // nolint: unused

// lastWinsizeEvent keeps track of the last window size event to prevent
// multiple size events from firing.
lastWinsizeEventX, lastWinsizeEventY int16 // nolint: unused
// keyState keeps track of the current Windows Console API key events state.
// It is used to decode ANSI escape sequences and utf16 sequences.
keyState win32InputState //nolint:unused

flags int // control the behavior of the driver.
}
Expand Down
6 changes: 6 additions & 0 deletions driver_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ package tea
func (d *driver) ReadEvents() ([]Msg, error) {
return d.readEvents()
}

// parseWin32InputKeyEvent parses a Win32 input key events. This function is
// only available on Windows.
func parseWin32InputKeyEvent(*win32InputState, uint16, uint16, rune, bool, uint32, uint16) Msg {
return nil
}
Loading

0 comments on commit 5d08fe9

Please sign in to comment.