Sweep every user-visible product string to Gwen: app menus (Quit,
Hide, Gwen Repository), feedback links (repo/issues now point at
github.com/kk376/zed, email to yenru@yrkaierx.com), move-to-Applications
and update dialogs, provider and settings copy, CLI help, installer and
desktop/flatpak/snap/plist metadata.
Rename user-facing settings values with back-compat aliases: base_keymap
"Gwen" (accepts "Zed"), fonts ".GwenMono"/".GwenSans" (accept
".ZedMono"/".ZedSans"), icon theme "Gwen (Default)". Fix F10
app-menu keymap arguments to "Gwen" and align the Windows installer
AppMutex with release_channel::app_identifier(). Internal identifiers,
wire protocol names, upstream service URLs and legal attribution are
intentionally kept.
Browser applications cannot rely on operating-system font discovery, but
embedding comprehensive emoji and CJK fonts makes the initial
WebAssembly payload prohibitively large. GPUI previously offered no
structured way to learn that fallback was exhausted, and adding a font
at runtime left descriptor and line-layout caches shaped against the old
font database.
This change lets WGPU text systems report unresolved grapheme clusters
through `App::on_missing_glyphs`. GPUI invokes one replaceable
application callback after shaping, carrying each complete grapheme and
whether its source run is proportional or monospace. Reports are
deduplicated and delivered through a bounded, nonblocking channel;
reporting remains disabled until the callback is installed, and queued
reports from an earlier font generation are discarded.
Successful font installation now advances a font generation. GPUI clears
descriptor and platform family resolution, reuses stable font IDs for
unchanged faces while refreshing their fallback chains, and invalidates
each window's current and previous line-layout caches when it observes
the new generation. This supplies the GPUI half of an on-demand web font
loader; fetching and selecting font assets remains application-owned.
Release Notes:
- N/A
---------
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
## Summary
- Replace the outdated Trunk URL in the GPUI examples README with
https://trunk-rs.github.io/trunk/.
## Verification
- Confirmed the replacement URL returns HTTP 200.
- Ran `git diff --check` successfully.
- No code tests needed for this documentation-only link change.
Release Notes:
- N/A
## Summary
Add browser-font fallback to GPUI on the web, so applications can render
emoji using the user’s local fonts without bundling an emoji font.
GPUI continues to shape text with Cosmic Text using application-provided
fonts. When those fonts cannot supply an eligible grapheme or its
requested emoji presentation, the web backend measures and rasterizes
the complete grapheme using Canvas 2D, then caches and paints the result
through GPUI’s existing glyph atlas.
### Configurable fallback
- **Emoji-only by default**, including supported variation-selector,
skin-tone, flag, keycap, and ZWJ sequences.
- Applications can opt into **CJK fallback** for a conservative subset
of horizontal Han, kana, and modern Hangul text.
- Applications can disable Canvas fallback entirely.
CJK fallback renders graphemes independently. It prioritizes readable
text over full fidelity to contextual spacing and font features. Browser
font coverage and appearance depend on the user’s environment.
### Web input and application lifecycle
- Fix text insertion that arrives without a corresponding keyboard
event, allowing emoji input through the browser’s text-input path.
- Keep the GPUI application alive after `Application::run` returns on
WebAssembly. Browser startup is asynchronous; releasing the application
after the startup callback previously caused the window to disappear.
### Browser example gallery
Make the existing GPUI examples available from a single development
server, with separate routes for hello world, styled text, text layout,
wrapping, input, and the prime sieve demo.
The gallery supports direct links and reloads, loads only the selected
example, and provides a simple way to exercise font fallback and text
input.
## Validation
- Native unit tests cover fallback eligibility and presentation, policy
defaults, glyph-cache reuse, and in-place glyph-run replacement.
- All six gallery binaries pass WASM compilation checks.
- Browser smoke coverage exercises emoji insertion, whole-grapheme
Canvas rendering, cache reuse, and deletion.
- Manually exercised the gallery and fallback rendering in Chrome.
Release Notes:
- N/A
## Summary
Replace GPUI's shared asset futures with owning cache entries. The
mutex-backed waiter collection in futures::future::Shared can contend
between a worker and the browser main thread, where blocking waits are
forbidden.
- Keep loading on the background executor, with one foreground task
publishing the cached result and notifying interested views.
- Deduplicate loads and view registrations; cancel pending work on
eviction without allowing completion to update a replacement entry.
- Change App::fetch_asset to return Option<A::Output>, remove
ImageLoadingTask, and make ImageCacheItem an opaque owning entry.
- Migrate the retain-all image cache and image gallery LRU example.
Repository-wide search found no further callers requiring migration.
Results become visible after the foreground completion task publishes
them. Entries expose neither cloneable nor awaitable task handles.
Release Notes:
- N/A
`gpui_web` currently embeds IBM Plex Sans and Lilex into every browser
application during platform construction. Applications such as Delta
already provide their own fonts, so those binaries contain overlapping
font bundles and register the same faces twice.
This change starts the web platform with an empty font database,
matching the ownership boundary used by native applications: the
application selects and registers its fonts before opening a window.
Delta already follows that sequence. GPUI's browser-capable examples now
load the former eight-face bundle explicitly through shared example
support, while the standalone `hello_web` example demonstrates
registering a minimal application font directly.
Testing performed:
- `cargo check -p gpui --examples --target wasm32-unknown-unknown`
- `cargo check -p gpui --examples`
- `cargo check -p gpui_web --target wasm32-unknown-unknown`
- `cargo check --manifest-path
crates/gpui_web/examples/hello_web/Cargo.toml --target
wasm32-unknown-unknown`
- `./script/clippy -p gpui_web --target wasm32-unknown-unknown`
- `cargo fmt -p gpui -p gpui_web --check`
Release Notes:
- N/A
# Objective
I wanted spring animations in GPUI for an application built atop of
GPUI.
## Solution
I texted @mikayla-maki about wanting spring animations; we collaborated
in Delta; this change is the co-authored result. We built atop of GPUI's
existing APIs, but this *is* new API surface. The verbiage is borrowed
from SwiftUI's approach.
First, what _are_ spring animations? If you're unfamiliar, they're the
bouncy, physical animations that you'd often see in mobile applications.
As Claude put it to me, "keyframe animation is a recording; a spring is
a simulation". There's a few consequences:
1. The animation API needs to support interrupts/cancelation, or the
application using spring animations will feel broken. You need to cancel
the momentum in a physically realistic way!
2. The API is more complex! GPUI's existing animations are, roughly,
`Fn(progress: f32) -> eased_progress: f32`, but a spring animation is
closer to `Fn(state: SpringState, target: f32, delta_time: f32) ->
SpringState`. Concretely, GPUI landed on the following:
```
pub fn step(
&self,
state: SpringState,
target: f32,
delta_time: f32,
) -> SpringState;
```
...where `&self` is:
```
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct SpringConfig {
/// The spring stiffness, conventionally written as $k$.
pub stiffness: f32,
/// The viscous damping coefficient, conventionally written as $c$.
pub damping: f32,
/// The moving mass, conventionally written as $m$.
pub mass: f32,
}
```
Conceptually, at each frame, GPUI does `let state = spring.step(state,
target, delta_time);`, or as an other LLM summarized:
```
// Ordinary animation:
progress: f32 -> phase: f32
// GPUI spring:
(state: { position, velocity }, target, dt)
-> new { position, velocity }
-> typed presentation value
```
---
Release Notes:
- gpui: Added spring animations
Browser Fetch APIs must run on the main thread, while GPUI image loading
can invoke its HTTP client from background WASM workers. This routes
`FetchHttpClient` requests through the web dispatcher's main-thread
mailbox, installs the client by default for web applications, and
removes thread-affine browser state from the safely movable dispatcher.
Release Notes:
- N/A
## Context
Static images decoded by GPUI ignored their EXIF `Orientation` tag, so
JPEGs that rely on it (photos from phones and cameras) rendered rotated
or flipped in image preview, Markdown preview, and other `ImageSource`
consumers. The `image` crate only exposes orientation through
`ImageDecoder::orientation()`, which must be read before the decoder is
consumed; `DynamicImage::from_decoder` does not apply it. The old path
went straight through `image::load_from_memory_with_format`, so the
metadata was never read.
Closes#60844.
Video of manual test below :
[Screencast from 2026-07-15
02-14-41.webm](https://github.com/user-attachments/assets/002b0324-44f8-4ddb-acbd-8c3e070d5248)
## How to Review
**Cargo.toml**
Raises the workspace `image` dependency minimum from `0.25.1` to
`0.25.4`, the first release exposing `orientation()` and
`apply_orientation()`. The lockfile already resolves to `0.25.10`, so no
lock change is required.
**crates/gpui/src/platform.rs**
Adds two crate-private helpers. `decode_static_image_from_decoder` reads
`orientation()`, decodes to a `DynamicImage`, applies the orientation,
then converts RGBA to GPUI's BGRA. `decode_static_image` builds a format
decoder from bytes and delegates to it. `Image::to_image_data` now
routes its static formats through these helpers instead of
`image::load_from_memory_with_format`. Adds
`test_image_to_image_data_applies_exif_orientation`, which decodes a
16x32 fixture stored upside down with EXIF Orientation 3 and asserts the
corner pixels were flipped upright; the test fails if orientation is
dropped.
**crates/gpui/src/elements/img.rs**
Routes `ImageAssetLoader` (Markdown paths, URLs, embedded resources)
through the same helpers, including the static WebP branch. GIF and
animated-WebP frame handling are left unchanged, since animated
orientation is out of scope.
## Self-Review Checklist
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the UI/UX checklist
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Fixed static images ignoring their EXIF orientation, which caused some
JPEGs to render rotated or flipped in image and Markdown preview.
Closes https://github.com/zed-industries/zed/issues/60595
cc Anthony-Eid since you did an initial pass on this.
# Objective
Currenly on macOs there is no way right now after the following
regression to use window management short keys to move them around. This
worked before, but was regressed initially in
https://github.com/zed-industries/zed/pull/59836 that tried fixing a
macos 27 clicking delay issue on the titlebar. That accidentally set the
`native_window.setMovable_(is_movable as BOOL)` to false. Because of
this mocos detects this and disables the window managements actions
because it thinks the window can/should not be able to move.
## Solution
The macOS 27 click delay actually comes from AppKit's native titlebar
dragging, not from `NSWindow.isMovable`. The problem is that
`is_movable` is also what enables the Window menu's tiling options, and
#59836 used it to turn off dragging, which disabled the tiling menu as a
side effect.
To fix this, I restored `is_movable` to its real meaning so the tiling
menu works again, and added a separate
`WindowOptions::app_owns_titlebar_drag` flag for windows that draw their
own titlebar and handle dragging via `Window::start_window_move`. On
macOS this tells AppKit to stop owning titlebar drags (removing the
click delay) without affecting `is_movable`. Zed's main window now sets
both `is_movable: true` and `app_owns_titlebar_drag: true`, so the
tiling menu stays enabled, the click delay is gone. I also added a
`window_movable` gpui example to make this behavior easy to test
manually.
## Testing
I added a gpui test example that helps testing this bug. You can run the
newly added gpui example with 4 different window configurations that
should confirm that this change is the right one for all of the window
types that we have.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
**After** (note this now shows the window managements entries as they
were greyed out.)
https://github.com/user-attachments/assets/192cc0e1-15d8-486f-b788-a92bb51fb7d1
**GPUI** (test examples with different window configurations.)
https://github.com/user-attachments/assets/c9e0f4d3-606b-4cd7-b4d8-a5bb16508164
---
Release Notes:
- Fix macos window management controlls were grayed out/not working
Adds a `container_query` element to GPUI, in the spirit of CSS container
queries: the element's own size is determined solely by its style and
the space offered by its parent, and once that size is known the
provided closure is called with the measured size to build the contents.
```rust
container_query(|size, _window, _cx| {
if size.width < px(240.) {
div().child("Narrow layout")
} else {
div().child("Wide layout")
}
});
```
Implementation notes:
- Defaults to filling its parent (`size_full()` semantics), overridable
via `Styled` since contents can't influence the container's size (the
same constraint CSS container queries impose).
- Reworks the `grid_layout` example (the Holy Grail layout) to
demonstrate it: the three-column grid collapses to a stacked column when
the window is narrower than 400px, and the header shows the live
measured width.
Release Notes:
- N/A
---------
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
This allows us to build powerful and flexible Input and TextArea
components
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# Objective
fix `cargo xtask web-examples --no-serve` error.
## Solution
Building GPUI web examples for wasm failed because gpui's ordinary
dev-dependencies were included in the wasm build graph. That pulled in
proptest's default fork/timeout support, which depends on wait-timeout.
wait-timeout does not support wasm32-unknown-unknown, so compilation
failed.
The a11y example also had a wasm_bindgen start function but was missing
the wasm no_main crate attribute, so Rust still expected a normal main
function and emitted E0601.
Move gpui's proptest dev-dependency behind the non-wasm target so web
example builds do not include native-only test timeout support. Add the
wasm no_main crate attribute to the a11y example.
Verified with:
```
cargo tree --target wasm32-unknown-unknown -p gpui -i wait-timeout
cargo xtask web-examples --no-serve
```
---
Release Notes:
- N/A or Added/Fixed/Improved ...
Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com>
Replaces the verbose struct-literal construction of `gpui::BoxShadow`
with a builder API:
- `BoxShadow::new(offset_x, offset_y, color)` takes the required fields,
with arguments ordered to match the CSS `box-shadow` property.
- `.blur_radius(_)`, `.spread_radius(_)`, and `.inset()` set the
optional fields.
All in-tree call sites are migrated, including the Tailwind-style
`shadow_xs`..`shadow_2xl` helpers in `gpui_macros`, the `ElevationIndex`
shadows in `ui`, and various widgets across `editor`, `workspace`,
`agent_ui`, and `ai_onboarding`. The fields on `BoxShadow` remain
public, so external code using struct-literal construction continues to
work.
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
## Context
GPUI API change only:
- added `.alpha(a: f32)` method to `RGBA`
- added `.opacity(factor: f32)` method to `RGBA`
- added documentation for both new methods
- added test coverage for both methods
These implementations already exist for the `HSLA` struct and were
missing for `RGBA`.
> [!NOTE]
> In my opinion, a trait implementation could be beneficial here. Let me
know what you think about that idea before I end up making unwanted
changes.
## How to Review
Just added the new methods, including documentation and test coverage.
## Self-Review Checklist
<!-- Check before requesting review: -->
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Added `gpui::Rgba::alpha` and `gpui::Rgba::opacity` methods for
setting and scaling a color's alpha channel, matching the existing
`gpui::Hsla` API
---------
Co-authored-by: dino <dinojoaocosta@gmail.com>
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Closes#58543 and extends to all instances of "Ok" button labels.
Release Notes:
- N/A
---------
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
GPUI AccessKit integration
This PR is replacing #51097 , and is much more limited in scope. This PR
*ONLY* adds AccessKit support to GPUI, and doesn't touch Zed. Once this
lands, we can start adding aria attributes to Zed's components.
This PR is the first step to addressing #41138 .
Release Notes:
- N/A or Added/Fixed/Improved ...
---------
Co-authored-by: John Tur <john-tur@outlook.com>
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
Co-authored-by: Agus Zubiaga <agus@zed.dev>
This PR adds support for inset shadows in the box shadow through the
`inset: true` field. It includes support for both the macOS as well WGSL
shaders. For now, there is no immediate application of it in Zed, so
nothing should change in the app.
<img width="600" alt="Screenshot 2026-05-25 at 8 46@2x"
src="https://github.com/user-attachments/assets/db564a6b-8af5-491a-a573-17c060a3647c"
/>
Run the example above with `cargo run --example shadow -p gpui`.
Release Notes:
- N/A
---------
Co-authored-by: Agus Zubiaga <agus@zed.dev>
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Closes #ISSUE
Release Notes:
- N/A
---------
Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
This allows us to move entities between windows without breaking all the
callbacks.
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
Relates to #5303 and
https://github.com/zed-industries/zed/issues/40826#issuecomment-3684556858
although I haven't found anywhere an actual request for `gpui` itself to
support a system alert sound.
### What
Basically, this PR adds a function that triggers an OS-dependent alert
sound, commonly used by terminal applications for `\a` / `BEL`, and GUI
applications to indicate an action failed in some small way (e.g. no
search results found, unable to move cursor, button disabled).
Also updated the `input` example, which now plays the bell if the user
presses <kbd>backspace</kbd> with nothing behind the cursor to delete,
or <kbd>delete</kbd> with nothing in front of the cursor.
Test with `cargo run --example input --features gpui_platform/font-kit`.
### Why
If this is merged, I plan to take a second step:
- Add a new Zed setting (probably something like
`terminal.audible_bell`)
- If enabled, `printf '\a'`, `tput bel` etc. would call this new API to
play an audible sound
This isn't the super-shiny dream of #5303 but it would allow users to
more easily configure tasks to notify when done. Plus, any TUI/CLI apps
that expect this functionality will work. Also, I think many terminal
users expect something like this (WezTerm, iTerm, etc. almost all
support this).
### Notes
~I was only able to test on macOS and Windows, so if there are any Linux
users who could verify this works for X11 / Wayland that would be a huge
help! If not I can try~
Confirmed Wayland + X11 both working when I ran the example on a NixOS
desktop
Release Notes:
- N/A
Closes#51198
This actually doesn't effect any of the scrollbars in Zed, as they have
a separate handler that prevents this issue from occurring
in `crates/ui/src/components/scrollbar.rs`, line 856
```rust
let current_offset = current_offset
.along(axis)
.clamp(-max_offset, Pixels::ZERO)
.abs();
```
so it is gpui specific. I still added a test case and I have a manual
test script:
<details><summary>Details</summary>
<p>
```rust
//! Reproduction of the scrollbar-offset bug in bottom-aligned `ListState`.
//!
//! Run with: cargo run -p gpui --example list_bottom_scrollbar_bug
//!
//! The list starts pinned to the bottom. Before the fix, the red scrollbar
//! thumb was pushed off the bottom of the track (invisible).
use gpui::{
App, Bounds, Context, ListAlignment, ListState, Window, WindowBounds, WindowOptions, div, list,
prelude::*, px, rgb, size,
};
use gpui_platform::application;
const ITEM_COUNT: usize = 40;
const COLORS: [u32; 4] = [0xE8F0FE, 0xFCE8E6, 0xE6F4EA, 0xFEF7E0];
struct BugRepro {
list_state: ListState,
}
impl BugRepro {
fn new() -> Self {
let list_state = ListState::new(ITEM_COUNT, ListAlignment::Bottom, px(5000.));
Self { list_state }
}
}
impl Render for BugRepro {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
let state = &self.list_state;
let max_offset = state.max_offset_for_scrollbar().y;
let raw_offset = -state.scroll_px_offset_for_scrollbar().y;
let viewport_h = state.viewport_bounds().size.height;
let content_h = max_offset + viewport_h;
let thumb_h = if content_h > px(0.) {
((viewport_h / content_h) * viewport_h).max(px(20.))
} else {
viewport_h
};
let thumb_top = if max_offset > px(0.) {
(raw_offset / max_offset) * (viewport_h - thumb_h)
} else {
px(0.)
};
div()
.size_full()
.flex()
.flex_row()
.bg(rgb(0xffffff))
.text_color(rgb(0x333333))
.text_xl()
.child(
div().flex_1().h_full().child(
list(state.clone(), |ix, _window, _cx| {
let height = if ix % 4 == 0 { px(70.) } else { px(40.) };
let bg = COLORS[ix % COLORS.len()];
div()
.h(height)
.w_full()
.bg(rgb(bg))
.border_b_1()
.border_color(rgb(0xcccccc))
.px_2()
.flex()
.items_center()
.child(format!("Item {ix}"))
.into_any()
})
.h_full()
.w_full(),
),
)
.child(
div()
.w(px(14.))
.h_full()
.bg(rgb(0xe0e0e0))
.relative()
.child(
div()
.absolute()
.right(px(0.))
.top(thumb_top)
.h(thumb_h)
.w(px(14.))
.rounded_sm()
.bg(rgb(0xff3333)),
),
)
}
}
fn main() {
application().run(|cx: &mut App| {
let bounds = Bounds::centered(None, size(px(400.), px(500.)), cx);
cx.open_window(
WindowOptions {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
|_, cx| cx.new(|_| BugRepro::new()),
)
.unwrap();
cx.activate(true);
});
}
```
</p>
</details>
where I was able to test it out, here is a video of the new working
behavior.
https://github.com/user-attachments/assets/02e26308-da18-418b-97fc-dd52a3325dab
Release Notes:
- gpui: fixed a bug where the scollbar would disappear when using a
bottom aligned list.
---------
Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
Continue #39876 to add `disabled` state to `MenuItem`.
Make this change for #44047 ready to have disabled state.
1. Add `disabled` state to `MenuItem`.
2. Add some builder methods to `Menu` and `MenuItem`.
3. Improve `set_menus` method to receive a `impl IntoIterator<Item =
Menu>`.
Release Notes:
- N/A
--
<img width="294" height="204" alt="image"
src="https://github.com/user-attachments/assets/688e0db8-6c4e-4f9b-a832-8228db0e95d8"
/>
```bash
cargo run -p gpui --example set_menus
```
Release Notes:
- N/A
To fix crash when use `deferred` in a `deferred`.
```
thread 'main' (4024343) panicked at /Users/jason/.cargo/git/checkouts/zed-a70e2ad075855582/5bde3cb/crates/gpui/src/window.rs:2411:9:
assertion `left == right` failed: cannot call defer_draw during deferred drawing
left: 1
right: 0
```
### When we need use nested deferred?
#### Case 1
- A Popover (used `deferred`) with a form.
- An Input element in the Popover form.
- Input have ContextMenu that used `deferred`.
- User right click Input to open menu.
<img width="539" height="331" alt="image"
src="https://github.com/user-attachments/assets/98c03b1e-58fd-4863-8bcd-0141252d1c51"
/>
#### Case 2
- A Popover (`deferred`) with some content.
- There have a `info` icon in the content to show some tip by open
another Popover.
### Test by `examples/popover.rs`
<img width="916" height="373" alt="image"
src="https://github.com/user-attachments/assets/7ed6a511-6d60-40fb-837b-ebab8f0cba37"
/>
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Lukas Wirth <lukas@zed.dev>
Implements a basic web platform for the wasm32-unknown-unknown target
for gpui
Release Notes:
- N/A *or* Added/Fixed/Improved ...
---------
Co-authored-by: John Tur <john-tur@outlook.com>
#2874 on steroids
Before you mark this PR as ready for review, make sure that you have:
- [ ] Added a solid test coverage and/or screenshots from doing manual
testing
- [ ] Done a self-review taking into account security and performance
aspects
- [ ] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
Release Notes:
- N/A
---------
Co-authored-by: Eric Holk <eric@zed.dev>
Had some trouble in a PR with missing a test API change until deep into
a refactor. Decided to move some example tests into the GPUI repo to put
those through their paces, and got carried away and made a big test
example file demonstrating all the testing features we have.
Release Notes:
- N/A
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Closes https://github.com/zed-industries/zed/issues/43208
This PR essentially unblocks the editable number field. The function
that shapes editor lines was hard-coding text alignment to the left,
meaning that whatever different alignment we'd pass through
`EditorStyles`would be ignored. To solve this, I just added a text align
and align width fields to the line paint function and updated all call
sites keeping the default configuration. Had to also add an
`alignment_offset()` helper to make sure the cursor positioning, the
selection background element, and the click-to-focus functionality were
kept in-sync with the non-left aligned editor.
Then... the big star of the show here is being able to add the `mode`
method to the number field, which uses `TextAlign::Center`, thus making
it work as we designed it to work.
https://github.com/user-attachments/assets/3539c976-d7bf-4d94-8188-a14328f94fbf
Next up, is turning the number filed to edit mode where applicable.
Release Notes:
- Fixed a bug where different text alignment configurations (i.e.,
center and right-aligned) wouldn't take effect in editors.
I've just enriched the existing tab_stop.rs example for GPUI with a
demonstration of tab_group. I don't think tab groups existed when the
original example was written.
(I didn't understand the behaviour for tab_group from the doccomments
and the example was missing, so I think this is a productive PR)
Release Notes:
- N/A
Closes #ISSUE
A [modal dialog](https://en.wikipedia.org/wiki/Modal_window) window is a
window that demands the user's immediate attention and blocks
interaction with other parts of the application until it's closed.
- On Windows this is done by disabling the parent window when the dialog
window is created and re-enabling the parent window when closed.
- On Wayland this is done using the
[`XdgDialog`](https://wayland.app/protocols/xdg-dialog-v1) protocol,
which hints to the compositor that the dialog should be modal. While
compositors like GNOME and KDE block parent interaction automatically,
the XDG specification does not guarantee this behavior, compositors may
deliver events to the parent window unfiltered. Since the specification
explicitly requires clients to implement event filtering logic
themselves, this PR implements client-side blocking in GPUI to ensure
consistent modal behavior across all Wayland compositors, including
those like Hyprland that don't block parent interaction.
- On X11 this is done by enabling the application window property
[`_NET_WM_STATE_MODAL`](https://specifications.freedesktop.org/wm/latest/ar01s05.html#id-1.6.8)
state.
I'm unable to implement this on MacOS as I lack the experience and the
hardware to test it. If anyone is interested on implementing this let me
know.
|Window|Linux (wayland)| Linux (x11) |MacOS|
|-|-|-|-|
|<video
src="https://github.com/user-attachments/assets/bfd0733a-445d-4b63-ac6b-ebe098a7dc74"></video>|<video
src="https://github.com/user-attachments/assets/024cd6ec-ff81-4250-a5be-5d207a023f8c"></video>|
N/A | <video
src="https://github.com/user-attachments/assets/656e60a5-26b2-4ee2-8368-1fbbe872453c"></video>|
TODO:
- [x] Block parent interaction client-side on X11
Release Notes:
- Added modal dialog window kind on GPUI
---------
Co-authored-by: Jason Lee <huacnlee@gmail.com>
Co-authored-by: Anthony Eid <anthony@zed.dev>
Co-authored-by: Anthony Eid <hello@anthonyeid.me>
Closes #ISSUE
Problem:
- The status bar’s pending keystroke indicator (shown next to --NORMAL--
in Vim mode) didn’t clear when focus moved to another context, e.g.
hitting g in the editor then clicking the Git panel. The keymap state
correctly canceled the prefix, but observers that render the indicator
never received a “pending input changed” notification, so the UI kept
showing stale prefixes until a new keystroke occurred.
Fix:
- The change introduces a `pending_input_changed_queued` flag and a new
helper `notify_pending_input_if_needed` which will flushes the queued
notification as soon as we have an App context. The
`pending_input_changed` now resets the flag after notifying subscribers.
Before:
https://github.com/user-attachments/assets/7bec4c34-acbf-42bd-b0d1-88df5ff099aa
After:
https://github.com/user-attachments/assets/2264dc93-3405-4d63-ad8f-50ada6733ae7
Release Notes:
- Fixed: pending keybinding prefixes on the status bar now clear
immediately when focus moves to another panel or UI context.
---------
Co-authored-by: Nathan Sobo <nathan@zed.dev>
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Closes#4644
Release Notes:
- Adds `MousePressureEvent`, an event that is sent anytime the touchpad
pressure changes, into `gpui`. MacOS only.
- Triggers go-to-defintion on force clicks in the editor.
This is my first contribution, let me know if I've missed something
here.
---------
Co-authored-by: Anthony Eid <anthony@zed.dev>
Co-authored-by: Antonio Scandurra <me@as-cii.com>
This reverts commit 3874594172.
This broke clicking, e.g. in snippets like
```rs
let x = vec![
1, 2, //
3,
];
```
clicking between `2` and `,` is quite off now.
Release Notes:
- N/A
Supersedes https://github.com/zed-industries/zed/pull/39910
At some point, these two (`index_for_x` and `closest_index_for_x`)
methods where separated out and some code paths used one, while other
code paths took the other. That said, their behavior is almost
identical:
- `index_for_x` computes the index behind the pixel offset, and returns
`None` if there's an overshoot
- `closest_index_for_x` computes the nearest index to the pixel offset,
taking into account whether the offset is over halfway through or not.
If there's an overshoot, it returns the length of the line.
Given these two behaviors, `closest_index_for_x` seems to be a more
useful API than `index_for_x`, and indeed the display map and other core
editor features use it extensively. So this PR is an experiment in
simply replacing one behavior with the other.
Release Notes:
- Improved the accuracy of mouse selections in Markdown
Release Notes:
- N/A
---
https://github.com/user-attachments/assets/d46b77ae-88ba-43da-93ad-3656a7fecaf9
The system menu is only support for macOS, so here just modify the macOS
platform special code.
The Windows, Linux used `ApplicationMenu`, I have already added
`checked` option to Zed's ContextMenu.
Then later when this PR merged, we can improve "View" menu to show check
state to panels (Project Panel, Outline Panel, ...).
This reintroduces `layer_shell` support after #32651 was reverted. On
top of that, it allows setting options for the created surface,
restricts the enum variant to the `wayland` feature, and adds an example
that renders a clock widget using the protocol.
I've renamed the `WindowKind` variant to `LayerShell` from `Overlay`,
since the protocol can also be used to render wallpapers and such, which
doesn't really fit with the word.
Things I'm still unsure of:
- We need to get the layer options types to the user somehow, but
nothing from the `platform::linux` crate was exported, I'm assuming
intentionally. I've kept the types inside the module (instead of doing
`pub use layer_shell::*` to not pollute the global namespace with
generic words like `Anchor` or `Layer` Let me know if you want to do
this differently.
- I've added the options to the `WindowKind` variant. That's the only
clean way I see to supply them when the window is created. This makes
the kind no longer implement `Copy`.
- The options don't have setter methods yet and can only be defined on
window creation. We'd have to make fallible functions for setting them,
which only work if the underlying surface is a `layer_shell` surface.
That feels un-rust-y.
CC @zeroeightysix
Thanks to @wuliuqii, whose layer-shell implementation I've also looked
at while putting this together.
Release Notes:
- Add support for the `layer_shell` protocol on wayland
---------
Co-authored-by: Ridan Vandenbergh <ridanvandenbergh@gmail.com>
Fixes a bug in https://github.com/zed-industries/zed/pull/39928
The bug caused all completions to appear in bold-face
Release Notes:
- Fixed a bug where bold-face font was applied to the wrong characters
in items in the autocomplete menu
Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>