Hey,
this is my fist PR to fix the bug I just published #8225
I hope it helps.
I tested the fix with wgpu but not glow.
I must say that I am not very happy to have very similar function
is_viewport_or_descendant_visible in both case.
Let me know if you would prefer that I try to factorize it.
* Closes <https://github.com/emilk/egui/issues/8225>
* [X] I have followed the instructions in the PR template
---------
Co-authored-by: Matthieu Casanova <public@kpouer.com>
Introduces live inspection for running egui apps over a small TCP
request/response protocol, plus the `egui::Plugin` that serves it.
This is the minimal surface to get the egui mcp in, we may want to
extend this in the future to add support for the inspection gui.
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## What
Adds a way for apps to push an RGBA bitmap as the OS cursor — the
missing companion to `Context::set_cursor_icon`. The integration
translates it into a real `winit::CustomCursor`, so the cursor is drawn
by the compositor and can extend past the egui window edge like any
native cursor.
## Why
Apps with custom-shaped windows (Winamp-style skins, themed launchers,
kiosk apps) currently have no clean way to display a custom cursor:
- `CursorIcon` is limited to the standard system enum.
- Painting the cursor sprite via `egui::Painter` works inside the canvas
but gets clipped at the window edge — the bottom/right of the cursor
disappears the moment the pointer is near the boundary, and there's no
way to render onto the desktop area exposed by a
transparent/region-shaped window.
`winit` 0.30+ already supports `CustomCursor::from_rgba` +
`ActiveEventLoop::create_custom_cursor`, but `egui-winit` doesn't
surface it. This PR exposes it through egui.
### Visual demonstration
Driving use case: a Winamp WSZ skin player
([all3f0r1/oneamp](https://github.com/all3f0r1/oneamp)) with a
transparent + region-shaped window where the skin ships its own `.cur`
files. The bottom-right corner of the playlist exposes the resize cursor
— notice how it gets clipped at the window edge in the painter-based
approach.
| Before (cursor painted via `egui::Painter`) | After (cursor pushed via
`set_cursor_image`) |
| --- | --- |
| 
| 
|
## API
```rust
// new in egui::data::output
pub struct CustomCursorImage {
pub rgba: std::sync::Arc<[u8]>,
pub size: [u16; 2], // matches winit's u16 to avoid lossy casts
pub hotspot: [u16; 2],
}
// new field on PlatformOutput (skipped from serde — ephemeral)
pub cursor_image: Option<CustomCursorImage>,
// new method on Context
ctx.set_cursor_image(Some(image)); // overrides cursor_icon for this frame
ctx.set_cursor_image(None); // revert to cursor_icon
```
`Arc<[u8]>` is intentional: the integration dedupes by `Arc::as_ptr`, so
reusing the same Arc across frames means the bitmap is only uploaded to
the OS once per skin, not once per frame.
## Integration changes
- `egui_winit::State::handle_platform_output_with_event_loop(window,
Option<&ActiveEventLoop>, ...)` is a new method that threads the active
event loop so it can call `event_loop.create_custom_cursor(...)`.
- The legacy `handle_platform_output(window, ...)` delegates with `None`
and silently drops `cursor_image`. **No existing callers break.**
- The icon and bitmap paths are unified in a private `apply_cursor`. The
no-flicker dedupe of the old `set_cursor_icon` is preserved on both
paths.
- If `CustomCursor::from_rgba` rejects the bitmap (bad dimensions,
hotspot OOB, etc.), we log a warning and fall back to the icon path.
- eframe's wgpu + glow integrations thread `&ActiveEventLoop` through
`run_ui_and_paint` (glow already had it; wgpu needed one extra
parameter) and call the new method.
- Immediate viewports keep the old path because they're invoked from a
`Context` callback that doesn't have an event loop reference. Custom
cursors are a no-op in immediate viewports — acceptable since they're a
niche path.
## Fallback semantics
| backend / context | what happens |
|--------------------------------|-------------------------------|
| eframe wgpu/glow main viewport | bitmap displayed via OS |
| eframe immediate viewport | falls back to `cursor_icon` |
| eframe web | falls back to `cursor_icon` |
| custom integrations not opted in | falls back to `cursor_icon` |
| `from_rgba` returns `BadImage` | warning + falls back to icon |
## Verification
- `cargo fmt --all -- --check` ✅
- `cargo clippy -p egui -p egui-winit -p eframe --all-targets
--all-features -- -D warnings` ✅
- `cargo doc --lib --no-deps -p egui -p egui-winit -p eframe
--all-features` ✅
- `cargo check -p egui --no-default-features --features serde` ✅
(validates the `serde(skip)` on `cursor_image`)
- Interactive validation on Linux/Wayland with the OneAmp WSZ skin
player — see screenshots above.
I haven't run the full snapshot test suite (`scripts/check.sh`) because
we're on Linux and the snapshots are macOS-rendered — happy to run it if
you'd like.
## Notes
Drafted per the contributing guide ("open a draft PR, you may get
helpful feedback early"). Open to design feedback on:
1. Whether `CustomCursorImage` should live in `egui::viewport` rather
than `egui::data::output`.
2. Whether the legacy `handle_platform_output` should grow `event_loop`
directly (breaking) instead of getting a sibling method (non-breaking,
what I did).
3. Whether to also wire it through eframe-web (probably not —
`wasm-bindgen-cursor` would need its own path).
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This lets you start up the test app from within the test itself, which
can be very useful when you have a specific test scenario set up that
you need to debug.
### Related
* Previous attempt: https://github.com/emilk/egui/pull/5418
### macOS
On macOS, you may only run UIs on the main loop, so you need a few
additional steps. Not ideal, but works!
```diff
diff --git a/crates/egui_demo_app/Cargo.toml b/crates/egui_demo_app/Cargo.toml
index f9a153268..4e0cc14ee 100644
--- a/crates/egui_demo_app/Cargo.toml
+++ b/crates/egui_demo_app/Cargo.toml
@@ -84,3 +84,7 @@ web-sys.workspace = true
[dev-dependencies]
egui_kittest = { workspace = true, features = ["eframe", "snapshot", "wgpu"] }
+
+[[test]]
+name = "test_demo_app"
+harness = false
diff --git a/crates/egui_demo_app/tests/test_demo_app.rs b/crates/egui_demo_app/tests/test_demo_app.rs
index e083c8455..7ad9ed516 100644
--- a/crates/egui_demo_app/tests/test_demo_app.rs
+++ b/crates/egui_demo_app/tests/test_demo_app.rs
@@ -4,7 +4,10 @@ use egui_demo_app::{Anchor, WrapApp};
use egui_kittest::SnapshotResults;
use egui_kittest::kittest::Queryable as _;
-#[test]
+fn main() {
+ test_demo_app();
+}
+
fn test_demo_app() {
let mut harness = egui_kittest::Harness::builder()
.with_size(Vec2::new(900.0, 600.0))
@@ -73,5 +76,8 @@ fn test_demo_app() {
harness.run_steps(4);
results.add(harness.try_snapshot(anchor.to_string()));
+
+ harness.spawn_eframe_app();
+ break;
}
}
```
This is a breaking public API change, but is otherwise trivial due to it
not changing any actual runtime behaviour.
This renames eframe's NativeOptions `vsync` option to `glow_vsync` to
make clear without even looking at docs fully that this is specific to
the `glow` backend.
While I think a better option would actually be to change the wgpu
creation options to match the vsync option if not specified (either to
`AutoVsync` or `AutoNoVsync` depending on setting) this would require
this be made an `Option<PresentMode>`, which would be confusing - and
the `WgpuConfiguration` should probably take priority over other options
here, as there's more than 2 present modes that are relevant. So I think
this is a suitable way to go.
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/main/CONTRIBUTING.md)
before opening a Pull Request!
* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.
Please be patient! I will review your PR, but my time is limited!
-->
* This does not close an issue - this was a trivial amount of code to
change, so I might as well just make it a PR on the spot.
* [x] I have followed the instructions in the PR template
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
## Summary
* Closes#5229
* Closes#7776
On Windows, once a window is hidden with
`ViewportCommand::Visible(false)`, two problems occur:
1. **Window can never be shown again** — Windows stops sending
`RedrawRequested` events to invisible windows, and viewport commands are
only processed during `run_ui_and_paint`, which is triggered by
`RedrawRequested`. This creates a deadlock:
```
Visible(false) → window hidden → no RedrawRequested → run_ui_and_paint never called → Visible(true) stuck in queue → window stays hidden forever
```
2. **High CPU usage** — The event loop spins at full speed with
`ControlFlow::Poll` even for invisible windows, and repaint requests are
scheduled immediately, causing a tight loop that burns CPU.
## Fix
**For #5229:** In `check_redraw_requests`, after calling
`window.request_redraw()`, detect invisible windows via
`window.is_visible() == Some(false)` and call `run_ui_and_paint`
directly for them. This ensures pending viewport commands (including
`Visible(true)`) are still processed even when the OS doesn't send
redraw events.
**For #7776:** Three layers of throttling for invisible windows:
- **Heartbeat scheduling:** After painting an invisible window, schedule
the next repaint 100ms in the future (instead of immediately). This
keeps viewport commands flowing while limiting to ~10 repaints/sec.
- **Event throttling:** In `user_event`, throttle `RequestRepaint`
events for invisible windows to at least 100ms delay, preventing egui's
repaint callback from bypassing the heartbeat.
- **ControlFlow fix:** Only set `ControlFlow::Poll` for visible windows.
Invisible windows use `WaitUntil` instead of spinning.
- **Backend sleep:** Add `is_visible() == Some(false)` alongside the
existing `is_minimized()` sleep check in both wgpu and glow backends
(defense in depth).
The fix is platform-agnostic: `is_visible()` returns `Some(false)` only
when the platform can confirm invisibility, so it won't trigger on
platforms where invisible windows still receive `RedrawRequested`.
## Test plan
- [x] `cargo fmt` passes
- [x] `cargo clippy -p eframe --all-features` passes with no warnings
- [x] Manual test on Windows: window reappears after `Visible(true)`
when hidden
- [x] Manual test on Windows: CPU stays near 0% while window is
invisible (was ~16% before fix)
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
## Summary
- Ignore raw device mouse motion unless the window is focused and the
pointer is inside it
- Also handles pointers starting down and then moving into or out of the
window (drag & drop)
- Prevents global mouse motion from triggering continuous repaint loops
- Applies to both glow and wgpu backends
## Testing
- I ran the check script, nothing seemed to fail
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/main/CONTRIBUTING.md)
before opening a Pull Request!
* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.
Please be patient! I will review your PR, but my time is limited!
-->
* [x] I have followed the instructions in the PR template
`get_proc_address` was introduced in #4145, but its lifetime was
designed to be tied to the lifetime `'s` of `CreationContext`. This
means that using `get_proc_address` outside the lifetime of
`CreationContext` is undefined behavior. This contradicts the original
intent behind introducing `get_proc_address`, as this API is intended
for integration with external libraries that cannot easily guarantee
alignment with egui's lifetimes. This PR changes the type of
`get_proc_address` from a reference to an `Arc`, decoupling its lifetime
from `CreationContext` to achieve safer memory management.
* Part of https://github.com/emilk/egui/issues/5113
* Part of https://github.com/emilk/egui/issues/3524
## What
This deprecates `eframe::App::update` and replaces it with two new
functions:
```rs
pub trait App {
/// Called just before `ui`, and in the future this will
/// also be called for background apps when needed.
fn logic(&mut self, ctx: &egui::Context, frame: &mut Frame) { }
/// Show your user interface to the user.
fn ui(&mut self, ui: &mut egui::Ui, frame: &mut Frame);
…
}
```
Similarly, `Context::run` is deprecated in favor of `Context::run_ui`.
`Plugin`s are now handed a `Ui` instead of just a `Context` in
`on_begin/end_frame`.
## TODO
…either in this PR or a later one
* [x] Deprecate `App::update`
* [x] Deprecate `Context::run`
* [x] Change plugins to get a `Ui`
* [x] Update kittest
* [x] Change viewports to get UI:s (`show_viewport_immediate` etc)
- https://github.com/emilk/egui/pull/7779
## Later PRs
* [ ] Deprecate `Panel::show`
* [ ] Deprecate `CentralPanel::show`
* [ ] Deprecate `CentralPanel` ?
### What
From the [lint
description](https://rust-lang.github.io/rust-clippy/master/index.html?search=or_fu#or_fun_call):
> The function will always be called. This is only bad if it allocates
or does some non-trivial amount of work.
But also:
> If the function has side-effects, not calling it will change the
semantic of the program, but you shouldn’t rely on that.
>
> The lint also cannot figure out whether the function you call is
actually expensive to call or not.
Still worth it to keep our happy paths clean, imo.
* Part of https://github.com/emilk/egui/issues/5889
* Closes https://github.com/emilk/egui/issues/7106
This changes the `eframe/wgpu` feature to also enable all the `default`
features of `wgpu` and `egui-wgpu`. This makes switching `eframe`
backend from `glow` to `wgpu` a lot easier.
To get the old behavior (depend on `wgpu` but you must opt-in to all its
features), use the new `wgpu_no_default_features` feature.
Using physical window sizes leads to all kinds of fun stuff: winit
always uses scale factor 1.0 on start to convert it back to logical
pixels and uses these logical pixels to set min/max size for
non-resizeable windows. You're supposed to adjust size after getting a
scale change event if you're using physical sizes, but adjusting min/max
sizes doesn't seem to work on sway, so the window is stuck with an
incorrect size.
The scale factor we guessed might also be wrong even if there's only a
single display since it doesn't take fractional scale into account.
TL;DR: winit actually wants logical sizes in these methods (since
Wayland in general operates mostly on logical sizes) and converting them
back and forth is lossy.
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/main/CONTRIBUTING.md)
before opening a Pull Request!
* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.
Please be patient! I will review your PR, but my time is limited!
-->
* Closes https://github.com/emilk/egui/issues/7095
* [x] I have followed the instructions in the PR template
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md)
before opening a Pull Request!
* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.
Please be patient! I will review your PR, but my time is limited!
-->
This pull request fixes a subset of #5492 by saving the application
state when the `suspended` event is received on Android. This way, even
if the user exits the app and closes it manually right after changing
some state, it will be saved since `suspended` gets fired when the app
is exited. It does not fix the `on_exit` function not being fired - this
seems to be a winit bug (the `exiting` function in the winit application
handler trait is not called on exit). Once it gets fixed, it may be
possible to remove logic introduced by this PR (however, I am not sure
how it would handle the app being killed by the system when in the
background, that would have to be tested).
I've tested the logic by:
* Leaving from the app to the home screen, then killing it from the
"recent apps" menu
* Leaving from the app to the "recent apps" menu and killing it
* Restarting the device while the app was running
In all of these instances, the state was saved (the last one being a
pleasant surprise). It was tested on the repository mentioned in #5492
with my forked repository as the source for eframe (I unfortunately am
not able to test it in a larger project of mine due to dependence on
"3rd party" egui libraries (like egui_notify) which do not compile along
with the master branch of eframe (different versions of egui), but I
believe it should work in the same manner in all scenarios). Tests were
conducted on a Galaxy Tab S8 running Android 14, One UI 6.1.1.
CI passed on my fork.
* [x] I have followed the instructions in the PR template
Hey! I am not sure if this is something that's been considered before
and decided against (I couldn't find any PR's or issues).
This change removes the internal profiling macros in library crates and
the `puffin` feature and replaces it with similar functions in the
[profiling](https://github.com/aclysma/profiling) crate. This crate
provides a layer of abstraction over various profiler instrumentation
crates and allows library users to pick their favorite (supported)
profiler.
An additional benefit for puffin users is that dependencies of egui are
included in the instrumentation output too (mainly wgpu which uses the
profiling crate), so more details might be available when profiling.
A breaking change is that instead of using the `puffin` feature on egui,
users that want to profile the crate with puffin instead have to enable
the `profile-with-puffin` feature on the profiling crate. Similarly they
could instead choose to use `profile-with-tracy` etc.
I tried to add a 'tracy' feature to egui_demo_app in order to showcase ,
however the /scripts/check.sh currently breaks on mutually exclusive
features (which this introduces), so I decided against including it for
the initial PR. I'm happy to iterate more on this if there is interest
in taking this PR though.
Screenshot showing the additional info for wgpu now available when using
puffin

This lets users trigger a screenshot from anywhere, and then when they
get back the results they have some context about what part of their
code triggered the screenshot.
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md)
before opening a Pull Request!
* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.
Please be patient! I will review your PR, but my time is limited!
-->
- I fixed the TODO to use the `log` crate instead of `eprintln`
- Set the rust-version in the `scripts/check.sh` to the same as egui is
on
- I made xtask use anyhow to remove some unwraps
* [x] I have followed the instructions in the PR template
* Closes https://github.com/emilk/egui/issues/4976
* Part of #4378
* Implements parts of #843
### Background
Some widgets (like `Grid` and `Table`) needs to know the width of future
elements in order to properly size themselves. For instance, the width
of the first column of a grid may not be known until all rows of the
grid has been added, at which point it is too late. Therefore these
widgets store sizes from the previous frame. This leads to "first-frame
jitter", were the content is placed in the wrong place for one frame,
before being accurately laid out in subsequent frames.
### What
This PR adds the function `ctx.request_discard` which discards the
visual output and does another _pass_, i.e. calls the whole app UI code
once again (in eframe this means calling `App::update` again). This will
thus discard the shapes produced by the wrongly placed widgets, and
replace it with new shapes. Note that only the visual output is
discarded - all other output events are accumulated.
Calling `ctx.request_discard` should only be done in very rare
circumstances, e.g. when a `Grid` is first shown. Calling it every frame
will mean the UI code will become unnecessarily slow.
Two safe-guards are in place:
* `Options::max_passes` is by default 2, meaning egui will never do more
than 2 passes even if `request_discard` is called on every pass
* If multiple passes is done for multiple frames in a row, a warning
will be printed on the screen in debug builds:

