Add callback for screen resize handling

This commit is contained in:
Kovid Goyal 2022-08-24 23:06:18 +05:30
parent c2ef6c986b
commit e68b5fa504
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 70 additions and 11 deletions

View File

@ -35,9 +35,15 @@ func write_ignoring_temporary_errors(fd int, buf []byte) (int, error) {
return n, err
}
type ScreenSize struct {
WidthCells, HeightCells, WidthPx, HeightPx, CellWidth, CellHeight uint
updated bool
}
type Loop struct {
controlling_term *tty.Term
terminal_options TerminalStateOptions
screen_size ScreenSize
escape_code_parser utils.EscapeCodeParser
keep_going bool
flush_write_buf bool
@ -56,6 +62,26 @@ type Loop struct {
// Called when text is received either from a key event or directly from the terminal
OnText func(loop *Loop, text string, from_key_event bool, in_bracketed_paste bool) error
// Called when the terminal is resize
OnResize func(loop *Loop, old_size ScreenSize, new_size ScreenSize) error
}
func (self *Loop) update_screen_size() error {
if self.controlling_term != nil {
return fmt.Errorf("No controlling terminal cannot update screen size")
}
ws, err := self.controlling_term.GetSize()
if err != nil {
return err
}
s := &self.screen_size
s.updated = true
s.HeightCells, s.WidthCells = uint(ws.Row), uint(ws.Col)
s.HeightPx, s.WidthPx = uint(ws.Ypixel), uint(ws.Xpixel)
s.CellWidth = s.WidthPx / s.WidthCells
s.CellHeight = s.HeightPx / s.HeightCells
return nil
}
func (self *Loop) handle_csi(raw []byte) error {
@ -125,6 +151,19 @@ func (self *Loop) on_SIGINT() error {
return nil
}
func (self *Loop) on_SIGWINCH() error {
self.screen_size.updated = false
if self.OnResize != nil {
old_size := self.screen_size
err := self.update_screen_size()
if err != nil {
return err
}
return self.OnResize(self, old_size, self.screen_size)
}
return nil
}
func (self *Loop) on_SIGTERM() error {
self.death_signal = SIGTERM
self.keep_going = false
@ -170,6 +209,14 @@ func (self *Loop) DeathSignalName() string {
return ""
}
func (self *Loop) ScreenSize() (ScreenSize, error) {
if self.screen_size.updated {
return self.screen_size, nil
}
err := self.update_screen_size()
return self.screen_size, err
}
func (self *Loop) KillIfSignalled() {
switch self.death_signal {
case SIGINT:
@ -198,7 +245,7 @@ func (self *Loop) Run() (err error) {
}()
sigchnl := make(chan os.Signal, 256)
reset_signals := notify_signals(sigchnl, SIGINT, SIGTERM, SIGTSTP, SIGHUP)
reset_signals := notify_signals(sigchnl, SIGINT, SIGTERM, SIGTSTP, SIGHUP, SIGWINCH)
defer reset_signals()
go func() {

View File

@ -10,16 +10,17 @@ import (
type Signal byte
const (
SIGNULL Signal = 0
SIGINT Signal = 1
SIGTERM Signal = 2
SIGTSTP Signal = 3
SIGHUP Signal = 4
SIGTTIN Signal = 5
SIGTTOU Signal = 6
SIGUSR1 Signal = 7
SIGUSR2 Signal = 8
SIGALRM Signal = 9
SIGNULL Signal = 0
SIGINT Signal = 1
SIGTERM Signal = 2
SIGTSTP Signal = 3
SIGHUP Signal = 4
SIGTTIN Signal = 5
SIGTTOU Signal = 6
SIGUSR1 Signal = 7
SIGUSR2 Signal = 8
SIGALRM Signal = 9
SIGWINCH Signal = 10
)
func (self *Signal) String() string {
@ -44,6 +45,8 @@ func (self *Signal) String() string {
return "SIGUSR2"
case SIGALRM:
return "SIGALRM"
case SIGWINCH:
return "SIGWINCH"
default:
return fmt.Sprintf("SIG#%d", *self)
}
@ -69,6 +72,8 @@ func as_signal(which os.Signal) Signal {
return SIGUSR2
case syscall.SIGALRM:
return SIGALRM
case syscall.SIGWINCH:
return SIGWINCH
default:
return SIGNULL
}
@ -96,6 +101,8 @@ func as_go_signal(which Signal) os.Signal {
return syscall.SIGUSR2
case SIGALRM:
return syscall.SIGALRM
case SIGWINCH:
return syscall.SIGWINCH
default:
return zero_go_signal
}
@ -146,6 +153,11 @@ func (self *Loop) read_signals(f *os.File, buf []byte) error {
if err != nil {
return err
}
case SIGWINCH:
err := self.on_SIGWINCH()
if err != nil {
return err
}
case SIGTSTP:
err := self.on_SIGTSTP()
if err != nil {