io/system,app: [API] move DestroyEvent, StageEvent, Stage to package app

They're only useful at the top-level event loop in combination with an
app.Window.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2023-10-12 18:15:17 -05:00
parent d7636ea273
commit d2085ab7c5
9 changed files with 64 additions and 66 deletions
+10 -10
View File
@@ -158,7 +158,7 @@ type window struct {
fontScale float32 fontScale float32
insets pixelInsets insets pixelInsets
stage system.Stage stage Stage
started bool started bool
animating bool animating bool
@@ -503,7 +503,7 @@ func Java_org_gioui_GioView_onCreateView(env *C.JNIEnv, class C.jclass, view C.j
w.loadConfig(env, class) w.loadConfig(env, class)
w.Configure(wopts.options) w.Configure(wopts.options)
w.SetInputHint(key.HintAny) w.SetInputHint(key.HintAny)
w.setStage(system.StagePaused) w.setStage(StagePaused)
w.callbacks.Event(ViewEvent{View: uintptr(view)}) w.callbacks.Event(ViewEvent{View: uintptr(view)})
return C.jlong(w.handle) return C.jlong(w.handle)
} }
@@ -518,7 +518,7 @@ func Java_org_gioui_GioView_onDestroyView(env *C.JNIEnv, class C.jclass, handle
func Java_org_gioui_GioView_onStopView(env *C.JNIEnv, class C.jclass, handle C.jlong) { func Java_org_gioui_GioView_onStopView(env *C.JNIEnv, class C.jclass, handle C.jlong) {
w := cgo.Handle(handle).Value().(*window) w := cgo.Handle(handle).Value().(*window)
w.started = false w.started = false
w.setStage(system.StagePaused) w.setStage(StagePaused)
} }
//export Java_org_gioui_GioView_onStartView //export Java_org_gioui_GioView_onStartView
@@ -534,7 +534,7 @@ func Java_org_gioui_GioView_onStartView(env *C.JNIEnv, class C.jclass, handle C.
func Java_org_gioui_GioView_onSurfaceDestroyed(env *C.JNIEnv, class C.jclass, handle C.jlong) { func Java_org_gioui_GioView_onSurfaceDestroyed(env *C.JNIEnv, class C.jclass, handle C.jlong) {
w := cgo.Handle(handle).Value().(*window) w := cgo.Handle(handle).Value().(*window)
w.win = nil w.win = nil
w.setStage(system.StagePaused) w.setStage(StagePaused)
} }
//export Java_org_gioui_GioView_onSurfaceChanged //export Java_org_gioui_GioView_onSurfaceChanged
@@ -556,7 +556,7 @@ func Java_org_gioui_GioView_onLowMemory(env *C.JNIEnv, class C.jclass) {
func Java_org_gioui_GioView_onConfigurationChanged(env *C.JNIEnv, class C.jclass, view C.jlong) { func Java_org_gioui_GioView_onConfigurationChanged(env *C.JNIEnv, class C.jclass, view C.jlong) {
w := cgo.Handle(view).Value().(*window) w := cgo.Handle(view).Value().(*window)
w.loadConfig(env, class) w.loadConfig(env, class)
if w.stage >= system.StageInactive { if w.stage >= StageInactive {
w.draw(env, true) w.draw(env, true)
} }
} }
@@ -567,7 +567,7 @@ func Java_org_gioui_GioView_onFrameCallback(env *C.JNIEnv, class C.jclass, view
if !exist { if !exist {
return return
} }
if w.stage < system.StageInactive { if w.stage < StageInactive {
return return
} }
if w.animating { if w.animating {
@@ -600,7 +600,7 @@ func Java_org_gioui_GioView_onWindowInsets(env *C.JNIEnv, class C.jclass, view C
left: int(left), left: int(left),
right: int(right), right: int(right),
} }
if w.stage >= system.StageInactive { if w.stage >= StageInactive {
w.draw(env, true) w.draw(env, true)
} }
} }
@@ -779,16 +779,16 @@ func (w *window) setVisible(env *C.JNIEnv) {
if width == 0 || height == 0 { if width == 0 || height == 0 {
return return
} }
w.setStage(system.StageRunning) w.setStage(StageRunning)
w.draw(env, true) w.draw(env, true)
} }
func (w *window) setStage(stage system.Stage) { func (w *window) setStage(stage Stage) {
if stage == w.stage { if stage == w.stage {
return return
} }
w.stage = stage w.stage = stage
w.callbacks.Event(system.StageEvent{stage}) w.callbacks.Event(StageEvent{stage})
} }
func (w *window) setVisual(visID int) error { func (w *window) setVisual(visID int) error {
+4 -4
View File
@@ -131,7 +131,7 @@ func onCreate(view, controller C.CFTypeRef) {
w.w.SetDriver(w) w.w.SetDriver(w)
views[view] = w views[view] = w
w.Configure(wopts.options) w.Configure(wopts.options)
w.w.Event(system.StageEvent{Stage: system.StagePaused}) w.w.Event(StageEvent{Stage: StagePaused})
w.w.Event(ViewEvent{ViewController: uintptr(controller)}) w.w.Event(ViewEvent{ViewController: uintptr(controller)})
} }
@@ -149,7 +149,7 @@ func (w *window) draw(sync bool) {
wasVisible := w.visible wasVisible := w.visible
w.visible = true w.visible = true
if !wasVisible { if !wasVisible {
w.w.Event(system.StageEvent{Stage: system.StageRunning}) w.w.Event(StageEvent{Stage: StageRunning})
} }
const inchPrDp = 1.0 / 163 const inchPrDp = 1.0 / 163
m := unit.Metric{ m := unit.Metric{
@@ -180,7 +180,7 @@ func (w *window) draw(sync bool) {
func onStop(view C.CFTypeRef) { func onStop(view C.CFTypeRef) {
w := views[view] w := views[view]
w.visible = false w.visible = false
w.w.Event(system.StageEvent{Stage: system.StagePaused}) w.w.Event(StageEvent{Stage: StagePaused})
} }
//export onDestroy //export onDestroy
@@ -188,7 +188,7 @@ func onDestroy(view C.CFTypeRef) {
w := views[view] w := views[view]
delete(views, view) delete(views, view)
w.w.Event(ViewEvent{}) w.w.Event(ViewEvent{})
w.w.Event(system.DestroyEvent{}) w.w.Event(DestroyEvent{})
w.displayLink.Close() w.displayLink.Close()
w.view = 0 w.view = 0
} }
+4 -4
View File
@@ -120,7 +120,7 @@ func newWindow(win *callbacks, options []Option) error {
w.Configure(options) w.Configure(options)
w.blur() w.blur()
w.w.Event(ViewEvent{Element: cont}) w.w.Event(ViewEvent{Element: cont})
w.w.Event(system.StageEvent{Stage: system.StageRunning}) w.w.Event(StageEvent{Stage: StageRunning})
w.resize() w.resize()
w.draw(true) w.draw(true)
for { for {
@@ -213,12 +213,12 @@ func (w *window) addEventListeners() {
return w.browserHistory.Call("back") return w.browserHistory.Call("back")
}) })
w.addEventListener(w.document, "visibilitychange", func(this js.Value, args []js.Value) interface{} { w.addEventListener(w.document, "visibilitychange", func(this js.Value, args []js.Value) interface{} {
ev := system.StageEvent{} ev := StageEvent{}
switch w.document.Get("visibilityState").String() { switch w.document.Get("visibilityState").String() {
case "hidden", "prerender", "unloaded": case "hidden", "prerender", "unloaded":
ev.Stage = system.StagePaused ev.Stage = StagePaused
default: default:
ev.Stage = system.StageRunning ev.Stage = StageRunning
} }
w.w.Event(ev) w.w.Event(ev)
return nil return nil
+12 -12
View File
@@ -249,7 +249,7 @@ type ViewEvent struct {
type window struct { type window struct {
view C.CFTypeRef view C.CFTypeRef
w *callbacks w *callbacks
stage system.Stage stage Stage
displayLink *displayLink displayLink *displayLink
// redraw is a single entry channel for making sure only one // redraw is a single entry channel for making sure only one
// display link redraw request is in flight. // display link redraw request is in flight.
@@ -488,12 +488,12 @@ func (w *window) runOnMain(f func()) {
}) })
} }
func (w *window) setStage(stage system.Stage) { func (w *window) setStage(stage Stage) {
if stage == w.stage { if stage == w.stage {
return return
} }
w.stage = stage w.stage = stage
w.w.Event(system.StageEvent{Stage: stage}) w.w.Event(StageEvent{Stage: stage})
} }
//export gio_onKeys //export gio_onKeys
@@ -583,11 +583,11 @@ func gio_onDraw(view C.CFTypeRef) {
func gio_onFocus(view C.CFTypeRef, focus C.int) { func gio_onFocus(view C.CFTypeRef, focus C.int) {
w := mustView(view) w := mustView(view)
w.w.Event(key.FocusEvent{Focus: focus == 1}) w.w.Event(key.FocusEvent{Focus: focus == 1})
if w.stage >= system.StageInactive { if w.stage >= StageInactive {
if focus == 0 { if focus == 0 {
w.setStage(system.StageInactive) w.setStage(StageInactive)
} else { } else {
w.setStage(system.StageRunning) w.setStage(StageRunning)
} }
} }
w.SetCursor(w.cursor) w.SetCursor(w.cursor)
@@ -782,7 +782,7 @@ func (w *window) draw() {
return return
} }
cfg := configFor(w.scale) cfg := configFor(w.scale)
w.setStage(system.StageRunning) w.setStage(StageRunning)
w.w.Event(frameEvent{ w.w.Event(frameEvent{
FrameEvent: FrameEvent{ FrameEvent: FrameEvent{
Now: time.Now(), Now: time.Now(),
@@ -804,7 +804,7 @@ func configFor(scale float32) unit.Metric {
func gio_onClose(view C.CFTypeRef) { func gio_onClose(view C.CFTypeRef) {
w := mustView(view) w := mustView(view)
w.w.Event(ViewEvent{}) w.w.Event(ViewEvent{})
w.w.Event(system.DestroyEvent{}) w.w.Event(DestroyEvent{})
w.displayLink.Close() w.displayLink.Close()
w.displayLink = nil w.displayLink = nil
deleteView(view) deleteView(view)
@@ -815,13 +815,13 @@ func gio_onClose(view C.CFTypeRef) {
//export gio_onHide //export gio_onHide
func gio_onHide(view C.CFTypeRef) { func gio_onHide(view C.CFTypeRef) {
w := mustView(view) w := mustView(view)
w.setStage(system.StagePaused) w.setStage(StagePaused)
} }
//export gio_onShow //export gio_onShow
func gio_onShow(view C.CFTypeRef) { func gio_onShow(view C.CFTypeRef) {
w := mustView(view) w := mustView(view)
w.setStage(system.StageRunning) w.setStage(StageRunning)
} }
//export gio_onFullscreen //export gio_onFullscreen
@@ -841,14 +841,14 @@ func gio_onWindowed(view C.CFTypeRef) {
//export gio_onAppHide //export gio_onAppHide
func gio_onAppHide() { func gio_onAppHide() {
for _, w := range viewMap { for _, w := range viewMap {
w.setStage(system.StagePaused) w.setStage(StagePaused)
} }
} }
//export gio_onAppShow //export gio_onAppShow
func gio_onAppShow() { func gio_onAppShow() {
for _, w := range viewMap { for _, w := range viewMap {
w.setStage(system.StageRunning) w.setStage(StageRunning)
} }
} }
+7 -7
View File
@@ -194,7 +194,7 @@ type window struct {
dir f32.Point dir f32.Point
} }
stage system.Stage stage Stage
dead bool dead bool
lastFrameCallback *C.struct_wl_callback lastFrameCallback *C.struct_wl_callback
@@ -277,7 +277,7 @@ func newWLWindow(callbacks *callbacks, options []Option) error {
err := w.loop() err := w.loop()
w.w.Event(WaylandViewEvent{}) w.w.Event(WaylandViewEvent{})
w.w.Event(system.DestroyEvent{Err: err}) w.w.Event(DestroyEvent{Err: err})
}() }()
return nil return nil
} }
@@ -551,7 +551,7 @@ func gio_onXdgSurfaceConfigure(data unsafe.Pointer, wmSurf *C.struct_xdg_surface
w.serial = serial w.serial = serial
w.redraw = true w.redraw = true
C.xdg_surface_ack_configure(wmSurf, serial) C.xdg_surface_ack_configure(wmSurf, serial)
w.setStage(system.StageRunning) w.setStage(StageRunning)
} }
//export gio_onToplevelClose //export gio_onToplevelClose
@@ -1677,9 +1677,9 @@ func (w *window) updateOutputs() {
w.redraw = true w.redraw = true
} }
if !found { if !found {
w.setStage(system.StagePaused) w.setStage(StagePaused)
} else { } else {
w.setStage(system.StageRunning) w.setStage(StageRunning)
w.redraw = true w.redraw = true
} }
} }
@@ -1725,12 +1725,12 @@ func (w *window) draw() {
}) })
} }
func (w *window) setStage(s system.Stage) { func (w *window) setStage(s Stage) {
if s == w.stage { if s == w.stage {
return return
} }
w.stage = s w.stage = s
w.w.Event(system.StageEvent{Stage: s}) w.w.Event(StageEvent{Stage: s})
} }
func (w *window) display() *C.struct_wl_display { func (w *window) display() *C.struct_wl_display {
+10 -10
View File
@@ -37,7 +37,7 @@ type window struct {
hwnd syscall.Handle hwnd syscall.Handle
hdc syscall.Handle hdc syscall.Handle
w *callbacks w *callbacks
stage system.Stage stage Stage
pointerBtns pointer.Buttons pointerBtns pointer.Buttons
// cursorIn tracks whether the cursor was inside the window according // cursorIn tracks whether the cursor was inside the window according
@@ -269,11 +269,11 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr
w.focused = false w.focused = false
w.w.Event(key.FocusEvent{Focus: false}) w.w.Event(key.FocusEvent{Focus: false})
case windows.WM_NCACTIVATE: case windows.WM_NCACTIVATE:
if w.stage >= system.StageInactive { if w.stage >= StageInactive {
if wParam == windows.TRUE { if wParam == windows.TRUE {
w.setStage(system.StageRunning) w.setStage(StageRunning)
} else { } else {
w.setStage(system.StageInactive) w.setStage(StageInactive)
} }
} }
case windows.WM_NCHITTEST: case windows.WM_NCHITTEST:
@@ -302,7 +302,7 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr
w.scrollEvent(wParam, lParam, true, getModifiers()) w.scrollEvent(wParam, lParam, true, getModifiers())
case windows.WM_DESTROY: case windows.WM_DESTROY:
w.w.Event(ViewEvent{}) w.w.Event(ViewEvent{})
w.w.Event(system.DestroyEvent{}) w.w.Event(DestroyEvent{})
if w.hdc != 0 { if w.hdc != 0 {
windows.ReleaseDC(w.hdc) windows.ReleaseDC(w.hdc)
w.hdc = 0 w.hdc = 0
@@ -339,15 +339,15 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr
switch wParam { switch wParam {
case windows.SIZE_MINIMIZED: case windows.SIZE_MINIMIZED:
w.config.Mode = Minimized w.config.Mode = Minimized
w.setStage(system.StagePaused) w.setStage(StagePaused)
case windows.SIZE_MAXIMIZED: case windows.SIZE_MAXIMIZED:
w.config.Mode = Maximized w.config.Mode = Maximized
w.setStage(system.StageRunning) w.setStage(StageRunning)
case windows.SIZE_RESTORED: case windows.SIZE_RESTORED:
if w.config.Mode != Fullscreen { if w.config.Mode != Fullscreen {
w.config.Mode = Windowed w.config.Mode = Windowed
} }
w.setStage(system.StageRunning) w.setStage(StageRunning)
} }
case windows.WM_GETMINMAXINFO: case windows.WM_GETMINMAXINFO:
mm := (*windows.MinMaxInfo)(unsafe.Pointer(uintptr(lParam))) mm := (*windows.MinMaxInfo)(unsafe.Pointer(uintptr(lParam)))
@@ -608,10 +608,10 @@ func (w *window) Wakeup() {
} }
} }
func (w *window) setStage(s system.Stage) { func (w *window) setStage(s Stage) {
if s != w.stage { if s != w.stage {
w.stage = s w.stage = s
w.w.Event(system.StageEvent{Stage: s}) w.w.Event(StageEvent{Stage: s})
} }
} }
+5 -5
View File
@@ -93,7 +93,7 @@ type x11Window struct {
// _NET_WM_STATE_MAXIMIZED_VERT // _NET_WM_STATE_MAXIMIZED_VERT
wmStateMaximizedVert C.Atom wmStateMaximizedVert C.Atom
} }
stage system.Stage stage Stage
metric unit.Metric metric unit.Metric
notify struct { notify struct {
read, write int read, write int
@@ -395,12 +395,12 @@ func (w *x11Window) window() (C.Window, int, int) {
return w.xw, w.config.Size.X, w.config.Size.Y return w.xw, w.config.Size.X, w.config.Size.Y
} }
func (w *x11Window) setStage(s system.Stage) { func (w *x11Window) setStage(s Stage) {
if s == w.stage { if s == w.stage {
return return
} }
w.stage = s w.stage = s
w.w.Event(system.StageEvent{Stage: s}) w.w.Event(StageEvent{Stage: s})
} }
func (w *x11Window) loop() { func (w *x11Window) loop() {
@@ -837,10 +837,10 @@ func newX11Window(gioWin *callbacks, options []Option) error {
C.XMapWindow(dpy, win) C.XMapWindow(dpy, win)
w.Configure(options) w.Configure(options)
w.w.Event(X11ViewEvent{Display: unsafe.Pointer(dpy), Window: uintptr(win)}) w.w.Event(X11ViewEvent{Display: unsafe.Pointer(dpy), Window: uintptr(win)})
w.setStage(system.StageRunning) w.setStage(StageRunning)
w.loop() w.loop()
w.w.Event(X11ViewEvent{}) w.w.Event(X11ViewEvent{})
w.w.Event(system.DestroyEvent{Err: nil}) w.w.Event(DestroyEvent{Err: nil})
w.destroy() w.destroy()
}() }()
return nil return nil
+1 -3
View File
@@ -1,8 +1,6 @@
// SPDX-License-Identifier: Unlicense OR MIT // SPDX-License-Identifier: Unlicense OR MIT
// Package system contains events usually handled at the top-level package app
// program level.
package system
// DestroyEvent is the last event sent through // DestroyEvent is the last event sent through
// a window event channel. // a window event channel.
+11 -11
View File
@@ -67,7 +67,7 @@ type Window struct {
frameAck chan struct{} frameAck chan struct{}
destroy chan struct{} destroy chan struct{}
stage system.Stage stage Stage
animating bool animating bool
hasNextFrame bool hasNextFrame bool
nextFrame time.Time nextFrame time.Time
@@ -374,8 +374,8 @@ func (w *Window) Option(opts ...Option) {
// Run f in the same thread as the native window event loop, and wait for f to // Run f in the same thread as the native window event loop, and wait for f to
// return or the window to close. Run is guaranteed not to deadlock if it is // return or the window to close. Run is guaranteed not to deadlock if it is
// invoked during the handling of a ViewEvent, system.FrameEvent, // invoked during the handling of a ViewEvent, FrameEvent,
// system.StageEvent; call Run in a separate goroutine to avoid deadlock in all // StageEvent; call Run in a separate goroutine to avoid deadlock in all
// other cases. // other cases.
// //
// Note that most programs should not call Run; configuring a Window with // Note that most programs should not call Run; configuring a Window with
@@ -404,7 +404,7 @@ func (w *Window) driverDefer(f func(d driver)) {
func (w *Window) updateAnimation(d driver) { func (w *Window) updateAnimation(d driver) {
animate := false animate := false
if w.stage >= system.StageInactive && w.hasNextFrame { if w.stage >= StageInactive && w.hasNextFrame {
if dt := time.Until(w.nextFrame); dt <= 0 { if dt := time.Until(w.nextFrame); dt <= 0 {
animate = true animate = true
} else { } else {
@@ -801,8 +801,8 @@ func (w *Window) processEvent(d driver, e event.Event) bool {
default: default:
} }
switch e2 := e.(type) { switch e2 := e.(type) {
case system.StageEvent: case StageEvent:
if e2.Stage < system.StageInactive { if e2.Stage < StageInactive {
if w.gpu != nil { if w.gpu != nil {
w.ctx.Lock() w.ctx.Lock()
w.gpu.Release() w.gpu.Release()
@@ -818,7 +818,7 @@ func (w *Window) processEvent(d driver, e event.Event) bool {
if e2.Size == (image.Point{}) { if e2.Size == (image.Point{}) {
panic(errors.New("internal error: zero-sized Draw")) panic(errors.New("internal error: zero-sized Draw"))
} }
if w.stage < system.StageInactive { if w.stage < StageInactive {
// No drawing if not visible. // No drawing if not visible.
break break
} }
@@ -862,13 +862,13 @@ func (w *Window) processEvent(d driver, e event.Event) bool {
deco.Add(wrapper) deco.Add(wrapper)
if err := w.validateAndProcess(d, viewSize, e2.Sync, wrapper, signal); err != nil { if err := w.validateAndProcess(d, viewSize, e2.Sync, wrapper, signal); err != nil {
w.destroyGPU() w.destroyGPU()
w.out <- system.DestroyEvent{Err: err} w.out <- DestroyEvent{Err: err}
close(w.destroy) close(w.destroy)
break break
} }
w.processFrame(d) w.processFrame(d)
w.updateCursor(d) w.updateCursor(d)
case system.DestroyEvent: case DestroyEvent:
w.destroyGPU() w.destroyGPU()
w.out <- e2 w.out <- e2
close(w.destroy) close(w.destroy)
@@ -920,7 +920,7 @@ func (w *Window) processEvent(d driver, e event.Event) bool {
} }
// NextEvent blocks until an event is received from the window, such as // NextEvent blocks until an event is received from the window, such as
// [io/system.FrameEvent]. It blocks forever if called after [io/system.DestroyEvent] // [FrameEvent]. It blocks forever if called after [DestroyEvent]
// has been returned. // has been returned.
func (w *Window) NextEvent() event.Event { func (w *Window) NextEvent() event.Event {
state := &w.eventState state := &w.eventState
@@ -928,7 +928,7 @@ func (w *Window) NextEvent() event.Event {
state.created = true state.created = true
if err := newWindow(&w.callbacks, state.initialOpts); err != nil { if err := newWindow(&w.callbacks, state.initialOpts); err != nil {
close(w.destroy) close(w.destroy)
return system.DestroyEvent{Err: err} return DestroyEvent{Err: err}
} }
} }
for { for {