gio icon indicating copy to clipboard operation
gio copied to clipboard

app,io/system: add FocusEvent

Open inkeliz opened this issue 2 years ago • 4 comments

Now, Gio will notify when window focus changes.

Signed-off-by: Inkeliz [email protected]

inkeliz avatar Jul 25 '22 15:07 inkeliz

Currently, the behavior of "focus" is defined by the OS, which doesn't match very well. On Windows, the "focus" is lost when some children is focused, on MacOS it's not, but there's another event for that case. However, the FocusEvent can be improved once Gio have better support for children windows.

inkeliz avatar Jul 25 '22 16:07 inkeliz

Currently, the behavior of "focus" is defined by the OS, which doesn't match very well. On Windows, the "focus" is lost when some children is focused, on MacOS it's not, but there's another event for that case. However, the FocusEvent can be improved once Gio have better support for children windows.

This difference between macOS and WIndows is fixed by https://github.com/gioui/gio/pull/93, right?

I don't use key.FocusEvent because of the reason mentioned by @whereswaldon. Also, the FocusEvent can work differently from key.FocusEvent.

I force-push to make the behavior differently. Now, the FocusEvent is only triggered when the window loses focus, instead of the keyboard focus. The word "focus" could be changed to "active", or something else.

Thanks for explaining. I agree that it would be useful to know the active state of an app.Window, separate from the focus. However, I'm not sure a separate event is necessary. Why not expand io/system.Stage with a StageInactive and rename StageRunning to StageActive?

eliasnaur avatar Aug 02 '22 15:08 eliasnaur

I initially thought about adding a new Stage, but on https://lists.sr.ht/~eliasnaur/gio/%3C96373f04-28fe-6848-25f4-2d9936aa0522%40gmail.com%3E#%3CCAMAFT9VY22-baCO+OyzM+cGH7ktVU08RvgKQOTrbAtAO91beWg@mail.gmail.com%3E, you mention to add that as a new FocusEventt.

However, I'm not sure how the new Stage will work, because we have some checks: if stage < system.StageRunning:

https://github.com/gioui/gio/blob/b67bef3e0d961e1c04eb4f9f449903a625664d5b/app/window.go#L828-L835


Currently, the Stage is either "Running" or "Inactive":

https://github.com/gioui/gio/blob/b5f12c5f2627dc5d557bb0f8ffc85a1a69258cfa/io/system/system.go#L61-L67

But, in the case of "not in focus" it's both of them, at same time. It's inactive at the perspective of the user, but it's active because it can generate new frames (it still displayed on the screen).

I don't think that it makes sense but maybe we can use 1 << iota +1 and then use StageRunning | StageInactive? So, it's running (gio is generating frames), but it's inactive (the window is not in focus).

inkeliz avatar Aug 04 '22 08:08 inkeliz

I initially thought about adding a new Stage, but on https://lists.sr.ht/~eliasnaur/gio/%3C96373f04-28fe-6848-25f4-2d9936aa0522%40gmail.com%3E#%3CCAMAFT9VY22-baCO+OyzM+cGH7ktVU08RvgKQOTrbAtAO91beWg@mail.gmail.com%3E, you mention to add that as a new FocusEventt.

FocusEvent could work if we can't cram the focused/active state into Stage.

However, I'm not sure how the new Stage will work, because we have some checks: if stage < system.StageRunning:

https://github.com/gioui/gio/blob/b67bef3e0d961e1c04eb4f9f449903a625664d5b/app/window.go#L828-L835

This check (and similar) should change to e2.Stage == system.StagePaused.

Currently, the Stage is either "Running" or "Inactive":

https://github.com/gioui/gio/blob/b5f12c5f2627dc5d557bb0f8ffc85a1a69258cfa/io/system/system.go#L61-L67

But, in the case of "not in focus" it's both of them, at same time. It's inactive at the perspective of the user, but it's active because it can generate new frames (it still displayed on the screen).

I don't think that it makes sense but maybe we can use 1 << iota +1 and then use StageRunning | StageInactive? So, it's running (gio is generating frames), but it's inactive (the window is not in focus).

Stage was designed to be an integer of increasing "liveness" of the window. So for active, inactive:

 const ( 
 	// StagePaused is the stage for windows that have no on-screen representation. 
 	// Paused Windows don't receive FrameEvents. 
 	StagePaused Stage = iota
        // StageInactive is the stage for windows that are visible, but not active.
        StageInactive
        // Inactive windows receive FrameEvents.
 	// StateRunning is for active and visible Windows.
        // Active windows receive FrameEvents. 
 	StageRunning 
 ) 

eliasnaur avatar Aug 07 '22 21:08 eliasnaur

Sorry for a lot of force pushes, but there's no change between them. That fixed comparison, as you suggest.

inkeliz avatar Sep 19 '22 07:09 inkeliz

Merged, thanks!

eliasnaur avatar Sep 19 '22 17:09 eliasnaur