tty: modify WindowSize method to return windowsize object

Modify the WindowSize method of the Tty interface to return a WindowSize
object. This object includes the window size in pixels, for use in
direct drawing of sixels. Terminals that do not support this feature
will have pixel sizes of 0,0.
This commit is contained in:
Tim Culverhouse 2023-03-19 10:30:08 -05:00 committed by Garrett D'Amore
parent bfc5242f05
commit c5c66b8427
4 changed files with 42 additions and 23 deletions

View File

@ -27,6 +27,7 @@ import (
"syscall" "syscall"
"time" "time"
"golang.org/x/sys/unix"
"golang.org/x/term" "golang.org/x/term"
) )
@ -133,11 +134,14 @@ func (tty *stdIoTty) Stop() error {
return nil return nil
} }
func (tty *stdIoTty) WindowSize() (int, int, error) { func (tty *stdIoTty) WindowSize() (WindowSize, error) {
w, h, err := term.GetSize(tty.fd) size := WindowSize{}
ws, err := unix.IoctlGetWinsize(tty.fd, unix.TIOCGWINSZ)
if err != nil { if err != nil {
return 0, 0, err return size, err
} }
w := int(ws.Col)
h := int(ws.Row)
if w == 0 { if w == 0 {
w, _ = strconv.Atoi(os.Getenv("COLUMNS")) w, _ = strconv.Atoi(os.Getenv("COLUMNS"))
} }
@ -150,7 +154,11 @@ func (tty *stdIoTty) WindowSize() (int, int, error) {
if h == 0 { if h == 0 {
h = 25 // default h = 25 // default
} }
return w, h, nil size.Width = w
size.Height = h
size.PixelWidth = int(ws.Xpixel)
size.PixelHeight = int(ws.Ypixel)
return size, nil
} }
func (tty *stdIoTty) NotifyResize(cb func()) { func (tty *stdIoTty) NotifyResize(cb func()) {

View File

@ -1091,19 +1091,22 @@ func (t *tScreen) Size() (int, int) {
} }
func (t *tScreen) resize() { func (t *tScreen) resize() {
if w, h, e := t.tty.WindowSize(); e == nil { ws, err := t.tty.WindowSize()
if w != t.w || h != t.h { if err != nil {
t.cx = -1 return
t.cy = -1
t.cells.Resize(w, h)
t.cells.Invalidate()
t.h = h
t.w = w
ev := NewEventResize(w, h)
_ = t.PostEvent(ev)
}
} }
if ws.Width == t.w && ws.Height == t.h {
return
}
t.cx = -1
t.cy = -1
t.cells.Resize(ws.Width, ws.Height)
t.cells.Invalidate()
t.h = ws.Height
t.w = ws.Width
ev := &EventResize{t: time.Now(), ws: ws}
_ = t.PostEvent(ev)
} }
func (t *tScreen) Colors() int { func (t *tScreen) Colors() int {
@ -1894,8 +1897,8 @@ func (t *tScreen) engage() error {
return err return err
} }
t.running = true t.running = true
if w, h, err := t.tty.WindowSize(); err == nil && w != 0 && h != 0 { if ws, err := t.tty.WindowSize(); err == nil && ws.Width != 0 && ws.Height != 0 {
t.cells.Resize(w, h) t.cells.Resize(ws.Width, ws.Height)
} }
stopQ := make(chan struct{}) stopQ := make(chan struct{})
t.stopQ = stopQ t.stopQ = stopQ

2
tty.go
View File

@ -50,7 +50,7 @@ type Tty interface {
// WindowSize is called to determine the terminal dimensions. This might be determined // WindowSize is called to determine the terminal dimensions. This might be determined
// by an ioctl or other means. // by an ioctl or other means.
WindowSize() (width int, height int, err error) WindowSize() (WindowSize, error)
io.ReadWriteCloser io.ReadWriteCloser
} }

View File

@ -27,6 +27,7 @@ import (
"syscall" "syscall"
"time" "time"
"golang.org/x/sys/unix"
"golang.org/x/term" "golang.org/x/term"
) )
@ -136,11 +137,14 @@ func (tty *devTty) Stop() error {
return nil return nil
} }
func (tty *devTty) WindowSize() (int, int, error) { func (tty *devTty) WindowSize() (WindowSize, error) {
w, h, err := term.GetSize(tty.fd) size := WindowSize{}
ws, err := unix.IoctlGetWinsize(tty.fd, unix.TIOCGWINSZ)
if err != nil { if err != nil {
return 0, 0, err return size, err
} }
w := int(ws.Col)
h := int(ws.Row)
if w == 0 { if w == 0 {
w, _ = strconv.Atoi(os.Getenv("COLUMNS")) w, _ = strconv.Atoi(os.Getenv("COLUMNS"))
} }
@ -153,7 +157,11 @@ func (tty *devTty) WindowSize() (int, int, error) {
if h == 0 { if h == 0 {
h = 25 // default h = 25 // default
} }
return w, h, nil size.Width = w
size.Height = h
size.PixelWidth = int(ws.Xpixel)
size.PixelHeight = int(ws.Ypixel)
return size, nil
} }
func (tty *devTty) NotifyResize(cb func()) { func (tty *devTty) NotifyResize(cb func()) {