github.com/xyproto/orbiton/v2@v2.65.12-0.20240516144430-e10a419274ec/signals.go (about)

     1  package main
     2  
     3  import (
     4  	"os"
     5  	"os/signal"
     6  	"path/filepath"
     7  	"syscall"
     8  	"time"
     9  
    10  	"github.com/xyproto/vt100"
    11  )
    12  
    13  // SetUpSignalHandlers sets up a signal handler for when ctrl-c is pressed (SIGTERM),
    14  // and also for when SIGUSR1 or SIGWINCH is received.
    15  func (e *Editor) SetUpSignalHandlers(c *vt100.Canvas, tty *vt100.TTY, status *StatusBar) {
    16  
    17  	// For the drawing and the statusbar
    18  	resizeMut.Lock()
    19  	mut.Lock()
    20  
    21  	sigChan := make(chan os.Signal, 1)
    22  
    23  	// Send a SIGWINCH signal to the parent process if "OG" is set,
    24  	// to signal that "o is ready" to resize. The "og" GUI will then
    25  	// send SIGWINCH back, which will trigger FullResetRedraw in the case below.
    26  	if inVTEGUI {
    27  		// Clear any previous terminate or USR handlers
    28  		signal.Reset(syscall.SIGTERM, syscall.SIGUSR1, syscall.SIGWINCH)
    29  		// Set up notifications
    30  		signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGUSR1, syscall.SIGWINCH)
    31  		// Send a SIGWINCH signal to the "og" GUI, which is catched there
    32  		syscall.Kill(os.Getppid(), syscall.SIGWINCH)
    33  	} else {
    34  		// Start these in the background, since the "og" GUI isn't waiting
    35  		defer func() {
    36  			// Clear any previous terminate or USR handlers
    37  			signal.Reset(syscall.SIGTERM, syscall.SIGUSR1, syscall.SIGWINCH)
    38  			// Set up notifications
    39  			signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGUSR1, syscall.SIGWINCH)
    40  		}()
    41  	}
    42  
    43  	// For the drawing and the statusbar
    44  	resizeMut.Unlock()
    45  	mut.Unlock()
    46  
    47  	go func() {
    48  		for {
    49  			// Block until the signal is received
    50  			sig := <-sigChan
    51  
    52  			switch sig {
    53  			case syscall.SIGTERM:
    54  				// Save the file
    55  				mut.Lock()
    56  				e.UserSave(c, tty, status)
    57  				mut.Unlock()
    58  			case syscall.SIGUSR1:
    59  				// Unlock the file
    60  				if absFilename, err := filepath.Abs(e.filename); err != nil {
    61  					// Just unlock the non-absolute filename
    62  					fileLock.Unlock(e.filename)
    63  				} else {
    64  					fileLock.Unlock(absFilename)
    65  				}
    66  				fileLock.Save()
    67  			case syscall.SIGWINCH:
    68  				// Full redraw, like if Esc was pressed
    69  				drawLines := true
    70  				e.FullResetRedraw(c, status, drawLines)
    71  				// Try twice
    72  				time.Sleep(300 * time.Millisecond)
    73  				e.FullResetRedraw(c, status, drawLines)
    74  			}
    75  		}
    76  	}()
    77  }