<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/main/CONTRIBUTING.md)
before opening a Pull Request!
* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.
Please be patient! I will review your PR, but my time is limited!
-->
* Fix [the Samsung Keyboard Korean Cheonjiin layout
bug](https://github.com/emilk/egui/pull/7967#issuecomment-4098503570)
* Partially fix (does not close) #8046
* Supersedes #7914
* Supersedes #8047
* Related: #8068
* Related: #7983
* Related: #8078
* [x] I have followed the instructions in the PR template
This PR reworks the text input handling logic in eframe's web
integration, primarily in `text_agent.rs`.
It also adds a new `ImeEvent::DeleteSurrounding` variant, along with the
corresponding handling logic in `egui` to support the changes.
## Fix: Samsung Keyboard Cheonjiin issue
This PR fixes a bug reported by @rustbasic when using Samsung Keyboard's
Cheonjiin Korean layout.
Since Samsung Keyboard is only available on Samsung devices, I wasn't
able to verify it myself. The fix is based on @rustbasic's testing and
confirmation.
The root cause is that the layout relies on the preceding text to
correctly handle batchim composition. Previously, the text agent eagerly
cleared the text input after every IME composition, removing the context
too early. This PR makes that cleanup more conservative, preserving the
text when it may still be needed.
My understanding is that this is a quirk specific to Samsung Keyboard:
The IME reports that composition has finished even though it is
effectively still active and the composed text may continue to change.
## Fix: Keystrokes resetting keyboard layout (numpad/symbols/etc.)
Partially fixes#8046.
Previously, keystrokes would cause the on-screen keyboard to switch back
to its primary layout.
One remaining issue is that tapping within the active `TextEdit` to
reposition the cursor still resets the keyboard to its primary layout.
## About text suggestions
I originally planned to include text suggestion support in this PR
because #8068 implemented it.
However, adding text suggestion support would broaden the scope of this
PR, so I think it is better addressed in a separate PR.
For reference, [the reverted
implementation](8a4f70859c)
works fine on Android (Gboard), but not on iOS (iPadOS 17 + SwiftKey).
We had a ton of issues around `TexturesDelta` that weren't properly
applied because we early-out of some function:
* https://github.com/emilk/egui/pull/8313
* https://github.com/emilk/egui/pull/8250
* https://github.com/emilk/egui/pull/8279
This PR changes texture updates, so that we always store them after
taking them out of `FullOutput` and keep the delta around until it's
actually applied (by passing &mut refs and draining instead of
iterating). So even if we add a new early return somewhere, that can't
break texture updates.
It also optimizes `TexturesDelta::append` by dropping any previous
deltas if there's a new `whole` delta or a `free`.
It also adds a debug assert that any `TexturesDelta` is empty when
dropped, as an additional safeguard in case the bug sneaks back in.
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Follow-up to #8296, part of
<https://github.com/emilk/egui/issues/8295>
* [x] I have followed the instructions in the PR template
Stacked on #8296 (base branch), kept as a separate PR so it can be
reverted independently.
The hidden text-agent `<input>` is now inserted as a *sibling of the
canvas* (instead of appended to `document.body`) and positioned with
`offsetLeft`/`offsetTop` instead of `getBoundingClientRect`. Since the
input and the canvas share the same containing block, the input stays
anchored to the canvas top-left corner no matter how the page is
scrolled or how the canvas is embedded.
Consequences:
* Fixes the IME popup position when the host page is scrolled —
`move_to` previously wrote *viewport* coordinates from
`getBoundingClientRect` into document-absolute `left`/`top`.
* Subsumes the mobile Safari virtual-keyboard workaround (it replaced
the flapping `getBoundingClientRect` y with `offsetTop`, which is now
used everywhere), so `is_mobile_safari()` is removed.
* Removes the special-casing of document vs shadow DOM roots — sibling
insertion works uniformly in both.
* The input is `position: absolute`, so it does not participate in
flex/grid layout of the canvas' parent and causes no layout shift.
Caveat: host CSS selectors like `div > canvas:only-child` would no
longer match.
Verified with `cargo clippy -p eframe --target wasm32-unknown-unknown
--all-features` and `cargo fmt --all`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
The `textures_delta` in `AppRunner::logic()` comes from
`TextureManager::take_delta()` via `end_pass()`. Previously, if
`is_visible` was `false`, these deltas would have been dropped and never
applied, so the `TextureManager` state gets out of sync with the
`Renderer`.
That causes https://github.com/emilk/egui/issues/8228: When the app is
loaded in a background tab and the first frame occurs via the
`setTimeout` path prior to the tab becoming visible, it loses the
`ImageDelta` representing the initial creation of the font atlas
texture. When the user then switches to the tab, it panics at
crates/egui-wgpu/src/renderer.rs:669:18 with `Tried to update a texture
that has not been allocated yet` when attempting to update the texture
that the wgpu renderer never saw when it was created.
Testing: To make it load in a background tab, put `data:text/html,<a
href=http://127.0.0.1:8765/>Click</a>` in the address bar and then
middle click the resulting link. On Chrome you also have to hover the
tab preview before switching to the tab to reproduce the issue.
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/main/CONTRIBUTING.md)
before opening a Pull Request!
* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.
Please be patient! I will review your PR, but my time is limited!
-->
* Closes <https://github.com/emilk/egui/issues/8228> and its duplicate
https://github.com/emilk/egui/issues/8278
* [x] I have followed the instructions in the PR template
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
- needs #8335
Previously it was impossible to correctly set modifiers via egui
inspection, since that only passes egui::Event and egui::Event had no
way to generally express modifiers.
Now modifiers are passed to egui as a Event and not as a field of
`RawInput`.
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
## Summary
- [x] I have followed the instructions in the PR template
Fixes comment-style violations of the `CONTRIBUTING.md` code style rule:
> `// Comment like this.` and not `//like this`
### Files changed
- `crates/epaint/src/shapes/bezier_shape.rs`: `//temporary solution` →
`// temporary solution`, and 22× `//add the start point` → `// add the
start point`
- `crates/egui/src/animation_manager.rs`: `//start new animation…` → `//
start new animation…`
- `crates/eframe/src/web/web_painter_wgpu.rs`:
`//create_new.instance_descriptor…` → `//
create_new.instance_descriptor…`
No code logic changes — only adding the missing space after `//` in
inline and standalone comments.
## Test plan
- [x] `cargo fmt --check`
- [x] `cargo clippy -p epaint -p egui`
- [x] `cargo test -p epaint --lib`
* Closes <https://github.com/emilk/egui/issues/8295>
* [x] I have followed the instructions in the PR template
When an eframe app is embedded in a scrollable host page, the host page
jumped to the top whenever the app booted or grabbed keyboard focus.
Cause: the hidden text-agent `<input>` sat at (0,0) of `<body>` with the
`autofocus` attribute, and all focus calls (text agent and canvas) used
plain `focus()`, so the browser scrolled the focused element into view —
i.e. to the top of the page.
Changes:
* All focus calls in `eframe` web (text agent, canvas, Gboard
blur/refocus workaround) now go through a new `focus_without_scroll()`
helper that uses `focus_with_options` with `preventScroll: true`
(supported by all evergreen browsers).
* The `autofocus` attribute is replaced with an explicit focus call
after DOM insertion — the browser-internal autofocus path always scrolls
the element into view and cannot be prevented by any focus option.
Boot-focus behavior is preserved.
* The text-agent input is initially parked at the canvas origin instead
of (0,0) of the page, so any residual scroll-into-view would target the
canvas rather than the top of the host page. (`move_to` keeps
repositioning it for IME as before.)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/main/CONTRIBUTING.md)
before opening a Pull Request!
* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.
Please be patient! I will review your PR, but my time is limited!
-->
* [X] I have followed the instructions in the PR template
This PR adds a `remove_string()` API to the Storage trait and also
implements it in the `FileStorage` and `LocalStorage` stucts.
**fix(web): prevent entire page from scrolling out of view in Chrome
(WASM)**
* Closes#7887
**Problem**
When using `egui` on the web, the browser (especially Chrome)
occasionally triggers an unwanted page-level scroll. This happens
because the hidden input element (text agent) used for IME/text input is
sometimes positioned outside the visible bounds of the canvas, causing
the browser to "scroll it into view."
**Solution**
I modified the `move_to` function in the web's `text_agent` to ensure
the input element's position stays within the canvas height. By clamping
the `top` property between `0.0` and `canvas_height`, we prevent the
browser from incorrectly scrolling the entire page when the text agent
moves.
- **Specific change:** Applied `clamp(0.0, canvas_height)` to the
`clamped_y` value before setting the CSS `top` property.
## What
Adds a way for apps to push an RGBA bitmap as the OS cursor — the
missing companion to `Context::set_cursor_icon`. The integration
translates it into a real `winit::CustomCursor`, so the cursor is drawn
by the compositor and can extend past the egui window edge like any
native cursor.
## Why
Apps with custom-shaped windows (Winamp-style skins, themed launchers,
kiosk apps) currently have no clean way to display a custom cursor:
- `CursorIcon` is limited to the standard system enum.
- Painting the cursor sprite via `egui::Painter` works inside the canvas
but gets clipped at the window edge — the bottom/right of the cursor
disappears the moment the pointer is near the boundary, and there's no
way to render onto the desktop area exposed by a
transparent/region-shaped window.
`winit` 0.30+ already supports `CustomCursor::from_rgba` +
`ActiveEventLoop::create_custom_cursor`, but `egui-winit` doesn't
surface it. This PR exposes it through egui.
### Visual demonstration
Driving use case: a Winamp WSZ skin player
([all3f0r1/oneamp](https://github.com/all3f0r1/oneamp)) with a
transparent + region-shaped window where the skin ships its own `.cur`
files. The bottom-right corner of the playlist exposes the resize cursor
— notice how it gets clipped at the window edge in the painter-based
approach.
| Before (cursor painted via `egui::Painter`) | After (cursor pushed via
`set_cursor_image`) |
| --- | --- |
| 
| 
|
## API
```rust
// new in egui::data::output
pub struct CustomCursorImage {
pub rgba: std::sync::Arc<[u8]>,
pub size: [u16; 2], // matches winit's u16 to avoid lossy casts
pub hotspot: [u16; 2],
}
// new field on PlatformOutput (skipped from serde — ephemeral)
pub cursor_image: Option<CustomCursorImage>,
// new method on Context
ctx.set_cursor_image(Some(image)); // overrides cursor_icon for this frame
ctx.set_cursor_image(None); // revert to cursor_icon
```
`Arc<[u8]>` is intentional: the integration dedupes by `Arc::as_ptr`, so
reusing the same Arc across frames means the bitmap is only uploaded to
the OS once per skin, not once per frame.
## Integration changes
- `egui_winit::State::handle_platform_output_with_event_loop(window,
Option<&ActiveEventLoop>, ...)` is a new method that threads the active
event loop so it can call `event_loop.create_custom_cursor(...)`.
- The legacy `handle_platform_output(window, ...)` delegates with `None`
and silently drops `cursor_image`. **No existing callers break.**
- The icon and bitmap paths are unified in a private `apply_cursor`. The
no-flicker dedupe of the old `set_cursor_icon` is preserved on both
paths.
- If `CustomCursor::from_rgba` rejects the bitmap (bad dimensions,
hotspot OOB, etc.), we log a warning and fall back to the icon path.
- eframe's wgpu + glow integrations thread `&ActiveEventLoop` through
`run_ui_and_paint` (glow already had it; wgpu needed one extra
parameter) and call the new method.
- Immediate viewports keep the old path because they're invoked from a
`Context` callback that doesn't have an event loop reference. Custom
cursors are a no-op in immediate viewports — acceptable since they're a
niche path.
## Fallback semantics
| backend / context | what happens |
|--------------------------------|-------------------------------|
| eframe wgpu/glow main viewport | bitmap displayed via OS |
| eframe immediate viewport | falls back to `cursor_icon` |
| eframe web | falls back to `cursor_icon` |
| custom integrations not opted in | falls back to `cursor_icon` |
| `from_rgba` returns `BadImage` | warning + falls back to icon |
## Verification
- `cargo fmt --all -- --check` ✅
- `cargo clippy -p egui -p egui-winit -p eframe --all-targets
--all-features -- -D warnings` ✅
- `cargo doc --lib --no-deps -p egui -p egui-winit -p eframe
--all-features` ✅
- `cargo check -p egui --no-default-features --features serde` ✅
(validates the `serde(skip)` on `cursor_image`)
- Interactive validation on Linux/Wayland with the OneAmp WSZ skin
player — see screenshots above.
I haven't run the full snapshot test suite (`scripts/check.sh`) because
we're on Linux and the snapshots are macOS-rendered — happy to run it if
you'd like.
## Notes
Drafted per the contributing guide ("open a draft PR, you may get
helpful feedback early"). Open to design feedback on:
1. Whether `CustomCursorImage` should live in `egui::viewport` rather
than `egui::data::output`.
2. Whether the legacy `handle_platform_output` should grow `event_loop`
directly (breaking) instead of getting a sibling method (non-breaking,
what I did).
3. Whether to also wire it through eframe-web (probably not —
`wasm-bindgen-cursor` would need its own path).
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
### Related
* Closes#8134.
* Related to #5136.
Possibly fixes:
* #8123
* #5145
### What
We did not properly handle the variants of
[`CurrentSurfaceTexture`](https://docs.rs/wgpu/latest/wgpu/enum.CurrentSurfaceTexture.html)
and always returned `SkipFrame`.
Because of this `egui` could end up in a state where frames are always
skipped after observing `Outdated`, without the chance to recover
(unless an event arrives from the outside).
> [!NOTE]
> This is not Wayland-specific, but could happen on all platforms. It
just happens frequently for Wayland compositors that directly resize a
window after creation (such as tiling/scrolling compositors like
`hyprland` and `niri`).
This PR improves this by separating the code paths for `Outdated` and
`Lost`, to help recover from those events.
This is a breaking public API change, but is otherwise trivial due to it
not changing any actual runtime behaviour.
This renames eframe's NativeOptions `vsync` option to `glow_vsync` to
make clear without even looking at docs fully that this is specific to
the `glow` backend.
While I think a better option would actually be to change the wgpu
creation options to match the vsync option if not specified (either to
`AutoVsync` or `AutoNoVsync` depending on setting) this would require
this be made an `Option<PresentMode>`, which would be confusing - and
the `WgpuConfiguration` should probably take priority over other options
here, as there's more than 2 present modes that are relevant. So I think
this is a suitable way to go.
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/main/CONTRIBUTING.md)
before opening a Pull Request!
* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.
Please be patient! I will review your PR, but my time is limited!
-->
* This does not close an issue - this was a trivial amount of code to
change, so I might as well just make it a PR on the spot.
* [x] I have followed the instructions in the PR template
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
Let apps change present_mode and desired_maximum_frame_latency at
runtime instead of only at startup.
API changes (egui-wgpu):
- New SurfaceConfig { present_mode, desired_maximum_frame_latency }.
- WgpuConfiguration now nests these as pub surface: SurfaceConfig (was
two top-level fields).
- RenderState gains pub surface_config: SurfaceConfig — the
currently-requested value.
API additions (eframe):
- Frame::wgpu_surface_config() / Frame::set_wgpu_surface_config(...) for
get/set.
- SurfaceConfig re-exported as eframe::SurfaceConfig.
How it works:
The wgpu painter compares render_state.surface_config to its
currently-applied values each paint. If they differ it updates its
config and flips
needs_reconfigure on every surface, piggybacking on the existing
deferred-reconfigure pathway.
Demo:
The backend panel (egui_demo_app) gets dropdowns for present mode and
desired max frame latency, wired through the new Frame accessors.
<img width="282" height="172" alt="image"
src="https://github.com/user-attachments/assets/0b1274b2-7e4e-4413-969b-0a014c415f79"
/>
* Closes N/A
* Partially replaces #7983
* Related: #8045
* [x] I have followed the instructions in the PR template
## Details
In #7983, I modified `Memory::request_focus` to interrupt any ongoing
IME composition. This fixed a bug where clicking inside an already
focused `TextEdit` failed to cancel the active composition, resulting in
duplicated text:
https://github.com/emilk/egui/pull/8045#issuecomment-4193310616
To avoid introducing API changes in that PR, I ensured the IME state was
reset by forcing `PlatformOutput::ime` to `None` for at least one frame.
While this works well on desktop platforms, it causes virtual keyboard
flickering on the web:
https://github.com/emilk/egui/pull/8045#issuecomment-4193035008
In this PR, I delegate the responsibility for handling IME composition
interruptions to integrations, allowing each integration to decide how
to interrupt compositions in a flexible manner.
### The new field `should_interrupt_composition` on `IMEOutput`.
Instead of introducing a new `OutputCommand` variant, this PR adds a new
field `should_interrupt_composition` to `IMEOutput`.
Interrupting an active composition is only meaningful when IME remains
allowed. If IME should be disabled altogether, `PlatformOutput::ime` can
simply be set to `None`.
Given this, IMO, it is more appropriate to attach the interrupt signal
to `IMEOutput` (i.e., the type of `PlatformOutput::ime`).
Log `localStorage` write failures in `local_storage_set`
**Description**
This PR improves `local_storage_set()` logging in
`eframe/src/web/storage.rs`.
It logs:
- write failures with key and browser error
- unavailable local storage
This helps diagnose web persistence issues such as `QuotaExceededError`
when `localStorage.setItem()` fails.
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/main/CONTRIBUTING.md)
before opening a Pull Request!
* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.
Please be patient! I will review your PR, but my time is limited!
-->
* Depends on #7967
* Closes#7485
* Should fix#7906 (This issue doesn't seem to have been resolved, but
the author closed it; I personally don't have the environment to verify
whether it is fixed.)
* Replaces #4137, #4896, and partially #7810
* [x] I have followed the instructions in the PR template
This PR started as a fix for #7485, but has since evolved into a broader
rewrite of IME-related logic.
## Overview
This PR primarily introduces a new public method, `owns_ime_events`, on
[`Memory`], and refactors parts of [`TextEdit`] to integrate with it.
Previously, each [`TextEdit`] widget independently determined whether to
handle IME events and stored its own IME-related state. This approach
made ownership-handling fragmented and was therefore error-prone.
With this PR:
- IME event ownership is centralized, ensuring that at most a single
widget owns IME events per frame.
- [`PlatformOutput`]'s `ime` field can be set to `None` for at least one
frame when IME composition is interrupted, allowing the IME to be
properly dismissed.
## Details
Two new public methods are introduced on [`Memory`]:
- `fn owns_ime_events(&self, id: Id) -> bool`: check IME event ownership
for the current frame for the widget with the given `id`.
- `fn interrupt_ime(&mut self)`: interrupt the current IME composition,
if any.
Since the newly added methods on [`Memory`] are public, other widgets
can also participate in IME handling without risking ownership conflicts
of IME events.
I also added an internal (`pub(crate)`) field on [`TextEditState`],
called `cursor_purpose`, to distinguish the role of the [`TextEdit`]
cursor.
Additionally, `egui::ImeEvent::Enabled` and `egui::ImeEvent::Disabled`
have been removed, as they are no longer used anywhere.
## Demonstrations
### Windows: The Korean IME text duplication bug fixed in #4137 does not
reappear.
<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
<th>Without this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Behavior</th>
<td>Correct (no regression)</td>
<td>Correct</td>
</tr>
<tr>
<th>Screencast</th>
<td>

</td>
<td>

</td>
</tr>
</tbody>
</table>
### Windows: Chinese and Japanese IMEs now behave more consistently with
the Korean IME in similar scenarios.
This change does not matter much, as composition is rarely interrupted
mid-process with these IMEs in typical usage.
<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
<th>Without this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Behavior</th>
<td>Composition can be interrupted by clicking (like Korean IMEs)</td>
<td>Composition can not interrupted by clicking</td>
</tr>
<tr>
<th>Screencast (Builtin Chinese IME)</th>
<td>

</td>
<td>

</td>
</tr>
<tr>
<th>Screencast (Builtin Japanese IME)</th>
<td>

</td>
<td>

</td>
</tr>
</tbody>
</table>
### macOS: was buggy, still buggy
Likely due to this upstream bug in `winit`:
https://github.com/rust-windowing/winit/issues/4432
Once `winit` is updated to a version that includes the fix, the behavior
should become correct with this PR.
<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
<th>Without this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Behavior</th>
<td>Buggy as before</td>
<td>Buggy: Characters are duplicated</td>
</tr>
<tr>
<th>Screencast</th>
<td>

</td>
<td>

</td>
</tr>
</tbody>
</table>
### Wayland + iBus: Korean IME duplication bug fixed
<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
<th>Without this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Behavior</th>
<td>Correct</td>
<td>Buggy: Characters are duplicated</td>
</tr>
<tr>
<th>Screencast</th>
<td>

</td>
<td>

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

</td>
<td>

</td>
</tr>
</tbody>
</table>
### Wayland + iBus: selection is also not broken
This PR does not reintroduce the selection bug fixed in #7973.
<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Behavior</th>
<td>Correct</td>
</tr>
<tr>
<th>Screencast</th>
<td>

</td>
</tr>
</tbody>
</table>
### X11 + Fcitx5: IME composition can be interrupted
But due to #7975, the experience is still subpar. (Uncommitted text is
lost after interruption.)
<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
<th>Without this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Screencast</th>
<td>

