1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-30 21:30:03 -04:00

Never run an egui pass when nothing will be shown (#8387)

* Closes <https://github.com/emilk/egui/issues/8266>
* Alternative to #8385

Not the most simple or beautiful code, but it works, and makes sense.

What makes it complex: `app.logic` should still see some input (e.g.
what viewports are visible) and emit some output (e.g. "open this link",
or "focus and repaint").

## TODO
* [x] test multiple viewports

## Clanker says
Instead of teaching egui to skip book-keeping during a pass where no ui
is shown, we simply run no pass at all. Then there is nothing to
special-case: all ui state is left untouched, and the app finds
everything where it left it when the window is shown again.

* New `Context::run_logic(&raw_input, f)`: ticks app logic without a
pass, returning the `LogicOutput` (platform output + viewport commands)
that a pass would otherwise have carried, so e.g.
`ViewportCommand::Focus` still reaches the integration.
* All three eframe backends (glow, wgpu, web) call `run_logic` instead
of `run_ui` when the viewport is minimized/occluded (and has no visible
descendant viewport) or, on web, when the tab is hidden.
* `App::logic` is still called from inside the pass when the window is
visible, so it sees the current frame's input.

While hidden, `run_logic` fills in only the window state
(`RawInput::viewports` / `focused`), so the app can tell that it is
hidden. The ui input (events, time, …) is not interpreted, and is
instead given to the next real pass.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Emil Ernerfeldt
2026-08-05 00:14:35 -07:00
committed by GitHub
parent 90e03028f7
commit e37d44ad8a
10 changed files with 519 additions and 132 deletions

View File

@@ -155,6 +155,12 @@ pub trait App {
///
/// You may NOT show any ui or do any painting during the call to [`Self::logic`].
///
/// While the window is hidden, `eframe` runs no egui pass at all (so that no ui state is
/// disturbed), and calls this via [`egui::Context::run_logic`] instead.
/// You can then still tell that the window is hidden with
/// [`egui::InputState::viewport`], but the rest of [`egui::Context::input`]
/// (events, time, …) is that of the last shown frame.
///
/// The [`egui::Context`] can be cloned and saved if you like.
///
/// To force another call to [`Self::logic`], call [`egui::Context::request_repaint`] at any time (e.g. from another thread).