diff options
Diffstat (limited to 'shiny/driver/internal/lifecycler/lifecycler.go')
-rw-r--r-- | shiny/driver/internal/lifecycler/lifecycler.go | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/shiny/driver/internal/lifecycler/lifecycler.go b/shiny/driver/internal/lifecycler/lifecycler.go new file mode 100644 index 0000000..53d3543 --- /dev/null +++ b/shiny/driver/internal/lifecycler/lifecycler.go @@ -0,0 +1,80 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package lifecycler tracks a window's lifecycle state. +// +// It eliminates sending redundant lifecycle events, ones where the From and To +// stages are equal. For example, moving a window from one part of the screen +// to another should not send multiple events from StageVisible to +// StageVisible, even though the underlying window system's message might only +// hold the new position, and not whether the window was previously visible. +package lifecycler // import "golang.org/x/exp/shiny/driver/internal/lifecycler" + +import ( + "sync" + + "golang.org/x/mobile/event/lifecycle" +) + +// State is a window's lifecycle state. +type State struct { + mu sync.Mutex + stage lifecycle.Stage + dead bool + focused bool + visible bool +} + +func (s *State) SetDead(b bool) { + s.mu.Lock() + s.dead = b + s.mu.Unlock() +} + +func (s *State) SetFocused(b bool) { + s.mu.Lock() + s.focused = b + s.mu.Unlock() +} + +func (s *State) SetVisible(b bool) { + s.mu.Lock() + s.visible = b + s.mu.Unlock() +} + +func (s *State) SendEvent(r Sender, drawContext interface{}) { + s.mu.Lock() + from, to := s.stage, lifecycle.StageAlive + // The order of these if's is important. For example, once a window becomes + // StageDead, it should never change stage again. + // + // Similarly, focused trumps visible. It's hard to imagine a situation + // where a window is focused and not visible on screen, but in that + // unlikely case, StageFocused seems the most appropriate stage. + if s.dead { + to = lifecycle.StageDead + } else if s.focused { + to = lifecycle.StageFocused + } else if s.visible { + to = lifecycle.StageVisible + } + s.stage = to + s.mu.Unlock() + + if from != to { + r.Send(lifecycle.Event{ + From: from, + To: to, + + // TODO: does shiny use this at all? + DrawContext: drawContext, + }) + } +} + +// Sender is who to send the lifecycle event to. +type Sender interface { + Send(event interface{}) +} |