From 90688fdd175f2a535382abd77df8663231b862b2 Mon Sep 17 00:00:00 2001 From: Inkeliz Date: Sat, 20 Aug 2022 17:30:50 +0100 Subject: [PATCH] app,io/system: [API] add StageInactive when window is not in focus Now, Gio will send one system.StageEvent with system.StageInactive when the window is not active. It is implemented on macOS and Windows. This change is not fully backward compatible, if your code compares the Stage (`stage < system.StageRunning`), you need to consider the new system.StageInactive. Signed-off-by: inkeliz --- app/internal/windows/windows.go | 1 + app/os_android.go | 6 +++--- app/os_macos.go | 7 +++++++ app/os_windows.go | 8 ++++++++ app/window.go | 6 +++--- io/system/system.go | 13 ++++++++++--- 6 files changed, 32 insertions(+), 9 deletions(-) diff --git a/app/internal/windows/windows.go b/app/internal/windows/windows.go index d79a650d..3c99d3d0 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 c850e41d..81071aa1 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.StageInactive { 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.StageInactive { 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.StageInactive { w.draw(env, true) } } diff --git a/app/os_macos.go b/app/os_macos.go index 0d50ea47..d067e335 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.StageInactive { + 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 0a49f94e..21a6ab4e 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.StageInactive { + 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 b6c36060..dac0b9e6 100644 --- a/app/window.go +++ b/app/window.go @@ -429,7 +429,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.StageInactive && w.hasNextFrame { if dt := time.Until(w.nextFrame); dt <= 0 { animate = true } else { @@ -829,7 +829,7 @@ func (w *Window) processEvent(d driver, e event.Event) bool { } switch e2 := e.(type) { case system.StageEvent: - if e2.Stage < system.StageRunning { + if e2.Stage < system.StageInactive { if w.gpu != nil { w.ctx.Lock() w.gpu.Release() @@ -845,7 +845,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.StageInactive { // No drawing if not visible. break } diff --git a/io/system/system.go b/io/system/system.go index 49b9c4a3..7dc4a0fa 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 FrameEvent. StagePaused Stage = iota - // StateRunning is for active Windows. + // StageInactive is the stage for windows that are visible, but not active. + // Inactive windows receive FrameEvent. + StageInactive + // StageRunning is for active and visible Windows. + // Running windows receive FrameEvent. 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: