Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event lifecycle docs (contribution volunteer) #2736

Open
jmaargh opened this issue Mar 13, 2023 · 5 comments · May be fixed by #2743
Open

Event lifecycle docs (contribution volunteer) #2736

jmaargh opened this issue Mar 13, 2023 · 5 comments · May be fixed by #2743
Labels
S - docs Awareness, docs, examples, etc.

Comments

@jmaargh
Copy link

jmaargh commented Mar 13, 2023

One thing I struggled with when starting with winit is a clear idea of the "lifecycle" of an event loop. That is: what's the order of events I can expect to be dispatched to the EventLoop::run closure? I would like to contribute some docs to this if you'd be amenable.

I think this problem is particularly important for winit because - as a new user - you're immediately made aware that winit is being very careful about cross-platform behaviour (being required to pass a move closure to run which entirely hijacks your main thread makes this clear), but one of the core aspects of that behaviour isn't immediately clear.

I realise most of this information is already in the docs - across the root docs, Event, and ControlFlow docs. I think all of those are appropriate docs for where they are, but propose an additional section in the root docs specifically to teach new users the high-level of what to expect from events. Ideally with a simple flowchart showing the most common orders of events (see, for example, this from the android docs).

I'd be happy to draft something, but wanted to check that it would be desirable first. Also, since I still don't fully understand this topic, it would require some careful review.

@rib
Copy link
Contributor

rib commented Mar 15, 2023

Yeah it certainly sounds like this would be good to have and more clarification here could also be good for ensuring that there is consistency amongst backend implementations too, and consistency across the different ways that an event loop can be run.

A few cases that seem particularly relevant here:

  1. It may not be immediately obvious but Resumed is intended to be a consistent event across all platforms (including non-mobile platforms) that can be used to initialize render state - and if you want to write portable code then apps should avoid trying to initialize render state, e.g. via Init events or before the event loop starts running.
  2. Backends are currently inconsistent with how they deal with StartCause::Init events. Some backends will run a full event loop iteration with StartCause::Init (including delivering a corresponding NewEvents, MainEventsCleared and RedrawEventsCleared) whereas other backends with simply emit one NewEvents callback as a special case)
  3. Applications that may currently invoke run_return instead of run can inadvertently end up repeatedly dispatching NewEvents with StartCause::Init as well as Resumed and LoopDestroyed events against the same event loop.

Also see #2706 for some recent discussion around this.

@madsmtm
Copy link
Member

madsmtm commented Mar 16, 2023

Related: I've been considering adding debug_assertions (or behind a feature-flag that developers can enable) that verify that the order of events are correct

@jmaargh
Copy link
Author

jmaargh commented Mar 16, 2023

Sounds like this is wanted, so I've taken an initial stab at a flowchart:
image

The thought is to keep this as a place for quickly informing new users what they should generally expect, and not try to go into all of the possible corner cases (linking to relevant docs elsewhere for those details). Blue events are what I'm classifying as "lifecycle" events, indicating changes in event loop state. The yellow "input events" are what I'm calling DeviceEvents, WindowEvents, and UserEvents. Dotted outlines indicate that these may not exist on any particular iteration of the loop. Finally, from what I've read I don't see any particular guarantees about when Suspend should be expected, hence its inclusion outside of the loop. Finally, as noted by @rib the initial "loop" is platform-dependent, indicated by big square brackets.

If this looks good I'll open up a PR with some text added to explain all of this. I'll probably add a key to the diagram too.

@rib
Copy link
Contributor

rib commented Mar 16, 2023

Cool, thanks for taking a look,

One comment on terminology; I think we should probably reserve the "lifecycle" designation for application lifecycle events (mainly for mobile devices), since I think that's a more common usage that's already well established (at least for Android and iOS I think a lot of devs will have preconceived ideas of what "lifecycle" events refer to)

We could clarify that some events are "Application lifecycle" vs "Event loop lifecycle" but maybe it would be less verbose to think of a different designation for the the event loop lifecycle events.

Maybe "Phase" could be used to refer to the NewEvents(cause), MainEventsCleared and RedrawEventsCleared events.

I think the above diagram is missing the MainEventsCleared phase event after "input events".

I suppose "input events" somehow needs expanding, or needs a more general name as this is where most events go, including WindowEvents and also including life cycle events like Suspend/Resumed (at least for Android).

Personally I think it could be good if Winit always guaranteed that it consistently delivered events within a full loop iteration that is organised like [NewEvents(cause), { window, life cycle + input events } MainEventsCleared {RedrawRequested} RedrawEventsCleared].

I feel like ideally we shouldn't be documenting that there are backend-specific inconsistencies with how the first events are delivered if we can instead just agree how to make all the backends consistent here.

If we create a nice flow chart vector graphic like above it would be good if we end up tracking the source svg, or some standard description to ensure it's practical to maintain the chart as changes will be needed over time.

@jmaargh
Copy link
Author

jmaargh commented Mar 16, 2023

One comment on terminology; I think we should probably reserve the "lifecycle" designation for application lifecycle events (mainly for mobile devices), since I think that's a more common usage that's already well established (at least for Android and iOS I think a lot of devs will have preconceived ideas of what "lifecycle" events refer to)

Of course, happy to use whatever word works. I'll draft it with something other than "lifecycle" (perhaps "loop stage"?)

I think the above diagram is missing the MainEventsCleared phase event after "input events".

Good spot

I suppose "input events" somehow needs expanding, or needs a more general name as this is where most events go, including WindowEvents and also including life cycle events like Suspend/Resumed (at least for Android).

Of course, this was always supposed to be accompanied by some text I'm yet to draft, that was definitely going to be explained. I used the phrase "input events" in the current docs (previously I was going to call them "main events" to match the MainEventsCleared event name).

Personally I think it could be good if Winit always guaranteed that it consistently delivered events within a full loop iteration that is organised like [NewEvents(cause), { window, life cycle + input events } MainEventsCleared {RedrawRequested} RedrawEventsCleared].

I feel like ideally we shouldn't be documenting that there are backend-specific inconsistencies with how the first events are delivered if we can instead just agree how to make all the backends consistent here.

Agreed, but I think changing behaviour is out-of-scope for this discussion. Were we talking about changing platform-specific behaviour or refactoring then I would have thoughts to contribute, but I don't think those discussions should block documenting what's here now -- the documentation can always evolve as implementation does.

If we create a nice flow chart vector graphic like above it would be good if we end up tracking the source svg, or some standard description to ensure it's practical to maintain the chart as changes will be needed over time.

Of course. I made this with diagrams.net and was going to check in the original file -- you can even edit it on the web direct from a github repo.

I'll put together a PR tomorrow where we can discuss specifics.

@jmaargh jmaargh linked a pull request Mar 17, 2023 that will close this issue
3 tasks
@kchibisov kchibisov added the S - docs Awareness, docs, examples, etc. label Apr 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S - docs Awareness, docs, examples, etc.
Development

Successfully merging a pull request may close this issue.

4 participants