Skip to content

Commit

Permalink
Reinstate gowid Screen's support for activation and deactivation
Browse files Browse the repository at this point in the history
We recently merged changes to help with a gowid use case where an
application wanted to provide its own tcell Screen object and not use
the one gowid creates. In doing so, I inadvertently broke correct screen
activation and deactivation. Activation means that the terminal screen
is taken over by the tcell screen, and deactivation means control is
given back and in practice the terminal screen's contents will return to
their appearance before the screen was activated. For example, in
termshark, if the user listens on an interface, termshark's UI will not
start right away, displaying:

(The termshark UI will start when packets are detected on eth0...)

It behaves like this in case listening on an interface requires
superuser permissions, which tshark will request - so this lets the user
see that prompt without the UI covering it up.

When packets arrive, termshark activates the tcell screen and the UI
appears. If the user hits ctrl-z, termshark deactivates the screen and
sends itself a SIGSTOP. This lets the user see what was on the terminal
before termshark launched. Emacs in the terminal behaves the same way
and I copied that.

I lost this behavior with recent gowid updates and didn't spot it until
recently. The fix here is to reinstate the DontActivate bool to the
App's options, but to only make use of it if the user does not supply
their own screen. If the gowid app passes its own tcell screen to the
gowid App, then ActivateScreen and DeactivateScreen should not be used.
  • Loading branch information
gcla committed May 30, 2022
1 parent 4b86a00 commit 072f088
Showing 1 changed file with 14 additions and 7 deletions.
21 changes: 14 additions & 7 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ type App struct {
prevWasMouseMove bool // True if we last processed simple mouse movement. We can optimize on slow
enableMouseMotion bool
enableBracketedPaste bool
// systems by discarding subsequent mouse movement events.
screenInited bool
dontOwnScreen bool

lastMouse MouseState // So I can tell if a button was previously clicked
MouseState // Track which mouse buttons are currently down
Expand All @@ -117,6 +118,7 @@ type AppArgs struct {
EnableMouseMotion bool
EnableBracketedPaste bool
Log log.StdLogger
DontActivate bool
}

// IUnhandledInput is used as a handler for application user input that is not handled by any
Expand Down Expand Up @@ -283,9 +285,10 @@ func newApp(args AppArgs) (rapp *App, rerr error) {
log: args.Log,
enableMouseMotion: args.EnableMouseMotion,
enableBracketedPaste: args.EnableBracketedPaste,
dontOwnScreen: args.Screen != nil,
}

if args.Screen == nil {
if !res.dontOwnScreen && !args.DontActivate {
if err := res.initScreen(); err != nil {
return nil, err
}
Expand Down Expand Up @@ -809,14 +812,13 @@ func (a *App) Quit() {
// I can't make tcell claim and release the same screen successfully. Clients of
// the app struct shouldn't cache the screen object returned via GetScreen().
//
// Assumes we own the screen...
func (a *App) ActivateScreen() error {
screen, err := tcellScreen()
if err != nil {
return WithKVs(err, map[string]interface{}{"TERM": os.Getenv("TERM")})
}
if a.screen != nil {
a.screen.Fini()
}
a.DeactivateScreen()
a.screen = screen
if err := a.initScreen(); err != nil {
return err
Expand All @@ -827,16 +829,21 @@ func (a *App) ActivateScreen() error {
return nil
}

// Assumes we own the screen
func (a *App) DeactivateScreen() {
a.screen.Fini()
a.screen = nil
if a.screen != nil && a.screenInited {
a.screen.Fini()
a.screen = nil
a.screenInited = false
}
}

func (a *App) initScreen() error {
if err := a.screen.Init(); err != nil {
return WithKVs(err, map[string]interface{}{"TERM": os.Getenv("TERM")})
}

a.screenInited = true
a.initColorMode()

defFg := ColorDefault
Expand Down

0 comments on commit 072f088

Please sign in to comment.