Native is already delayed by a frame because it calls
`handle_viewport_output` -> `egui_winit::process_viewport_commands`
after drawing. On web however, we process input including viewport
commands separately from drawing.
This adds an arbitrary frame delay mechanism for web and then uses this
with 1 frame delay always
When there are multiple layers (e.g. with custom transforms) close to
each other, the hit test code used to only consider widgets in the layer
directly under the mouse. This can make it difficult to hit thin widgets
just on the outside of a transform layer.
This PR fixes that.
It also prioritizes thin widgets, so that if there is both a thin widget
and a thick widget under the mouse cursor, you will always hit the thin
widgets, even if the thin widgets is layered behind the thick one. This
makes it easier to hit thin resize-handles.
In theory this should allow us to make `resize_grab_radius_side` and
`resize_grab_radius_corner` smaller in a future PR, if we want to.
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

We used to always set the cursor to `Grabbing` when a drag and drop
payload is set, but this shadows user code trying to set an alternative
cursor (e.g. `NoDrop`). This PR no only change the cursor to `Grabbing`
if is way previously set to `Default`.
<!--
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!
-->
Android support is "almost there". This PR pushes it just a bit further
by allowing `eframe` to be used on Android. It works by smuggling the
`AndroidApp` required by `winit` through `NativeOptions`.
The example isn't great because it doesn't leave space on the display
for Android's top status bar or the lower navigation bar. I don't know
what to do about that, yet. This is as far as I've managed to get it
working.
Another problem is that the development environment setup is completely
awful for Android unless you happen to already be a full-time Android
developer with everything configured on your build host. As a Rustacean,
this makes me very sad.
I've had some luck moving all of that mess to a container, adapted from
https://github.com/SergioRibera/docker-rust-android. It takes care of
all of the build dependencies, Android SDK, and the `cargo-apk` patches
for bugs that I hit while getting the example to work on my device. (I
also had to install an adb driver on my host and downloaded the Android
platform-tools to get access to `adb`. An alternative is exposing the
USB device to Docker. On Windows hosts, that means [installing
`usbipd`](https://learn.microsoft.com/en-us/windows/wsl/connect-usb). A
second alternative is using an `mtp` client to upload the APK as a file
with USB file transfer enabled, then manually install it through the
device's file manager.)
I'm not including the docker stuff in this PR, but here are the files
and instructions for future reference (and it will probably simplify
manual testing and CI, FWIW!)
<details><summary><code>Dockerfile</code></summary>
```dockerfile
FROM rust:1.76.0-slim
# Variable arguments
ARG JAVA_VERSION=17
ARG NDK_VERSION=25.1.8937393
ARG BUILDTOOLS_VERSION=30.0.0
ARG PLATFORM_VERSION=android-30
ARG CLITOOLS_VERSION=8512546_latest
# Install Android requirements
RUN apt-get update -yqq && \
apt-get install -y --no-install-recommends \
libcurl4-openssl-dev libssl-dev pkg-config build-essential git python3 wget zip unzip openjdk-${JAVA_VERSION}-jdk && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# Install android targets
RUN rustup target add armv7-linux-androideabi aarch64-linux-android
# Install cargo-apk
RUN git clone -b fix/bin-targets-workspace-members https://github.com/parasyte/cargo-apk.git /tmp/cargo-apk && \
cargo install --path /tmp/cargo-apk/cargo-apk
# Generate Environment Variables
ENV JAVA_VERSION=${JAVA_VERSION}
ENV ANDROID_HOME=/opt/Android
ENV NDK_HOME=/opt/Android/ndk/${NDK_VERSION}
ENV ANDROID_NDK_ROOT=${NDK_HOME}
ENV PATH=$PATH:${ANDROID_HOME}:${ANDROID_NDK_ROOT}:${ANDROID_HOME}/build-tools/${BUILDTOOLS_VERSION}:${ANDROID_HOME}/cmdline-tools/bin
# Install command line tools
RUN mkdir -p ${ANDROID_HOME}/cmdline-tools && \
wget -qc "https://dl.google.com/android/repository/commandlinetools-linux-${CLITOOLS_VERSION}.zip" -P /tmp && \
unzip -d ${ANDROID_HOME} /tmp/commandlinetools-linux-${CLITOOLS_VERSION}.zip && \
rm -fr /tmp/commandlinetools-linux-${CLITOOLS_VERSION}.zip
# Install sdk requirements
RUN echo y | sdkmanager --sdk_root=${ANDROID_HOME} --install \
"build-tools;${BUILDTOOLS_VERSION}" "ndk;${NDK_VERSION}" "platforms;${PLATFORM_VERSION}"
# Create APK keystore for debug profile
# Adapted from caa806283d/ndk-build/src/ndk.rs (L393-L423)
RUN keytool -genkey -v -keystore ${HOME}/.android/debug.keystore -storepass android -alias androiddebugkey \
-keypass android -dname 'CN=Android Debug,O=Android,C=US' -keyalg RSA -keysize 2048 -validity 10000
# Cleanup
RUN rm -rf /tmp/*
WORKDIR /src
ENTRYPOINT [ "cargo", "apk", "build" ]
```
</details>
<details><summary><code>.dockerignore</code></summary>
```ignore
# Ignore everything, only the Dockerfile is needed to build the container
*
```
</details>
```sh
docker build -t rust-android:latest .
docker run --rm -it -v "$PWD:/src" rust-android:latest -p hello_android
adb install target/debug/apk/hello_android.apk
```
* Part of #2066
* [x] I have followed the instructions in the PR template
This implements web support for taking screenshots in an eframe app (and
adds a nice demo).
It also updates the native screenshot implementation to work with the
wgpu gl backend.
The wgpu implementation is quite different than the native one because
we can't block to wait for the screenshot result, so instead I use a
channel to pass the result to a future frame asynchronously.
* Closes <https://github.com/emilk/egui/issues/5425>
* [x] I have followed the instructions in the PR template
https://github.com/user-attachments/assets/67cad40b-0384-431d-96a3-075cc3cb98fb
This makes it easy to get the current transform of a layer, and uses
consistent naming everywhere.
`Memory::layer_transforms` is now called `Memory::to_global`, because
the old name was ambiguous (transform into what direction?)
<!--
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
This PR makes an area's interact rect intersect its constrain rect. This
fixes an issue where masked areas would still intercept input.
Before:

After:

<!--
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 introduced this in #5433.
TL;DR: there are two termination conditions for drag-and-drop
operations:
- ESC
- release mouse
The former _must_ happen at frame start (to properly capture the
keystroke). The latter _must_ happen at end-of-frame (to _not_ shadow
the mouse release event from user code).
This is now properly documented.
<!--
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
### Problem
When clicking on a TextEdit sometimes the cursor doesn't appear
immediately which makes it feel like the click was not registered for a
second. This is because the start time for the blinking animation is
only reset on keyboard input, but not on mouse interaction.
It's hard to tell on the video but the cursor doesn't show immediately
after clicking if the blink timer happens to be off.
https://github.com/user-attachments/assets/9f049bd0-0375-4291-b2ef-697777fb854d
### Solution
Reset the click timer every time a `TextEdit` is clicked.
Additionally, the cursor is now correctly painted on the pixel boundary.
IMO we should default to 1px cursor (instead of 2px) but that's not
included in this PR. Happy to make that change too.
https://github.com/user-attachments/assets/6c489414-f2c4-4dc6-85dd-f8bc457edad0
This moves `egui::util::cache` to `egui::cache` (the old path is
deprecated, but still works).
It also adds the `FramePublisher` helper, which can be used to publish a
value which will be retained for this frame and the next:
``` rs
pub type MyPublisher = egui::cache::FramePublisher<MyKey, MyValue>;
// Publish:
ctx.memory_mut(|mem| {
mem.caches.cache::<MyPublisher>().set(key, value);
});
// Retrieve:
let value: Option<MyValue> = ctx.memory_mut(|mem| {
mem.caches
.cache::<MyPublisher>()
.get(key)
.clone()
})
```
* Closes https://github.com/emilk/egui/issues/5423
New output is actionable
```
failures:
---- demo::demo_app_windows::tests::demos_should_match_snapshot stdout ----
thread 'demo::demo_app_windows::tests::demos_should_match_snapshot' panicked at crates/egui_demo_lib/src/demo/demo_app_windows.rs:433:9:
Errors: [
"'demos/Code Example' Image size did not match snapshot. Expected: (402, 574), Actual: (415, 574).
Run `UPDATE_SNAPSHOTS=1 cargo test` to update the snapshots.",
]
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
demo::demo_app_windows::tests::demos_should_match_snapshot
```
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.
* 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 cranky`.
* 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#1531
### Before
Notice how the cursor hides after third enter and when the line is long.
https://github.com/user-attachments/assets/8e45736e-d6c7-4dc6-94d0-213188c199ff
### After
Cursor is always visible
https://github.com/user-attachments/assets/43200683-3524-471b-990a-eb7b49385fa9
- `ScrollArea` now checks if there's a `scroll_target` in `begin`, if
there is, it saves it because it's not from its children, then restore
it in `end`.
- `TextEdit` now allocates additional space if its galley grows during
the frame. This is needed so that any surrounding `ScrollArea` can bring
the cursor to view, otherwise the cursor lays outside the the
`ScrollArea`'s `content_ui`.
<!--
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!
-->
Title.
* [x] I have followed the instructions in the PR template
* Closes#686
* Closes#839
* #5370 should be merged before this
* [x] I have followed the instructions in the PR template
This adds modals to egui.
This PR
- adds a new `Modal` struct
- adds `Memory::set_modal_layer` to limit focus to a layer and above
(used by the modal struct, but could also be used by custom modal
implementations)
- adds `Memory::allows_interaction` to check if a layer is behind a
modal layer, deprecating `Layer::allows_interaction`
Current problems:
- ~When a button is focused before the modal opens, it stays focused and
you also can't hit tab to focus the next widget. Seems like focus is
"stuck" on that widget until you hit escape. This might be related to
https://github.com/emilk/egui/issues/5359~ fixed!
Possible future improvements:
- The titlebar from `window` should be made into a separate widget and
added to the modal
- The state whether the modal is open should be stored in egui
(optionally), similar to popup and menu. Ideally before this we would
refactor popup state to unify popup and menu
---------
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!
-->
* [X] I have followed the instructions in the PR template
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
eframe has features for selecting between x11 and wayland. eframe does
not forward the features to glutin. This makes glutin always compile
with both backends enabled. This change forwards the feature. This
allows users of egui to compile less dependencies when they only need
one of x11, wayland.
To understand this change, read the glutin Cargo.toml [1] and the glutin
build.rs [2]. You always have to enable glutin's glx feature with the
x11 feature. The other default features (egl, wgl) stay enabled. This is
intentional so that everything continues to work as before. We could
further minimize when egl and wgl are enabled, but that is not part of
this change. There is little reason to do so because those feature
already only add dependencies when you compile glutin for the right
platform (for example wgl on windows).
[1]
https://github.com/rust-windowing/glutin/blob/v0.32.1/glutin/Cargo.toml
[2]
https://github.com/rust-windowing/glutin/blob/v0.32.1/glutin/build.rs
- fixes https://github.com/emilk/egui/issues/5359
For the test I added a `Harness::press_key` function. We should
eventually add these to kittest, probably via a trait one can implement
for the `Harness` but for now this should do.
As someone who uses "grey" instead of "gray", it is annoying that my
autocomplete can never find any of the "gray" color related things, so
this adds doc aliases for that.
* [x] I have followed the instructions in the PR template
The allows us to pass any state to the ui closure. While it is possible
to just store state in the closure itself, accessing that state after
the harness was created to e.g. read or modify it would require interior
mutability. With this change there are new `Harness::new_state`,
`Harness::run_state`, ... methods that allow passing state on each run.
This builds on top of #5301, which should be merged first
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This adds a `Harness::new_ui`, which accepts a Ui closure and shows the
ui in a central panel. One big benefit is that this allows us to add a
fit_contents method that can run the ui closure with a sizing pass and
resize the "screen" based on the content size.
I also used this to add a snapshot test for the rendering_test at
different scales.
<!--
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 removed the webp supported URI test given that the webp feature would
have to be enabled. I kept that webp is not supported in the other
tests.
There might need to be an additional warning in the changelog that image
support detection is now stricter.
egui never accesses the `FontDefinitions`' member fields mutably, except
in `fonts_tweak_ui` where it cloned the `FontDefinitions` object anyway.
This patch reduces system memory consumption for shared font
definitions.
And also removes some overhead from copying (e.g. for the per
`pixel_per_points` font atlas)
Also it allows to keep a copy of the font definitions outside of egui.
In my App that uses international fonts:
Before:

New:

Note: If `Arc` is not wanted, then it could ofc be abstracted away.
I know this is quite a breaking change API wise, but would like to hear
your opinion.
<!--
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!
-->
The `RawInput::dropped_files` documentation referred to `NativeOptions`,
but the `drag_and_drop` option was moved to `ViewportBuilder` and is now
enabled by default.
Note that drag-and-drop is not *explicitly* enabled by default here, but
rather is enabled by default in winit. We only override winit's default
if the API consumer specifies it. It might be a good idea in general to
provide explicit defaults for everything in `ViewportBuilder` so we're
not relying on winit's behavior, but that's best left for another PR.
* Closes N/A
* [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!
-->
* [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.
This adds `egui_kittest::try_image_snapshot_options` and
`egui_kittest::image_snapshot_options`, as well as
`Harness::wgpu_snapshot_options` and
`Harness::try_wgpu_snapshot_options`
* [X] I have followed the instructions in the PR template
When mixing and matching eframe with other wgpu applications
(https://github.com/tracel-ai/burn in my case), it can be helpful to use
an existing wgpu setup to initialize eframe with. This PR changes the
WpuConfiguration (in a non-backwards compat way :/), to either take some
options how to create a wgpu setup, or an existing wgpu setup
(consisting of an instance, adapter, device and queue).
* [x] I have followed the instructions in the PR template
---------
Co-authored-by: Andreas Reich <r_andreas2@web.de>
This is controlled by the `accesskit` feature and nothing needs the
implicit `accesskit_winit` feature, so use `dep:` syntax to prevent it
from being created.
* [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!
-->
Currently `Style::override_font_id` does not affect widgets with their
`TextStyle` like `Button`s, `ComboBox`es, `CheckBox`es, etc. This PR
fixes this behavior such that all widgets using default configuration of
`RichText` are affected by this setting.
* [x] I have followed the instructions in the PR template
Fix: Window::default_pos does not work
Issues: Since `default_size` is not applied to `area`,
`style.spacing.default_area_size` is applied, causing problems.
* Closes#5314
Exposed the underlying PopupCloseBehavior of ComboBox in order to allow
more control of ComboBox behavior.
This allows ComboBox to be used rather than manually managing a popup
directly, while also gaining the convenience features of ComboBox such
as popup auto-sizing.
* [x] I have followed the instructions in the PR template
`Box<str>` is an immutable heap-allocated string slice.
This PR makes it more convenient to use them in labels for example.
Before this PR
```rust
let text: Box<str> = "Hello".into();
ui.label(text.into_string());
let text_ref: &Box<str> = &"Hello".into();
ui.label(text_ref.clone().into_string());
// or
ui.label(text_ref.as_ref());
// or
ui.label(&**text_ref);
```
After this PR
```rust
let text: Box<str> = "Hello".into();
ui.label(text);
let text_ref: &Box<str> = &"Hello".into();
ui.label(text_ref);
```
* [x] I have followed the instructions in the PR template
When using fonts with an average of 50,000 characters,
'epaint texture atlas overflowed!' may be printed and cause problems.
It is necessary to expand the max value related to texture.
* Closes#5256
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
Previously, all widgets would be listed in accesskit as children of the
toplevel window.
With this change, they will be reported as child of the `egui::Window`
they are in, Which should increase parseability of the ui for
screenreaders and integration tests.
Added an accesskit test to check that it is indeed working.
Co-authored-by: Wybe Westra <w.westra@kwantcontrols.nl>
Since textedit is doing the justify layout calculation itself, we need
to report the original desired_size as intrinsic size, instead of the
value passed to allocate_space.
I wonder though, is it still necessary that the TextEdit does the
justify calculation itself instead of relying on the ui layout to do it?
As far as I understand it, justify should be handled by the
ui.allocate_space call.
make it easier to add fonts.
For example if I want to add a custom FontFamily or if the user wants to
add a Chinese fallback
* [x] I have followed the instructions in the PR template
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
winit::Window::inner_size returns size of safe area on iOS. use
winit::Window::outer_size on iOS
The dimensions of outer_size include the title bar and borders, but as
far as I know there is no way to actually display the title bar or
borders on iOS so it should be fine.
<!--
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#3547
* [X] I have followed the instructions in the PR template
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This shortcut was previously triggering the Undo action due to the
matches_logically method ignoring the state of the Shift key. This was
solved by simply inverting the order of the undo and redo arms, so the
undo is not matched if the shortcut corresponds to redo.
* Closes <https://github.com/emilk/egui/issues/5255>
* [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!
-->
Run this code
```rs
CentralPanel::default().show(ctx, |ui| {
Sides::new().show(
ui,
|ui| {
ui.label("1");
},
|ui| {
ui.label("2");
},
);
Sides::new().show(
ui,
|ui| {
ui.label("11");
},
|ui| {
ui.label("22");
},
);
Sides::new().show(
ui,
|ui| {
ui.label("111");
},
|ui| {
ui.label("222");
},
);
});
```
Before

After

This should hopefully make it easier for egui contributors and
egui_kittest users to understand the snapshot tests
* [X] I have followed the instructions in the PR template
- closes#3491
- closes#3926
This adds a testing library to egui based on
[kittest](https://github.com/rerun-io/kittest). Kittest is a new
[AccessKit](https://github.com/AccessKit/accesskit/)-based testing
library. The api is inspired by the js
[testing-library](https://testing-library.com/) where the idea is also
to query the dom based on accessibility attributes.
We made kittest with egui in mind but it should work with any rust gui
framework with AccessKit support.
It currently has support for:
- running the egui app, frame by frame
- building the AccessKit tree
- ergonomic queries via kittest
- via e.g. get_by_name, get_by_role
- simulating events based on the accesskit node id
- creating arbitrary events based on Harness::input_mut
- rendering screenshots via wgpu
- snapshot tests with these screenshots
A simple test looks like this:
```rust
fn main() {
let mut checked = false;
let app = |ctx: &Context| {
CentralPanel::default().show(ctx, |ui| {
ui.checkbox(&mut checked, "Check me!");
});
};
let mut harness = Harness::builder().with_size(egui::Vec2::new(200.0, 100.0)).build(app);
let checkbox = harness.get_by_name("Check me!");
assert_eq!(checkbox.toggled(), Some(Toggled::False));
checkbox.click();
harness.run();
let checkbox = harness.get_by_name("Check me!");
assert_eq!(checkbox.toggled(), Some(Toggled::True));
// You can even render the ui and do image snapshot tests
#[cfg(all(feature = "wgpu", feature = "snapshot"))]
egui_kittest::image_snapshot(&egui_kittest::wgpu::TestRenderer::new().render(&harness), "readme_example");
}
```
~Since getting wgpu to run in ci is a hassle, I'm taking another shot at
creating a software renderer for egui (ideally without a huge dependency
like skia)~ (this didn't work as well as I hoped and it turns out in CI
you can just run tests on a mac runner which comes with a real GPU)
Here is a example of a failed snapshot test in ci, it will say which
snapshot failed and upload an artifact with the before / after and diff
images:
https://github.com/emilk/egui/actions/runs/11183049487/job/31090724606?pr=5166
* Closes#5224
I'm unfamiliar with wgpu, so I'd like someone to confirm, that calling
`wgpu::Texture` _after_ `wgpu::Queue::submit` is in fact the right thing
to do.
---------
Co-authored-by: Andreas Reich <r_andreas2@web.de>
Fixes#5174.
The drag velocity was not being updated unless the cursor counted as
"dragging", which only happens when it's in motion. This effectively
guarantees that the drag velocity will never be zero, even if the cursor
is not moving, and results in spurious scroll velocity being applied
when the cursor is released.
Instead, we update the velocity only when the drag is stopped, which is
when the kinetic scrolling actually needs to begin. Note that we
immediately *apply* the scroll velocity on the same frame that we first
set it, to avoid a 1-frame gap where the scroll area doesn't move.
I believe that *not* setting `scroll_stuck_to_end` and `offset_target`
when the drag is released is the correct thing to do, as they should
apply immediately once the user stops dragging. Should we maybe clear
the drag velocity instead if `scroll_stuck_to_end` is true or
`offset_target` exists?
* Closes#5174
* [x] I have followed the instructions in the PR template
This adds a new `Ui::unique_id` used in `Ui::response`.
I'll make a follow-up PR where the old `id` is renamed `stable_id`, and
deprecate `fn id` to force users to think through which `id` they want.
* Closes https://github.com/emilk/egui/issues/5190
Since ui's initial sound is a "y", it should be "a ui", not "an ui".
Replaced case-sensitively using regex `([aA])n ([uU][iI])` replacement
`$1 $2`
* [x] I have followed the instructions in the PR template
This will allow disabling the animation that occurs during
`scroll_to_row` calls. Follows the same coding style as the other scroll
options in `TableBuilder`.
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
It cannot be made const with the current version of Rust, and that is
counterintuitive since it does compile-time checks, so we make that
clear in the documentation. It might be possible to make it const once
MSRV is bumped to 1.82.
* See <https://github.com/emilk/egui/issues/5160>
* [x] I have followed the instructions in the PR template
Affects `.on_hover_text(…)` with dynamic content (i.e. content that
changes over time).
* Closes https://github.com/emilk/egui/issues/5167
`.on_hover_ui` with dynamic content can still hit the shrinking problem.
The general solution depends on solving
https://github.com/emilk/egui/issues/5138 but a work-around is to add
this to your tooltips:
```diff
response.on_hover_ui(|ui| {
+ ui.set_max_width(ui.spacing().tooltip_width);
// …
});
```
* Closes https://github.com/emilk/egui/pull/5106
* Closes https://github.com/emilk/egui/issues/5084
Protect against rounding errors in egui layout code.
Say the user asks to wrap at width 200.0.
The text layout wraps, and reports that the final width was 196.0
points.
This than trickles up the `Ui` chain and gets stored as the width for a
tooltip (say).
On the next frame, this is then set as the max width for the tooltip,
and we end up calling the text layout code again, this time with a wrap
width of 196.0.
Except, somewhere in the `Ui` chain with added margins etc, a rounding
error was introduced,
so that we actually set a wrap-width of 195.9997 instead.
Now the text that fit perfectly at 196.0 needs to wrap one word earlier,
and so the text re-wraps and reports a new width of 185.0 points.
And then the cycle continues.
So this PR limits the text wrap-width to be an integer.
Related issues:
* https://github.com/emilk/egui/issues/4927
* https://github.com/emilk/egui/issues/4928
* https://github.com/emilk/egui/issues/5163
---
Pleas test this @rustbasic
A very common usability issue on egui-wgpu callbacks is that `paint`
can't access any data that doesn't strictly outlive the callback
resources' data. E.g. if the callback resources have an `Arc` to some
resource manager, you can't easily pull out resources since you
statically needed to ensure that those resource references outlived the
renderpass, whose lifetime was only constrained to the callback
resources themselves.
Wgpu 22 no longer has this restriction! Its (render/compute-)passes take
care of the lifetime of any passed resource internally. The lifetime
constraint is _still_ opt-out since it protects from a common runtime
error of adding commands/passes on the parent encoder while a previously
created pass wasn't closed yet.
This is not a concern in egui-wgpu since the paint method where we have
to access the render pass doesn't even have access to the encoder!
<!--
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
Adds support for mipmaps in the `glow` backend.
Should be possible to implement for `wgpu` in the future as well, but
requires a custom compute kernel.
<!--
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#5053
* [x] I have followed the instructions in the PR template
This fixes#5053 by adding a Sense parameter to UiBuilder, using that in
Context::create_widget, so the Widget is registered with the right Sense
/ focusable. Additionally, I've added a ignore_focus param to
create_widget, so the focus isn't surrendered / reregistered on
Ui::interact_bg.
The example from #5053 now works correctly:
https://github.com/user-attachments/assets/a8a04b5e-7635-4e05-9ed8-e17d64910a35
<details><summary>Updated example code</summary>
<p>
```rust
ui.button("I can focus");
ui.scope_builder(
UiBuilder::new()
.sense(Sense::click())
.id_source("focus_test"),
|ui| {
ui.label("I can focus for a single frame");
let response = ui.interact_bg();
let t = if response.has_focus() {
"has focus"
} else {
"doesn't have focus"
};
ui.label(t);
},
);
ui.button("I can't focus :(");
```
</p>
</details>
---
Also, I've added `Ui::interact_scope` to make it easier to read a Ui's
response in advance, without having to know about the internals of how
the Ui Ids get created.
This makes it really easy to created interactive container elements or
custom buttons, without having to use Galleys or
Painter::add(Shape::Noop) to style based on the interaction.
<details><summary>
Example usage to create a simple button
</summary>
<p>
```rust
use eframe::egui;
use eframe::egui::{Frame, InnerResponse, Label, RichText, UiBuilder, Widget};
use eframe::NativeOptions;
use egui::{CentralPanel, Sense, WidgetInfo};
pub fn main() -> eframe::Result {
eframe::run_simple_native("focus test", NativeOptions::default(), |ctx, _frame| {
CentralPanel::default().show(ctx, |ui| {
ui.button("Regular egui Button");
custom_button(ui, |ui| {
ui.label("Custom Button");
});
if custom_button(ui, |ui| {
ui.label("You can even have buttons inside buttons:");
if ui.button("button inside button").clicked() {
println!("Button inside button clicked!");
}
})
.response
.clicked()
{
println!("Custom button clicked!");
}
});
})
}
fn custom_button<R>(
ui: &mut egui::Ui,
content: impl FnOnce(&mut egui::Ui) -> R,
) -> InnerResponse<R> {
let auto_id = ui.next_auto_id();
ui.skip_ahead_auto_ids(1);
let response = ui.interact_scope(
Sense::click(),
UiBuilder::new().id_source(auto_id),
|ui, response| {
ui.style_mut().interaction.selectable_labels = false;
let visuals = response
.map(|r| ui.style().interact(&r))
.unwrap_or(&ui.visuals().noninteractive());
let text_color = visuals.text_color();
Frame::none()
.fill(visuals.bg_fill)
.stroke(visuals.bg_stroke)
.rounding(visuals.rounding)
.inner_margin(ui.spacing().button_padding)
.show(ui, |ui| {
ui.visuals_mut().override_text_color = Some(text_color);
content(ui)
})
.inner
},
);
response
.response
.widget_info(|| WidgetInfo::new(egui::WidgetType::Button));
response
}
```
</p>
</details>
https://github.com/user-attachments/assets/281bd65f-f616-4621-9764-18fd0d07698b
---------
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!
-->
* Closes#5121
* [x] I have followed the instructions in the PR template
This unifies the code paths in `update_texture` somewhat, so that the
texture sampler and bind group are always replaced.
Not sure whether removing and reinserting the texture from and into the
`textures` map, or creating a new bind group, has much of a performance
impact. An alternative, as described in #5121, would be to split the
functionality for updating a texture's data from updating its options,
so that we don't have to unconditionally update the bind group (or do
something like store the options to check if they're changed).
Fix: `Event::Copy` and `Event::Cut` behave as if they select the entire
text when there is no selection.
It's unexpected and disconcerting that this behavior occurs when there
is no selected area.
Fix: panic when dragging window between monitors of different
pixels_per_point
This will continue to help us as we develop `egui`.
I hope you agree with my defense of `panic`.
* Relate #3959
* Relate #4088
* Closes#4178
* Closes#4179
There is also a way to add log if necessary.
```
log::debug!("Anti-panic behavior occurs");
```
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
When using a `DragValue`, there are three common modes of range clamping
that the user may want:
A) no clamping
B) clamping only user input (dragging or editing text), but leave
existing value intact
C) always clamp
The difference between mode B and C is:
```rs
let mut x = 42.0;
ui.add(DragValue::new(&mut x).range(0.0..=1.0));
// What will `x` be here?
```
With this PR, we now can get the three behaviors with:
* A): don't call `.range()` (or use `-Inf..=Inf`)
* B) call `.range()` and `.clamp_existing_to_range(false)`
* C) call `.range()`
## Slider clamping
Slider clamping is slightly different, since a slider always has a
range.
For a slider, there are these three cases to consider:
A) no clamping
B) clamp any value that the user enters, but leave existing values
intact
C) always clamp all values
Out of this, C should probably be the default.
I'm not sure what the best API is for this yet. Maybe an `enum` 🤔
I'll take a pass on that in a future PR.
## Related
* https://github.com/emilk/egui/pull/4728
* https://github.com/emilk/egui/issues/4881
* https://github.com/emilk/egui/pull/4882
Fix for a regression in 0.28
* `App::save` will now be called when the web app is hidden (e.g. goes
to a background tab)
* `App::update` will now be called when the web app is un-hidden (e.g.
becomes the foreground tab)
<!--
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
Note this will break people depending on eframe or egui-wgpu with
--no-default-features.
I don't know what to do about that to be honest.
* Closes#4914
* [x] I have followed the instructions in the PR template
---------
Co-authored-by: Andreas Reich <r_andreas2@web.de>
* 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!
-->
* Closes https://github.com/emilk/egui/issues/3549
* [X] I have followed the instructions in the PR template
The syntax highlighting font size was always hardcoded to 12 or 10
depending on what case it was hitting (so not consistent). This is
particularly noticeable when you increase the font size to something
larger for the rest of the ui.
With this the default monospace font size is used by default.
Since the issue is closely related to #3549 I decided to implement the
ability to use override_font_id too.
## Visualized
Default monospace is set to 15 in all the pictures
Before/After without syntect:

Before/after _with_ syntect:

Font override after without/with syntect (monospace = 20):

### Breaking changes
- `CodeTheme::dark` and `CodeTheme::light` takes in the font size
- `CodeTheme::from_memory` takes in `Style`
- `highlight` function takes in `Style`
* [X] I have followed the instructions in the PR template
This allows you to transform widgets without having to put them on a new
layer.
Example usage:
https://github.com/user-attachments/assets/6b547782-f15e-42ce-835f-e8febe8d2d65
```rust
use eframe::egui;
use eframe::egui::{Button, Frame, InnerResponse, Label, Pos2, RichText, UiBuilder, Widget};
use eframe::emath::TSTransform;
use eframe::NativeOptions;
use egui::{CentralPanel, Sense, WidgetInfo};
pub fn main() -> eframe::Result {
eframe::run_simple_native("focus test", NativeOptions::default(), |ctx, _frame| {
CentralPanel::default().show(ctx, |ui| {
let response = ui.ctx().read_response(ui.next_auto_id());
let pressed = response
.as_ref()
.is_some_and(|r| r.is_pointer_button_down_on());
let hovered = response.as_ref().is_some_and(|r| r.hovered());
let target_scale = match (pressed, hovered) {
(true, _) => 0.94,
(_, true) => 1.06,
_ => 1.0,
};
let scale = ui
.ctx()
.animate_value_with_time(ui.id().with("Down"), target_scale, 0.1);
let mut center = response
.as_ref()
.map(|r| r.rect.center())
.unwrap_or_else(|| Pos2::new(0.0, 0.0));
if center.any_nan() {
center = Pos2::new(0.0, 0.0);
}
let transform = TSTransform::from_translation(center.to_vec2())
* TSTransform::from_scaling(scale)
* TSTransform::from_translation(-center.to_vec2());
ui.with_visual_transform(transform, |ui| {
Button::new(RichText::new("Yaaaay").size(20.0))
.sense(Sense::click())
.ui(ui)
});
});
})
}
```
Improves performances significantly (about 40 times) according to the
benchmarks.
* Closes <https://github.com/emilk/egui/issues/5086>
* [x] I have followed the instructions in the PR template
As most of the code refers to types in epaint, it makes sense to use the
Color32 alias from epaint as well.
<!--
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
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>
Remove the crate visibility of the frame module. Useful at least when
using `Frame::begin` as otherwise the returned type is opaque to library
users and prevents from creating containers that use `Frame` with a
similar interface.
Alternative is to only export `frame::Prepared` as `PreparedFrame` or
something, but I saw that other submodules of containers are already
public.
<!--
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#2106
* [x] I have followed the instructions in the PR template
Extracted out of #4805
I'm using this widget type in [`egui-theme-switch`] but since it's not
built in I have to call `accesskit_node_builder` which is a bit
cumbersome :)
* [x] I have followed the instructions in the PR template
[`egui-theme-switch`]:
https://github.com/bash/egui-theme-switch/blob/main/src/lib.rs
Use `UiBuilder::new().sizing_pass().invisible()` instead.
Also changes `UiBuilder::sizing_pass` to no longer turn the ui
invisible. You'll have to opt-in to that instead when it makes sense,
e.g. for the first frame of a tooltip, but not when auto-sizing a column
in a `Table`.
This takes 3 hardcoded constants from `input_state.rs` and puts them in
a `InputOptions` struct that then gets added to `Options`. This allows
adjusting these values at runtime, for example, to increase
`MAX_CLICK_DIST` for touchscreen usage.
* [x] I have followed the instructions in the PR template
Currently egui will prevent all web events from propagating. This causes
issues in contexts where you are using egui in a larger web context that
wants to receive events that egui does not directly respond to. For
example, currently using egui in a VSCode extension will block all app
hotkeys, such as saving and opening the panel.
This adds a closure to `WebOptions` that takes in a reference to the
egui event that is generated from a web event and returns if the
corresponding web event should be propagated or not. The default for it
is to always return false.
Alternatives I considered were:
1. Having the propagation filter be a property of the focus in memory.
That way it could be configured by the view currently selected. I opted
away from that because I wanted to avoid lowering eframe implementation
specific stuff into egui.
2. Having events contain a `web_propagate` flag that could be set when
handling them. However, that would not be compatible with the current
system of egui events being handled outside of the web event handler.
I just recently started using egui so I am not sure how idiomatic my
approach here is. I would be happy to switch this over to a different
architecture if there are suggestions.
<!--
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 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
eframe now has its own logic to find the storage_dir to persist the app
when the persistence feature is enabled, instead of using the
directories crate. The directory should be the same as before (verified
with a unit test).
* Closes <https://github.com/emilk/egui/issues/4884>
* [x] I have followed the instructions in the PR template
Fix: The viewport stops working when the program is minimized.
Fix: Logically, the weird parts have been normalized.
**Issue :**
The viewport stops working when the program is minimized.
* Related #3321
* Related #3877
* Related #3985
* Closes#3972
* Closes#4772
* Related #4832
* Closes#4892
**Solution :**
When `request_redraw()` is performed in Minimized state, the occasional
screen tearing phenomenon has disappeared.
( Probably expected to be the effect of #4814 )
To address the issue of the `Immediate Viewport` not updating in
Minimized state, we can call `request_redraw()`.
Adding the proposed changes from @SymmetricChaos
* Closes https://github.com/emilk/egui/issues/5044
* [x] I have followed the instructions in the PR template
* [x] I ran the check script
You can see this feature in action
[here](https://docs.rs/sysinfo/latest/src/sysinfo/common/system.rs.html#46)
or on any of dtolnay's crates and many others. I found myself going
through your project code recently on docs.rs and I was a bit sad I
couldn't have this feature enabled. This should fix it at next release.
:)
<!--
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/4776>
* [x] I have followed the instructions in the PR template
I've been meaning to look into this for a while but finally bit the
bullet this week. Contrary to what I initially thought, the problem of
blurry lines is unrelated to feathering because it also happens with
feathering disabled.
The root cause is that lines tend to land on pixel boundaries, and
because of that, frequently used strokes (e.g. 1pt), end up partially
covering pixels. This is especially noticeable on 1ppp displays.
There were a couple of things to fix, namely: individual lines like
separators and indents but also shape strokes (e.g. Frame).
Lines were easy, I just made sure we round them to the nearest pixel
_center_, instead of the nearest pixel boundary.
Strokes were a little more complicated. To illustrate why, here’s an
example: if we're rendering a 5x5 rect (black fill, red stroke), we
would expect to see something like this:

The fill and the stroke to cover entire pixels. Instead, egui was
painting the stroke partially inside and partially outside, centered
around the shape’s path (blue line):

Both methods are valid for different use-cases but the first one is what
we’d typically want for UIs to feel crisp and pixel perfect. It's also
how CSS borders work (related to #4019 and #3284).
Luckily, we can use the normal computed for each `PathPoint` to adjust
the location of the stroke to be outside, inside, or in the middle.
These also are the 3 types of strokes available in tools like Photoshop.
This PR introduces an enum `StrokeKind` which determines if a
`PathStroke` should be tessellated outside, inside, or _on_ the path
itself. Where "outside" is defined by the directions normals point to.
Tessellator will now use `StrokeKind::Outside` for closed shapes like
rect, ellipse, etc. And `StrokeKind::Middle` for the rest since there's
no meaningful "outside" concept for open paths. This PR doesn't expose
`StrokeKind` to user-land, but we can implement that later so that users
can render shapes and decide where to place the stroke.
### Strokes test
(blue lines represent the size of the rect being rendered)
`Stroke::Middle` (current behavior, 1px and 3px are blurry)

`Stroke::Outside` (proposed default behavior for closed paths)

`Stroke::Inside` (for completeness but unused at the moment)

### Demo App
The best way to review this PR is to run the demo on a 1ppp display,
especially to test hover effects. Everything should look crisper. Also
run it in a higher dpi screen to test that nothing broke 🙏.
Before:

After (notice the sharper lines):

<!--
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
Fix: Ensures correct IME behavior when the text input area gains or
loses focus.
Fix: Handling `state.ime_enabled` in multiple `TextEdit`.
Fix: A symptom of characters being copied when there are multiple
TextEdits.
* Related #4137
* Related #4358
* Closes#4374
* Related #4436
* Related #4794
* Related #4908
* Related #5008
Fix Issues: When focus is moved elsewhere, you must set
`state.ime_enabled = false`, otherwise the IME will have problems when
focus returns.
Fix Issues: A symptom of characters being copied when there are multiple
TextEdits.
Deletes all current `IME events`, preventing them from being copied to
`other TextEdits`, without saving the `TextEdit ID`,
( Related Issues: Some `LINUX` seem to trigger an IME enable event on
startup. So, when we gained focus, we do `state.ime_enabled = false`. )
When a `ScrollArea` is added to a `Ui` or its contents change
dynamically, the contents will briefly escape the container. This occurs
because `ScrollArea` internally maintains `content_is_too_large` flags,
from which it determines when to clip. The `content_is_too_large` flags
are calculated after painting, so they always lag one frame behind. This
can lead to flickering.
To fix this, I have changed the `ScrollArea` so that it always clips
scrollable content. I believe that this should fix things without
negatively impacting other behavior. To see this, consider how
`ScrollArea` calculates the `content_is_too_large` flag:
```rust
// This calculates a new inner rect, after painting, from the initial clip rect
let inner_rect = {
// At this point this is the available size for the inner rect.
let mut inner_size = inner_rect.size();
for d in 0..2 {
inner_size[d] = match (scroll_enabled[d], auto_shrink[d]) {
(true, true) => inner_size[d].min(content_size[d]), // shrink scroll area if content is small
(true, false) => inner_size[d], // let scroll area be larger than content; fill with blank space
(false, true) => content_size[d], // Follow the content (expand/contract to fit it).
(false, false) => inner_size[d].max(content_size[d]), // Expand to fit content
};
}
Rect::from_min_size(inner_rect.min, inner_size)
};
let outer_rect = Rect::from_min_size(inner_rect.min, inner_rect.size() + current_bar_use);
let content_is_too_large = Vec2b::new(
scroll_enabled[0] && inner_rect.width() < content_size.x,
scroll_enabled[1] && inner_rect.height() < content_size.y,
);
```
If `scroll_enabled[d] == true`, then the actual `inner_rect` (which is
calculated after painting contents) will always be smaller than the
original `inner_rect`. Hence, it is safe to unconditionally clip the
contents to `inner_rect` whenever `scroll_enabled[d] == true`.
<!--
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/4742>
* [x] I have followed the instructions in the PR template
I was having trouble with id collisions and was not able to resolve it
using `push_id` and `child_ui_with_id_source`.
When investigating the issue I found
https://github.com/emilk/egui/pull/2262 which matched the issues I had
so I forked egui and implemented the changes from that PR for the latest
version.
It solved the issue for me.
I did not notice any regressions in my project or the egui web viewer.
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
Hello,
I have made several corrections to stabilize the virtual keyboard on
Android and IOS (Chrome and Safari).
I don't know if these corrections can have a negative impact in certain
situations, but at the moment they don't cause me any problems.
I'll be happy to answer any questions you may have about these fixes.
These fixes correct several issues with the display of the virtual
keyboard, particularly since update 0.28, which can be reproduced on the
egui demo site.
We hope to be able to help you.
Thanks a lot for your work, I'm having a lot of fun with egui :)
As mentioned in #4950 I added `max_decimals_opt` to the Slider
* Closes <https://github.com/emilk/egui/issues/4950>
* [x] I have followed the instructions in the PR template
* [x] I ran the script in `scripts/check.sh`
On multiple-monitor systems, eframe was incorrectly selecting first ones
dimensions for centering
Would also appretiate releasing 0.28.2 with fix included on crates.io
As we have two Margin widgets in the same UI and this widget has a Grid
with a hardcoded Id, we have to force a different Id to one of them to
avoid clashes.
* Closes <https://github.com/emilk/egui/issues/4965>
* [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!
-->
* Closes <https://github.com/emilk/egui/issues/3482>
* [x] I have followed the instructions in the PR template
Regarding the statement in #3482,
https://docs.rs/egui/latest/egui/layers/struct.GraphicLayers.html#method.drain
accepts a HashMap, but not sure if that is enough to keep the re-export.
<!--
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 PR
- adds a pipeline to check the ios build
- removes the iOS WaitUntil workaround, which doesn't seem to be
necessary anymore after the winit update (and caused the build for iOS
to fail again because of a missing self
- ~removes a iOS workaround for window size which doesn't seem necessary
anymore~
Turns out it was still needed (but you need to actually restart the app
for the issue to show up, so I didn't catch it first)
- fixes some cargo check errors in run.rs
I've done all these changes in a single PR because otherwise the
pipeline doesn't run but I can also split them in separate PRs if that
makes it easier to review
This request focus on a TextEdit when clicked, so that touch events on
Android can now focus it.
This looks like a reasonable fix for
https://github.com/emilk/egui/issues/4941.
* 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>
Similar to #4889
Updated the `ui` method of the `Button` widget so that the alignment
given by the layout is applied to the image contained in the button (if
one exists).
Currently, only the text inside the button has alignment applied to it,
and only when it is not accompanied by an image or shortcut text. Images
within buttons are always aligned to the centre left, no matter the
alignment of the containing `Ui`. This update now also applies this
alignment to an image when it has no accompanying text, which makes
buttons with an image and no text more consistent with the appearance of
ones with text and no image.
I've also made an additional change so that the vertical alignment is
now also respected when displaying some combination of image and text,
but the original horizontal alignment remains the same, so that the
image always appears left of the text. Any shortcut text now also
follows vertical alignment, but is always horizontally aligned to the
right.
Here are some comparisons of the difference between how buttons look
with different alignments, before and after this change:
### Before

### After

* [x] I have followed the instructions in the PR template
Fix: Changed the handling method of `Ime::Preedit(_, None)`
Fix: backspace fail after ime input
* Related #4358
* Related #4430
* Related #4436
* Related #4794
* Related #4896
* Closes#4908
Issues: backspace fail after ime input
* #4908 (Chinese)
Changed the handling method of `Ime::Preedit(_, None)`
Since #4849, running `./scripts/check.sh` fails with:
```
...
error[E0277]: the trait bound `ActiveEventLoop: raw_window_handle::borrowed::HasDisplayHandle` is not satisfied
--> crates/egui_glow/src/winit.rs:43:13
|
43 | event_loop,
| ^^^^^^^^^^ the trait `raw_window_handle::borrowed::HasDisplayHandle` is not implemented for `ActiveEventLoop`
|
= help: the following other types implement trait `raw_window_handle::borrowed::HasDisplayHandle`:
raw_window_handle::borrowed::DisplayHandle<'a>
&H
&mut H
= note: required for the cast from `&ActiveEventLoop` to `&dyn raw_window_handle::borrowed::HasDisplayHandle`
```
This PR adds the missing `rwh_06` to the winit dependency (in
egui-glow).
* [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 add commits to your PR.
* Remember to run `cargo fmt` and `cargo cranky`.
* 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#4295
I based this on #4303, I'll rebase once that one gets merged.
This allows license checking tools to omit the OFL and UFL licenses when
`default_fonts` are turned off.
There was some discussion of versioning on the original issue; I have
chosen to label this version as `0.28.1` to match the other crates.
Happy to adjust the version as needed.
<!--
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/2321>
* [X] I have followed the instructions in the PR template
---------
Co-authored-by: Alex Pinkus <pinkus@amazon.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>
Updated the `show_content` method of the `TextEdit` widget so that the
requested text alignment (if any) is also applied to the hint text.
Currently, hint text is always aligned to the top left of the widget,
which may be inconsistent with the actual location of text entered by
the user. I think it's more intuitive for the hint text to be positioned
as if the user had entered the same text themselves.
Here are some comparisons of the difference between how the hint text
and the entered text looks, before and after this change:
### Previous Behaviour

### Updated Behaviour

* [x] I have followed the instructions in the PR template
* [x] I have followed the instructions in the PR template
Clarified that `eframe::run_simple_native()` does in fact save some
state (if persistence is enabled) but does not allow user to save state.
<!--
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 (less the
self-review using the script as it's only a single word change).
<!--
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!
-->
added return ScrollAreaOutput.
This can be used to monitor the scroll progress of a table(usage
example: custom scroll progress bar or lazy loading table)
* [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!
-->
* Closes https://github.com/emilk/egui/issues/3453
* [x] I have followed the instructions in the PR template
I'm fairly new to egui.
I read the code, but I didn't follow the approach mentioned in
https://github.com/emilk/egui/issues/3453#issuecomment-2208255433.
I believe this is an easier way to achieve that, though I'm not certain
if it's the best method.
<img width="760" alt="image"
src="https://github.com/user-attachments/assets/4b3c561f-1c24-446b-9581-a2f4e9858480">
I get really nice svg with this patch.
@emilk Can you please take a look? I really need this!
<!--
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!
-->
I find myself wanting this API quite a lot, and I imagine it'll probably
be useful for others.
# What?
This PR adds `Rect::scale` and `Rect::scale2` functions, which work a
lot like `expand`, but instead multiply by a scale.
i.e.
```rs
rect.scale(2.0); // rect is 2x as big, still in same center
rect.scale2(vec2(1.5, 2.0)); // rect is 1.5x as big on x axis, 2.0x as big on y axis. still in same center
```
# Why?
Before this you either had to write this yourself or use a `expand` in a
cumbersome way:
```rs
rect.expand2(vec2(rect.width() * scale.x / 2.0, rect.height() * scale.y / 2.0));
```
I find myself wanting to scale things up by a factor frequently enough,
and it seems like a useful addition to have a multiply-based variant of
`expand`.
I realise this is pretty minor, but it seems useful enough to me!
---------
Co-authored-by: zkldi <20380519+zkldi@users.noreply.github.com>
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
# Changes
- Adds a new function `egui::Ui::columns_const()`, which is the same as
`egui::Ui::columns()` except that it uses a `const` parameter for the
column count.
- Backed by an array `[Ui; NUM_COL] instead of a `Vec<Ui>`, so fewer
allocations
- Inner closure takes in an array reference, instead of a slice
reference. This makes it possible to use pattern destructuring on the
columns, as shown in the example, and makes it more ergonomic to use
# Example
```rust
// ORIGINAL
ui.columns(2, |cols| {
cols[0].label("one");
cols[1].label("two");
});
// NEW
ui.columns_const(|[a,b]| {
a.label("one");
b.label("two");
});
```
# Checks
- [X] `cargo fmt`
- [X] `cargo clippy`
- [X] `./scripts/check.sh`
- [X] Docs
- [ ] Review
* Closes https://github.com/emilk/egui/issues/1713
I almost went to implement my own undo/redo system, and then found the
egui undoer.
Went to make a small demo to test for myself how it worked, and then
found the linked issue.
So here is a tweaked version of that :)
Co-authored-by: Wybe Westra <w.westra@kwantcontrols.nl>
<!--
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 added a util function `set_hovered` to change the hovered state of a
row from tables in `egui_extras` which matches the already present
`set_selected` function.
* [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!
-->
* Closes https://github.com/emilk/egui/discussions/4670
* [x] I have followed the instructions in the PR template
`egui::Table` has a weirdly specific default `max_scroll_height` set to
800.0. This means that even with `vscroll(true)` and `auto_shrink([_,
false])`, the table will not expend to the full available height. This
PR changes this value to `f32::INFINITY`. This makes it consistent with
the corresponding default value of `ScrollArea::max_size.y`, which is
where that `max_scroll_height` ends up being used.
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.
In order to make it possible that all buttons can have the same style
with a text and an image I created a `menu_text_image_button`.
It works the same way as all the other menu buttons.
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
Handle the `IME` event first
There is a need to handle the Ime event first.
Fix Issues : When you press `BackSpace`, the entire text is erased, and
when you press another letter, it appears again.
Fix Issues : When you press `Left`, the character being entered will be
copied once more.
Fix Issues : When you press `Enter`, `Enter` with `repeat` set is
entered and `Enter` is entered twice.
Fix Issues : When you press a key in `IME` mode, `repeat` is often set.
Fix Issues : Since you may be selecting something in the IME, this also
disables the `Arrow` keys.