### Breaking changes
A bunch of things that had "frame" in the name now has "pass" in them
instead:
* Functions called `begin_frame` and `end_frame` are now called
`begin_pass` and `end_pass`
* `FrameState` is now `PassState`
* etc
### TODO
* [x] Figure out good names for everything (`ctx.request_discard`)
* [x] Add API to query if we're gonna repeat this frame (to early-out
from expensive rendering)
* [x] Clear up naming confusion (pass vs frame) e.g. for `FrameState`
* [x] Figure out when to call this
* [x] Show warning on screen when there are several frames in a row with
multiple passes
* [x] Document
* [x] Default on or off?
* [x] Change `Context::frame_nr` name/docs
* [x] Rename `Context::begin_frame/end_frame` and deprecate the old ones
* [x] Test with Rerun
* [x] Document breaking changes
Before making this PR, I did take notice of a similar PR,
https://github.com/emilk/egui/pull/4833, but as it appears to be
abandoned, I decided to make this PR.
**Missing**
One of the checks doesn't pass as wgpu still uses glow `0.13.1`
```shell
cargo deny --all-features --log-level error --target aarch64-apple-darwin check
```
* [x] I have followed the instructions in the PR template
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
I love egui! Thank you Emil <3
This request specifically enables an `eframe::App` which stores a
lifetime.
In general, I believe this is necessary because `eframe::App` currently
does not seem to provide a good place to allocate and then borrow from
long-lived data between `update()` calls. To attempt to borrow such
long-lived data from a field of the `App` itself would be to create a
self-referential struct. A hacky alternative is to allocate long-lived
data with `Box::leak`, but that's a code smell and would cause problems
if a program ever creates multiple Apps.
As a more specific motivating example, I am developing with the
[inkwell](https://github.com/TheDan64/inkwell/) crate which requires
creating a `inkwell::context::Context` instance which is then borrowed
from by a bazillion things with a dedicated `'ctx` lifetime. I need such
a `inkwell::context::Context` for the duration of my `eframe::App` but I
can't store it as a field of the app. The most natural solution to me is
to simply to lift the inkwell context outside of the App and borrow from
it, but that currently fails because the AppCreator implicitly has a
`'static` lifetime requirement due to the use of `dyn` trait objects.
Here is a simpler, self-contained motivating example adapted from the
current [hello world example](https://docs.rs/eframe/latest/eframe/):
```rust
use eframe::egui;
struct LongLivedThing {
message: String,
}
fn main() {
let long_lived_thing = LongLivedThing {
message: "Hello World!".to_string(),
};
let native_options = eframe::NativeOptions::default();
eframe::run_native(
"My egui App",
native_options,
Box::new(|cc| Ok(Box::new(MyEguiApp::new(cc, &long_lived_thing)))),
// ^^^^^^^^^^^^^^^^^
// BORROWING from long_lived_thing in App
);
}
struct MyEguiApp<'a> {
long_lived_thing: &'a LongLivedThing,
}
impl<'a> MyEguiApp<'a> {
fn new(cc: &eframe::CreationContext<'_>, long_lived_thing: &'a LongLivedThing) -> Self {
// Customize egui here with cc.egui_ctx.set_fonts and cc.egui_ctx.set_visuals.
// Restore app state using cc.storage (requires the "persistence" feature).
// Use the cc.gl (a glow::Context) to create graphics shaders and buffers that you can use
// for e.g. egui::PaintCallback.
MyEguiApp { long_lived_thing }
}
}
impl<'a> eframe::App for MyEguiApp<'a> {
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
egui::CentralPanel::default().show(ctx, |ui| {
ui.heading(&self.long_lived_thing.message);
});
}
}
```
This currently fails to compile with:
```plaintext
error[E0597]: `long_lived_thing` does not live long enough
--> src/main.rs:16:55
|
16 | Box::new(|cc| Ok(Box::new(MyEguiApp::new(cc, &long_lived_thing)))),
| ----------------------------------------------^^^^^^^^^^^^^^^^----
| | | |
| | | borrowed value does not live long enough
| | value captured here
| cast requires that `long_lived_thing` is borrowed for `'static`
17 | );
18 | }
| - `long_lived_thing` dropped here while still borrowed
|
= note: due to object lifetime defaults, `Box<dyn for<'a, 'b> FnOnce(&'a CreationContext<'b>) -> Result<Box<dyn App>, Box<dyn std::error::Error + Send + Sync>>>` actually means `Box<(dyn for<'a, 'b> FnOnce(&'a CreationContext<'b>) -> Result<Box<dyn App>, Box<dyn std::error::Error + Send + Sync>> + 'static)>`
```
With the added lifetimes in this request, I'm able to compile and run
this as expected on Ubuntu + Wayland. I see the CI has been emailing me
about some build failures and I'll do what I can to address those.
Currently running the check.sh script as well.
This is intended to resolve https://github.com/emilk/egui/issues/2152
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md)
before opening a Pull Request!
* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.
Please be patient! I will review your PR, but my time is limited!
-->
* Closes https://github.com/emilk/egui/issues/2152
* [x] I have followed the instructions in the PR template
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md)
before opening a Pull Request!
* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.
Please be patient! I will review your PR, but my time is limited!
-->
I removed (I hope so) all wildcard imports I found.
For me on my pc this improved the build time:
- for egui -5s
- for eframe -12s
* [x] I have followed the instructions in the PR template
* Fixes#3959
There are two bugs racing each other here, which is why it sometimes
crashes and sometimes the app just silently exists
Bug 1
When the window is recreated a Destroyed event arrives (due to the Drop
of the old window). The code that receives this event does not look to
see if its the main viewport or a secondary one and unconditionally
closes the app. The code path for other platforms is slightly different
and does check.
I have moved the code that handles the destroy to be in the same place
and have the same behavior as the other platforms.
Bug 2
At recreate time the window and winit entries of the viewport are set to
None (forcin g them to be recreated). But the surface is still bound to
the old window, this causes the next context switch to fail. So I simply
added a viewport.gl_surface = None too,
This is my first egui PR so I hope I have not broken anything. If
nothing else I understand a little better how egui works.
This updates winit to 0.30.5.
https://github.com/emilk/egui/pull/4849 Had to pin the version to
0.30.2, as a Winit patch changed the behavior of selecting a theme.
Winit 0.30.5 reverts this, so we could stick with `window.theme()`, but
the newly added `ActiveEventLoop::system_theme` is more like what egui
wants anyway, as individual windows can have theme overrides.
Also bump `smithay-clipboard` to prevent some now duplicate
dependencies.
* Some initial progress towards #4490
This PR just moves `Theme` and the "follow system theme" settings to
egui and adds `RawInput.system_theme`.
A follow-up PR can then introduce the two separate `dark_mode_style` and
`light_mode_style` fields on `Options`.
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md)
before opening a Pull Request!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.
Please be patient! I will review your PR, but my time is limited!
-->
* [x] I have followed the instructions in the PR template
### Breaking changes
The options `follow_system_theme` and `default_theme` has been moved
from `eframe` into `egui::Options`, settable with `ctx.options_mut`
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
* Closes https://github.com/emilk/egui/issues/1918
* Closes https://github.com/emilk/egui/issues/4437
* Closes https://github.com/emilk/egui/issues/4709
* [x] I have followed the instructions in the PR template
Hiya,
I need new winit for a specific fix for a android_native_actvity. There
are already two PRs, but both don't seem to have a lot of movement, or
are entirely complete:
https://github.com/emilk/egui/pull/4466
Seems to have gone stale & is missing some bits.
https://github.com/emilk/egui/pull/4702
Also seems stale (if less so), and is missing a refactor to
run_on_demand. I also *think* the accesskit integration has a mistake
and can't be enabled. I've marked them as a co-author on this as I
started from this branch. (I think! Haven't done that on git before...).
Sorry for the wall of text but just dumping some details / thoughts
here:
- There's an issue with creating child windows in winit 0.30.1 and up on
macOS. The multiple_viewports, "create immediate viewport" example
crashes on anything later 0.30.1, with a stack overflow in unsafe code.
I've create [a winit
issue](https://github.com/rust-windowing/winit/issues/3800), it *might*
already be fixed in 0.31.0 but I can't test as 0.31 will likely require
another refactoring. For now I have just pinned things to 0.30.0 exatly.
- Winit has deprecated run_on_demand, instead requiring the
ApplicationHandler interface. In 0.31.0 run_on_demand is removed. I've
refactored both the integration and the WinitApp trait to follow this
pattern. I've left user_events a bit more opaque, as it seems 0.31.0 is
doing a rework of UserEvents too.
- I've used the new lazy init approach for access kit from this branch
https://github.com/mwcampbell/egui/tree/accesskit-new-lazy-init and
marked Matt as co-author, thanks Matt!
- There was very similair but not quite the same code for run_and_return
and run_and_exit. I've merged them, but looking at the github issues
graveyard it seems vey finnicky. I *hope* this is more robust than
before but it's a bit scary.
- when receiving new_events this also used to check the redraw timing
dictionary. That doesn't seem necesarry so left this out, but that is a
slight behaviour change?
- I have reeneabled serial_windows on macOS. I wondered whether it was
fixed after this PR and does seem to be! However, even before this PR it
seems to work, so maybe winit has sorted things out before that...
Windows also works fine now without the extra hack.
- I've done a very basic test of AccessKit on Windows and screen reader
seems ok but I'm really not knowleadgable enough to say whether it's all
good or not.
- I've tested cargo tests & all examples on Windows & macOS, and ran a
basic Android app. Still, testing native platforms is wel... hard so if
anyone can test linux / iOs / older mac versions / windows 10 would
probably be a good idea!
- For consistencys sake I've made all event like functions in WinitApp
return a `Result<EventResult>`. There's quite a bit of Ok-wrapping now,
maybe too annoying? Not sure.
Thank you for having a look!
# Tested on
* [x] macOS
* [x] Windows
* [x] Wayland (thanks [SiebenCorgie](https://github.com/SiebenCorgie))
* [x] X11 (thanks
[crumblingstatue](https://github.com/crumblingstatue)!,
[SiebenCorgie](https://github.com/SiebenCorgie))
# TODO
* [x] Fix "follow system theme" not working on initial startup (winit
issue, pinning to 0.30.2 for now).
* [x] Fix `request_repaint_after`
---------
Co-authored-by: mwcampbell <mattcampbell@pobox.com>
Co-authored-by: j-axa <josef.axa@gmail.com>
Co-authored-by: DataTriny <datatriny@gmail.com>
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
Improved `change_gl_context()`
**Before:**
Create a new `not_current_glcontext`.
**After:**
If `not_current_glcontext` exists, apply it. Otherwise, create it.
This will make the program smoother when dragging, etc.
The closure passed to `eframe::run_native` now returns a `Result`,
allowing you to return an error during app creation, which will be
returned to the caller of `run_native`.
This means you need to wrap your `Box::new(MyApp::new(…))` in an
`Ok(…)`.
* Closes https://github.com/emilk/egui/issues/4474
This allows customizing the persistence path in NativeOptions.
Previously, persistence wouldn't work with android because
directories-next doesn't support android so eframe would just fail to
find a place where it could store its config.
* Closes#4098 (android users can now specify a path that works with
android, by e.g. using app_dirs2, which supports android)
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md)
before opening a Pull Request!
* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.
Please be patient! I will review your PR, but my time is limited!
-->
Related to #3482
Not sure what the "best practice" is, to me it seems like one should
import from "the original location" if possible, but now it should at
least be possible to not re-export ahash without any breakage in the
egui code base (but possibly in projects using egui, so one should
probably deprecate it if one would like to go that path). It also seems
like epaint re-exports ahash.