diff --git a/app/app.go b/app/app.go index 84cf3828..e4b4e4c6 100644 --- a/app/app.go +++ b/app/app.go @@ -4,66 +4,14 @@ package app import ( "errors" - "image" "math" "os" "strings" "time" - "gioui.org/op" "gioui.org/unit" ) -// A FrameEvent asks for a new frame in the form of a list of -// operations. -type FrameEvent struct { - Config Config - // Size is the dimensions of the window. - Size image.Point - // Insets is the insets to apply. - Insets Insets - // Frame replaces the window's frame with the new - // frame. - Frame func(frame *op.Ops) - // Whether this draw is system generated and needs a complete - // frame before proceeding. - sync bool -} - -// DestroyEvent is the last event sent through -// a window event channel. -type DestroyEvent struct { - // Err is nil for normal window closures. If a - // window is prematurely closed, Err is the cause. - Err error -} - -// Insets is the space taken up by -// system decoration such as translucent -// system bars and software keyboards. -type Insets struct { - Top, Bottom, Left, Right unit.Value -} - -// A StageEvent is generated whenever the stage of a -// Window changes. -type StageEvent struct { - Stage Stage -} - -// CommandEvent is a system event. -type CommandEvent struct { - Type CommandType - // Suppress the default action of the command. - Cancel bool -} - -// Stage of a Window. -type Stage uint8 - -// CommandType is the type of a CommandEvent. -type CommandType uint8 - type windowRendezvous struct { in chan windowAndOptions out chan windowAndOptions @@ -75,20 +23,6 @@ type windowAndOptions struct { opts *windowOptions } -const ( - // StagePaused is the Stage for inactive Windows. - // Inactive Windows don't receive FrameEvents. - StagePaused Stage = iota - // StateRunning is for active Windows. - StageRunning -) - -const ( - // CommandBack is the command for a back action - // such as the Android back button. - CommandBack CommandType = iota -) - const ( inchPrDp = 1.0 / 160 mmPrDp = 25.4 / 160 @@ -109,17 +43,6 @@ const ( // Set with the go linker flag -X. var extraArgs string -func (l Stage) String() string { - switch l { - case StagePaused: - return "StagePaused" - case StageRunning: - return "StageRunning" - default: - panic("unexpected Stage value") - } -} - func init() { if extraArgs != "" { args := strings.Split(extraArgs, "|") @@ -149,8 +72,8 @@ func Main() { main() } -// Config implements the layout.Config interface. -type Config struct { +// config implements the system.Config interface. +type config struct { // Device pixels per dp. pxPerDp float32 // Device pixels per sp. @@ -158,11 +81,11 @@ type Config struct { now time.Time } -func (c *Config) Now() time.Time { +func (c *config) Now() time.Time { return c.now } -func (c *Config) Px(v unit.Value) int { +func (c *config) Px(v unit.Value) int { var r float32 switch v.U { case unit.UnitPx: @@ -202,8 +125,3 @@ func newWindowRendezvous() *windowRendezvous { }() return wr } - -func (_ FrameEvent) ImplementsEvent() {} -func (_ StageEvent) ImplementsEvent() {} -func (_ *CommandEvent) ImplementsEvent() {} -func (_ DestroyEvent) ImplementsEvent() {} diff --git a/app/os_android.go b/app/os_android.go index 34820e96..5646cc2f 100644 --- a/app/os_android.go +++ b/app/os_android.go @@ -27,6 +27,7 @@ import ( "gioui.org/f32" "gioui.org/io/key" "gioui.org/io/pointer" + "gioui.org/io/system" "gioui.org/unit" ) @@ -37,9 +38,9 @@ type window struct { dpi int fontScale float32 - insets Insets + insets system.Insets - stage Stage + stage system.Stage started bool mu sync.Mutex @@ -112,7 +113,7 @@ func onCreateView(env *C.JNIEnv, class C.jclass, view C.jobject) C.jlong { handle := C.jlong(view) views[handle] = w w.loadConfig(env, class) - w.setStage(StagePaused) + w.setStage(system.StagePaused) return handle } @@ -129,7 +130,7 @@ func onDestroyView(env *C.JNIEnv, class C.jclass, handle C.jlong) { func onStopView(env *C.JNIEnv, class C.jclass, handle C.jlong) { w := views[handle] w.started = false - w.setStage(StagePaused) + w.setStage(system.StagePaused) } //export onStartView @@ -147,7 +148,7 @@ func onSurfaceDestroyed(env *C.JNIEnv, class C.jclass, handle C.jlong) { w.mu.Lock() w.win = nil w.mu.Unlock() - w.setStage(StagePaused) + w.setStage(system.StagePaused) } //export onSurfaceChanged @@ -171,7 +172,7 @@ func onLowMemory() { func onConfigurationChanged(env *C.JNIEnv, class C.jclass, view C.jlong) { w := views[view] w.loadConfig(env, class) - if w.stage >= StageRunning { + if w.stage >= system.StageRunning { w.draw(true) } } @@ -182,7 +183,7 @@ func onFrameCallback(env *C.JNIEnv, class C.jclass, view C.jlong, nanos C.jlong) if !exist { return } - if w.stage < StageRunning { + if w.stage < system.StageRunning { return } w.mu.Lock() @@ -199,7 +200,7 @@ func onFrameCallback(env *C.JNIEnv, class C.jclass, view C.jlong, nanos C.jlong) //export onBack func onBack(env *C.JNIEnv, class C.jclass, view C.jlong) C.jboolean { w := views[view] - ev := &CommandEvent{Type: CommandBack} + ev := &system.CommandEvent{Type: system.CommandBack} w.event(ev) if ev.Cancel { return C.JNI_TRUE @@ -216,13 +217,13 @@ func onFocusChange(env *C.JNIEnv, class C.jclass, view C.jlong, focus C.jboolean //export onWindowInsets func onWindowInsets(env *C.JNIEnv, class C.jclass, view C.jlong, top, right, bottom, left C.jint) { w := views[view] - w.insets = Insets{ + w.insets = system.Insets{ Top: unit.Px(float32(top)), Right: unit.Px(float32(right)), Bottom: unit.Px(float32(bottom)), Left: unit.Px(float32(left)), } - if w.stage >= StageRunning { + if w.stage >= system.StageRunning { w.draw(true) } } @@ -233,16 +234,16 @@ func (w *window) setVisible() { if width == 0 || height == 0 { return } - w.setStage(StageRunning) + w.setStage(system.StageRunning) w.draw(true) } -func (w *window) setStage(stage Stage) { +func (w *window) setStage(stage system.Stage) { if stage == w.stage { return } w.stage = stage - w.event(StageEvent{stage}) + w.event(system.StageEvent{stage}) } func (w *window) nativeWindow(visID int) (*C.ANativeWindow, int, int) { @@ -296,16 +297,18 @@ func (w *window) draw(sync bool) { return } ppdp := float32(w.dpi) * inchPrDp - w.event(FrameEvent{ - Size: image.Point{ - X: int(width), - Y: int(height), - }, - Insets: w.insets, - Config: Config{ - pxPerDp: ppdp, - pxPerSp: w.fontScale * ppdp, - now: time.Now(), + w.event(frameEvent{ + FrameEvent: system.FrameEvent{ + Size: image.Point{ + X: int(width), + Y: int(height), + }, + Insets: w.insets, + Config: &config{ + pxPerDp: ppdp, + pxPerSp: w.fontScale * ppdp, + now: time.Now(), + }, }, sync: sync, }) diff --git a/app/os_ios.go b/app/os_ios.go index 2eca3144..84e2f883 100644 --- a/app/os_ios.go +++ b/app/os_ios.go @@ -25,6 +25,7 @@ import ( "gioui.org/f32" "gioui.org/io/key" "gioui.org/io/pointer" + "gioui.org/io/system" "gioui.org/unit" ) @@ -61,7 +62,7 @@ func onCreate(view C.CFTypeRef) { w.layer = C.CFTypeRef(layerFactory()) C.gio_addLayerToView(view, w.layer) views[view] = w - w.w.event(StageEvent{StagePaused}) + w.w.event(system.StageEvent{Stage: system.StagePaused}) } //export onDraw @@ -74,27 +75,29 @@ func onDraw(view C.CFTypeRef, dpi, sdpi, width, height C.CGFloat, sync C.int, to w.visible.Store(true) C.gio_updateView(view, w.layer) if !wasVisible { - w.w.event(StageEvent{StageRunning}) + w.w.event(system.StageEvent{Stage: system.StageRunning}) } isSync := false if sync != 0 { isSync = true } - w.w.event(FrameEvent{ - Size: image.Point{ - X: int(width + .5), - Y: int(height + .5), - }, - Insets: Insets{ - Top: unit.Px(float32(top)), - Right: unit.Px(float32(right)), - Bottom: unit.Px(float32(bottom)), - Left: unit.Px(float32(left)), - }, - Config: Config{ - pxPerDp: float32(dpi) * inchPrDp, - pxPerSp: float32(sdpi) * inchPrDp, - now: time.Now(), + w.w.event(frameEvent{ + FrameEvent: system.FrameEvent{ + Size: image.Point{ + X: int(width + .5), + Y: int(height + .5), + }, + Insets: system.Insets{ + Top: unit.Px(float32(top)), + Right: unit.Px(float32(right)), + Bottom: unit.Px(float32(bottom)), + Left: unit.Px(float32(left)), + }, + Config: &config{ + pxPerDp: float32(dpi) * inchPrDp, + pxPerSp: float32(sdpi) * inchPrDp, + now: time.Now(), + }, }, sync: isSync, }) @@ -104,14 +107,14 @@ func onDraw(view C.CFTypeRef, dpi, sdpi, width, height C.CGFloat, sync C.int, to func onStop(view C.CFTypeRef) { w := views[view] w.visible.Store(false) - w.w.event(StageEvent{StagePaused}) + w.w.event(system.StageEvent{Stage: system.StagePaused}) } //export onDestroy func onDestroy(view C.CFTypeRef) { w := views[view] delete(views, view) - w.w.event(DestroyEvent{}) + w.w.event(system.DestroyEvent{}) C.gio_removeLayer(w.layer) C.CFRelease(w.layer) w.layer = 0 diff --git a/app/os_js.go b/app/os_js.go index d3fbaa63..0432089b 100644 --- a/app/os_js.go +++ b/app/os_js.go @@ -11,6 +11,7 @@ import ( "gioui.org/f32" "gioui.org/io/key" "gioui.org/io/pointer" + "gioui.org/io/system" ) type window struct { @@ -53,7 +54,7 @@ func createWindow(win *Window, opts *windowOptions) error { go func() { w.w.setDriver(w) w.focus() - w.w.event(StageEvent{StageRunning}) + w.w.event(system.StageEvent{Stage: system.StageRunning}) w.draw(true) select {} w.cleanup() @@ -338,24 +339,26 @@ func (w *window) showTextInput(show bool) { func (w *window) draw(sync bool) { width, height, scale, cfg := w.config() - if cfg == (Config{}) { + if cfg == (config{}) { return } w.mu.Lock() w.scale = float32(scale) w.mu.Unlock() cfg.now = time.Now() - w.w.event(FrameEvent{ - Size: image.Point{ - X: width, - Y: height, + w.w.event(frameEvent{ + FrameEvent: system.FrameEvent{ + Size: image.Point{ + X: width, + Y: height, + }, + Config: &cfg, }, - Config: cfg, - sync: sync, + sync: sync, }) } -func (w *window) config() (int, int, float32, Config) { +func (w *window) config() (int, int, float32, config) { rect := w.cnv.Call("getBoundingClientRect") width, height := rect.Get("width").Float(), rect.Get("height").Float() scale := w.window.Get("devicePixelRatio").Float() @@ -368,7 +371,7 @@ func (w *window) config() (int, int, float32, Config) { w.cnv.Set("height", ih) } const ppdp = 96 * inchPrDp * monitorScale - return iw, ih, float32(scale), Config{ + return iw, ih, float32(scale), config{ pxPerDp: ppdp * float32(scale), pxPerSp: ppdp * float32(scale), } diff --git a/app/os_macos.go b/app/os_macos.go index e4103f14..8d125225 100644 --- a/app/os_macos.go +++ b/app/os_macos.go @@ -4,13 +4,6 @@ package app -/* -#cgo CFLAGS: -DGL_SILENCE_DEPRECATION -Werror -Wno-deprecated-declarations -fmodules -fobjc-arc -x objective-c - -#include -#include "os_macos.h" -*/ -import "C" import ( "errors" "image" @@ -22,8 +15,17 @@ import ( "gioui.org/f32" "gioui.org/io/key" "gioui.org/io/pointer" + "gioui.org/io/system" ) +/* +#cgo CFLAGS: -DGL_SILENCE_DEPRECATION -Werror -Wno-deprecated-declarations -fmodules -fobjc-arc -x objective-c + +#include +#include "os_macos.h" +*/ +import "C" + func init() { // Darwin requires that UI operations happen on the main thread only. runtime.LockOSThread() @@ -32,7 +34,7 @@ func init() { type window struct { view C.CFTypeRef w *Window - stage Stage + stage system.Stage ppdp float32 scale float32 } @@ -89,12 +91,12 @@ func (w *window) setAnimating(anim bool) { C.gio_setAnimating(w.view, animb) } -func (w *window) setStage(stage Stage) { +func (w *window) setStage(stage system.Stage) { if stage == w.stage { return } w.stage = stage - w.w.event(StageEvent{stage}) + w.w.event(system.StageEvent{Stage: stage}) } // Use a top level func for onFrameCallback to avoid @@ -197,14 +199,16 @@ func (w *window) draw(sync bool) { height := int(hf*w.scale + .5) cfg := configFor(w.ppdp, w.scale) cfg.now = time.Now() - w.setStage(StageRunning) - w.w.event(FrameEvent{ - Size: image.Point{ - X: width, - Y: height, + w.setStage(system.StageRunning) + w.w.event(frameEvent{ + FrameEvent: system.FrameEvent{ + Size: image.Point{ + X: width, + Y: height, + }, + Config: &cfg, }, - Config: cfg, - sync: sync, + sync: sync, }) } @@ -217,9 +221,9 @@ func getPixelsPerDp(scale float32) float32 { return ppdp / scale } -func configFor(ppdp, scale float32) Config { +func configFor(ppdp, scale float32) config { ppdp = ppdp * scale - return Config{ + return config{ pxPerDp: ppdp, pxPerSp: ppdp, } @@ -230,7 +234,7 @@ func gio_onTerminate(view C.CFTypeRef) { viewDo(view, func(views viewMap, view C.CFTypeRef) { w := views[view] delete(views, view) - w.w.event(DestroyEvent{}) + w.w.event(system.DestroyEvent{}) }) } @@ -238,7 +242,7 @@ func gio_onTerminate(view C.CFTypeRef) { func gio_onHide(view C.CFTypeRef) { viewDo(view, func(views viewMap, view C.CFTypeRef) { w := views[view] - w.setStage(StagePaused) + w.setStage(system.StagePaused) }) } @@ -246,7 +250,7 @@ func gio_onHide(view C.CFTypeRef) { func gio_onShow(view C.CFTypeRef) { viewDo(view, func(views viewMap, view C.CFTypeRef) { w := views[view] - w.setStage(StageRunning) + w.setStage(system.StageRunning) }) } diff --git a/app/os_wayland.go b/app/os_wayland.go index 5cf77168..1019791e 100644 --- a/app/os_wayland.go +++ b/app/os_wayland.go @@ -21,6 +21,7 @@ import ( "gioui.org/internal/fling" "gioui.org/io/key" "gioui.org/io/pointer" + "gioui.org/io/system" syscall "golang.org/x/sys/unix" ) @@ -116,7 +117,7 @@ type window struct { dir f32.Point } - stage Stage + stage system.Stage dead bool pendingErr error lastFrameCallback *C.struct_wl_callback @@ -302,7 +303,7 @@ func gio_onXdgSurfaceConfigure(data unsafe.Pointer, wmSurf *C.struct_xdg_surface w.serial = serial w.needAck = true w.mu.Unlock() - w.setStage(StageRunning) + w.setStage(system.StageRunning) w.draw(true) } @@ -772,7 +773,7 @@ loop: break } if w.dead { - w.w.event(DestroyEvent{Err: w.pendingErr}) + w.w.event(system.DestroyEvent{Err: w.pendingErr}) break } // Clear poll events. @@ -979,16 +980,16 @@ func (w *window) updateOutputs() { } w.mu.Unlock() if !found { - w.setStage(StagePaused) + w.setStage(system.StagePaused) } else { - w.setStage(StageRunning) + w.setStage(system.StageRunning) w.draw(true) } } -func (w *window) config() (int, int, Config) { +func (w *window) config() (int, int, config) { width, height := w.width*w.scale, w.height*w.scale - return width, height, Config{ + return width, height, config{ pxPerDp: w.ppdp * float32(w.scale), pxPerSp: w.ppsp * float32(w.scale), } @@ -1015,7 +1016,7 @@ func (w *window) draw(sync bool) { return } width, height, cfg := w.config() - if cfg == (Config{}) { + if cfg == (config{}) { return } if animating && w.lastFrameCallback == nil { @@ -1024,22 +1025,24 @@ func (w *window) draw(sync bool) { C.gio_wl_callback_add_listener(w.lastFrameCallback, unsafe.Pointer(w.surf)) } cfg.now = time.Now() - w.w.event(FrameEvent{ - Size: image.Point{ - X: width, - Y: height, + w.w.event(frameEvent{ + FrameEvent: system.FrameEvent{ + Size: image.Point{ + X: width, + Y: height, + }, + Config: &cfg, }, - Config: cfg, - sync: sync, + sync: sync, }) } -func (w *window) setStage(s Stage) { +func (w *window) setStage(s system.Stage) { if s == w.stage { return } w.stage = s - w.w.event(StageEvent{s}) + w.w.event(system.StageEvent{s}) } func (w *window) display() *C.struct_wl_display { diff --git a/app/os_windows.go b/app/os_windows.go index 0f9e24ee..7520d7ae 100644 --- a/app/os_windows.go +++ b/app/os_windows.go @@ -17,6 +17,7 @@ import ( "gioui.org/f32" "gioui.org/io/key" "gioui.org/io/pointer" + "gioui.org/io/system" ) var winMap = make(map[syscall.Handle]*window) @@ -60,7 +61,7 @@ type window struct { w *Window width int height int - stage Stage + stage system.Stage dead bool mu sync.Mutex @@ -183,7 +184,7 @@ func createWindow(window *Window, opts *windowOptions) error { defer delete(winMap, w.hwnd) w.w = window w.w.setDriver(w) - defer w.w.event(DestroyEvent{}) + defer w.w.event(system.DestroyEvent{}) showWindow(w.hwnd, _SW_SHOWDEFAULT) setForegroundWindow(w.hwnd) setFocus(w.hwnd) @@ -326,9 +327,9 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr case _WM_SIZE: switch wParam { case _SIZE_MINIMIZED: - w.setStage(StagePaused) + w.setStage(system.StagePaused) case _SIZE_MAXIMIZED, _SIZE_RESTORED: - w.setStage(StageRunning) + w.setStage(system.StageRunning) w.draw(true) } } @@ -395,9 +396,9 @@ func (w *window) postRedraw() { } } -func (w *window) setStage(s Stage) { +func (w *window) setStage(s system.Stage) { w.stage = s - w.w.event(StageEvent{s}) + w.w.event(system.StageEvent{Stage: s}) } func (w *window) draw(sync bool) { @@ -407,13 +408,15 @@ func (w *window) draw(sync bool) { w.height = int(r.bottom - r.top) cfg := configForDC(w.hdc) cfg.now = time.Now() - w.w.event(FrameEvent{ - Size: image.Point{ - X: w.width, - Y: w.height, + w.w.event(frameEvent{ + FrameEvent: system.FrameEvent{ + Size: image.Point{ + X: w.width, + Y: w.height, + }, + Config: &cfg, }, - Config: cfg, - sync: sync, + sync: sync, }) } @@ -474,14 +477,14 @@ func convertKeyCode(code uintptr) (rune, bool) { return r, true } -func configForDC(hdc syscall.Handle) Config { +func configForDC(hdc syscall.Handle) config { dpi := getDeviceCaps(hdc, _LOGPIXELSX) ppdp := float32(dpi) * inchPrDp * monitorScale // Force a minimum density to keep text legible and to handle bogus output geometry. if ppdp < minDensity { ppdp = minDensity } - return Config{ + return config{ pxPerDp: ppdp, pxPerSp: ppdp, } diff --git a/app/window.go b/app/window.go index ac4a275a..42ac61cd 100644 --- a/app/window.go +++ b/app/window.go @@ -12,6 +12,7 @@ import ( "gioui.org/app/internal/input" "gioui.org/io/event" "gioui.org/io/profile" + "gioui.org/io/system" "gioui.org/op" "gioui.org/unit" ) @@ -24,6 +25,12 @@ type windowOptions struct { Title string } +type frameEvent struct { + system.FrameEvent + + sync bool +} + // Window represents an operating system window. type Window struct { driver *window @@ -37,7 +44,7 @@ type Window struct { invalidates chan struct{} frames chan *op.Ops - stage Stage + stage system.Stage animating bool hasNextFrame bool nextFrame time.Time @@ -170,7 +177,7 @@ func (w *Window) updateAnimation() { w.delayedDraw.Stop() w.delayedDraw = nil } - if w.stage >= StageRunning && w.hasNextFrame { + if w.stage >= system.StageRunning && w.hasNextFrame { if dt := time.Until(w.nextFrame); dt <= 0 { animate = true } else { @@ -210,10 +217,10 @@ func (w *Window) waitAck() { func (w *Window) destroy(err error) { // Ack the current event. w.ack <- struct{}{} - w.out <- DestroyEvent{err} + w.out <- system.DestroyEvent{Err: err} for e := range w.in { w.ack <- struct{}{} - if _, ok := e.(DestroyEvent); ok { + if _, ok := e.(system.DestroyEvent); ok { return } } @@ -223,7 +230,7 @@ func (w *Window) run(opts *windowOptions) { defer close(w.in) defer close(w.out) if err := createWindow(w, opts); err != nil { - w.out <- DestroyEvent{err} + w.out <- system.DestroyEvent{Err: err} return } for { @@ -240,9 +247,9 @@ func (w *Window) run(opts *windowOptions) { w.updateAnimation() case e := <-w.in: switch e2 := e.(type) { - case StageEvent: + case system.StageEvent: if w.gpu != nil { - if e2.Stage < StageRunning { + if e2.Stage < system.StageRunning { w.gpu.Release() w.gpu = nil } else { @@ -253,18 +260,18 @@ func (w *Window) run(opts *windowOptions) { w.updateAnimation() w.out <- e w.waitAck() - case FrameEvent: + case frameEvent: if e2.Size == (image.Point{}) { panic(errors.New("internal error: zero-sized Draw")) } - if w.stage < StageRunning { + if w.stage < system.StageRunning { // No drawing if not visible. break } w.drawStart = time.Now() w.hasNextFrame = false e2.Frame = w.update - w.out <- e2 + w.out <- e2.FrameEvent var frame *op.Ops // Wait for either a frame or the ack event, // which meant that the client didn't draw. @@ -303,12 +310,12 @@ func (w *Window) run(opts *windowOptions) { return } } - case *CommandEvent: + case *system.CommandEvent: w.out <- e w.waitAck() case driverEvent: w.driver = e2.driver - case DestroyEvent: + case system.DestroyEvent: w.out <- e2 w.ack <- struct{}{} return diff --git a/io/system/system.go b/io/system/system.go new file mode 100644 index 00000000..c2d8f168 --- /dev/null +++ b/io/system/system.go @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +// Package system contains events usually handled at the top-level +// program level. +package system + +import ( + "image" + "time" + + "gioui.org/op" + "gioui.org/unit" +) + +// A FrameEvent asks for a new frame in the form of a list of +// operations. +type FrameEvent struct { + Config Config + // Size is the dimensions of the window. + Size image.Point + // Insets is the insets to apply. + Insets Insets + // Frame replaces the window's frame with the new + // frame. + Frame func(frame *op.Ops) + // Whether this draw is system generated and needs a complete + // frame before proceeding. + sync bool +} + +// Config define the essential properties of +// the environment. +type Config interface { + // Now returns the current animation time. + Now() time.Time + + unit.Converter +} + +// DestroyEvent is the last event sent through +// a window event channel. +type DestroyEvent struct { + // Err is nil for normal window closures. If a + // window is prematurely closed, Err is the cause. + Err error +} + +// Insets is the space taken up by +// system decoration such as translucent +// system bars and software keyboards. +type Insets struct { + Top, Bottom, Left, Right unit.Value +} + +// A StageEvent is generated whenever the stage of a +// Window changes. +type StageEvent struct { + Stage Stage +} + +// CommandEvent is a system event. +type CommandEvent struct { + Type CommandType + // Suppress the default action of the command. + Cancel bool +} + +// Stage of a Window. +type Stage uint8 + +// CommandType is the type of a CommandEvent. +type CommandType uint8 + +const ( + // StagePaused is the Stage for inactive Windows. + // Inactive Windows don't receive FrameEvents. + StagePaused Stage = iota + // StateRunning is for active Windows. + StageRunning +) + +const ( + // CommandBack is the command for a back action + // such as the Android back button. + CommandBack CommandType = iota +) + +func (l Stage) String() string { + switch l { + case StagePaused: + return "StagePaused" + case StageRunning: + return "StageRunning" + default: + panic("unexpected Stage value") + } +} + +func (_ FrameEvent) ImplementsEvent() {} +func (_ StageEvent) ImplementsEvent() {} +func (_ *CommandEvent) ImplementsEvent() {} +func (_ DestroyEvent) ImplementsEvent() {} diff --git a/layout/layout.go b/layout/layout.go index 3ace2667..f5160893 100644 --- a/layout/layout.go +++ b/layout/layout.go @@ -4,9 +4,9 @@ package layout import ( "image" - "time" "gioui.org/io/event" + "gioui.org/io/system" "gioui.org/op" "gioui.org/unit" ) @@ -53,20 +53,11 @@ type Context struct { // operation. Dimensions Dimensions - Config + system.Config event.Queue *op.Ops } -// Config define the essential properties of -// the environment. -type Config interface { - // Now returns the current animation time. - Now() time.Time - - unit.Converter -} - const ( Start Alignment = iota End @@ -104,7 +95,7 @@ func (s *Context) Layout(cs Constraints, w Widget) Dimensions { // Reset the context. The constraints' minimum and maximum values are // set to the size. -func (c *Context) Reset(cfg Config, size image.Point) { +func (c *Context) Reset(cfg system.Config, size image.Point) { c.Constraints = RigidConstraints(size) c.Dimensions = Dimensions{} c.Config = cfg