</td>
<td>

</td>
</tr>
</tbody>
</table>
[`Memory`]: https://docs.rs/egui/latest/egui/struct.Memory.html
[`TextEdit`]:
https://docs.rs/egui/latest/egui/widgets/text_edit/struct.TextEdit.html
[`PlatformOutput`]:
https://docs.rs/egui/latest/egui/struct.PlatformOutput.html
[`TextEditState`]:
https://docs.rs/egui/latest/egui/widgets/text_edit/struct.TextEditState.html
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/main/CONTRIBUTING.md)
before opening a Pull Request!
* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.
Please be patient! I will review your PR, but my time is limited!
-->
This improves cases where the canvas does not cover the full screen,
which was a goal in [release
0.28.0](https://github.com/emilk/egui/releases/tag/0.28.0).
* Closes <https://github.com/emilk/egui/issues/8035>
* [X] I have followed the instructions in the PR template
* [x] I have followed the instructions in the PR template
This updates wgpu to v29 across the egui crate stack.
There a a few API changes due to the requirement to provide a display
handle up front to properly support GLES on linux. I have done my best
to make the api changes as reasonable as possible, but I don't have all
the greater project context, so lmk if things should be done a bit
differently.
I've also updated glow to 0.17 to make cargo deny happy, there are no
source changes. I'm not sure how you want to land these.
---------
Co-authored-by: lucasmerlin <hi@lucasmerlin.me>
* Part of https://github.com/emilk/egui/issues/5113
* Part of https://github.com/emilk/egui/issues/3524
## What
This deprecates `eframe::App::update` and replaces it with two new
functions:
```rs
pub trait App {
/// Called just before `ui`, and in the future this will
/// also be called for background apps when needed.
fn logic(&mut self, ctx: &egui::Context, frame: &mut Frame) { }
/// Show your user interface to the user.
fn ui(&mut self, ui: &mut egui::Ui, frame: &mut Frame);
…
}
```
Similarly, `Context::run` is deprecated in favor of `Context::run_ui`.
`Plugin`s are now handed a `Ui` instead of just a `Context` in
`on_begin/end_frame`.
## TODO
…either in this PR or a later one
* [x] Deprecate `App::update`
* [x] Deprecate `Context::run`
* [x] Change plugins to get a `Ui`
* [x] Update kittest
* [x] Change viewports to get UI:s (`show_viewport_immediate` etc)
- https://github.com/emilk/egui/pull/7779
## Later PRs
* [ ] Deprecate `Panel::show`
* [ ] Deprecate `CentralPanel::show`
* [ ] Deprecate `CentralPanel` ?
* Closes https://github.com/emilk/egui/issues/5889
See the above issue for motivation.
To use glow instead, disable the default features of `eframe` and opt-in
to `glow`.
This also changes egui.rs to use wgpu, which means WebGPU when
available, and WebGL otherwise
* Part of https://github.com/emilk/egui/issues/5889
* Closes https://github.com/emilk/egui/issues/7106
This changes the `eframe/wgpu` feature to also enable all the `default`
features of `wgpu` and `egui-wgpu`. This makes switching `eframe`
backend from `glow` to `wgpu` a lot easier.
To get the old behavior (depend on `wgpu` but you must opt-in to all its
features), use the new `wgpu_no_default_features` feature.
* Closes#7657
* [x] I have followed the instructions in the PR template
On native this uses a new "touch phase" parameter of the mouse wheel
event to know if a scroll action is done.
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>