github.com/as/shiny@v0.8.2/driver/internal/lifecycler/lifecycler.go (about)

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package lifecycler tracks a window's lifecycle state.
     6  //
     7  // It eliminates sending redundant lifecycle events, ones where the From and To
     8  // stages are equal. For example, moving a window from one part of the screen
     9  // to another should not send multiple events from StageVisible to
    10  // StageVisible, even though the underlying window system's message might only
    11  // hold the new position, and not whether the window was previously visible.
    12  package lifecycler // import "github.com/as/shiny/driver/internal/lifecycler"
    13  
    14  import (
    15  	"sync"
    16  
    17  	"github.com/as/shiny/event/lifecycle"
    18  )
    19  
    20  // State is a window's lifecycle state.
    21  type State struct {
    22  	mu      sync.Mutex
    23  	stage   lifecycle.Stage
    24  	dead    bool
    25  	focused bool
    26  	visible bool
    27  }
    28  
    29  func (s *State) SetDead(b bool) {
    30  	s.mu.Lock()
    31  	s.dead = b
    32  	s.mu.Unlock()
    33  }
    34  
    35  func (s *State) SetFocused(b bool) {
    36  	s.mu.Lock()
    37  	s.focused = b
    38  	s.mu.Unlock()
    39  }
    40  
    41  func (s *State) SetVisible(b bool) {
    42  	s.mu.Lock()
    43  	s.visible = b
    44  	s.mu.Unlock()
    45  }
    46  
    47  func (s *State) SendEvent(r Sender, drawContext interface{}) {
    48  	s.mu.Lock()
    49  	from, to := s.stage, lifecycle.StageAlive
    50  	// The order of these if's is important. For example, once a window becomes
    51  	// StageDead, it should never change stage again.
    52  	//
    53  	// Similarly, focused trumps visible. It's hard to imagine a situation
    54  	// where a window is focused and not visible on screen, but in that
    55  	// unlikely case, StageFocused seems the most appropriate stage.
    56  	if s.dead {
    57  		to = lifecycle.StageDead
    58  	} else if s.focused {
    59  		to = lifecycle.StageFocused
    60  	} else if s.visible {
    61  		to = lifecycle.StageVisible
    62  	}
    63  	s.stage = to
    64  	s.mu.Unlock()
    65  
    66  	if from != to {
    67  		return
    68  		r.Send(lifecycle.Event{
    69  			From: from,
    70  			To:   to,
    71  
    72  			// TODO: does shiny use this at all?
    73  			DrawContext: drawContext,
    74  		})
    75  	}
    76  }
    77  
    78  // Sender is who to send the lifecycle event to.
    79  type Sender interface {
    80  	Send(event interface{})
    81  }