app: [API] remove StageEvent and Stage

StageEvent served only redundant purposes:

- To detect whether the window has focus. That is covered by
  key.FocusEvent.
- To detect whether the window is currently visible. That is covered by
  the absence or presence of FrameEvents.
- To detect when the window native handle is valid. That is
  covered by ViewEvent.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2023-12-15 16:45:02 -06:00
parent f3fc0d62b8
commit d58d386b9b
9 changed files with 41 additions and 162 deletions
+9 -21
View File
@@ -161,7 +161,7 @@ type window struct {
fontScale float32
insets pixelInsets
stage Stage
visible bool
started bool
animating bool
@@ -509,11 +509,11 @@ func Java_org_gioui_GioView_onCreateView(env *C.JNIEnv, class C.jclass, view C.j
w.detach(env)
}
w.view = view
w.visible = false
w.handle = cgo.NewHandle(w)
w.loadConfig(env, class)
w.setConfig(env, cnf)
w.SetInputHint(w.inputHint)
w.setStage(StagePaused)
w.processEvent(AndroidViewEvent{View: uintptr(view)})
return C.jlong(w.handle)
}
@@ -528,7 +528,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) {
w := cgo.Handle(handle).Value().(*window)
w.started = false
w.setStage(StagePaused)
w.visible = false
}
//export Java_org_gioui_GioView_onStartView
@@ -544,7 +544,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) {
w := cgo.Handle(handle).Value().(*window)
w.win = nil
w.setStage(StagePaused)
w.visible = false
}
//export Java_org_gioui_GioView_onSurfaceChanged
@@ -566,9 +566,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) {
w := cgo.Handle(view).Value().(*window)
w.loadConfig(env, class)
if w.stage >= StageInactive {
w.draw(env, true)
}
}
//export Java_org_gioui_GioView_onFrameCallback
@@ -577,10 +575,7 @@ func Java_org_gioui_GioView_onFrameCallback(env *C.JNIEnv, class C.jclass, view
if !exist {
return
}
if w.stage < StageInactive {
return
}
if w.animating {
if w.visible && w.animating {
w.draw(env, false)
callVoidMethod(env, w.view, gioView.postFrameCallback)
}
@@ -610,9 +605,7 @@ func Java_org_gioui_GioView_onWindowInsets(env *C.JNIEnv, class C.jclass, view C
left: int(left),
right: int(right),
}
if w.stage >= StageInactive {
w.draw(env, true)
}
}
//export Java_org_gioui_GioView_initializeAccessibilityNodeInfo
@@ -816,18 +809,10 @@ func (w *window) setVisible(env *C.JNIEnv) {
if width == 0 || height == 0 {
return
}
w.setStage(StageRunning)
w.visible = true
w.draw(env, true)
}
func (w *window) setStage(stage Stage) {
if stage == w.stage {
return
}
w.stage = stage
w.processEvent(StageEvent{stage})
}
func (w *window) setVisual(visID int) error {
if C.ANativeWindow_setBuffersGeometry(w.win, 0, 0, C.int32_t(visID)) != 0 {
return errors.New("ANativeWindow_setBuffersGeometry failed")
@@ -864,6 +849,9 @@ func (w *window) SetAnimating(anim bool) {
}
func (w *window) draw(env *C.JNIEnv, sync bool) {
if !w.visible {
return
}
size := image.Pt(int(C.ANativeWindow_getWidth(w.win)), int(C.ANativeWindow_getHeight(w.win)))
if size != w.config.Size {
w.config.Size = size
-3
View File
@@ -138,7 +138,6 @@ func onCreate(view, controller C.CFTypeRef) {
w.displayLink = dl
C.gio_viewSetHandle(view, C.uintptr_t(cgo.NewHandle(w)))
w.Configure(wopts.options)
w.ProcessEvent(StageEvent{Stage: StageRunning})
w.ProcessEvent(UIKitViewEvent{ViewController: uintptr(controller)})
}
@@ -189,14 +188,12 @@ func (w *window) draw(sync bool) {
func onStop(h C.uintptr_t) {
w := viewFor(h)
w.hidden = true
w.ProcessEvent(StageEvent{Stage: StagePaused})
}
//export onStart
func onStart(h C.uintptr_t) {
w := viewFor(h)
w.hidden = false
w.ProcessEvent(StageEvent{Stage: StageRunning})
w.draw(true)
}
-12
View File
@@ -115,7 +115,6 @@ func newWindow(win *callbacks, options []Option) {
w.Configure(options)
w.blur()
w.processEvent(JSViewEvent{Element: cont})
w.processEvent(StageEvent{Stage: StageRunning})
w.resize()
w.draw(true)
}
@@ -195,17 +194,6 @@ func (w *window) addEventListeners() {
}
return w.browserHistory.Call("back")
})
w.addEventListener(w.document, "visibilitychange", func(this js.Value, args []js.Value) interface{} {
ev := StageEvent{}
switch w.document.Get("visibilityState").String() {
case "hidden", "prerender", "unloaded":
ev.Stage = StagePaused
default:
ev.Stage = StageRunning
}
w.processEvent(ev)
return nil
})
w.addEventListener(w.cnv, "mousemove", func(this js.Value, args []js.Value) interface{} {
w.pointerEvent(pointer.Move, 0, 0, args[0])
return nil
+15 -21
View File
@@ -309,7 +309,8 @@ type AppKitViewEvent struct {
type window struct {
view C.CFTypeRef
w *callbacks
stage Stage
anim bool
visible bool
displayLink *displayLink
// redraw is a single entry channel for making sure only one
// display link redraw request is in flight.
@@ -507,7 +508,8 @@ func (w *window) ShowTextInput(show bool) {}
func (w *window) SetInputHint(_ key.InputHint) {}
func (w *window) SetAnimating(anim bool) {
if anim {
w.anim = anim
if w.anim && w.visible {
w.displayLink.Start()
} else {
w.displayLink.Stop()
@@ -524,14 +526,6 @@ func (w *window) runOnMain(f func()) {
})
}
func (w *window) setStage(stage Stage) {
if stage == w.stage {
return
}
w.stage = stage
w.ProcessEvent(StageEvent{Stage: stage})
}
//export gio_onKeys
func gio_onKeys(h C.uintptr_t, cstr C.CFTypeRef, ti C.double, mods C.NSUInteger, keyDown C.bool) {
str := nsstringToString(cstr)
@@ -619,13 +613,6 @@ func gio_onDraw(h C.uintptr_t) {
func gio_onFocus(h C.uintptr_t, focus C.int) {
w := windowFor(h)
w.ProcessEvent(key.FocusEvent{Focus: focus == 1})
if w.stage >= StageInactive {
if focus == 0 {
w.setStage(StageInactive)
} else {
w.setStage(StageRunning)
}
}
w.SetCursor(w.cursor)
}
@@ -804,6 +791,10 @@ func (w *window) draw() {
case <-w.redraw:
default:
}
w.visible = true
if w.anim {
w.SetAnimating(w.anim)
}
w.scale = float32(C.getViewBackingScale(w.view))
wf, hf := float32(C.viewWidth(w.view)), float32(C.viewHeight(w.view))
sz := image.Point{
@@ -818,7 +809,6 @@ func (w *window) draw() {
return
}
cfg := configFor(w.scale)
w.setStage(StageRunning)
w.ProcessEvent(frameEvent{
FrameEvent: FrameEvent{
Now: time.Now(),
@@ -865,7 +855,8 @@ func gio_onAttached(h C.uintptr_t, attached C.int) {
w.ProcessEvent(AppKitViewEvent{View: uintptr(w.view), Layer: uintptr(layer)})
} else {
w.ProcessEvent(AppKitViewEvent{})
w.setStage(StagePaused)
w.visible = false
w.SetAnimating(w.anim)
}
}
@@ -882,13 +873,14 @@ func gio_onDestroy(h C.uintptr_t) {
//export gio_onHide
func gio_onHide(h C.uintptr_t) {
w := windowFor(h)
w.setStage(StagePaused)
w.visible = false
w.SetAnimating(w.anim)
}
//export gio_onShow
func gio_onShow(h C.uintptr_t) {
w := windowFor(h)
w.setStage(StageRunning)
w.draw()
}
//export gio_onFullscreen
@@ -956,7 +948,9 @@ func (w *window) init() error {
return
}
w.runOnMain(func() {
if w.visible {
C.setNeedsDisplay(w.view)
}
})
})
w.displayLink = dl
+6 -14
View File
@@ -199,7 +199,7 @@ type window struct {
dir f32.Point
}
stage Stage
configured bool
lastFrameCallback *C.struct_wl_callback
animating bool
@@ -549,7 +549,7 @@ func gio_onXdgSurfaceConfigure(data unsafe.Pointer, wmSurf *C.struct_xdg_surface
w := callbackLoad(data).(*window)
w.serial = serial
C.xdg_surface_ack_configure(wmSurf, serial)
w.setStage(StageRunning)
w.configured = true
w.draw(true)
}
@@ -1738,10 +1738,7 @@ func (w *window) updateOutputs() {
C.wl_surface_set_buffer_scale(w.surf, C.int32_t(w.scale))
w.draw(true)
}
if !found {
w.setStage(StagePaused)
} else {
w.setStage(StageRunning)
if found {
w.draw(true)
}
}
@@ -1755,6 +1752,9 @@ func (w *window) getConfig() (image.Point, unit.Metric) {
}
func (w *window) draw(sync bool) {
if !w.configured {
return
}
w.flushScroll()
size, cfg := w.getConfig()
if cfg == (unit.Metric{}) {
@@ -1785,14 +1785,6 @@ func (w *window) draw(sync bool) {
})
}
func (w *window) setStage(s Stage) {
if s == w.stage {
return
}
w.stage = s
w.ProcessEvent(StageEvent{Stage: s})
}
func (w *window) display() *C.struct_wl_display {
return w.disp.disp
}
-19
View File
@@ -39,7 +39,6 @@ type window struct {
hwnd syscall.Handle
hdc syscall.Handle
w *callbacks
stage Stage
pointerBtns pointer.Buttons
// cursorIn tracks whether the cursor was inside the window according
@@ -275,14 +274,6 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr
case windows.WM_KILLFOCUS:
w.focused = false
w.ProcessEvent(key.FocusEvent{Focus: false})
case windows.WM_NCACTIVATE:
if w.stage >= StageInactive {
if wParam == windows.TRUE {
w.setStage(StageRunning)
} else {
w.setStage(StageInactive)
}
}
case windows.WM_NCHITTEST:
if w.config.Decorated {
// Let the system handle it.
@@ -348,15 +339,12 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr
switch wParam {
case windows.SIZE_MINIMIZED:
w.config.Mode = Minimized
w.setStage(StagePaused)
case windows.SIZE_MAXIMIZED:
w.config.Mode = Maximized
w.setStage(StageRunning)
case windows.SIZE_RESTORED:
if w.config.Mode != Fullscreen {
w.config.Mode = Windowed
}
w.setStage(StageRunning)
}
case windows.WM_GETMINMAXINFO:
mm := (*windows.MinMaxInfo)(unsafe.Pointer(lParam))
@@ -645,13 +633,6 @@ func (w *window) wakeup() {
}
}
func (w *window) setStage(s Stage) {
if s != w.stage {
w.stage = s
w.ProcessEvent(StageEvent{Stage: s})
}
}
func (w *window) draw(sync bool) {
if w.config.Size.X == 0 || w.config.Size.Y == 0 {
return
-10
View File
@@ -95,7 +95,6 @@ type x11Window struct {
// _NET_WM_STATE_MAXIMIZED_VERT
wmStateMaximizedVert C.Atom
}
stage Stage
metric unit.Metric
notify struct {
read, write int
@@ -437,14 +436,6 @@ func (w *x11Window) window() (C.Window, int, int) {
return w.xw, w.config.Size.X, w.config.Size.Y
}
func (w *x11Window) setStage(s Stage) {
if s == w.stage {
return
}
w.stage = s
w.ProcessEvent(StageEvent{Stage: s})
}
func (w *x11Window) dispatch() {
if w.x == nil {
// Only Invalidate can wake us up.
@@ -879,7 +870,6 @@ func newX11Window(gioWin *callbacks, options []Option) error {
C.XMapWindow(dpy, win)
w.Configure(options)
w.ProcessEvent(X11ViewEvent{Display: unsafe.Pointer(dpy), Window: uintptr(win)})
w.setStage(StageRunning)
return nil
}
-36
View File
@@ -10,40 +10,4 @@ type DestroyEvent struct {
Err error
}
// A StageEvent is generated whenever the stage of a
// Window changes.
type StageEvent struct {
Stage Stage
}
// Stage of a Window.
type Stage uint8
const (
// StagePaused is the stage for windows that have no on-screen representation.
// Paused windows don't receive frames.
StagePaused Stage = iota
// StageInactive is the stage for windows that are visible, but not active.
// Inactive windows receive frames.
StageInactive
// StageRunning is for active and visible Windows.
// Running windows receive frames.
StageRunning
)
// String implements fmt.Stringer.
func (l Stage) String() string {
switch l {
case StagePaused:
return "StagePaused"
case StageInactive:
return "StageInactive"
case StageRunning:
return "StageRunning"
default:
panic("unexpected Stage value")
}
}
func (StageEvent) ImplementsEvent() {}
func (DestroyEvent) ImplementsEvent() {}
+8 -23
View File
@@ -7,6 +7,7 @@ import (
"fmt"
"image"
"image/color"
"reflect"
"runtime"
"sync"
"time"
@@ -53,7 +54,6 @@ type Window struct {
update chan time.Time
}
stage Stage
animating bool
hasNextFrame bool
nextFrame time.Time
@@ -109,7 +109,6 @@ type eventSummary struct {
cfg *ConfigEvent
view *ViewEvent
frame *frameEvent
stage *StageEvent
destroy *DestroyEvent
}
@@ -328,7 +327,7 @@ func (w *Window) updateAnimation() {
return
}
animate := false
if w.stage >= StageInactive && w.hasNextFrame {
if w.hasNextFrame {
if dt := time.Until(w.nextFrame); dt <= 0 {
animate = true
} else {
@@ -566,10 +565,6 @@ func (c *callbacks) nextEvent() (event.Event, bool) {
e := *s.cfg
s.cfg = nil
return e, true
case s.stage != nil:
e := *s.stage
s.stage = nil
return e, true
case s.frame != nil:
e := *s.frame
s.frame = nil
@@ -582,28 +577,12 @@ func (c *callbacks) nextEvent() (event.Event, bool) {
func (w *Window) processEvent(e event.Event) bool {
switch e2 := e.(type) {
case StageEvent:
if e2.Stage < StageInactive {
if w.gpu != nil {
w.ctx.Lock()
w.gpu.Release()
w.gpu = nil
w.ctx.Unlock()
}
}
w.stage = e2.Stage
w.updateAnimation()
w.coalesced.stage = &e2
case wakeupEvent:
w.coalesced.wakeup = true
case frameEvent:
if e2.Size == (image.Point{}) {
panic(errors.New("internal error: zero-sized Draw"))
}
if w.stage < StageInactive {
// No drawing if not visible.
break
}
w.metric = e2.Metric
w.hasNextFrame = false
e2.Frame = w.driver.Frame
@@ -643,6 +622,12 @@ func (w *Window) processEvent(e event.Event) bool {
}
w.coalesced.destroy = &e2
case ViewEvent:
if reflect.ValueOf(e2).IsZero() && w.gpu != nil {
w.ctx.Lock()
w.gpu.Release()
w.gpu = nil
w.ctx.Unlock()
}
w.coalesced.view = &e2
case ConfigEvent:
w.decorations.Config = e2.Config