|
|
|
|
@ -3,7 +3,9 @@
|
|
|
|
|
package tty
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"os"
|
|
|
|
|
"errors"
|
|
|
|
|
"syscall"
|
|
|
|
|
"unsafe"
|
|
|
|
|
|
|
|
|
|
@ -122,11 +124,13 @@ type charInfo struct {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type TTY struct {
|
|
|
|
|
in *os.File
|
|
|
|
|
out *os.File
|
|
|
|
|
st uint32
|
|
|
|
|
rs []rune
|
|
|
|
|
ws chan WINSIZE
|
|
|
|
|
in *os.File
|
|
|
|
|
out *os.File
|
|
|
|
|
st uint32
|
|
|
|
|
rs []rune
|
|
|
|
|
ws chan WINSIZE
|
|
|
|
|
sigwinchCtx context.Context
|
|
|
|
|
sigwinchCtxCancel context.CancelFunc
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func readConsoleInput(fd uintptr, record *inputRecord) (err error) {
|
|
|
|
|
@ -183,6 +187,7 @@ func open() (*TTY, error) {
|
|
|
|
|
procSetConsoleMode.Call(h, uintptr(st))
|
|
|
|
|
|
|
|
|
|
tty.ws = make(chan WINSIZE)
|
|
|
|
|
tty.sigwinchCtx, tty.sigwinchCtxCancel = context.WithCancel(context.Background())
|
|
|
|
|
|
|
|
|
|
return tty, nil
|
|
|
|
|
}
|
|
|
|
|
@ -206,10 +211,24 @@ func (tty *TTY) readRune() (rune, error) {
|
|
|
|
|
switch ir.eventType {
|
|
|
|
|
case windowBufferSizeEvent:
|
|
|
|
|
wr := (*windowBufferSizeRecord)(unsafe.Pointer(&ir.event))
|
|
|
|
|
tty.ws <- WINSIZE{
|
|
|
|
|
ws := WINSIZE{
|
|
|
|
|
W: int(wr.size.x),
|
|
|
|
|
H: int(wr.size.y),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := tty.sigwinchCtx.Err(); err != nil {
|
|
|
|
|
// closing
|
|
|
|
|
// the following select might panic without this guard close
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
select {
|
|
|
|
|
case tty.ws <- ws:
|
|
|
|
|
case <-tty.sigwinchCtx.Done():
|
|
|
|
|
return 0, tty.sigwinchCtx.Err()
|
|
|
|
|
default:
|
|
|
|
|
return 0, nil // no one is currently trying to read
|
|
|
|
|
}
|
|
|
|
|
case keyEvent:
|
|
|
|
|
kr := (*keyEventRecord)(unsafe.Pointer(&ir.event))
|
|
|
|
|
if kr.keyDown != 0 {
|
|
|
|
|
@ -307,8 +326,9 @@ func (tty *TTY) readRune() (rune, error) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (tty *TTY) close() error {
|
|
|
|
|
close(tty.ws)
|
|
|
|
|
procSetConsoleMode.Call(tty.in.Fd(), uintptr(tty.st))
|
|
|
|
|
tty.sigwinchCtxCancel()
|
|
|
|
|
close(tty.ws)
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -321,6 +341,15 @@ func (tty *TTY) size() (int, int, error) {
|
|
|
|
|
return int(csbi.window.right - csbi.window.left + 1), int(csbi.window.bottom - csbi.window.top + 1), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (tty *TTY) sizePixel() (int, int, int, int, error) {
|
|
|
|
|
x, y, err := tty.size()
|
|
|
|
|
if err != nil {
|
|
|
|
|
x = -1
|
|
|
|
|
y = -1
|
|
|
|
|
}
|
|
|
|
|
return x, y, -1, -1, errors.New("no implemented method for querying size in pixels on Windows")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (tty *TTY) input() *os.File {
|
|
|
|
|
return tty.in
|
|
|
|
|
}
|
|
|
|
|
@ -349,6 +378,6 @@ func (tty *TTY) raw() (func() error, error) {
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (tty *TTY) sigwinch() chan WINSIZE {
|
|
|
|
|
func (tty *TTY) sigwinch() <-chan WINSIZE {
|
|
|
|
|
return tty.ws
|
|
|
|
|
}
|
|
|
|
|
|