diff --git a/app/internal/windows/windows.go b/app/internal/windows/windows.go index d79a650d6..3c99d3d0d 100644 --- a/app/internal/windows/windows.go +++ b/app/internal/windows/windows.go @@ -243,6 +243,7 @@ const ( WM_MOUSEMOVE = 0x0200 WM_MOUSEWHEEL = 0x020A WM_MOUSEHWHEEL = 0x020E + WM_NCACTIVATE = 0x0086 WM_NCHITTEST = 0x0084 WM_PAINT = 0x000F WM_QUIT = 0x0012 diff --git a/app/os_android.go b/app/os_android.go index c850e41dd..df01a1b4a 100644 --- a/app/os_android.go +++ b/app/os_android.go @@ -552,7 +552,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 >= system.StageRunning { + if w.stage > system.StagePaused { w.draw(env, true) } } @@ -563,7 +563,7 @@ func Java_org_gioui_GioView_onFrameCallback(env *C.JNIEnv, class C.jclass, view if !exist { return } - if w.stage < system.StageRunning { + if w.stage == system.StagePaused { return } if w.animating { @@ -596,7 +596,7 @@ func Java_org_gioui_GioView_onWindowInsets(env *C.JNIEnv, class C.jclass, view C left: int(left), right: int(right), } - if w.stage >= system.StageRunning { + if w.stage > system.StagePaused { w.draw(env, true) } } diff --git a/app/os_macos.go b/app/os_macos.go index 0d50ea47a..b2f72f2e9 100644 --- a/app/os_macos.go +++ b/app/os_macos.go @@ -561,6 +561,13 @@ func gio_onDraw(view C.CFTypeRef) { func gio_onFocus(view C.CFTypeRef, focus C.int) { w := mustView(view) w.w.Event(key.FocusEvent{Focus: focus == 1}) + if w.stage > system.StagePaused { + if focus == 0 { + w.setStage(system.StageInactive) + } else { + w.setStage(system.StageRunning) + } + } w.SetCursor(w.cursor) } diff --git a/app/os_windows.go b/app/os_windows.go index 0a49f94ef..add8ea65e 100644 --- a/app/os_windows.go +++ b/app/os_windows.go @@ -283,6 +283,14 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr case windows.WM_KILLFOCUS: w.focused = false w.w.Event(key.FocusEvent{Focus: false}) + case windows.WM_NCACTIVATE: + if w.stage > system.StagePaused { + if wParam == windows.TRUE { + w.setStage(system.StageRunning) + } else { + w.setStage(system.StageInactive) + } + } case windows.WM_NCHITTEST: if w.config.Decorated { // Let the system handle it. diff --git a/app/window.go b/app/window.go index f18d71e2f..5f2ed7116 100644 --- a/app/window.go +++ b/app/window.go @@ -426,7 +426,7 @@ func (w *Window) driverDefer(f func(d driver)) { func (w *Window) updateAnimation(d driver) { animate := false - if w.stage >= system.StageRunning && w.hasNextFrame { + if w.stage > system.StagePaused && w.hasNextFrame { if dt := time.Until(w.nextFrame); dt <= 0 { animate = true } else { @@ -826,7 +826,7 @@ func (w *Window) processEvent(d driver, e event.Event) bool { } switch e2 := e.(type) { case system.StageEvent: - if e2.Stage < system.StageRunning { + if w.stage == system.StagePaused { if w.gpu != nil { w.ctx.Lock() w.gpu.Release() @@ -842,7 +842,7 @@ func (w *Window) processEvent(d driver, e event.Event) bool { if e2.Size == (image.Point{}) { panic(errors.New("internal error: zero-sized Draw")) } - if w.stage < system.StageRunning { + if w.stage == system.StagePaused { // No drawing if not visible. break } diff --git a/io/system/system.go b/io/system/system.go index 49b9c4a30..f24eef57f 100644 --- a/io/system/system.go +++ b/io/system/system.go @@ -59,17 +59,24 @@ type StageEvent struct { type Stage uint8 const ( - // StagePaused is the Stage for inactive Windows. - // Inactive Windows don't receive FrameEvents. + // StagePaused is the stage for windows that have no on-screen representation. + // Paused windows don't receive FrameEvents. StagePaused Stage = iota - // StateRunning is for active Windows. + // StageInactive is the stage for windows that are visible, but not active. + // Inactive windows receive FrameEvents. + StageInactive + // StageRunning is for active and visible Windows. + // Running windows receive FrameEvents. 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: