Conversation
Handle the `WM_QUERYENDSESSION` and `WM_ENDSESSION` messages, which are used by Windows when shutting down an application. For example, Restart Manager uses this mechanism to gracefully close applications (e.g. when installing an update to the application). Release Notes: - N/A
Prewarming cosmic-text font cache completely eliminated expensive `get_font_matches` calls and thus reducing the time it takes to call `cosmic_text::shape::ShapeLine::new`. Release Notes: - Improved rendering performance on Linux by prewarming font match caches.
Allow disabling stacker in gpui (as on wasm it uncondtionally allocates more stack) Release Notes: - N/A
Release Notes: - Improved rasterization performance on Linux by caching glyphs after measuring bounds.
Extends the existing GPUI frame-duration telemetry with the average time from a window's first invalidation through presentation. - Record dirty-to-present durations in each window profiler - Include the declared root entity type name on window handles - Add the average and root type to the existing five-minute `Frame Duration Report` event Testing: - `cargo fmt --all -- --check` - `cargo test -p gpui --features profiler records_dirty_to_present_durations` - `cargo check -p gpui --no-default-features` - `cargo check -p input_latency_ui -p zed` Release Notes: - N/A
# Objective I’m building a component library with GPUI and ran into a panic when I enabled the profiler feature for a `wasm32-unknown-unknown` build. Dispatching an action calls std::time::Instant::now(), which has no clock implementation on this target, and the browser reports time not implemented on this platform. The panic then triggers RefCell already borrowed errors and leaves the GPUI window unresponsive. The current `main` fails to compile this feature combination because the action profiler’s std::time::Instant does not match the scheduler-based timestamps in the profiler journal. I want GPUI’s action profiler to use the same cross-platform clock as the rest of the profiler and keep this configuration covered by CI. ## Solution Use `scheduler::Instant`, the scheduler crate's cross-platform instant type, for action timings so they match the rest of the GPUI profiler. Keep the existing downstream wasm check and add a separate profiler-enabled GPUI wasm check so CI covers both feature configurations. ## Testing - `cargo check --target wasm32-unknown-unknown -p gpui --no-default-features --features profiler` - `cargo -Zbuild-std=std,panic_abort check --target wasm32-unknown-unknown -p gpui_platform -p cloud_api_client --features gpui/profiler` - `cargo test -p gpui --no-default-features --features profiler profiler::` (48 tests passed) - `./script/clippy -p gpui` I ran a wasm GPUI app in Edge with WebGPU. The app opens a window and dispatches an action with `profiler` enabled. Before this change, the action produced the clock panic and follow-on borrow errors. After the fix change, the action completed and the window remained active. I did not run the browser harness in Firefox or Safari, though the wasm compile check covers the changed profiler configuration without depending on a browser. ## 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); this PR has no UI changes - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable
… layers # Objective olor emoji (COLR glyphs) are rasterized on the GPU by compositing each glyph layer into a D3D11 render target that is created with `pInitialData: None` and, until now, never cleared. The texture contents are undefined: texels not covered by any layer quad retained garbage (typically leftovers from previous rasterizations via the DXGI allocation pool). ## Solution - Clear the render target with `[0, 0, 0, 0]` (premultiplied transparent) immediately after binding it and before drawing the layers. ## Testing add test to test this specifically ## Showcase before : <img width="1634" height="754" alt="ezgif-1a339c7dea79f905" src="https://github.com/user-attachments/assets/6e282c46-d2a4-4043-9c1c-7f4ee9232fcc" /> after : <img width="1677" height="690" alt="Screenshot 2026-08-26 015248" src="https://github.com/user-attachments/assets/c922909e-c70b-49f0-88fd-5a0c7cbe574b" />
## Objective GPUI's X11 `WM_CLASS` property omits its final NUL terminator, so any window manager that relies on the terminator reads the class one byte short. `WM_CLASS` is specified by [ICCCM §4.1.2.5](https://tronche.com/gui/x/icccm/sec-4.html#s-4.1.2.5) as two consecutive NUL-**terminated** strings, `instance\0class\0`. `set_app_id` writes the separator but not the final terminator: ```rust let mut data = Vec::with_capacity(app_id.len() * 2 + 1); data.extend(app_id.bytes()); // instance data.push(b'\0'); data.extend(app_id.bytes()); // class <- no trailing NUL ``` This affects Zed itself. `ReleaseChannel::app_id()` returns `dev.zed.Zed` on stable, so under X11 and XWayland the class is read as `dev.zed.Ze`. The shipped desktop file is `dev.zed.Zed.desktop`, so the association it depends on is exactly the string being truncated, and window-manager rules or taskbar grouping matching `dev.zed.Zed` silently fail to apply. Wayland is unaffected, since the app id is set through `xdg_toplevel` rather than an X11 property. ## Solution Append the missing terminator after the class string, and size the `Vec` capacity to match (`* 2 + 2` rather than `* 2 + 1`). ## Testing Tested manually on Arch Linux with Hyprland v0.56.2 (wlroots) via XWayland. **Reproducing the bug** — Zed 1.14.2, before the fix: ``` $ env -u WAYLAND_DISPLAY zeditor some-dir $ hyprctl clients -j | jq '.[] | select(.xwayland) | .class' "dev.zed.Zed\u0000dev.zed.Ze" ``` The same window read with `xprop`, which does not require the terminator, shows the intended value — confirming the property itself is malformed rather than the compositor misreading it: ``` $ xprop -id 0x800001 WM_CLASS WM_CLASS(STRING) = "dev.zed.Zed", "dev.zed.Zed" ``` **Control** — on the same compositor and the same XWayland path, Alacritty (winit, which writes the trailing NUL) reports its class intact: ``` $ hyprctl clients -j | jq '.[] | select(.xwayland) | .class' "Alacritty" ``` The same truncation was reproduced independently with a third-party GPUI application using `app_id: Some("sprite")`, which reports `sprite\u0000sprit`. **Platforms:** verified on Linux/XWayland only. Wayland does not use this code path. macOS and Windows have their own `set_app_id` implementations and are unaffected by this change. **Needs more testing:** confirmation on a bare X11 session (not XWayland) and on a non-wlroots window manager such as i3, KWin, or Mutter would be welcome — the malformed property is compositor-independent, but which readers visibly truncate it is not. ## Self-Review Checklist - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments — *none added* - [x] The content adheres to Zed's UI standards — *N/A, no UI change* - [ ] Tests cover the new/changed behavior — *see note below* - [x] Performance impact has been considered and is acceptable — *one additional byte in a property set once per window* "No automated test: asserting the property bytes requires a live X server. Happy to add one if there's an existing pattern for X11 window tests I've missed." Co-authored-by: Lukas Wirth <lukas@zed.dev>
…#63012)
# Objective
`gpui_macos` implements `PlatformWindow::render_to_image` — the
MetalRenderer samples an offscreen target, so a **hidden** window can be
captured. `gpui_windows` does not implement it, so the method falls
through to the trait default and returns `Err("render_to_image not
implemented for this platform")`.
That leaves Windows consumers (tests, headless screenshot harnesses) on
`PrintWindow`-style workarounds, which require the window to actually be
on screen: a DirectComposition swap chain that never presents has no
frame to read, so you get a visible flash — or an off-screen parking
trick — for every capture.
This closes the macOS/Windows gap. Linux (`gpui_linux`) still returns
the trait default; a Blade/wgpu readback is the obvious follow-up but is
not in this PR.
## Solution
The DirectX analogue of the Metal path:
- `DirectXRenderer::draw`'s clear, scene upload and batch encoding are
factored into a shared `render(scene, background_appearance)`. `draw` is
now `render` + `present`; `render_to_image` is `render` + readback.
Nothing about how a frame is produced is duplicated between them, so the
two cannot drift.
- `render_to_image` renders into the **existing** render target —
created at window construction, so no window need ever be shown — then
copies it into a `D3D11_USAGE_STAGING` texture, `Map`s it, and converts
BGRA → RGBA. `RowPitch` padding is honoured per row; the copy loop
carries a safety comment.
- It refuses to run while `skip_draws` is set. That flag marks a pending
device-lost recovery, where the atlas still holds tile references from
the previous device — drawing before the forced re-render rebuilds them
panics in `DirectXAtlasState::texture` (the case
`WindowState::force_render_pending` documents). Returning an error beats
panicking in a capture harness.
- Gated on `cfg(any(test, feature = "test-support"))` to match the trait
method. `gpui_platform`'s `test-support` now forwards to
`gpui_windows/test-support`, the way it already does for `gpui_macos`.
No behaviour change outside `test-support`/`cfg(test)` builds beyond the
`render` factoring, which is a pure code move.
## Testing
- **Windows, functional:** an earlier revision of this patch has been in
production use since June in the `--screenshot` harness of a GPUI app I
ship ([Ferail](https://github.com/jonx/Ferail)), capturing a hidden
window (`show: false`) with no flash. BGRA→RGBA output was verified
against the on-screen rendering.
- **This exact revision** has been cross-checked from macOS only: `cargo
clippy -p gpui_windows --no-default-features --features test-support
--target x86_64-pc-windows-msvc -- -D warnings` is clean, both with and
without `test-support` (clang-cl + `xwin`; `--no-default-features` skips
only the `windows-manifest` embed-resource step, which is irrelevant
here). I'm relying on CI for a native Windows build of this revision —
happy to report back from a Windows host if that's a blocker for review.
- **Not covered by an automated test.** The behaviour needs a live D3D11
device, so it can only be exercised by a Windows-hosted test. Happy to
add one under `gpui_windows` if you'd like it — say the word and I'll
push it rather than guess at the shape you want.
- **Reviewers:** the interesting part is the staging-texture readback in
`directx_renderer.rs`. Worth a second pair of eyes on the `skip_draws`
guard and on premultiplied alpha (the swap chain is
`DXGI_ALPHA_MODE_PREMULTIPLIED`, so non-opaque captures come back
premultiplied — same as the macOS path, but it does mean
semi-transparent regions are not straight-alpha).
## 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) — n/a, no UI surface
- [ ] Tests cover the new/changed behavior — see Testing; needs a
Windows host, happy to add
- [x] Performance impact has been considered and is acceptable — the
readback path is `test-support`-only; `draw` is unchanged apart from the
`render` factoring
## Showcase
<!-- TODO: drop in the headless Windows capture (and the macOS one
beside it) -->
…(#62743) # Objective `LineWrapper` treats every punctuation character as a break opportunity, so a wrap can land right before `!`, `?`, `/`, `)`, `]`, `}`, a closing quote or an ellipsis. Text such as `please fix this plz!`, `8.0/8.0`, `cli/install`, `(see)` or `“quoted”` then wraps with the closing mark orphaned at the start of the next line. ## Solution Add the "UAX 14 LB13 rule" to `LineWrapper::is_word_char`, which is to not break before `! ? / ) ] } " ” » …` ## Testing Added unit tests and manually tested myself with a long paragraph in a gpui app. ## 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 - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable (one extra `matches!` per character in the wrap loop)
…t DPI scaling (#62859) # Objective Fixes #48927. On Windows, when monitors have different DPI scaling factors, a new window opened on a secondary monitor can be positioned partially off-screen, with the title bar unreachable. ## Solution `WindowsWindow::new` calls `CreateWindowExW` with `CW_USEDEFAULT` for the window's initial position, so Windows picks a starting spot (typically based on where the previous window was, which is often the primary monitor) before the window is explicitly moved to its intended monitor via `SetWindowPlacement`. `WindowsWindowState::new` immediately reads the window's scale factor via `GetDpiForWindow(hwnd)` at that point — i.e. the DPI of wherever Windows initially placed it, not necessarily the target monitor. `retrieve_window_placement` then used that scale factor to convert the target monitor's logical bounds into physical pixels. When the two monitors have different scaling (e.g. 150% vs 100%, as in the linked issue), this produces the wrong physical rect, leaving the window off-screen. The target `WindowsDisplay` already computes its own correct `scale_factor` from the actual monitor (`get_scale_factor_for_monitor`) — this is also what `check_given_bounds` already uses. This PR exposes that value via `WindowsDisplay::scale_factor()` and uses it in `retrieve_window_placement` instead of the transient window's scale factor, since the bounds being converted are expressed in logical pixels for that target display. ## Testing - Verified the logic by tracing through `WindowsWindowState::new` → `retrieve_window_placement` → `calculate_window_rect` and confirming the target monitor's own DPI (not the temporarily-assigned window DPI) is now used to compute the physical placement rect, matching the approach `WindowsDisplay::check_given_bounds` already uses for the same target/temporary-monitor mismatch. - I wasn't able to build/run Zed locally in this environment (missing Windows SDK components in the local toolchain, unrelated to this change) to reproduce the original multi-monitor/mixed-DPI repro steps first-hand. I'd appreciate a maintainer or anyone who can reproduce #48927 double-checking on real mixed-DPI hardware. - Platforms: Windows only (`gpui_windows` crate); no other platform code touched. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments (no new unsafe blocks added) - [ ] The content adheres to Zed's UI standards (N/A, no UI change) - [ ] Tests cover the new/changed behavior (no existing test harness for Windows-specific placement logic; happy to add one if pointed at the right pattern) - [x] Performance impact has been considered and is acceptable (no measurable impact; same number of DPI queries, just reading from the already-computed `WindowsDisplay` instead of the window) Release Notes: - Fixed: new windows on Windows could open partially off-screen when placed on a secondary monitor with a different DPI scaling factor than the monitor Windows initially placed them on. --------- Co-authored-by: Lukas Wirth <lukas@zed.dev> Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
`gpui::bench` previously required GPUI's full `test-support` feature. Any benchmark using the supported GPUI harness therefore compiled test-only APIs and fakes, even when the benchmark otherwise followed production dependency paths. This change introduces `bench-support` as GPUI's canonical benchmark feature and keeps `bench` as a compatibility alias for existing consumers. The benchmark feature now exposes only the existing GPUI internals that `BenchAppContext` needs: the real threaded dispatcher, profiler integration, and a headless platform surface. Benchmark HTTP requests use the production `BlockedHttpClient`, so accidental network access fails instead of silently entering a fake response path. The current headless implementation reuses the cfg-stripped core of `TestPlatform`. Test-only prompt state, simulation APIs, and test executors remain unavailable under `bench-support`. Cargo feature-tree checks confirm that both `bench-support` and the compatibility alias remain independent of `test-support`. This also adds a `gpui-bench` agent skill covering production-shaped fixtures, frame and foreground responsiveness, macOS headless Metal rendering, deterministic correctness guards, Criterion measurement, Instruments symbolication, and the requirement that a benchmark's complete dependency graph contain no `test-support` feature. Two follow-ups are intentionally deferred to keep this feature-isolation change reviewable: - Extract the shared headless implementation into `HeadlessPlatformCore`, with separate `BenchPlatform` and `TestPlatform` wrappers. This will remove benchmark-related cfg branches from the test-facing type and make their supported surfaces explicit. - Add a shared scripted HTTP client that compiles independently under either `http_client/test-support` or `http_client/bench-support`. Tests and benchmarks could then serve predefined responses through the same deterministic transport boundary without either support feature enabling the other; the default benchmark context should remain network-blocked. This PR only isolates GPUI itself. Migrating downstream benchmark fixtures that explicitly request other crates' `test-support` features remains separate work. Testing performed: - `cargo tree --offline --package gpui --no-default-features --features bench-support --edges features --invert gpui` - `cargo tree --offline --package gpui --no-default-features --features bench --edges features --invert gpui` - `cargo check -p gpui --no-default-features --features bench-support` - `cargo check -p gpui --no-default-features --features bench` - `git diff --check` Release Notes: - N/A
GPUI's `bench-support` feature provides the benchmark context and headless-renderer interface without enabling `test-support`, but the platform implementation remained available only through `gpui_platform/test-support`. As a result, consumers could not use `#[gpui::bench]` with a fully isolated feature graph because the generated benchmark harness calls `gpui_platform::current_headless_renderer()`. This threads `bench-support` through `gpui_platform`, `gpui_macos`, and `gpui_apple`, exposing the existing Metal headless renderer without widening unrelated test window or prompt APIs. The existing benchmark package now requests the platform's canonical `bench-support` feature. Its other test-backed fixtures are intentionally unchanged and remain outside this focused dependency fix. Validation: - Confirmed `gpui_apple/bench-support`, `gpui_macos/bench-support`, and `gpui_platform/bench-support` resolve no `test-support` feature with `cargo tree --locked --no-default-features --features bench-support -e no-dev,features`. - Ran `cargo check --locked -p benchmarks --benches` to compile every existing `#[gpui::bench]` target against the real platform headless renderer. - Ran `cargo nextest run --locked -p gpui_apple -p gpui_macos -p gpui_platform`. - Ran `./script/clippy` for each changed platform package with `--no-default-features --features bench-support`. - Ran `cargo fmt --check`. Release Notes: - N/A
Deduplicates crates with different versions from the graph, drops unused features. `cargo tree -d duplicate` listing: 160 -> 112 lines. <details> <summary>Deduplicated list</summary> ``` base64 (v0.22.1, v0.21.7 -> v0.22.1) convert_case (v0.11.0, v0.10.0, v0.8.0 -> v0.11.0, v0.10.0) core-foundation (v0.10.0, v0.9.4 -> v0.10.0) cssparser (v0.36.0, v0.35.0 -> v0.37.0, v0.36.0) fancy-regex (v0.18.0, v0.16.2 -> v0.19.0) fixedbitset (v0.5.7, v0.4.2 -> v0.5.7) h2 (v0.4.12, v0.3.27 -> v0.4.12) heck (v0.5.0, v0.4.1, v0.3.3 -> v0.5.0, v0.4.1) html5ever (v0.39.0, v0.35.0 -> v0.39.0) hyper (v1.7.0, v0.14.32 -> v1.7.0) hyper-rustls (v0.27.9, v0.24.2 -> v0.27.9) mach2 (v0.6.0, v0.5.0, v0.4.3 -> v0.6.0, v0.5.0) markup5ever (v0.39.0, v0.35.0 -> v0.39.0) phf (v0.13.1, v0.12.1, v0.11.3 -> v0.13.1, v0.11.3) phf_codegen (v0.13.1, v0.11.3 -> v0.13.1) phf_generator (v0.13.1, v0.12.1, v0.11.3 -> v0.13.1, v0.11.3) phf_macros (v0.13.1, v0.12.1, v0.11.3 -> v0.13.1, v0.11.3) phf_shared (v0.13.1, v0.12.1, v0.11.3 -> v0.13.1, v0.11.3) prost (v0.12.6, v0.9.0 -> v0.14.4) prost-build (v0.12.6, v0.9.0 -> v0.14.4) prost-derive (v0.12.6, v0.9.0 -> v0.14.4) prost-types (v0.12.6, v0.9.0 -> v0.14.4) rustix (v1.1.4, v0.38.44 -> v1.1.4) rustls (v0.23.40, v0.21.12 -> v0.23.40) rustls-native-certs (v0.8.3, v0.6.3 -> v0.8.3) rustls-pemfile (v2.2.0, v1.0.4 -> v2.2.0) rustls-webpki (v0.103.13, v0.101.7 -> v0.103.13) security-framework (v3.5.1, v2.11.1 -> v3.5.1) socket2 (v0.6.3, v0.5.10 -> v0.6.3) string_cache (v0.9.0, v0.8.9 -> v0.9.0) string_cache_codegen (v0.6.1, v0.5.4 -> v0.6.1) strum (v0.28.0, v0.27.2 -> v0.28.0) strum_macros (v0.28.0, v0.27.2 -> v0.28.0) tendril (v0.5.1, v0.4.3 -> v0.5.1) tokio-rustls (v0.26.4, v0.24.1 -> v0.26.4) tungstenite (v0.28.0, v0.27.0 -> v0.28.0) web_atoms (v0.2.6, v0.1.3 -> v0.2.6) which (v6.0.3, v4.4.2 -> v8.0.5) ``` </details> Release Notes: - N/A
Allows setting various attributes for the underlying mirror textarea on the web. Allows GPUI app authors to specify things like "this element should be auto-corrected"
This prepares for the keybinding hints PR. To reproduce, press `ctrl-b` in a GPUI app with `ctrl-b h` and `ctrl-b j` bindings, then call `window.blur()`. The live pending state clears, but observers still report `ctrl-b`. `Window::blur` now clears pending input and notifies observers after the current effect cycle. I don't think we currently exercise this path in Zed, and I was only able to reproduce it with an example GPUI app. Release Notes: - N/A
When syncing text to the browser IME mirror, we sometimes need to mark a particular range as "editable". Native clients have a pull-based model, so don't need this mechanism, but on the web we need to proactively push content to the IME mirror `textarea`.
- Simplify PowerShell discovery, and add support for .NET global tool installations. - Fix Git Bash discovery in the case where Zed was launched from within Git Bash. Git Bash prepends its internal `mingw64\bin` directory to `PATH`, so `which git` returns a different `bash` executable that causes the relative path lookup to fail. Release Notes: - N/A
Adds support to GPUI for touch events, important for mobile web browsers, and any potential native ios/android platforms
`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
GPUI's scheduler exposed synchronous blocking APIs on WebAssembly even though the platform implementation could only panic. This became an implicit crash when cancellation dropped a scoped background operation: preserving the borrowed task lifetime called `Scheduler::block`, which panicked with `Cannot block on wasm`. This change removes blocking scheduler and executor APIs from WebAssembly builds, including borrowed background scopes and the separate `pollster::block_on` export. Native behavior remains unchanged. Application shutdown now runs WebAssembly quit handlers asynchronously as best-effort cleanup rather than blocking the browser event-loop thread. Release Notes: - Fixed a GPUI Web crash caused by synchronous executor blocking.
…572) # Objective Rust 1.96 emits a warning when compiling the `block` crate, that it will no longer compile past some future version of Rust. The `block` crate provides `ConcreteBlock` and `RcBlock`, which are stack- and heap-based functions often passed as callbacks to MacOS. The old `objc` crate family is deprecated and no longer maintained. The goal of the PR is to replace one call to `block::ConcreteBlock` by migrating a standalone portion of code to the objc2 crate family. A full migration to `objc2` by Zed has been long on the horizon (#22408) Additional benefits: The new code is completely typed, uses automatic memory management, and reduces lines of unsafe Rust from 50+ to 1. The lingering unsafe converts a raw pointer stored by `self` to the respective `objc2` type, since the rest of the window implementation does not use the new crates yet. ## Solution Migrate `PlatformWindow::prompt`'s MacOS implementation to `objc2`. ## Testing Direct platform code is quite fragile and hard to test, however you can exercise the codepath by running the following `gpui` example and clicking on the prompt buttons. ```sh cargo run -p gpui --example window ``` I've also built Zed with these changes and tried codepaths which activate prompts, such as deleting a file. ## 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) - [ ] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable
Adds platform-specific scroll behaviour, and also exposes predicted events for better latency
[corgi](https://github.com/ConradIrwin/corgi) is a cargo-compatible build tool that runs `build.rs` scripts and proc-macros in a sandbox (no network, no ambient env, reads limited to a package's own `.rs` sources unless declared). This makes Zed buildable under it. Cargo builds (dev and release) are unaffected. ### Changes - **`scratch` patch**: patch `scratch` to a small local copy (`corgi-patches/scratch`) that reads `OUT_DIR` at runtime instead of baking it in at compile time. `cxx-build` writes its shared cxxbridge headers into `scratch::path(...)`; upstream returns a single global dir (outside any action's `OUT_DIR`) that the sandbox can't grant, while this patch gives each build script a private, writable dir in its own entry. webrtc-sys is self-contained, so per-crate scratch dirs are sufficient. Kept local rather than a cxx git fork because a git checkout of cxx needs symlink support that Windows cargo CI lacks. - **Dev asset loading**: add `util::dev_fs_embed!` and switch dev-mode `rust_embed` asset sources (`assets`, `settings`, `grammars`, `agent`, `edit_prediction_cli`) to read from the checkout at runtime, locating the repo root by walking from the executable up to the enclosing `.git`. This avoids baking `CARGO_MANIFEST_DIR` into the binary (corgi rejects artifacts that embed the build-time checkout path, and it's wrong in any other worktree). Release builds still embed via `#[derive(RustEmbed)]`. - **Stop baking checkout paths into artifacts**: drop `gpui::GPUI_MANIFEST_DIR`; resolve `../gpui` from `gpui_apple`'s build script; stage the metal shader into `OUT_DIR` before compiling so the `.metallib` records the output dir, not the checkout; resolve the repo root at runtime in `remote` and `inspector_ui` (removing `inspector_ui`'s `build.rs` / `ZED_REPO_DIR`). - **corgi.toml**: declare the pinned tools (`cmake`, prebuilt libwebrtc via `LK_CUSTOM_WEBRTC`), a release-only `ZED_COMMIT_SHA` probe, and the non-`.rs` / cross-package reads each package performs. ### Validation - `corgi check` + `corgi build`, dev and release, for `zed` (plus `cli`, `remote_server`, `ep`) with a warm C++ cache — clean; built binaries embed no checkout path. - `corgi fmt --check`, `corgi clippy`, and `corgi test` on the changed crates (922 tests pass). - `cargo check -p util` locally; relying on CI for the full cargo build/test matrix. ### Notes for the reviewer - Per the repo rule, the first two lines of `README.md` are the review-confirmation marker; remove them before merging (this is what Danger is failing on). - `remote_server` cross-compilation (linux-musl via zigbuild) is not yet covered by `corgi.toml` — host (macOS arm64) only for now. ### Suggested .rules additions Only if the team wants corgi guidance in `.rules` (it recurred several times here): dev builds must not bake the checkout path into artifacts — no `env!("CARGO_MANIFEST_DIR")` or `file!()`-derived absolute paths in library/binary output. Resolve the repo root at runtime via `util::dev_repo_root()` (walks to `.git`), and use `util::dev_fs_embed!` for dev-mode `rust_embed` sources. Release Notes: - N/A --------- Co-authored-by: Ben Kunkle <ben@zed.dev>
# Objective
`to_cmd_variable` and `to_powershell_variable` removed the last byte of
a
`${...}` argument assuming it was the closing brace, without checking
one was
there
```rust
// If the input starts with "${", remove the trailing "}"
format!("$env:{}", &var_str[..var_str.len() - 1])
```
# Solution
Use strip_suffix('}') and pass the input through when it isn't a
variable reference
## Testing
added tests to cover this
To reproduce on Windows, add a context server with a malformed argument
to settings.json:
```
"context_servers": {
"crash-repro": {
"command": "does-not-matter",
"args": ["${"]
}
}
}
````
Opening the agent panel and zed will crash
Release Notes:
- Fixed a panic when converting a malformed `${` shell variable
reference on Windows
---------
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
Fixes a few edge cases where we weren't correctly tracking whether to hide the keyboard when touch events happen Also forces a synchronous render on web after the viewport resizes (which happens when the keyboard appears/disappears). This prevents a 1 frame delay where the browser would use the old bitmap, stretched to the new size
Touch pans currently preserve small amounts of movement on both axes, including in the synthetic momentum generated after release. In a nested scrolling layout, a mostly vertical fling that starts over a horizontally scrollable child can therefore move the child horizontally while its ancestor moves vertically. This locks each touch pan to the dominant axis of its accumulated movement when it crosses the touch-slop threshold. Initial movement, predicted updates, release correction, velocity, and momentum are projected onto that axis, so every scroll listener sees the same one-dimensional gesture for its full lifetime. The existing trackpad and wheel behavior remains unchanged; the new rule is applied by the portable raw-touch recognizer before it emits semantic scroll events. Testing: - `cargo nextest run -p gpui --lib gestures::tests` - `cargo fmt --all -- --check` - `./script/clippy -p gpui` - Built Delta Web for `wasm32-unknown-unknown` with this GPUI worktree and reached a successful Trunk release build Release Notes: - N/A
`wayland-backend` falls back to `eprintln!` when its optional `log` feature is disabled. If a Wayland connection fails while standard error is unavailable, that fallback panics while trying to report the original error. Closes ZED-8BW Enable the existing `log` feature on `gpui_linux`'s direct `wayland-backend` dependency. `gpui_linux` already depends on the `log` facade, so this introduces no new logging system; it routes backend errors through the configured logger and avoids the secondary standard-error panic. Testing performed: Release Notes: - Fixed a Linux crash when reporting a Wayland connection error while standard error is unavailable.
GPUI's touch gesture recognizer handles taps and pans, but its long-press event was only a placeholder. Applications therefore could not distinguish a deliberate press-and-hold from a tap or scroll using the portable touch path. This adds deadline-driven long-press recognition and dispatches a phased event stream through GPUI's existing capture and bubble listener path. A listener claims the gesture by preventing the initial event's default behavior and capturing it for an entity. Unclaimed gestures remain eligible for the existing tap and pan behaviors, while claimed gestures receive movement and termination events without also producing taps or scrolling. The timer is cancelled when the pending gesture resolves. `gpui_web` now translates reusable browser pointer identifiers into touch identifiers that remain unique for each touch lifetime, preventing an old timer from acting on a newer touch. Native macOS trackpad scrolling remains on its existing `ScrollWheelEvent` path and does not enter touch gesture recognition. Testing performed: - `cargo fmt --all -- --check` - `cargo nextest run -p gpui --lib long_press` (10 passed) - `RUSTC_BOOTSTRAP=1 cargo check -p gpui_web --target wasm32-unknown-unknown` Release Notes: - N/A
… (#63577) Zed's `fs_embed!` macro hand-implements rust-embed's `RustEmbed` trait in its dev arm so debug builds read assets from the checkout at runtime (introduced with corgi support in #63396). That trait returns `rust_embed::Filenames`, an enum with exactly one variant per compilation context: `Dynamic` when rust-embed's `debug-embed` feature is off, `Embedded` when it is on. The dev arm constructed `Filenames::Dynamic` unconditionally. Cargo unifies features across the entire build graph, so a downstream workspace that consumes Zed's crates by git dependency and enables `rust-embed/debug-embed` anywhere (Delta did, for self-contained debug binaries) changes the enum's shape for `util` itself, and `util` stops compiling with `E0599: no variant named Dynamic`. Zed's own CI can never catch this because nothing in Zed's graph enables the feature; it only surfaces in embedding workspaces, where it blocks any dependency bump past #63396. This change makes the combination supported. `util` gains a forwarding `debug-embed` feature, and `__fs_embed_iter` now has two implementations under cfgs that mirror rust-embed's variant availability: the existing boxed-iterator path when the feature is off, and an `Embedded` path when it is on, which scans the checkout once per embed site and leaks the cached name list (the `Embedded` variant requires `'static` names; a per-process list matches the macro's documented contract that dev edits appear on the next launch, and `get` still reads file contents fresh on every call). Consumers must enable the feature through `util/debug-embed` rather than directly on rust-embed — enabling it behind util's back still breaks, which only rust-embed itself could fix; the feature's documentation says so. A new test exercises the dev arm's `iter` and `get` through the macro, and running util's suite with `--features debug-embed` covers the other variant; both configurations pass 133 tests, plus clippy and fmt. Release Notes: - N/A --------- Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Relicenses `zlog`, `ztracing`, and `ztracing_macro` from GPL-3.0-or-later to Apache-2.0. GPUI depends on `ztracing`, which depends on `zlog`, so these crates have to be non-copyleft for GPUI to ship as a permissively licensed project. - Switched the `license` field to `Apache-2.0` in all three manifests. - Added the `LICENSE-APACHE` symlink to `zlog`, and dropped the `LICENSE-GPL` symlinks from all three. `ztracing` and `ztracing_macro` already carried both symlinks; now the on-disk license matches the manifest. - Declared `license = "Apache-2.0"` for `gpui_util`, which had a `LICENSE-APACHE` symlink but no `license` field. `script/check-licenses` doesn't catch that, since it only inspects symlinks. No source changes; none of these crates carry GPL headers or in-source license references. Checked the rest of the subtree while here: the only first-party crates reachable from `ztracing` via `cargo tree -e normal` are `collections`, `gpui_util`, `zlog`, and `ztracing_macro`, all Apache-2.0 now. Third-party deps (`tracing`, `tracing-subscriber`, `chrono`, `log`, `anyhow`, `tracy-client`) are MIT/Apache. `script/check-licenses` passes. Release Notes: - N/A
Zed's `fs_embed!` macro normally reads assets from the checkout in debug builds. The new `util/debug-embed` feature is intended to compile those assets into debug binaries, but it previously changed only the `rust_embed::Filenames` variant while leaving file loading on the runtime path. That breaks downstream workspaces such as Delta: the runtime loader identifies Delta as the repository root, then looks for Zed grammar assets under Delta's checkout. Tests consequently panic when language configuration files cannot be found. This makes `util/debug-embed` select a compile-time `RustEmbed` expansion in every profile. Builds without the feature retain live filesystem loading in debug mode. The runtime iterator no longer depends on a feature-specific `rust_embed::Filenames` variant, so Cargo feature unification remains safe when another package enables `rust-embed/debug-embed` directly. The regression fixture uses a deliberately invalid runtime path when `debug-embed` is enabled, so it proves that the embedded path is used rather than passing only because the Zed checkout contains the test assets. Testing performed: - `cargo fmt --all -- --check` - `cargo nextest run -p util --lib` - `cargo nextest run -p util --lib --features debug-embed` - `cargo check -p remote_server --features debug-embed` - `./script/clippy -p util` - Delta's previously failing `tools::edit_file::tests::test_edit_file_rejects_scratch_paths_as_read_only` against this PR's head commit Release Notes: - N/A
…4ms (#63586) Hang incidents come in two classes that consumers could only tell apart by comparing `stall_ms` against the hang threshold, which is not recorded in the event: a single event over the threshold, or an interval whose cumulative foreground spend reached the frame budget. This PR makes the class explicit and re-tunes the budget. - `HangIncident` and `SerializedHangIncident` gain `trigger: HangTrigger` (`threshold` | `budget`). - The `Hang Incidents` telemetry event reports `threshold_incidents` and `budget_incidents` alongside the existing `total_incidents` (kept for existing queries; it is now the sum of the two). - The release frame budget moves from 8 ms to 24 ms. At 8 ms almost every busy 60 Hz frame qualified, so the budget class dominated incident counts without saying much. 24 ms is above every refresh period, so a budget incident now means the interval dropped at least one frame on any display. Frame smoothness below that is measured per-frame by `Frame Duration Report`. `budget_incidents` is the signal for lowering it further as hangs get fixed. Debug builds already used 100 ms and are unchanged. Part of a series on hang-telemetry data quality; #63588 handles withheld-frame `dirty_at`, and marking OS prompt waits so they stop registering as task-poll hangs is next. Release Notes: - N/A
* 1st commit fixes bumps `quinn-proto` and `serde_with` to fix the dependabot alerts * 2nd commit deduplicates more dependencies `cargo tree -d` listing: 194 -> 187 top-level entries on the host target, 298 -> 287 unique duplicated crate-versions across all targets. <details> <summary>Deduplicated list</summary> ``` accesskit_consumer (v0.35.0, v0.37.0 -> v0.38.0) bindgen (v0.71.1, v0.72.1 -> v0.72.1) nix (v0.28.0, v0.29.0, v0.30.1 -> v0.28.0, v0.30.1) ordered-float (v2.10.1, v4.6.0 -> v5.5.0) quick-xml (v0.30.0, v0.37.5, v0.38.3, v0.39.3, v0.41.0 -> v0.30.0, v0.37.5, v0.39.3, v0.41.0) sysinfo (v0.31.4, v0.37.2 -> v0.31.4, v0.39.6) wasm-encoder (v0.252.0, v0.254.0 -> v0.254.0) wasmparser (v0.252.0, v0.254.0 -> v0.254.0) windows-registry (v0.4.0, v0.5.3, v0.6.1 -> v0.4.0, v0.6.1) ``` `ordered-float v4.6.0` remains in the lockfile only as an inactive optional dependency of `sea-query`; the compiled graph is fully deduplicated to v5.5.0. </details> Release Notes: - N/A
Previously, we manually synchronized the keyboard state in response to tap events, but this meant that several common cases were unreliable. Now, we use GPUI's focused element as the source of truth, and use `sync_virtual_keyboard` in cases where they have gotten out of sync (i.e. a user manually dismisses a keyboard while the input is still focused).
When scrolling, mispredicted touch events could cause scroll jitter. We now ignore predictions that are "travelling the wrong direction".
Adds `TouchDragEvent` and coresponding APIs. This allows web/touch-based code to capture long press events without having to go through scroll-like APIs
…g scroll (#62296) # Objective Follow-up to #62135, taking the approach suggested there: fix the error at its source in GPUI instead of hiding it in the scrollbar. At fractional rem sizes (`py_1` at an odd UI font size), a container whose content fits becomes scrollable by a sub-pixel amount, and every uniform-list picker grows a full-height scrollbar thumb for that phantom range. ## Solution Taffy lays boxes out with every authored length snapped to the device pixel grid (`to_taffy`), and the final bounds are snapped again after layout. However, `Interactivity::clamp_scroll_position` recomputed the padding from the raw style with no snapping at all, so the padded content size exceeded the snapped bounds by up to half a device pixel, far past the existing two-decimal float-noise rounding, and `scroll_max` came out positive. The fix snaps the recomputed padding with the same `pixel_snap` helper the rest of the pipeline uses, so both operands of the subtraction sit on the same grid and the phantom range never comes into existence. Two neighbouring cases are deliberately left out to keep this scoped, both are follow-up candidates: percentage-based padding resolves inside Taffy without pre-snapping, so a discrepancy is still theoretically possible there; and `ListState::max_scroll_offset` (the older `list()` element) has no rounding protection at all. ## Testing - New regression test: a 50px container with `py(4.25)` padding and a child that fits exactly. It fails on main (`max_offset` comes out at 0.5px) and passes with the fix; verified in both directions. - Full gpui suite: 241 tests pass. - Reviewers can see the original symptom by opening any picker at a UI font size that makes `py_1` fractional in device pixels: a spurious full-height scrollbar thumb appears on main and is gone with this change. The math is logical-pixel only, so the behavior is platform-independent. ## 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 - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable (one pixel-snap per padding edge per clamp, negligible against existing per-frame layout work) cc @MrSubidubi Release Notes: - Fixed containers becoming scrollable by a sub-pixel amount, with a phantom full-height scrollbar thumb, at fractional UI font sizes. Co-authored-by: MrSubidubi <finn@zed.dev>
…ut (#63614) While working on zed-industries/zed#63343, I ran into a problem with the pending key binding indicator. Hovering pauses its countdown, but pressing the next key made `on_hover` report false even though the mouse had not moved. The countdown then resumed while the pointer was still over the indicator. `on_hover` currently follows GPUI's normal hover rules. GPUI clears hover after keyboard input so the item under a stationary mouse does not interfere with keyboard navigation, for example list popover navigation with keyboard. This PR adds `HoverListenerMode` and `hover_listener_mode`. Callers that need to track the pointer across key presses can opt in like this: ```rs div() .hover_listener_mode(HoverListenerMode::InputModalityIndependent) .on_hover(|is_hovered, window, cx| { // ... }) ``` `InputModalityAware` remains the default. Release Notes: - N/A
This PR makes Zed's one-second key binding delay visible. Say both ctrl-w and ctrl-w left have bindings. After you press ctrl-w, Zed waits to see whether left follows. The PR shows that wait in the status bar with a countdown. Hovering the indicator shows which bindings can still match. It also adds a setting to hide the indicator. It does not change how Zed resolves key bindings. <img height="100" alt="dyn-db84a840272e2f6250a3f527a59b1efd" src="https://github.com/user-attachments/assets/e42c6a6c-4677-499f-a1d3-835960ebb21a" /> <br/> <img height="100" alt="dyn-8012278d030b41bc8ebfae1540504eff" src="https://github.com/user-attachments/assets/250928d5-f913-40f0-9068-00ccb5cdf59f" /> <br/> <img height="100" alt="file-5e6ffa90944faa294e7870f471b4e65b" src="https://github.com/user-attachments/assets/c250e6eb-a269-4e2c-a5a0-0be9b5006f99" /> Release Notes: - Added a status bar countdown for pending multi-stroke key bindings. --------- Co-authored-by: Kirill Bulatov <kirill@zed.dev>
Adds `Hitbox::is_hovered_at` to improve touch selection on delta web
…606) # Objective Fixes #63569 `run_docker_command` Debug-formatted the whole `docker exec` command, so every `-e NAME=VALUE` pair forwarded into a dev container was written to `Zed.log` in plaintext: once at DEBUG, and again in the error message that `remote_client.rs` logs at ERROR on a failed reconnect. ## Solution Render the command with `redact_arguments`, which replaces the value of every `-e NAME=VALUE` argument with `<redacted>` before the arguments are flattened, and pass the remaining arguments and stderr through `util::redact::redact_command`. Validate `containerEnv` and `remoteEnv` keys in `spawn_dev_container` before any container is reused or built, because an empty key produced `-e =VALUE`, which the Docker CLI rejects while echoing the value verbatim to stderr. Skip invalid names in `remote` as well, since `remote_env` is also rehydrated from the workspace database. The shared predicate lives in `util::redact::is_valid_environment_name`. The DEBUG line now logs the redacted command and exit status only; the previous stdout and stderr byte dumps are gone. ## Testing `cargo test -p remote -p dev_container --lib`. Unit tests cover redaction of forwarded env, argument boundaries, assignments inside program arguments and stderr, invalid-name skipping and rejection, and the podman CLI. Release Notes: - Fixed dev container environment variables being logged in full --------- Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
# Objective - Removes Agent Panel menu item when AI disabled toggle is on. - Fixes #63497 ## Solution - Use the global DisableAiSettings - disable_ai check in `app_menus.rs`. To keep the order the same I 1. Check the disable AI setting 2. If true push to the `view_items` vec![] 3. Extend the vec![] with the remaining Menu Items and Separators. ## Testing This can be tested visually: 1. Open Zed with AI settings enabled 2. Click View when Zed is focused 3. Noting where Agent Panel is on the list and to make sure clicking it opens up the Agent Panel. 4. Open settings 5. Navigate to AI settings 6. Toggle disable AI on 7. Click View Expected: Agent Panel is gone from the menu. The opposite is also expected. - This was tested on macOS 26.6.2 (25G83). ## 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) - [] Tests cover the new/changed behavior To keep this PR simple, I did not add any testing to this, as there were no tests in this file already. - [x] Performance impact has been considered and is acceptable ## Showcase <details> <summary>Click to view showcase</summary> https://github.com/user-attachments/assets/50db44ac-6c11-4101-a064-fd4e3b285620 </details>
…n (#63759) # Objective Fixes #52884 On macOS, with **"Double-click a window's title bar"** set to **Fill** and **"Tiled windows have margins"** enabled (System Settings > Desktop & Dock), double-clicking Zed's title bar fills the whole visible frame with no margins, while native apps leave the margin in place. The `"Fill"` arm of `titlebar_double_click` currently falls back to `zoom:`, with a comment stating that there is no documented API for the Fill action. `zoom:` is the classic maximize: it targets the screen's visible frame and never goes through the system tiling path, so the margin preference cannot apply. ## Solution AppKit does implement the action: `_zoomFill:` is the selector behind **Window > Move & Resize > Fill**, and it goes through the system tiling path. Prefer it for the `"Fill"` case, keeping `zoom:` as a fallback when the window does not respond to it. This means the margin geometry stays owned by the OS: neither `EnableTiledWindowMargins` nor `TiledWindowSpacing` has to be read or reimplemented in gpui, and the behavior follows the setting when the user toggles it. The selector is underscore-prefixed, hence the `respondsToSelector:` guard and the `zoom:` fallback. ## Testing Measured on macOS 26.6.2 (25G76), aarch64, on a 2560x1440 display with the Dock on the left, so `visibleFrame` is `(80, 0, 2480, 1410)`. Probe: a plain `NSWindow` (`titled`, `resizable`) in a standalone AppKit binary, with `EnableTiledWindowMargins = 1` and `TiledWindowSpacing` unset (default 8). | action | resulting frame | insets vs `visibleFrame` | | --- | --- | --- | | `zoom:` | `(80, 0, 2480, 1410)` | 0 on all four sides | | `_zoomFill:` | `(88, 8, 2464, 1394)` | 8 pt on all four sides | `respondsToSelector: _zoomFill:` returns `YES` on that build. `cargo check -p gpui_macos` and `cargo fmt -p gpui_macos -- --check` both pass. To reproduce as a reviewer: enable both settings above, then double-click the title bar. Before this change the window touches the screen edges, after it the margin matches Finder or Safari. With "Tiled windows have margins" off, both behave the same. One behavior difference worth flagging: `zoom:` toggles, so a second double-click used to restore the previous frame, while `_zoomFill:` stays filled. AppKit exposes `_zoomUntile:` for the reverse direction, which restores the pre-fill frame in my testing. I left it out to keep the diff minimal, but I am happy to add the toggle if you would prefer that a second double-click untiles. I could not find a way to cover this with an automated test, since the assertion would be about AppKit's own tiling geometry. ## 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
Member
|
Hey, thanks for the PR. Could you split this into separate PRs, one for each change? Mixing an upstream sync with unrelated changes makes this difficult to review properly. Feel free to close this PR and submit the changes individually. |
vrdons
force-pushed
the
sync-upstream
branch
from
September 7, 2026 13:47
d29b2a4 to
72534ba
Compare
Author
i will use this pr for sync upstream & update dependencies |
git: 22 packages incompatible: 93 packages latest: 201 packages local: 23 packages pinned: 4 packages
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.