* 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` ?
## Short bluesky announcement:
We just released egui 0.33.0!
Highlights:
- `egui::Plugin` a improved way to create and access egui plugins
- [kitdiff](https://github.com/rerun-io/kitdiff), a viewer for
egui_kittest image snapshots (and a general image diff tool)
- better kerning (check the diff on
[kitdiff](https://rerun-io.github.io/kitdiff/?url=https://github.com/emilk/egui/pull/7431))
https://github.com/user-attachments/assets/971f0493-6dae-42e5-8019-58b74cf5d203
## Relaese Changelog:
egui is an easy-to-use immediate mode GUI for Rust that runs on both web
and native.
Try it now: <https://www.egui.rs/>
egui development is sponsored by [Rerun](https://www.rerun.io/), a
startup building an SDK for visualizing streams of multimodal data.
# egui 0.33.0 changelog
Highlights from this release:
- `egui::Plugin` a improved way to create and access egui plugins
- [kitdiff](https://github.com/rerun-io/kitdiff), a viewer for
egui_kittest image snapshots (and a general image diff tool)
- better kerning
### Improved kerning
As a step towards using [parley](https://github.com/linebender/parley)
for font rendering, @valadaptive has refactored the font loading and
rendering code. A result of this (next to the font rendering code being
much nicer now) is improved kerning.
Notice how the c moved away from the k:

### `egui::Plugin` trait
We've added a new trait-based plugin api, meant to replace
`Context::on_begin_pass` and `Context::on_end_pass`.
This makes it a lot easier to handle state in your plugins. Instead of
having to write to egui memory it can live right on your plugin struct.
The trait based api also makes easier to add new hooks that plugins can
use. In addition to `on_begin_pass` and `on_end_pass`, the `Plugin`
trait now has a `input_hook` and `output_hook` which you can use to
inspect / modify the `RawInput` / `FullOutput`.
### kitdiff, a image diff viewer
At rerun we have a ton of snapshots. Some PRs will change most of them
(e.g. [the](https://github.com/rerun-io/rerun/pull/11253/files)
[one](https://rerun-io.github.io/kitdiff/?url=https://github.com/rerun-io/rerun/pull/11253/files)
that updated egui and introduced the kerning improvements, ~500
snapshots changed!).
If you really want to look at every changed snapshot it better be as
efficient as possible, and the experience on github, fiddeling with the
sliders, is kind of frustrating.
In order to fix this, we've made
[kitdiff](https://rerun-io.github.io/kitdiff/).
You can use it locally via
- `kitdiff files .` will search for .new.png and .diff.png files
- `kitdiff git` will compare the current files to the default branch
(main/master)
Or in the browser via
- going to https://rerun-io.github.io/kitdiff/ and pasting a PR or
github artifact url
- linking to kitdiff via e.g. a github workflow
`https://rerun-io.github.io/kitdiff/?url=<link_to_pr_or_artefact>`
To install kitdiff run `cargo install --git
https://github.com/rerun-io/kitdiff`
Here is a video showing the kerning changes in kitdiff ([try it
yourself](https://rerun-io.github.io/kitdiff/?url=https://github.com/rerun-io/rerun/pull/11253/files)):
https://github.com/user-attachments/assets/74640af1-09ba-435a-9d0c-2cbeee140c8f
### Migration guide
- `egui::Mutex` now has a timeout as a simple deadlock detection
- If you use a `egui::Mutex` in some place where it's held for longer
than a single frame, you should switch to the std mutex or parking_lot
instead (egui mutexes are wrappers around parking lot)
- `screen_rect` is deprecated
- In order to support safe areas, egui now has `viewport_rect` and
`content_rect`.
- Update all usages of `screen_rect` to `content_rect`, unless you are
sure that you want to draw outside the `safe area` (which would mean
your Ui may be covered by notches, system ui, etc.)
Breaking change!
* `Rounding` -> `CornerRadius`
* `rounding` -> `corner_radius`
This is to:
* Clarify
* Conform to other systems (e.g. Figma)
* Avoid confusion with `GuiRounding`
* Part of https://github.com/emilk/egui/issues/4019
`Frame` now includes the width of the stroke as part of its size. From
the new docs:
### `Frame` docs
The total (outer) size of a frame is `content_size + inner_margin +
2*stroke.width + outer_margin`.
Everything within the stroke is filled with the fill color (if any).
```text
+-----------------^-------------------------------------- -+
| | outer_margin |
| +------------v----^------------------------------+ |
| | | stroke width | |
| | +------------v---^---------------------+ | |
| | | | inner_margin | | |
| | | +-----------v----------------+ | | |
| | | | ^ | | | |
| | | | | | | | |
| | | |<------ content_size ------>| | | |
| | | | | | | | |
| | | | v | | | |
| | | +------- content_rect -------+ | | |
| | | | | |
| | +-------------fill_rect ---------------+ | |
| | | |
| +----------------- widget_rect ------------------+ |
| |
+---------------------- outer_rect ------------------------+
```
The four rectangles, from inside to outside, are:
* `content_rect`: the rectangle that is made available to the inner
[`Ui`] or widget.
* `fill_rect`: the rectangle that is filled with the fill color (inside
the stroke, if any).
* `widget_rect`: is the interactive part of the widget (what sense
clicks etc).
* `outer_rect`: what is allocated in the outer [`Ui`], and is what is
returned by [`Response::rect`].
### Notes
This required rewriting a lot of the layout code for `egui::Window`,
which was a massive pain. But now the window margin and stroke width is
properly accounted for everywhere.
<!--
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!
-->
* [X] I have followed the instructions in the PR template
I am preparing a separate PR that adds support for JXL with `jxl-oxide`,
which is unlikely to be added to the `image` crate anytime soon (more
context will be provided in that PR).
`jxl-oxide` makes use of the
[`array::each_mut`](https://doc.rust-lang.org/stable/std/primitive.array.html#method.each_mut)
API which was stabilized in 1.77, which is the motivation for this MSRV
bump.
Rust 1.77 was officially released to stable on 21 March, 2024.
* Closes <https://github.com/emilk/egui/issues/4490>
* [x] I have followed the instructions in the PR template
---
Unfortunately, this PR contains a bunch of breaking changes because
`Context` no longer has one style, but two. I could try to add some of
the methods back if that's desired.
The most subtle change is probably that `style_mut` mutates both the
dark and the light style (which from the usage in egui itself felt like
the right choice but might be surprising to users).
I decided to deviate a bit from the data structure suggested in the
linked issue.
Instead of this:
```rust
pub theme: Theme, // Dark or Light
pub follow_system_theme: bool, // Change [`Self::theme`] based on `RawInput::system_theme`?
```
I decided to add a `ThemePreference` enum and track the current system
theme separately.
This has a couple of benefits:
* The user's theme choice is not magically overwritten on the next
frame.
* A widget for changing the theme preference only needs to know the
`ThemePreference` and not two values.
* Persisting the `theme_preference` is fine (as opposed to persisting
the `theme` field which may actually be the system theme).
The `small_toggle_button` currently only toggles between dark and light
(so you can never get back to following the system). I think it's easy
to improve on this in a follow-up PR :)
I made the function `pub(crate)` for now because it should eventually be
a method on `ThemePreference`, not `Theme`.
To showcase the new capabilities I added a new example that uses
different "accent" colors in dark and light mode:
<img
src="https://github.com/user-attachments/assets/0bf728c6-2720-47b0-a908-18bd250d15a6"
width="250" alt="A screenshot of egui's widget gallery demo in dark mode
using a purple accent color instead of the default blue accent">
<img
src="https://github.com/user-attachments/assets/e816b380-3e59-4f11-b841-8c20285988d6"
width="250" alt="A screenshot of egui's widget gallery demo in light
mode using a green accent color instead of the default blue accent">
---------
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!
-->
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
* Closes#4534
This PR:
- Introduces `Ui::stack()`, which returns the `UiStack` structure
providing information on the current `Ui` hierarchy.
- **BREAKING**: `Ui::new()` now takes a `UiStackInfo` argument, which is
used to populate some of this `Ui`'s `UiStack`'s fields.
- **BREAKING**: `Ui::child_ui()` and `Ui::child_ui_with_id_source()` now
take an `Option<UiStackInfo>` argument, which is used to populate some
of the children `Ui`'s `UiStack`'s fields.
- New `Area::kind()` builder function, to set the `UiStackKind` value of
the `Area`'s `Ui`.
- Adds a (minimalistic) demo to egui demo (in the "Misc Demos" window).
- Adds a more thorough `test_ui_stack` test/playground demo.
TODO:
- [x] benchmarks
- [x] add example to demo
Future work:
- Add `UiStackKind` and related support for more container (e.g.
`CollapsingHeader`, etc.)
- Add a tag/property system that would allow adding arbitrary data to a
stack node. This data could then be queried by nested `Ui`s. Probably
needed for #3284.
- Add support to track columnar layouts.
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
Fix: example `custom_window_frame`
Sending `ViewportCommand::StartDrag` when the secondary button is
clicked in Windows will disable drag, and drag will not be possible with
the primary button afterwards.
So in the example `custom_window_frame`, modified to use
`dragged_by(PointerButton::Primary)` instead of
`is_pointer_button_down_on()`.
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
Motivation: I want to replace `cargo-cranky` with workspace lints, first
available in Rust 1.74.
However, `cargo doc` would hange on `wgpu` and `wgpu-core` on 1.74 and
1.75… so now we're on 1.76.
I think this is fine - when 1.78 is released next week we're still two
versions behind the bleeding edge.
…and the branch name is just wrong 🤦
* Closes https://github.com/emilk/egui/issues/3941
Workspace dependencies can be annoying.
If you don't set them to `default-features=false`, then you cannot opt
out of their default features anywhere else, and get warnings if you
try.
So you set `default-features=false`, and then you need to manually opt
in to the default features everywhere else.
Or, as in my case, don't.
I don't have the energy to do this tonight, so I'll just revert.
* Part of https://github.com/emilk/egui/issues/3556
This PR replaces a bunch of options in `eframe::NativeOptions` with
`egui::ViewportBuilder`. For instance:
``` diff
let options = eframe::NativeOptions {
- initial_window_size: Some(egui::vec2(320.0, 240.0)),
- drag_and_drop_support: true,
+ viewport: egui::ViewportBuilder::default()
+ .with_inner_size([320.0, 240.0])
+ .with_drag_and_drop(true),
centered: true,
..Default::default()
};
```
* Part of https://github.com/emilk/egui/issues/3556
## In short
You now almost never need to use `eframe::Frame` - instead use
`ui.input(|i| i.viewport())` for information about the current viewport
(native window), and use `ctx.send_viewport_cmd` to modify it.
## In detail
This PR removes most commands from `eframe::Frame`, and replaces them
with `ViewportCommand`.
So `frame.close()` becomes
`ctx.send_viewport_cmd(ViewportCommand::Close)`, etc.
`frame.info().window_info` is now also gone, replaced with `ui.input(|i|
i.viewport())`.
`frame.info().native_pixels_per_point` is replaced with `ui.input(|i|
i.raw.native_pixels_per_point)`.
`RawInput` now contains one `ViewportInfo` for each viewport.
Screenshots are taken with
`ctx.send_viewport_cmd(ViewportCommand::Screenshots)` and are returned
in `egui::Event` which you can check with:
``` ust
ui.input(|i| {
for event in &i.raw.events {
if let egui::Event::Screenshot { viewport_id, image } = event {
// handle it here
}
}
});
```
### Motivation
You no longer need to pass around the `&eframe::Frame` everywhere.
This also opens the door for other integrations to use the same API of
`ViewportCommand`s.