1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 22:53:14 -04:00
Commit Graph

501 Commits

Author SHA1 Message Date
Jochen Görtler
7dba2e99fa Fix random hangs by improving wgpu::Surface lifecycle handling (#8171)
### Related

* Closes #8134.
* Related to #5136.

Possibly fixes:

* #8123
* #5145 

### What

We did not properly handle the variants of
[`CurrentSurfaceTexture`](https://docs.rs/wgpu/latest/wgpu/enum.CurrentSurfaceTexture.html)
and always returned `SkipFrame`.

Because of this `egui` could end up in a state where frames are always
skipped after observing `Outdated`, without the chance to recover
(unless an event arrives from the outside).

> [!NOTE]
> This is not Wayland-specific, but could happen on all platforms. It
just happens frequently for Wayland compositors that directly resize a
window after creation (such as tiling/scrolling compositors like
`hyprland` and `niri`).

This PR improves this by separating the code paths for `Outdated` and
`Lost`, to help recover from those events.
2026-05-19 11:06:09 +02:00
Lucas Meurer
e3d7a01a6a Bump version to 0.34.2 and update changelogs (#8147)
Brings the 0.34.2 release commit back to `main` so it tracks the latest
published version and has updated changelogs.
2026-05-05 13:13:14 +02:00
Emil Ernerfeldt
56aabda7b3 Add Harness::spawn_eframe_app (#8120)
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;
     }
 }
```
2026-04-20 14:07:45 +02:00
Tap
d7e55b8381 Group glow config in a struct (#8108)
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>
2026-04-20 11:39:31 +02:00
Emil Ernerfeldt
f342ab8847 wgpu: Allow configuring VSync and frame latency at runtime (#8114)
Let apps change present_mode and desired_maximum_frame_latency at
runtime instead of only at startup.
API changes (egui-wgpu):
- New SurfaceConfig { present_mode, desired_maximum_frame_latency }.
- WgpuConfiguration now nests these as pub surface: SurfaceConfig (was
two top-level fields).
- RenderState gains pub surface_config: SurfaceConfig — the
currently-requested value.
API additions (eframe):
- Frame::wgpu_surface_config() / Frame::set_wgpu_surface_config(...) for
get/set.
- SurfaceConfig re-exported as eframe::SurfaceConfig.
                                                       
How it works:
The wgpu painter compares render_state.surface_config to its
currently-applied values each paint. If they differ it updates its
config and flips
needs_reconfigure on every surface, piggybacking on the existing
deferred-reconfigure pathway.
                                                       
Demo:
The backend panel (egui_demo_app) gets dropdowns for present mode and
desired max frame latency, wired through the new Frame accessors.

<img width="282" height="172" alt="image"
src="https://github.com/user-attachments/assets/0b1274b2-7e4e-4413-969b-0a014c415f79"
/>
2026-04-17 11:39:47 +02:00
Emil Ernerfeldt
1cd89b5edc Remove everything that was marked #[deprecated] (#8105)
Simplify. Streamline. Spring cleaning.
2026-04-14 20:19:36 +02:00
Emil Ernerfeldt
5c96f4f080 Document glow-only fields in NativeOptions (#8104) 2026-04-14 13:00:35 +02:00
Dimitris Papaioannou
41b64fc6f3 Call pre_present_notify before presenting (#8089) 2026-04-12 16:06:12 +02:00
Umaĵo
86a7f47738 Delegate handling of IME interruptions to integrations to fix virtual keyboard flickering on web (#8078)
* Closes N/A
* Partially replaces #7983
* Related: #8045
* [x] I have followed the instructions in the PR template

## Details

In #7983, I modified `Memory::request_focus` to interrupt any ongoing
IME composition. This fixed a bug where clicking inside an already
focused `TextEdit` failed to cancel the active composition, resulting in
duplicated text:

https://github.com/emilk/egui/pull/8045#issuecomment-4193310616

To avoid introducing API changes in that PR, I ensured the IME state was
reset by forcing `PlatformOutput::ime` to `None` for at least one frame.
While this works well on desktop platforms, it causes virtual keyboard
flickering on the web:

https://github.com/emilk/egui/pull/8045#issuecomment-4193035008

In this PR, I delegate the responsibility for handling IME composition
interruptions to integrations, allowing each integration to decide how
to interrupt compositions in a flexible manner.

### The new field `should_interrupt_composition` on `IMEOutput`.

Instead of introducing a new `OutputCommand` variant, this PR adds a new
field `should_interrupt_composition` to `IMEOutput`.

Interrupting an active composition is only meaningful when IME remains
allowed. If IME should be disabled altogether, `PlatformOutput::ime` can
simply be set to `None`.
Given this, IMO, it is more appropriate to attach the interrupt signal
to `IMEOutput` (i.e., the type of `PlatformOutput::ime`).
2026-04-08 10:04:15 +02:00
rustbasic
188ffacf41 Log localStorage write failures in local_storage_set (#8062)
Log `localStorage` write failures in `local_storage_set`

**Description**  
This PR improves `local_storage_set()` logging in
`eframe/src/web/storage.rs`.

It logs:
- write failures with key and browser error
- unavailable local storage

This helps diagnose web persistence issues such as `QuotaExceededError`
when `localStorage.setItem()` fails.

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2026-04-07 10:38:57 +02:00
Umaĵo
33e89e33be Improve IME handling, add public method owns_ime_events on Memory (#7983)
<!--
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!
-->

* Depends on #7967
* Closes #7485
* Should fix #7906 (This issue doesn't seem to have been resolved, but
the author closed it; I personally don't have the environment to verify
whether it is fixed.)
* Replaces #4137, #4896, and partially #7810
* [x] I have followed the instructions in the PR template

This PR started as a fix for #7485, but has since evolved into a broader
rewrite of IME-related logic.

## Overview

This PR primarily introduces a new public method, `owns_ime_events`, on
[`Memory`], and refactors parts of [`TextEdit`] to integrate with it.

Previously, each [`TextEdit`] widget independently determined whether to
handle IME events and stored its own IME-related state. This approach
made ownership-handling fragmented and was therefore error-prone.

With this PR:
- IME event ownership is centralized, ensuring that at most a single
widget owns IME events per frame.
- [`PlatformOutput`]'s `ime` field can be set to `None` for at least one
frame when IME composition is interrupted, allowing the IME to be
properly dismissed.

## Details

Two new public methods are introduced on [`Memory`]:

- `fn owns_ime_events(&self, id: Id) -> bool`: check IME event ownership
for the current frame for the widget with the given `id`.
- `fn interrupt_ime(&mut self)`: interrupt the current IME composition,
if any.

Since the newly added methods on [`Memory`] are public, other widgets
can also participate in IME handling without risking ownership conflicts
of IME events.

I also added an internal (`pub(crate)`) field on [`TextEditState`],
called `cursor_purpose`, to distinguish the role of the [`TextEdit`]
cursor.

Additionally, `egui::ImeEvent::Enabled` and `egui::ImeEvent::Disabled`
have been removed, as they are no longer used anywhere.

## Demonstrations

### Windows: The Korean IME text duplication bug fixed in #4137 does not
reappear.

<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
<th>Without this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Behavior</th>
<td>Correct (no regression)</td>
<td>Correct</td>
</tr>
<tr>
<th>Screencast</th>
<td>


![win-kor-after](https://github.com/user-attachments/assets/1b080c8f-2031-406f-8781-aacafd5c879a)
</td>
<td>


![win-kor-before](https://github.com/user-attachments/assets/20258841-72fe-4652-b9a9-9b40e338ccf2)
</td>
</tr>
</tbody>
</table>

### Windows: Chinese and Japanese IMEs now behave more consistently with
the Korean IME in similar scenarios.

This change does not matter much, as composition is rarely interrupted
mid-process with these IMEs in typical usage.

<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
<th>Without this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Behavior</th>
<td>Composition can be interrupted by clicking (like Korean IMEs)</td>
<td>Composition can not interrupted by clicking</td>
</tr>
<tr>
<th>Screencast (Builtin Chinese IME)</th>
<td>


![win-cmn-after](https://github.com/user-attachments/assets/2c76b0a9-da6d-48e1-84e0-47d9631f1196)
</td>
<td>


![win-cmn-before](https://github.com/user-attachments/assets/ea125fb8-c325-48d5-abaf-17d495b8f075)
</td>
</tr>
<tr>
<th>Screencast (Builtin Japanese IME)</th>
<td>


![win-jpn-after](https://github.com/user-attachments/assets/c69e5f48-65b1-4c0f-af4a-522d2f47b75d)
</td>
<td>


![win-jpn-before](https://github.com/user-attachments/assets/a0f1fdad-4f6c-40c2-af57-029f42acf6d5)
</td>
</tr>
</tbody>
</table>

### macOS: was buggy, still buggy

Likely due to this upstream bug in `winit`:
https://github.com/rust-windowing/winit/issues/4432
Once `winit` is updated to a version that includes the fix, the behavior
should become correct with this PR.

<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
<th>Without this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Behavior</th>
<td>Buggy as before</td>
<td>Buggy: Characters are duplicated</td>
</tr>
<tr>
<th>Screencast</th>
<td>


![mac-kor-after](https://github.com/user-attachments/assets/c2bd90e8-e473-49c8-9537-c970c92889bf)
</td>
<td>


![mac-kor-before](https://github.com/user-attachments/assets/63b6cd8a-8903-4743-98bf-ee15296354ba)
</td>
</tr>
</tbody>
</table>

### Wayland + iBus: Korean IME duplication bug fixed

<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
<th>Without this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Behavior</th>
<td>Correct</td>
<td>Buggy: Characters are duplicated</td>
</tr>
<tr>
<th>Screencast</th>
<td>


![wayland-kor-after-2](https://github.com/user-attachments/assets/b154add5-a1ce-4e3a-b243-e72480820c1b)
</td>
<td>


![wayland-kor-before-2](https://github.com/user-attachments/assets/43b28374-f273-4b6f-9845-3efd96ec9a37)
</td>
</tr>
</tbody>
</table>

### Wayland + iBus: #7485 is fixed

<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
<th>Without this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Behavior</th>
<td>Correct</td>
<td>Buggy: Only a single ASCII character can be typed after
<code>TextEdit</code> is focused</td>
</tr>
<tr>
<th>Screencast</th>
<td>


![wayland-7485-after](https://github.com/user-attachments/assets/ec33a54d-1d4e-40f9-8c82-202104bd2d85)
</td>
<td>


![wayland-7485-before](https://github.com/user-attachments/assets/20d2d395-03fd-4966-a376-87249a41aab3)
</td>
</tr>
</tbody>
</table>

### Wayland + iBus: selection is also not broken

This PR does not reintroduce the selection bug fixed in #7973.

<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Behavior</th>
<td>Correct</td>
</tr>
<tr>
<th>Screencast</th>
<td>


![wayland-focus-after](https://github.com/user-attachments/assets/daa29197-f7f7-4a7b-b454-c28ee9afa9c1)
</td>
</tr>
</tbody>
</table>

### X11 + Fcitx5: IME composition can be interrupted

But due to #7975, the experience is still subpar. (Uncommitted text is
lost after interruption.)

<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
<th>Without this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Screencast</th>
<td>


![x11-after](https://github.com/user-attachments/assets/e626d9ed-89a2-4825-9cde-3a67723bcb82)
</td>
<td>


![x11-before](https://github.com/user-attachments/assets/da93b351-9488-4da9-aa56-b64190e84ec3)
</td>
</tr>
</tbody>
</table>


[`Memory`]: https://docs.rs/egui/latest/egui/struct.Memory.html
[`TextEdit`]:
https://docs.rs/egui/latest/egui/widgets/text_edit/struct.TextEdit.html
[`PlatformOutput`]:
https://docs.rs/egui/latest/egui/struct.PlatformOutput.html
[`TextEditState`]:
https://docs.rs/egui/latest/egui/widgets/text_edit/struct.TextEditState.html
2026-04-06 10:24:50 +02:00
Emil Ernerfeldt
4a09782fce Enable a few more clippy lints (#8064)
Enable these new clippy lints and fix all warnings:

* `format_push_string` — use `write!` instead of `s += &format!(…)` to
avoid extra allocations
* `ignored_unit_patterns` — use `()` instead of `_` when matching unit
* `missing_fields_in_debug` — ensure manual `Debug` impls account for
all fields
* `needless_raw_string_hashes` — remove unnecessary `r#` on string
literals
* `ref_option` — prefer `Option<&T>` over `&Option<T>` in function
signatures
2026-04-04 16:20:29 +02:00
Emil Ernerfeldt
c2b482ff7e Flip if-else:s with a negation (#8063) 2026-04-04 12:03:41 +02:00
Emil Ernerfeldt
a01193d032 Release 0.34.1: Enable WebGL fallback in eframe 2026-03-27 11:25:58 +01:00
Matt Keeter
f325097611 Only apply cursor style to the <canvas> (#8036)
<!--
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 improves cases where the canvas does not cover the full screen,
which was a goal in [release
0.28.0](https://github.com/emilk/egui/releases/tag/0.28.0).

* Closes <https://github.com/emilk/egui/issues/8035>
* [X] I have followed the instructions in the PR template
2026-03-27 11:18:52 +01:00
Emil Ernerfeldt
3cf3141e8f wgpu backend: Enable WebGL fallback (#8038)
* Fix for https://github.com/emilk/eframe_template/issues/223
* Related: https://github.com/gfx-rs/wgpu/pull/9319

By default, we would only turn on the WebGPU backend on web, which means
browsers without WebGPU support would just crash.

You can still opt-out of all the default `wgpu` features by enabling
`eframe/wgpu_no_default_features` instead of `eframe/wgpu`
2026-03-27 11:12:46 +01:00
Lucas Meurer
82a578e58c Release 0.34.0 - More Ui, less Context (#8028)
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2026-03-26 12:15:41 +01:00
Lucas Meurer
f1236f1c61 Fix missing objc2-app-kit features (#8025)
Was missing some features
2026-03-25 19:00:28 +01:00
Emil Ernerfeldt
0887b54c93 Add eframe::WindowChromeMetrics (macOS only) (#8015)
When using `egui::ViewportBuilder::with_fullsize_content_view` one must
be careful not to paint anything where the "traffic light" buttons are:

<img width="87" height="47" alt="image"
src="https://github.com/user-attachments/assets/0e878c8e-7141-4fed-bbc8-4d542ddb5251"
/>

`eframe::WindowChromeMetrics` helps you with that!
2026-03-25 10:54:17 +01:00
Gautier Cailly
cd3c38cf2a Improve behavior of invisible windows (#7905)
## 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>
2026-03-24 16:20:57 +01:00
Emil Ernerfeldt
96cae39fb8 Update a couple of dependencies (#8009)
* Closes https://github.com/emilk/egui/pull/7992
2026-03-24 15:59:53 +01:00
Andreas Reich
d985bf9b83 Fill in DisplayHandle automatically on web painter just like it's done on winit (#8006)
* Closes https://github.com/emilk/egui/issues/8001
* Follow-up to https://github.com/emilk/egui/pull/7990

Also simplified/shortened the comments around display handle a bit. Lots
a repetition there made it hard to upgrade otherwise.
2026-03-24 12:37:33 +01:00
Emil Ernerfeldt
7fbd1315ec Include LICENSE files in published crates (#8004)
* Closes https://github.com/emilk/egui/issues/7977
2026-03-24 11:28:49 +01:00
Connor Fitzgerald
a59e803f25 Update to wgpu 29 (#7990)
* [x] I have followed the instructions in the PR template

This updates wgpu to v29 across the egui crate stack.

There a a few API changes due to the requirement to provide a display
handle up front to properly support GLES on linux. I have done my best
to make the api changes as reasonable as possible, but I don't have all
the greater project context, so lmk if things should be done a bit
differently.

I've also updated glow to 0.17 to make cargo deny happy, there are no
source changes. I'm not sure how you want to land these.

---------

Co-authored-by: lucasmerlin <hi@lucasmerlin.me>
2026-03-23 18:21:25 +01:00
Emil Ernerfeldt
49fad9a7b2 Roll out new egui icon and logo (#7995)
For the first time _ever_, egui has a logo!

<img width="3925" height="1406" alt="egui-logo"
src="https://github.com/user-attachments/assets/cfaf1d43-9338-490f-ae82-99b420baa1b0"
/>

Made by [Studio Gruhl](https://www.studiogruhl.com/) and paid for by
[Rerun.io](https://rerun.io/).
2026-03-21 22:47:15 +01:00
SuchAFuriousDeath
41b8f5f4e7 Update wgpu to 28.0.0 (#7853)
Co-authored-by: lucasmerlin <hi@lucasmerlin.me>
2026-03-16 11:56:07 +01:00
Emil Ernerfeldt
1b8a9fe95e Only run App::ui if the application is visible (#7950)
* Closes https://github.com/emilk/egui/issues/5113
* Part of https://github.com/emilk/egui/issues/5112
* Part of https://github.com/emilk/egui/issues/5136

If the application is invisible (occluded or minimized), and the user
calls `.request_repaint`, then we should call `App::logic`, but NOT
`App::ui`.

There are still some situations where `App::logic` is not called when it
should be, but at least now we can skip running the UI code when the app
is invisible.
2026-03-02 19:30:24 +01:00
Emil Ernerfeldt
2be6e225bf Add ViewportInfo::occluded and visible (#7948)
* Part of https://github.com/emilk/egui/issues/5112
* Part of https://github.com/emilk/egui/issues/5113
* Part of https://github.com/emilk/egui/issues/5136

Once we support calling `App::logic` when an app is occluded or
minimized, it is useful to know that it is, in fact, occluded or
minimized.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-02 18:36:04 +01:00
Matthew Runo
9276778181 Avoid repaints on device mouse motion outside window (#7866)
## 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>
2026-03-02 13:00:18 +01:00
Jiayi Zhuang
e505d98215 Fix: update get_proc_address to use Arc for better ownership management (#7922)
<!--
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.
2026-03-02 08:59:29 +01:00
Jasper Riedel
661d5f9173 Update MSRV from 1.88 to 1.92 (#7793) 2025-12-20 13:52:34 +01:00
Emil Ernerfeldt
8d98763fe1 Replace #[allow attributes with expect (#7796)
We do have `clippy::allow_attributes` turned on, but it doesn't seem to
work properly
2025-12-19 20:55:50 +01:00
Emil Ernerfeldt
7fe58bbfd4 Forbid uses of unwrap() in the code (#7795) 2025-12-19 20:34:18 +01:00
Emil Ernerfeldt
011c59c2ad Apply nightly clippy suggestions/fixes (#7794)
* Reduce the diff for https://github.com/emilk/egui/pull/7793
2025-12-19 18:43:58 +01:00
Emil Ernerfeldt
986c2c0ffb Use explicit Arc::clone to clarify when clones are cheap (#7784) 2025-12-17 17:19:18 +01:00
Emil Ernerfeldt
2f6fe9c572 eframe: Replace Frame::update with fn logic and fn ui (#7775)
* 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` ?
2025-12-16 17:05:50 +01:00
Emil Ernerfeldt
453e34b4df Rename functions in Context to avoid confusion (#7773)
It's important to avoid confusion after
* https://github.com/emilk/egui/pull/7770
2025-12-14 16:49:51 +01:00
Emil Ernerfeldt
bc48599f65 Rename Context::style to global_style; avoid confusion w/ Ui::style (#7772)
This is important after
* https://github.com/emilk/egui/pull/7770
2025-12-14 16:41:13 +01:00
Emil Ernerfeldt
a0bb4cfef8 Release 0.33.3: update cargo version and changelog 2025-12-11 15:42:15 +01:00
switch
2115ca941b egui-wgpu: attach stencil buffer (#7702) 2025-12-07 23:34:26 +01:00
Jochen Görtler
2dbfe3a083 Enable or_fun_call lint to avoid unnecessary allocations (#7754)
### 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.
2025-12-05 10:46:34 +01:00
Emil Ernerfeldt
d53a4a9c1d Update docs to reflect that wgpu is the default renderer (#7719)
I missed a few parts when merging
* https://github.com/emilk/egui/pull/7615
2025-11-18 15:56:35 +01:00
Bruno Paré-Simard
5b6a0196f9 Add Panel to replace SidePanel and TopBottomPanel (#5659)
This combines `SidePanel` and `TopBottomPanel` into a single `Panel`.

The old types are still there as type aliases, but are deprecated.

`.min_width(…)` etc are now called `.min_size(…)` etc.

Again, the old names are still there, but deprecated.

(edited by @emilk)

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2025-11-18 15:46:01 +01:00
Emil Ernerfeldt
01770be13e Update changelogs and version for 0.33.2 2025-11-13 15:33:08 +01:00
Emil Ernerfeldt
9ef610e16b Make wgpu the default renderer for eframe and egui.rs (#7615)
* Closes https://github.com/emilk/egui/issues/5889

See the above issue for motivation.

To use glow instead, disable the default features of `eframe` and opt-in
to `glow`.

This also changes egui.rs to use wgpu, which means WebGPU when
available, and WebGL otherwise
2025-11-13 11:16:23 +01:00
Stefan Tammer
51b0d0e4b9 [egui-wgpu] Put the capture module behind a feature flag, make the egui dependency optional (#7698)
This PR enables users of `egui-wgpu` to render `epaint` primitives
without having to bring in the complete `egui` crate and all it's
dependencies.

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2025-11-13 11:16:10 +01:00
Emil Ernerfeldt
df6f35d568 eframe: add feature wgpu_no_default_features (#7700)
* 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.
2025-11-12 10:51:38 +01:00
Emil Ernerfeldt
1af5d1d37e Remove accesskit feature and always depend on accesskit (#7701)
* Closes #3137

With this, `egui` will always depend on `accesskit`, removing a lot of
`#[cfg(feature = "accesskit")]` throughout the code.
2025-11-12 10:51:28 +01:00
Emil Ernerfeldt
31d313572b Make sure native_pixels_per_point is set during app creation (#7683)
Useful for things like analytics
2025-11-05 10:35:57 +01:00
ASPCartman
c5347f28e4 Fix jittering during window resize on MacOS for WGPU/Metal (#7641)
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2025-11-01 12:55:56 +01:00