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.
Bundle Gwen Dark (Hallowed Night) and Gwen Light in assets/themes/gwen,
derived from the champion's canon palette: hallowed mist cyan for
accents/functions, Gwen blue for types, violet for keywords, Camavor
gold for constants, pink-stitching rose for properties, mist mint for
strings over a Black Mist night base.
Set Gwen as the default theme pair in settings and the shipped settings
templates, surface it as the first tile in the onboarding theme picker
and the theme preview gallery, and guard the family with a bundled
theme regression test.
## Objective
Group the threads sidebar settings together in JSON and the Settings
Editor, using consistent “Threads Sidebar” terminology.
This follows up on #63452 now that #62883 has added configurable default
width, and includes the auto-open setting added since then.
## Solution
- Group `position`, `default_width`, and `auto_open` under
`agent.threads_sidebar`, and display their controls together in
Settings.
- Automatically migrate `agent.sidebar_side`,
`agent.threads_sidebar_default_width`, and
`agent.threads_sidebar_auto_open` across supported settings scopes,
preserving existing nested values.
- Apply changes to the default width immediately, including when the
sidebar was manually resized, and clear the saved width override.
Unrelated settings changes preserve manual sizing.
- Document all three settings, including the previously missing position
entry.
## Testing
The following targeted checks passed on the local changes:
- `cargo test -p migrator nest_agent_threads_sidebar_settings` — 7 tests
passed.
- `cargo test -p sidebar -p workspace -p agent_settings -p gpui_platform
--features gpui_platform/runtime_shaders --lib -- width
threads_sidebar_settings test_open_directory_in_existing_window` — 9
tests passed.
- `cargo fmt --all` completed successfully.
- `git diff --check` passed.
- From `docs`: `npx prettier --check src/reference/all-settings.md
src/ai/parallel-agents.md` passed.
Coverage includes migration precedence and supported scopes, settings
defaults and width limits, manual sizing and resets, persisted widths,
and auto-open behavior.
Full application tests and manual UI testing were not run. Clippy was
not rerun after the final terminology changes.
## 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
Release Notes:
- Improved threads sidebar settings by grouping position, default width,
and auto-open together, and applying default-width changes even after
manual resizing.
Fixes the git panel's active repository being silently overridden by the
cursor position in `ProjectDiff`.
Closes#58792Closes#61530
## Summary
When a multi-buffer item (e.g. `ProjectDiff`) gains focus, the workspace
calls `set_active_repo_for_path` with the cursor's project path to
automatically switch the active git repository. This was safe when
multi-buffer items returned `None` from `active_project_path`, but PR
#57236 changed `ProjectDiff` to return the cursor-based path (for
project panel highlighting), inadvertently allowing the cursor position
to override the user's explicit repository selection.
Fix the issue by restoring the `Singleton` guard that was removed in PR
#57236: only call `set_active_repo_for_path` when the active item is
backed by a single buffer.
## Changes
- **`workspace.rs`**: Only call `set_active_repo_for_path` when the
active item's `buffer_kind` is `Singleton`. Multi-buffer items (e.g.
`ProjectDiff`, diagnostics, search results) span multiple repositories,
so their cursor position should not trigger an automatic repository
switch.
## Before
https://github.com/user-attachments/assets/6ca4fa61-b42a-447b-9de7-8b6ec1f1181a
## After
https://github.com/user-attachments/assets/9b045ad9-2bb5-4862-ac45-41e9fdd3dc96Closes#58792
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:
- Fixed the Git panel unexpectedly switching repositories when viewing
changes in multi-repository projects.
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
Co-authored-by: dino <dinojoaocosta@gmail.com>
Closes https://github.com/zed-industries/zed/discussions/64266
Opening a folder in an existing window force-opens the Threads Sidebar,
and there is no way to prevent it. `open_paths` called
`MultiWorkspace::open_sidebar` unconditionally on the reused window, so
the sidebar reopened on every such open regardless of whether the user
had closed it.
This adds `agent.threads_sidebar_auto_open`, defaulting to `true` so
current behavior is unchanged. With `false`, the folder still opens in
the existing window, but the sidebar stays closed.
This path is reached when `default_open_behavior` or
`cli_default_open_behavior` is set to `existing_window`.
`open_sidebar` was doing double duty: besides showing the sidebar, it
pinned the workspace being navigated away from so it survives the
switch. When the setting is disabled, `retain_active_workspace` is
called instead, so only sidebar visibility changes.
https://github.com/user-attachments/assets/fc299df0-27e2-4ac6-98cb-d817d5f71d0e
## Tests
Two tests in `multi_workspace_tests.rs` cover both branches: the sidebar
opens by default, and stays closed when the setting is disabled while
the folder still opens in the same window.
Release Notes:
- Added `agent.threads_sidebar_auto_open` to control whether opening a
folder in an existing window also opens the Threads Sidebar
Addresses #9640 (the Spaces part).
On macOS, Zed already restores each window's size, position, and
display, but not its Space (virtual desktop). So after a restart, all
windows open on whatever Space is active at launch, not the Space they
were on before. This is the most reported problem in #9640.
A window's Space is not part of the window bounds we save. It is handled
by AppKit's own window state restoration. So instead of tracking the
Space myself, this PR uses that AppKit feature:
- I mark `GPUIWindow` as restorable and encode its native state (frame +
Space) by calling `encodeRestorableStateWithCoder:` with an
`NSKeyedArchiver`. A delegate skips the `NSView`/`NSWindow` objects that
do not support `NSSecureCoding`.
- I save the blob per workspace in a new `restorable_window_states`
table.
- When a saved workspace is opened again, I create the window and then
replay the blob with `restoreStateWithCoder:`. AppKit then moves the
window back to its Space.
On other platforms, and when there is no saved blob, this does nothing.
Verification:
- Added a round-trip test for the database part (save / overwrite /
read, and `ON DELETE CASCADE`).
- The macOS encode/restore part calls into AppKit, so I could not
unit-test it. I checked it by hand: I put several windows on different
Spaces, quit with Cmd+Q, started Zed again, and each window came back on
the Space it was closed on. I also checked that the saved blob is a real
AppKit archive (it starts with `bplist00`).
For now this only works for local workspaces. Remote workspaces could
use the same way later.
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:
- macOS: Restored windows now reopen on the Space (virtual desktop) they
were on, instead of all landing on the currently active Space.
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
This is a pure refactoring PR to make our FS watching code more
testable. It does two things:
1. Make the `GlobalWatcher` be owned by `RealFs` or `FakeFs` instead of
being a process-wide global.
2. Delete `FakeWatcher` and its `Watcher` implementation, and instead
mock the notify crate itself in `FakeFs` tests via the existing
`WatchBackend` trait. Now all our FS watching code down to the notify
boundary runs the same in tests and production.
Release Notes:
- N/A
## Summary
- Add `window_title_format` and `window_title_separator` settings for
customizing the window title
- Expose `${projectName}`, `${fileName}`, `${filePath}`,
`${relativePath}`, `${fileStem}`, `${remoteName}`, `${remoteHost}`,
`${appName}`, and `${separator}` as the native Zed window-title
variables
- Keep the collab `↗/↙` indicator hard-appended
- Translate VS Code `window.title` / `window.titleSeparator` aliases
into Zed's canonical variables during settings import, including
`${appName}` passthrough support and mapping VS Code's
`${activeEditorMedium}` onto Zed's `${relativePath}`
- Gate path-, remote-, and release-channel-derived lookups on whether
the active template references the corresponding variable, so the
default template avoids the extra work and still uses the existing
`last_window_title` cache to skip redundant platform updates
An alternative approach is at #49638. I went with `${variable}` names
over `$ZED_*`, canonical Zed variable names with VS Code aliases handled
at import time, kept `${separator}` as the only structural token, and
left `${dirty}` out of scope.
## Implementation reasoning and notes
### Variables considered but not included
- **collab/shared indicator variable**: kept hard-appended instead.
Folding it into the template would need whitespace/separator logic the
other variables don't need, and I'd rather not bake those semantics in
without a concrete need for it.
- **dirty variable**: The glyph choice and interaction with OS-level
edited indicators (like macOS's titlebar dot via `set_window_edited`)
felt like a separate design call I wasn't confident making here.
A separator-style config for each of collab/shared/dirty would solve the
above, but I didn't want to add too many additional settings initially.
### Performance
`update_window_title` is on a hot path, so two short-circuits apply:
- Path-, remote-, and release-channel-derived lookups (`absolute_path`,
relative-path string, `file_stem`, `remote_connection_options`,
`ReleaseChannel::try_global`) are gated on `template.contains(...)` via
`WindowTitleNeeds::from_template`, so the default template avoids the
extra work.
- The existing `last_window_title` cache still skips the platform call
when the rendered title is unchanged.
## Screenshots
Settings Editor entries for `window_title_format` and
`window_title_separator`:
<img width="774" height="324" alt="Settings Editor screenshot"
src="https://github.com/user-attachments/assets/b3378ec7-5649-4de3-9de6-164a42bce3fd"
/>
Customized Zed window titles in AltTab app switcher (remote, local,
empty):
<img width="774" height="324" alt="AltTab app switcher screenshot"
src="https://github.com/user-attachments/assets/a189945e-fc68-41b9-aab9-6dc04d5ef4ab"
/>
## 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#14534
Release Notes:
- Added configurable window title formatting with `window_title_format`
/ `window_title_separator`, including `${appName}` / `${remoteName}` /
`${remoteHost}` variables and VS Code `window.title` import support
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
## Objective
Markdown preview appearance settings are split between root theme
settings and
`markdown_preview`, and Markdown files always open as source editors
even when a user primarily
wants the rendered preview.
## Solution
- Group the Markdown preview font settings under `markdown_preview`,
migrate their legacy keys
across supported settings scopes, and update defaults, Settings UI, and
documentation.
- Add `markdown_preview.open_markdown_files_in_preview`, defaulting to
false. When enabled, clean
Markdown opens are replaced by a rendered preview while preserving dirty
editors, temporary-tab
behavior, pane activation and focus, targeted navigation, workspace
restoration, and the escape
back to source.
## Testing
- Manually verified on macOS that enabling the setting opens Markdown
files as preview-only.
- `cargo test -p markdown_preview` (three consecutive runs)
- `cargo test -p migrator nest_markdown_preview`
- `cargo test -p settings_content`
- `cargo check -p markdown -p markdown_preview -p migrator -p settings
-p settings_content -p settings_ui -p theme_settings -p workspace`
- `./script/clippy -p gpui_apple -p markdown -p markdown_preview -p
migrator -p settings -p settings_content -p settings_ui -p
theme_settings -p workspace --features gpui_apple/runtime_shaders`
- `cargo fmt --all -- --check`
- `git diff --check`
## 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
## Recordings
https://github.com/user-attachments/assets/032ab36d-f934-4ef7-aa18-53f3955a7df8https://github.com/user-attachments/assets/dc872265-2fe0-45ac-95eb-ff820d3a8164
Release Notes:
- Added a setting to open Markdown files directly in preview mode and
grouped Markdown preview settings together.
# Objective
The `git::FileHistory` action ("View File History") silently does
nothing when a diff view is the active item (single-file or multibuffer
project diff).
## Solution
Diff views wrap their inner `Editor` and expose it via `act_as`, but
`resolve_file_history_target` used a strict `active_item_as::<Editor>`
downcast, which returns `None` for these wrappers. Resolve through
`act_as` instead.
## Testing
Added a regression test which opens a `ProjectDiff`, dispatches
`git::FileHistory`, and asserts the file's history graph opens. I've
verified it fails without the `act_as` fix, and confirmed the fix
manually (see Showcase).
## 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 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
Left is before, right is after:
https://github.com/user-attachments/assets/39972bdf-b24f-4583-afd7-d6eb5226f50f
---
Release Notes:
- Fixed viewing a file's Git history when in a diff view.
Allows anchoring background images via `background.position`:
`center` (default), `top_left`, `top_right`, `bottom_left`,
`bottom_right`, matching CSS `background-position` semantics.
Also adds `none` to `background.fit` to keep the original image size,
making watermark-style bottom-right or corner positioning possible
without stretching or cover cropping.
Replaces the whole-UI opacity hack with a theme-level surface tint:
- background.opacity now scales the alpha of editor/terminal/panel
surface colors only, so the image shows through the code area while
text, borders, tabs and chrome stay fully opaque and readable
- the image element renders at full opacity behind the workspace
- theme reloads automatically when background settings change
- Move the background image load and decode off the foreground thread
(they were being polled there and tripped hang detection)
- Add background.ui_opacity: scales the opacity of everything drawn on
top of the image so it shows through panels
# Objective
- This PR fixes the captured focus in modals.
- Fixes#63480 (and actually this was not specific to the task modal. it
was generic and applied to all modals)
## Solution
- Previously when a modal was opened the `previous_focus_handle` was
stealing the focus because it was captured in `show_modal`. The fix was
to capture it before calling `show_modal` or `reveal_stashed_modal` and
pass it to `show_modal`. That fixes the bug :) (yuhuu).
## Testing
- Tested by running the build and trying to reproduce the bug. I
couldn't reproduce it anymore.
- For testing, a reviewer also needs to test the revelal stashed modal
functionality. I did it with the file finder.
## 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
---
Release Notes:
- Fixed previous window focus handle not being captured correctly when
opening modals
Adds a workspace background image that renders behind all UI, configured
via a new `background` settings section (path, fit, opacity).
The image is loaded asynchronously with a 2-second timeout and is never
read on the render path, so an unreachable source (e.g. a dead network
mount) cannot block or freeze the workspace. The first successful read is
cached under the data directory (written once, never rewritten), and when
the source is unavailable the cached image is served from that cache, so
the background keeps working offline.
# Objective
Fixes#12572
## Solution
- Adds an opt-in `reveal_if_open` setting which enables searching and
revealing an already open buffer
- Ensures this only happens if there is no pane target for the open
intent
## Testing
- Built for and tested on my Mac
- Tests added covering the scope of the feature
## 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
https://github.com/user-attachments/assets/cdcc78cd-85fd-4b56-b562-feba375ecd03
---
Release Notes:
- Added configuration to reveal buffers already open in a different pane
instead of the active pane, via `reveal_if_open`
---------
Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
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
# Objective
- Add file-level hyperlink support for opening and copying hyperlinks
for Git remote source control to project panel and tabs
- Unify the language for Git remote hyperlinks across blame, project
panels, and tabs to be similar to GitLens' definitions (which are
commonly used in VS Code)
## Solution
- Updated the Git crate to expose relevant metadata to surface new
options within the editor
- Added new options for `Open File on Remote` and `Copy Remote File URL`
to project panel/file explorer and file tabs
- Altered the blame UI options to be consistent with new labels / more
clear
## Testing
- Ran `cargo run` to boot app and manually smoke test (see proof below)
- Added unit tests for this change
## 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
https://github.com/user-attachments/assets/d600ca4f-47e7-438c-90e1-f40124a606b4
---
Release Notes:
- Added options to open or copy whole-file permalinks from file tabs and
the Project Panel.
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Follow-up to https://github.com/zed-industries/zed/pull/60477Closes#25022
We have more places that need a similar synchronization before quitting
the app: restarts on update, reloading the workspace.
On top of it, two more findings:
* `on_app_will_quit` was redundant: the global `on_app_quit` hook
flushes a strict superset of the same tasks and runs before windows are
cleared, while the entity hook held only a weak handle and could never
flush the `Window`-dependent workspace state anyway.
* previously, shutdown was run as `cx.spawn`, yet main threads got
parked on app shutdown: now using `cx.background_spawn` instead
Release Notes:
- Improved data persistence during various app shutdown cases
---------
Co-authored-by: Kostia R <k-bx@k-bx.com>
Closes https://github.com/zed-industries/zed/issues/48468
## Solution
This change addresses a macOS shutdown ordering issue where closing the
last window with the native close button could clear session state
before persistence tasks complete, causing next launch to open no
project/untitled.
-
[crates/workspace/src/workspace.rs](/Users/caleul/Documents/Work/Projects/zed/crates/workspace/src/workspace.rs)
- Make `save_last_workspace` dynamic on macOS based on whether closing
the last window will quit the app (`on_last_window_closed == quit_app`).
- Keeps `save_last_workspace` true only when the window close path is
equivalent to quit, so last-session data remains valid only in the
intended scenario.
-
[crates/workspace/src/multi_workspace.rs](/Users/caleul/Documents/Work/Projects/zed/crates/workspace/src/multi_workspace.rs)
- In `close_window`, before removing the window, explicitly flush:
- workspace serialization tasks
- pending workspace removal tasks
- multi-workspace serialization task
- This prevents losing in-memory state on fast close/quit paths.
-
[crates/session/src/session.rs](/Users/caleul/Documents/Work/Projects/zed/crates/session/src/session.rs)
- Guard `app_will_quit` to only persist window stack when non-empty,
preventing empty-stack state from being written during close path that
destroys the window stack first.
## Testing
- Did you test these changes?
- Manual repro/fix confirmed in local testing flow by the previous
author.
- Please confirm after merge with:
1) open 2–3 projects in workspace sidebar
2) set `on_last_window_closed: "quit_app"` and `restore_on_startup:
"last_session"`
3) close with red X
4) relaunch app and verify sessions restore all active workspaces
- Are there any parts that need more testing?
- Multi-window mixed close scenarios and one-window with dirty
non-serializable items.
- Regression for non-quit close mode (`on_last_window_closed: "close")
to ensure behavior remains unchanged.
- How can others test this?
- Follow the 4-step repro path above on macOS.
- Check logs for `timed out waiting on app_will_quit` in
`~/Library/Logs/Zed/Zed.log` and confirm no restore regression.
- Platforms tested:
- Verified for macOS (target path of bug).
- Not validated on Linux/Windows in this patch path.
## 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 (no UI/UX diff here)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes
- Closing last macOS window via the red close button now correctly
preserves and restores last-session workspace state when configured to
quit on last-window close.
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
Closes https://github.com/zed-industries/zed/issues/62435
Part of https://github.com/zed-industries/zed/issues/60548
Before:
https://github.com/user-attachments/assets/6b5147da-44cb-40c7-9da5-c50145e2ab4e
After:
https://github.com/user-attachments/assets/c58423cc-ea99-40d9-ad18-23b31dfb8e5d
Previously, `TerminalPanel::load` awaited full deserialization of
serialized
terminals (each awaiting directory environment capture via a login
shell)
before the panel was registered in the dock.
Until then, `terminal_panel::Toggle{Focus}` was a silent no-op: the
workspace finds no
panel in any dock, the keystroke is eaten, and nothing happens.
When it got eventually restored, it would close whatever panel in the
dock was open manually instead, wrecking the workflow.
Repro:
1. Add `case "$ZSH_EXECUTION_STRING" in *--printenv*) sleep 10;; esac`
to `~/.zshrc`.
2. Open a project, open at least one terminal in the panel, quit Zed
(Cmd+Q).
3. Relaunch via Dock/Spotlight (not the `zed` CLI, which skips env
capture via
`cli_environment`).
4. Press the terminal shortcut within 10s: nothing happens; after ~10s
the
panel appears and the shortcut works.
* `Register terminal panel before restoring serialized terminals` — the
panel
is now created and registered immediately, and restoration runs in
panel-owned tasks (cancelled on panel drop, nothing detached).
Terminal-adding paths were initially queued behind restoration (later
replaced by grafting, see below); the default shell spawns only if the
panel ends up active and empty after restore.
* `Stop replaying serialized dock state over manual panel changes` —
fixes a
related race: `Dock::add_panel` replayed the serialized dock state
(active
panel, visibility, zoom) on every panel insertion, so a late-loading
panel
would re-activate the serialized panel over one the user had switched to
in
the meantime (e.g. the terminal panel yanking the dock away from the
agent
panel), or re-open a dock the user had closed. Serialized state is now
applied at most once and is discarded as soon as the user changes the
dock
state manually. The new tests fail without this change and pass with it.
* `Show restoration progress in the terminal panel and allow spawning
terminals during it` — while terminals restore, the panel shows a
spinner
with "Restoring terminals…" instead of a blank pane, and logs the
restored
count and elapsed time. Supersedes the queuing from the first commit:
new
terminals spawn immediately, and any that land mid-restore are grafted
into
the restored layout instead of being lost. Serialization is paused
during
restoration, so quitting mid-restore can no longer persist a partial tab
list and silently drop terminals.
Release Notes:
- Fixed the terminal panel not opening at all under certain
circumstances, made panels no longer switching back to the serialized
one when opened during startup.
# Objective
Read-only marked files in zed could still be affected by format on save
feature. This PR fixes that.
FIXES#62899
## Solution
These changes add an early return on Editor's `Item::save`
implementation so neither formatting nor the write to disk occurs.
## Testing
I've tested by reproducing the issue in the original ticket.
## 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
---
Release Notes:
- Fixed read-only files being formatted and saved when `format_on_save`
is enabled
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
Saves the recent navigation history (up to 20 entries) to the workspace
DB so it survives restarts. When reopening a workspace, persisted paths
that resolve to the current project are merged into the file finder's
history, deduplicated against files already opened in the session.
https://github.com/user-attachments/assets/3d8934e1-0da6-4445-8f3d-acc5597d7ac8
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: https://github.com/zed-industries/zed/issues/56271
Release Notes:
- Improved file finder history to include recently opened files from
previous sessions.
# Objective
- Add an `in_preview` context that is available when the current editor
is in preview mode (opened from project panel or go to definition).
- closes https://github.com/zed-industries/zed/discussions/61765
## Solution
- In `editor.rs`, added a check in `key_context()` that detects if the
editor is the active preview item in its pane, and if so, adds
`"in_preview"` to the key context.
- Uses existing `workspace.pane_for_item_id()` and
`pane.is_active_preview_item()` methods — no new APIs introduced.
## Testing
- Added two tests in `editor_tests.rs`:
- `test_in_preview_context_added_when_in_preview_mode` — verifies
`in_preview` is present when editor is set as preview item.
- `test_in_preview_context_not_added_when_not_in_preview_mode` —
verifies `in_preview` is absent for regular (non-preview) tabs.
- Tested on Linux.
## 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
---
Release Notes:
- Added `in_preview` keybinding context for when an editor is in preview
mode.
# Objective
Fixes#62664
File names may contain control characters (`\n`, `\r`, `\t`, …) on most
platforms. Zed rendered them verbatim, so a file named `notes\ndraft.md`
broke the layout of its tab and of its project panel entry instead of
showing a readable name. The same held anywhere else a name reached the
screen without going through `Label::single_line`.
## Solution
The substitution lives in one shared place,
`ui::utils::replace_control_characters`, reached through
`Label::single_line`. `\n` keeps rendering as the `⏎` Zed already used,
so nothing that renders correctly today changes; every other C0 control
character maps onto the Unicode "Control Pictures" block by a single
rule (`U+2400 + code point`), giving `␉` for tab and `␍` for carriage
return. `DEL` maps to `␡`. C1 controls are left alone, having no
equivalent there.
Where that is wired in:
- **`Label::single_line`** — replaces its previous `\n`-only
substitution. The project panel already used it everywhere, including
folded directory components, so the panel is fixed by this alone.
- **Editor tabs** and the **default `Item::tab_content`**, neither of
which called `single_line`.
- **Terminal tab titles**, which render through their own `tab_content`.
Those titles come from OSC escape sequences, so the control characters
in them are attacker-controlled.
- **`HighlightedLabel::single_line`**, which never substituted anything
— not even `\n`. See below.
- **The file finder**, for both the file name and the path.
- **Nine `tab_content` overrides in git_ui**, by deleting them.
- **`HighlightedMatchWithPaths`**, for both the match label and its
paths — it backs the tab switcher and the outline panel, among others.
### `HighlightedLabel` needs its offsets moved, not just its text
Its highlight indices are byte offsets, and every stand-in is wider in
bytes than the character it replaces, so the offsets have to move with
the text. Left alone they index into the middle of a character, and
`highlight_ranges` slices the string at exactly those offsets — which
panics in release builds too. The constructor's `debug_panic!` does not
cover this, since `single_line` runs after construction.
So `replace_control_characters_remapping_offsets` substitutes and remaps
in one pass, over an old-to-new byte offset table built the way
`ensure_uniform_list_compatible_label` does it in `lsp_store`. This also
fixes the call sites that already asked for a single line, including the
branch picker and the tabular column filter values.
### Deleting the git_ui overrides
Nine files replicated the default `Item::tab_content` verbatim except
for the colour, hardcoding `selected ? Default : Muted` instead of
`params.text_color()`. Deleting them lets those tabs inherit the fixed
default, and fixes a second bug along the way: none of them dimmed when
the pane lost focus. Titles and icons are unaffected — they come from
`tab_content_text` and `tab_icon`, which the default calls.
`git_graph.rs` already did it this way.
### Tabular column headers
These never went through a `Label` at all: the raw `SharedString` was a
child of a `div`. They now display stand-ins, while right-click-copy
still yields the real column name.
Two notes for reviewers:
- Both helpers avoid allocating when there is nothing to replace, so the
common path is untouched. The previous `self.label.replace('\n', "⏎")`
allocated a `String` on every render for every label — including every
visible project panel entry, every frame.
- Every stand-in is exactly one character, so character offsets are
preserved and the existing `truncate_and_trailoff` math on tab titles
stays correct.
## Testing
- Unit tests cover both helpers: each control character's substitution,
repeated occurrences, multi-byte characters (accents, emoji), the
borrow-vs-own behaviour, the preserved character count, C1 passthrough,
and — for the remapping — offsets before, at and after a replacement,
offsets at and past the end, and the invariant that every remapped
offset lands on a character boundary.
- Unit tests cover `Label::single_line` and
`HighlightedLabel::single_line`, the entry points every call site uses.
`highlighted_label.rs` had no tests before.
- `cargo test -p ui -p file_finder -p workspace -p project_panel -p
git_ui -p git_ui_core -p terminal_view -p tabular_data_preview` passes
(774 tests), as do `cargo clippy` and `cargo fmt --check`.
- No existing test changes behaviour: tests assert on
`tab_content_text`, which is untouched; only rendering paths changed.
- Verified manually on macOS (aarch64) — see Showcase.
## 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
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
A directory holding `report<TAB>table.csv`, `notes<LF>draft.md`,
`carriage<CR>return.txt` and a normally named `normal.txt`, all four
open as tabs.
**Before**

**After**

Three things change:
1. **The `notes<LF>draft.md` tab** is the clearest one. Before, the
literal newline splits the tab across two lines — `notes` above
`draft.md` — distorting the whole tab bar. After, it stays on one line.
2. **`carriage<CR>return.txt` in the project panel** renders as
`carriagereturn.txt` before: the `\r` is completely invisible, so the
name reads as one word and there is no way to tell a character is there.
After, it renders as `carriage␍return.txt`.
3. **`report<TAB>table.csv`** shows a bare gap before, indistinguishable
from a space. After, it renders as `report␉table.csv`.
Note that `notes<LF>draft.md` looks the same in the project panel in
both shots: that entry already called `single_line`, which already
handled `\n`. That is precisely the asymmetry this PR removes.
### File finder
Before, the newline also breaks the list itself — the
`notes<LF>draft.md` row grows to two lines and overlaps the row beneath
it.
**Before**

**After**

Searching for `table` exercises the offset remapping, the match falling
after the control character:
**Before**

**After**

One thing this PR does **not** cover: the breadcrumb below the tab bar
still renders the raw tab character, as it goes through a different
path.
## Release Notes:
- Fixed file names containing control characters, such as tabs and
newlines, rendering unreadably in tabs, the project panel, the file
finder, the tab switcher and terminal tab titles.
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
# Objective
Follow-up of #61374.
Zed now supports Windows as a remote target, but when connecting from a
Unix platform to Windows, some path handling still uses the native
client's path style (Unix) to construct paths, which causes weird path
displays in different areas.
One of them is the project path stored in the `settings.json` file,
which is related to the open path picker in the codebase:
https://github.com/zed-industries/zed/blob/0500fd9ee99a4a98b36e339f3674e391697690fd/crates/open_path_prompt/src/open_path_prompt.rs#L668-L679
For example, if I have a remote project at `D:\code\test_python` and
want to open it in remote development, I usually use path completions,
with `D:\code\` as the parent path and `test_python` as the selected
candidate. Zed directly joins them using `Path::join` on the Unix
platform, which results in `D:\code\/test_python`.
A second thing I found is the displayed name for the git repo. The
related source code is:
https://github.com/zed-industries/zed/blob/0500fd9ee99a4a98b36e339f3674e391697690fd/crates/title_bar/src/title_bar.rs#L262-L268
Also taking `D:\code\test_python` as an example: the passed-in
`common_dir_abs_path` is `D:\code\test_python\.git`, and
`repo_identity_path()` directly uses `Path::file_name()` and
`Path::parent()` from the standard library to handle this:
https://github.com/zed-industries/zed/blob/0500fd9ee99a4a98b36e339f3674e391697690fd/crates/project/src/git_store.rs#L9956-L9965
Ideally, this function should return `D:\code\test_python`. But due to
the platform mismatch, `D:\code\test_python\.git` is returned; after
further processing in the title bar, we get `D:\code\test_python\` as
the displayed name, while the expected display name is `test_python`.
In the past, only Unix-like systems could serve as remote servers, and
their path separator (`/`) is valid on Windows, so everything looked
fine. But Unix does not support `\` as a valid separator — that's the
root cause. We need to use `PathStyle`, which is designed for processing
paths across platforms, to deal with these cases.
## Solution
- Added new APIs `PathStyle::parent()` and `PathStyle::file_name()`,
which serve as replacements for `Path::parent()` and `Path::file_name()`
to process paths cross-platform.
- Adopted the new APIs in `repo_identity_path()`, and updated the
relevant call sites.
- For the open path picker, use `PathStyle::join_path()` instead of
`Path::join`.
## Testing
The added `PathStyle::parent()` and `PathStyle::file_name()` are covered
by detailed unit tests. These tests verify that the behavior matches the
corresponding methods in `Path`, just independent of the host platform.
For the path display issues, I built and tested manually; a comparison
is attached in the Showcase section.
## 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
## Showcase
<details>
<summary>Click to view showcase</summary>
| Content | Before | After |
|:--:|:--:|:--:|
|title bar|<img width="486" height="272" alt="title_bar_before"
src="https://github.com/user-attachments/assets/d14d0e37-a1b8-43ab-b51b-fe9dd1b977eb"
/> | <img width="406" height="274" alt="title_bar_after"
src="https://github.com/user-attachments/assets/fc9193f4-d42c-47a8-a254-4ed08c806a11"
/> |
|path storage| <img width="337" height="264" alt="project_path_before"
src="https://github.com/user-attachments/assets/3352add3-20df-43b9-8a20-10ee7d96e703"
/>| <img width="319" height="262" alt="project_path_after"
src="https://github.com/user-attachments/assets/fa3d7feb-f393-416a-868d-85eb0af5cfb8"
/>|
|open remote| <img width="554" height="135" alt="open_remote_before"
src="https://github.com/user-attachments/assets/62983eca-22ad-472f-8333-8561cfc17357"
/>|<img width="562" height="176" alt="open_remote_after"
src="https://github.com/user-attachments/assets/22528a6b-0e73-4a12-a825-673ba57a63da"
/> |
</details>
## Other things to note
This PR also did a little refactoring: it moved the `PathStyle`-related
tests from the `util` crate to the `path` crate, and updated the
documentation to reflect that Windows can serve as a remote platform.
The recent project picker also suffers from the same cross-platform bug,
but it is not fixed here, because a clean fix requires dealing with
database storage, unlike the direct API changes made here. I will
address it in a follow-up PR.
This PR looks very large, but most of the changes are the test migration
and the new API implementation. I hope the unit tests and comments can
offload some of the burden for reviewers.
---
Release Notes:
- Fixed project paths being built incorrectly when connecting from Unix
machines to Windows remote servers.
@SomeoneToIgnore this is the follow up you asked for in #62692, done as
discussed.
`deserialize_to` keeps a `None` in `items` for every item that failed to
deserialize, and those are never added to the pane. Any later tab
therefore sits at a lower index in the pane than the one it was
serialized with, so activating and previewing by serialized index lands
on the tab that shifted into that slot. When the failing item is the
last one, the index points past the end of the pane and nothing is
activated or previewed.
The serialized index is now mapped to the pane's index by counting the
items before it that actually restored, and an index whose own item
failed to restore is skipped.
Closes#62843
Release Notes:
- Fixed the wrong tab being activated when restoring a workspace
containing items that fail to open
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
Pinned tabs are the leading tabs of a pane, and that is persisted as a
plain count. Both sides of workspace serialization could leave the count
out of step with the tabs it is meant to describe:
- When serializing, `serialize_pane_handle` drops items that cannot be
serialized (a pinned diagnostics or project search tab, for example)
from the pane's children, but still stored the pane's raw pinned count.
- When restoring, `SerializedPane::deserialize_to` keeps a `None` in
`items` for every item that failed to deserialize. Those are never added
to the pane, but `self.pinned_count.min(items.len())` counted them
anyway.
In both cases the count ends up pointing past the tabs that were
actually pinned, so the tabs that shift into those slots come back
pinned even though they never were. This also explains the `Pinned tab
count (N) exceeds actual tab count (M)` warning from #33342.
Now the serialized count shrinks with each dropped pinned item, and on
restore only the pinned items that were actually restored are counted.
Closes#62003
Release Notes:
- Fixed tabs being wrongly marked as pinned after reloading a workspace
or updating Zed
Closes#60013
# Objective
Right now Zed can go full screen but it does not allow you to fix the
hole screen,
by that I mean that Zed can go behind the notch so you don't have extra
useless room left.
## Solution
You can now use the `fullscreen_mode` = `simple` setting to use the new
simple full screen feature, that lives besides the normal full screen
feature. But allows you to have an option to go 100% full screen without
losing any useless space on your macbook screen.
**Note** this is mostly usefull when you have a macbook that has a notch
whitch is kinda in the way of your work flow.
## 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
**Before**
<img width="5712" height="4284" alt="IMG_0339"
src="https://github.com/user-attachments/assets/9f908ffd-7cef-4999-a454-c80f72c40dc8"
/>
**After** (Note now Zed is behind your notch when using the simple full
screen feature)
<img width="5712" height="4284" alt="IMG_0360"
src="https://github.com/user-attachments/assets/5917ed4d-2a64-4464-a794-bc46fd034521"
/>
---
Release Notes:
- Added support for simple fullscreen mode using the `fullscreen_mode`
setting, set it to `simple` to try it out.
Closes#57388.
When a dock is listed in `resize_all_panels_in_dock`, reset its
compatible panels to the active panel's default size. This applies to
the reset actions and resize-handle double-clicks. Docks not listed in
the setting continue to reset only the active panel.
Adds regression coverage for fixed panels with different defaults,
flexible panels, and active-panel-only resets.
Release Notes:
- Fixed dock size reset commands only resetting the active panel when
`resize_all_panels_in_dock` is enabled.
---------
Co-authored-by: dino <dinojoaocosta@gmail.com>
# Objective
- The sidebar already supports moving project groups through its **Move
Up** and **Move Down** context-menu entries, but those entries use
callbacks that cannot be referenced from `keymap.json`. Moving a project
several positions therefore requires reopening the menu for every step.
- Follow-up to #57448. Related to #61647.
## Solution
- Add `multi_workspace::MoveProjectUp` and
`multi_workspace::MoveProjectDown` actions. The handlers resolve the
active project group and delegate to the existing `MultiWorkspace`
reordering methods, keeping ordering and persistence behavior unchanged.
- Associate the actions with the existing context-menu entries so
configured shortcuts are shown alongside the menu commands. The menu
callbacks still operate on the project that was clicked.
## Testing
- Added a GPUI test that dispatches both actions and verifies that the
active project group moves in the expected direction and remains
unchanged at list boundaries:
- `cargo test -p workspace test_move_active_project_group_actions --
--nocapture`
- Manually verified on macOS with an isolated Zed user-data directory
and three project folders:
- Assigned custom shortcuts to both actions in `keymap.json`.
- Confirmed that the active project moves up and down in the sidebar.
- Ran formatting, compilation, and lint checks:
- `cargo fmt --all -- --check`
- `cargo check -p sidebar`
- `./script/clippy -p workspace -p sidebar -p gpui_platform --features
gpui_platform/runtime_shaders`
## 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
<details>
<summary>Move projects with custom keybindings</summary>
https://github.com/user-attachments/assets/09432817-318b-484e-b630-a6012e9599cd
</details>
---
Release Notes:
- Sidebar: Added key-bindable actions for moving projects up and down.
`ThreadView::regenerate` does `thread.rewind()` which de-focused the
message editor mid-flight causing the zoomed panel to disappear.
* workspace: Keep zoomed panels open when window focus is lost
Commit adds a test + tweaks a default, generic, fallback to be more
lenient: instead of focusing the workspace (and hiding all panels right
away), try to fall back to whatever panel open
* gpui: Restore focus to nearest surviving ancestor when focus is lost
Commit tries to push it down to a library level and add a way to fall
back to closest ancestor that's still visible with the focus instead.
Release Notes:
- Fixed the zoomed agent panel closing unexpectedly on rewind
Fixes https://github.com/zed-industries/zed/issues/35780
Collab schema migration PR:
https://github.com/zed-industries/cloud/pull/3422
The corresponding database schema migration has been created in the
Cloud repo and applied to the production database.
Before, Zed scanned each and every entry in the tree down from the
directory it was opened in, except gitignored files and scan exclusions.
The approach is unchanged, if Zed detects it was open inside a git
repository: e.g. the directory open in Zed contains `.git` directory.
For the rest of the projects, 2 optimizations are made:
* Limit the depth of file scan traversal.
Now, `file_scan_depth` (default `5`) restricts Zed from traversing any
directory that has same number or more segments in its file path.
Such directories behave similar to gitignored directories: their
contents is not available in file finder, project search and project
panel, but can be lazily traversed when the directory is expanded (e.g.
project panel expands it or a nested file is open by path via terminal,
etc.)
To indicate that to the users, a status entry is shown firs time the
limitation is hit in the project:
<img width="858" height="133" alt="image"
src="https://github.com/user-attachments/assets/7da6cfbb-98b4-4cc3-bf2a-8902a9597a15"
/>
* During the scan, any git repositories that are not direct children of
the directory open in Zed (depth >= 2), are traversed and indexed
normally, but their git metadata is never fetched eagerly.
Only when Zed opens a buffer from that repo the git metadata is fetched
and applied.
All that combined now uses a way more moderate amount of CPU and RAM
when opening `~`:
<img width="1717" height="368" alt="Screenshot 2026-08-13 at 17 43 53"
src="https://github.com/user-attachments/assets/ec83e2a9-f7cc-452b-8eb7-af158284ca4e"
/>
File scan inclusions and exclusions are considered still for such
projects.
Set `file_scan_depth` to `0` to enable old behavior.
The setting is supported in the project settings, so custom values can
be set based on the project's structure.
---
Release Notes:
- Fixed Zed using a lot of memory and CPU in large, non-git-tracked,
directory trees
While building Zed with nightly rustc I've noticed it doesn't compile
because of good old pathfinder_simd. It also emits a bunch of warnings
about use of f64 literals where f32 is expected, so I've fixed them - it
should make future upgrades more straightforward.
# Objective
Follow-up to #62028. When archiving removed a thread's workspace, the
replacement
was derived from whichever sidebar row sat adjacent to the archived one.
Rows are
a flat list with project headers as separators, so archiving the oldest
thread in
a project selected the next project's newest thread and moved the user
out of the
project they were working in — and when that neighbor was remote,
connected to
its host just to pick a fallback.
# Solution
- `MultiWorkspace::remove` now chooses the replacement itself from a
`RemovalIntent` (keep the project vs close it): a live workspace in the
same
project, the project's own roots when kept, the nearest retained
neighbor,
an adjacent local project, then an empty workspace. The workspaces being
removed are excluded from that search in one place instead of five.
- Sidebar neighbor selection stays within the entry's project section.
- The three archive paths now share one removal orchestration, and the
three
"open the closed workspace first" helpers collapse into one.
# Testing
New tests cover: the keep-project fallback, neighbor selection staying
inside the
project section, and archiving with a mock-remote neighboring project
never
connecting to it. Each was verified to fail against the previous
behavior.
## 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
---
Release Notes:
- Fixed archiving a thread switching the window to a different project.
- Fixed a possible crash when archiving a thread while its window was
closing.
# Objective
Fix the `fallback workspace must not be one of the workspaces being
removed` panic.
Fixes FR-148
Fixes ZED-AKR
Fixes ZED-97M
# Solution
The remote path of `find_or_create_workspace` opened a project, then
returned the
window's *active* workspace instead of the one it created. The open
awaits toolchain
loading and item restoration, and a save prompt from a concurrent
workspace removal
can re-activate a workspace being removed during that wait; the stale
return value
then trips the assert in `MultiWorkspace::remove`.
Return the created workspace from `open_remote_project_inner` and use it
at the
call sites instead of re-reading the active workspace after the await.
# Testing
Added
`test_find_or_create_workspace_returns_the_created_remote_workspace`:
opens a
mock remote project and re-activates the previous workspace mid-open
(standing in
for the save prompt), then asserts the open returns the workspace it
created.
Verified it fails against the pre-fix behavior.
## 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
---
Release Notes:
- Fixed a crash when a workspace was removed while a remote project was
opening in the same window.
# Objective
When working across multiple projects open in the same window, closing
the **currently selected** project requried a two-step flow: switch to
another project first then close the one that you initially wanted to.
The project's close button was hidden on the active project, so the only
way to remove the project was to navigate away first.
## Solution
Always render the close button in the project picker, including for the
active project. Closing the active project now removes it and switches
to a neighboring project automatically.
This worked well for local projects but broke for remote ones. For any
remote neighbor it actually fell through to an empty workspace.
There are 3 cases now:
1. Activate the neighbor's already open workspace when one exists (now
either if its local or remote)
2. Load the neighbor through the host-aware **find_or_create_workspace**
which connects and opens a remote neighbor when it isn't already open
3. Fallback to an empty workspace only when no neighbor remains
## Testing
- Did you test these changes? If so, how?
- Are there any parts that need more testing?
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
## 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
> This section is optional. If this PR does not include a visual change
or does not add a new user-facing feature, you can delete this section.
- Help others understand the result of this PR by showcasing your
awesome work!
- If this PR includes a visual change, consider adding a screenshot,
GIF, or video
- A before/after comparison is very useful for changes to existing
features!
While a showcase should aim to be brief and digestible, you can use a
toggleable section to save space on longer showcases:
<details>
<summary>Click to view showcase</summary>
https://github.com/user-attachments/assets/6e1d1968-702a-4f13-9442-5e90fe7ae9f9
</details>
---
Release Notes:
- Improved the project switcher to allow closing the currently selected
project, switching to a neighboring project (local or remote)
automatically.
---------
Co-authored-by: dino <dinojoaocosta@gmail.com>
Dropping a local Windows file (e.g. `E:\foo\bar.md`) onto a Zed window
connected to a WSL remote previously forwarded the path verbatim. On the
remote Linux side `E:\foo\bar.md` isn't absolute, so it got joined with
the worktree CWD, producing nonsense like `/home/user/E:\foo\bar.md` and
a "failed to canonicalize root path" error from the worktree scanner.
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#49915
before:
<img width="1343" height="331" alt="before"
src="https://github.com/user-attachments/assets/193cfbf6-d07e-4c5f-b941-75e4a0c62345"
/>
after:
<img width="1181" height="288" alt="after"
src="https://github.com/user-attachments/assets/7ad56e13-3723-4b48-aa3d-59eca6038a7f"
/>
Release Notes:
- Fixed dragging local Windows files onto a Zed window connected to a
WSL remote.
Closes#59235
When a panel's `default_size` changes (e.g. `git_panel.default_width` is
edited in settings), the persisted per-workspace size is now cleared so
the new default takes effect immediately. Previously the saved dragged
size took precedence forever, making `default_width` effectively useless
after the first manual resize.
This fix is at the Dock level (`crates/workspace/src/dock.rs`), so it
applies to all panels — Git Panel, Project Panel, Terminal Panel, etc.
Release Notes:
- Fixed panel `default_width` setting being ignored after manually
resizing the panel
https://github.com/user-attachments/assets/97ef69b2-387f-4e29-bc4c-0f336f24eb0b