Skip to content

Commit

Permalink
app,io/system: [API] add StageInactive when window is not in focus
Browse files Browse the repository at this point in the history
Now, Gio will send one system.StageEvent with system.StageInactive when
the window is not active. That is currently implemented to MacOS
and Windows.

This change is not fully backward compatible, if your code compares
the Stage, such as `stage < system.StageRunning`, you need to consider
the new system.StageInactive.

Signed-off-by: Inkeliz <inkeliz@inkeliz.com>
  • Loading branch information
inkeliz committed Aug 20, 2022
1 parent 26e7101 commit a1c7838
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 9 deletions.
1 change: 1 addition & 0 deletions app/internal/windows/windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions app/os_android.go
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,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.IsReceivingFrames() {
w.draw(env, true)
}
}
Expand All @@ -559,7 +559,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.IsReceivingFrames() {
return
}
if w.animating {
Expand Down Expand Up @@ -587,7 +587,7 @@ func Java_org_gioui_GioView_onFocusChange(env *C.JNIEnv, class C.jclass, view C.
func Java_org_gioui_GioView_onWindowInsets(env *C.JNIEnv, class C.jclass, view C.jlong, top, right, bottom, left C.jint) {
w := cgo.Handle(view).Value().(*window)
w.insets = image.Rect(int(left), int(top), int(right), int(bottom))
if w.stage >= system.StageRunning {
if w.stage.IsReceivingFrames() {
w.draw(env, true)
}
}
Expand Down
7 changes: 7 additions & 0 deletions app/os_macos.go
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,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.IsReceivingFrames() {
if focus == 0 {
w.setStage(system.StageInactive)
} else {
w.setStage(system.StageRunning)
}
}
w.SetCursor(w.cursor)
}

Expand Down
8 changes: 8 additions & 0 deletions app/os_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,14 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr
w.w.Event(key.FocusEvent{Focus: true})
case windows.WM_KILLFOCUS:
w.w.Event(key.FocusEvent{Focus: false})
case windows.WM_NCACTIVATE:
if w.stage.IsReceivingFrames() {
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.
Expand Down
6 changes: 3 additions & 3 deletions app/window.go
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,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.IsReceivingFrames() && w.hasNextFrame {
if dt := time.Until(w.nextFrame); dt <= 0 {
animate = true
} else {
Expand Down Expand Up @@ -825,7 +825,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.IsReceivingFrames() {
if w.gpu != nil {
w.ctx.Lock()
w.gpu.Release()
Expand All @@ -841,7 +841,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.IsReceivingFrames() {
// No drawing if not visible.
break
}
Expand Down
19 changes: 16 additions & 3 deletions io/system/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,24 +59,37 @@ 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:
panic("unexpected Stage value")
}
}

// IsReceivingFrames returns true if the window is receiving
// FrameEvent.
func (l Stage) IsReceivingFrames() bool {
return l >= StageInactive
}

func (FrameEvent) ImplementsEvent() {}
func (StageEvent) ImplementsEvent() {}
func (DestroyEvent) ImplementsEvent() {}

0 comments on commit a1c7838

Please sign in to comment.