# 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:
5e1fd392f6/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:
5e1fd392f6/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:
5e1fd392f6/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
### Objective
PR #36859 made native macOS and Windows controls respect `is_resizable`
and `is_minimizable`, but custom window decorations cannot access those
values from `Window`. Linux custom controls and client-side resize
interactions remain active, macOS custom titlebar double-click does not
check either option and custom Windows caption buttons still appear
enabled even though the backend blocks their actions.
### Solution
Expose `is_resizable` and `is_minimizable` on `Window`. Use them to
disable custom window controls and titlebar actions and omit client-side
resize cursors and hitboxes for non-resizable windows.
## 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)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
Closes#61671
A submodule's `.git` is a file pointing into the superproject's
`.git/modules/<name>`, which looks just like a linked worktree's `.git`
file. The identity-path resolution used for recent projects and project
grouping treated them the same, so submodules got registered under
`.git/modules/<name>` instead of their own folder.
The fix detects submodule git dirs (`is_submodule_git_dir`) and skips
resolution for them, so a submodule keeps its own working directory as
its identity. Linked worktrees and bare repos are unaffected.
### Current vs. Expected
Current: opening submodule `Foo/Bar` registers the path as
`Foo/.git/modules/Bar`.
Expected: it registers as `Foo/Bar`, like any other project.
### Video
https://github.com/user-attachments/assets/e2eee5e7-ef64-47ed-9780-6fcafda5ae30
### Tests
- `is_submodule_git_dir` unit test
- `resolve_git_worktree_to_main_repo` returns `None` for a submodule
- persistence test asserting the submodule identity stays at its own
folder
Release Notes:
- Fixed Git submodules being registered under the parent repository's
`.git/modules` directory instead of their own path
Closes#60733
# Objective
Markdown Preview treats a relative `path:line[:column]` destination as a
literal filename. When that file does not exist, the link falls through
to the system URL handler instead of opening the workspace file at the
requested position.
## Solution
- Recognize position suffixes on relative Markdown links.
- Convert GitHub-style `#L42` fragments into the same positioned target
used by `path:42`, so both forms share one resolution and opening path.
- Resolve links with `workspace::path_link::possible_open_target` using
the Markdown source directory. This keeps the remote-project path
resolution added in #61438.
- Open resolved targets with `editor::items::open_resolved_target`,
including its one-based row and column handling.
- Preserve valid URI schemes and fall back to the existing Markdown link
behavior when no workspace target resolves.
## Testing
- Extended the Markdown Preview GPUI regression test to cover relative
`path:line:column`, GitHub-style `#Lline`, subfolder-relative
resolution, and custom URI schemes.
- `git diff --check` passes.
- The focused Rust test could not start in the current macOS environment
because the Rust toolchain binaries hang in the dynamic loader before
Cargo runs. PR Actions are awaiting maintainer approval.
## Self-Review Checklist:
- [x] I have reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed UI and icon guidelines
- [x] Tests cover the new and changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Fixed Markdown Preview links using workspace-relative paths with line
and column suffixes.
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Closes FR-139
Most focus-lost issues that close the agent panel in Zen mode stem from
panels returning a transient child editor's focus handle from
`Focusable::focus_handle`. The Zen-mode check closes the zoomed panel
when the focused element is not a descendant of the panel's focus
handle, so any focus movement inside the panel that landed outside that
child editor looked like the panel losing focus.
This PR separates the two roles that handle was serving:
- `Focusable::focus_handle` now always returns a stable handle tracked
at the panel's root element, used for containment checks (Zen-mode
auto-close, `toggle_panel_focus`, dock focus subscriptions).
- The new `Panel::activation_focus_handle` returns what should receive
focus when the panel is activated (e.g. a filter/commit/message editor)
and must be a focus-tree descendant of the root handle. All "focus the
panel" callsites in workspace/dock now use it.
Migrated panels: `AgentPanel` (including thread views and the toolbar
title editor), `CollabPanel`, `GitPanel`, `OutlinePanel`, and
`TerminalPanel` (previously delegated to the active pane, so focus in a
non-active pane dropped containment). `CollabPanel` activation falls
back to the panel root when signed out or collaboration is disabled,
since the filter editor isn't rendered in those states. Also fixes
duplicate element ids for tool calls with multiple content blocks.
Tests: a regression test that clicks tool-call output and focuses the
thread title editor while zoomed (both previously closed Zen mode), and
a dock-level test asserting the activation handle receives focus on
panel activation while the panel root reports containment.
Release Notes:
- Fixed zoomed panels (e.g. the agent panel in Zen mode) closing
unexpectedly when focus moved to elements inside the panel, such as tool
call output or the thread title editor.
Save tasks can suspend while waiting for prompts, formatting, or
filesystem I/O. Holding only a WeakEntity<Pane> allowed the pane to be
released during those suspension points, surfacing an internal 'entity
released' error as a failed save.
Instead upgrade the pane once the save operation starts so we can ensure
it finishes.
---
Release Notes:
- N/A or Added/Fixed/Improved ...
### Summary
This PR fixes three small bugs that could cause a multi-workspace's
reported location to be out of sync with its actual location, which
causes following to break in multiplayer collaboration sessions.
The first bug was that each child workspace's title bar within a
multi-workspace had its own `cx.observe_window_activation` subscription
that would set the associated child workspace's project location. This
caused problems because it ran for all child workspaces instead of just
the active workspace within the multi-workspace. The fix was moving
`cx.observe_window_activation` to the `cx.observe_new` call in the
`call` crate that tracks newly created windows/multi-workspaces.
The second bug was caused by an incorrect `if` statement in a
`MultiWorkspace` subscription that would return early if the window was
active and the event emitted by `MultiWorkspace` wasn't
`ActiveWorkspaceChanged`. This caused issues when the window was
inactive because it would incorrectly set the active call's location to
the wrong project. The fix was making the early return happen if the
window wasn't active.
The third bug was that every child `Workspace` also observed window
activation and called `update_active_view_for_followers`. This allowed
hidden workspaces to report their active view instead of only the active
workspace.
### Testing
I added a property test for bugs one/two and another prop test for bug 3
Release Notes:
- collab: Fix out of sync following bugs
## Context
The editor tab's read-only controls used "File" terminology in their
tooltips and the tab context menu ("Make File Read-Only", "Locked File",
"Read-Only File", etc.). This was misleading in two ways: the option
also appears on unsaved and non-file tabs that have no file on disk, and
the toggle only controls whether the buffer is editable in the editor,
it does not change filesystem permissions. This renames the labels to
lock/unlock "Tab" language, matching the lock icon shown when the tab is
toggled.
Closes#60079.
Behavior after the change :
[Screencast from 2026-07-17
15-35-30.webm](https://github.com/user-attachments/assets/5fb018cb-515f-449c-a57e-0c0bead250bd)
## How to Review
1 file changed:
**crates/workspace/src/pane.rs**
Renames three sets of user-facing strings, all pure text changes with no
behavior change. The read-only toggle button tooltips become "Unlock
Tab" / "This will make this tab editable" and "Locked Tab" / "This tab
is read-only". The tab tooltip meta label becomes "Read-Only Tab". The
context menu entry, whose label already depends on
`capability.editable()`, becomes "Lock Tab for Editing" (when currently
editable) and "Unlock Tab for Editing" (when currently read-only); the
click handler still calls `toggle_read_only`, so the mapping from label
to action is preserved.
## Self-Review Checklist
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the UI/UX checklist
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Improved read-only tab controls to use "Tab" instead of "File" in
tooltips and the tab context menu, since the toggle affects editability
in the editor rather than filesystem permissions.
---------
Co-authored-by: Nathan Sobo <nathan@zed.dev>
GPUI allocates every element for a draw in a single per-App bump arena,
and `Arena::clear()` assumed no draw was in progress. But draws can
nest: on Windows, the window procedure re-enters whenever the main
thread pumps messages mid-draw (cross-thread `SendMessage` dispatch,
modal message loops entered by COM/OLE calls such as clipboard reads),
and on any platform a draw can be triggered from within another draw
(e.g. `open_window`). When a nested draw finished, its arena clear freed
and rewound memory the outer draw was still using. The `ArenaBox`
validity flag only guards new derefs, so `&mut` references already held
by the outer draw silently pointed into reused memory. That
use-after-free corrupted element-state keys
(`GlobalElementId`/`SharedString` Arcs) and heap metadata, crashing
later in innocent-looking frames — seen in the wild as
`EXCEPTION_ACCESS_VIOLATION_READ / 0xffffffffffffffff` in
`Frame::finish` and element allocation
([ZED-9QN](https://zed-dev.sentry.io/issues/7577818040/),
[ZED-7JC](https://sentry.io/organizations/zed-dev/issues/7465778926/),
[ZED-7C6](https://zed-dev.sentry.io/issues/7460258444/)), plus
occasional "attempted to dereference an ArenaRef after its Arena was
cleared" panics (ZED-96P, ZED-8XN), Windows-dominant and spanning
versions 1.1.7–1.8.2.
The fix makes the arena sound under nesting: `ElementArenaScope` tracks
a scope depth on the arena, and `Arena::clear()` is deferred while any
scope is active — the outermost draw's clear drops both draws'
allocations. Since arena chunks are stable heap blocks and allocation
only appends, nested allocation was already safe; the mid-draw clear was
the only destructive operation. Scopes are ended via a consuming
`exit(arena)` call that asserts arena identity (by pointer comparison,
never dereferencing), and `ArenaClearNeeded::clear(cx)` reaches the
arena through the App, so this bookkeeping contains no unsafe code
beyond what existed before. A panic that unwinds a draw balances the
scope depth in the guard's `Drop`, so later clears still run; only the
unwound draw's own clear token is never produced, leaving the arena
populated until the next draw's clear — a one-frame leak at worst, never
a use-after-free.
Additionally, draws are no longer run re-entrantly: GPUI's
`on_request_frame` callback skips requests that arrive while a draw is
already on the thread's stack (remembering `force_render` for the next
frame), and on Windows a `DrawCoordinator` owned by the platform and
shared with every window additionally guards the wider `draw_window`
span (presentation, IME updates). Deferred windows validate their update
region (so nested message pumps don't busy-loop on WM_PAINT) and are
repainted at most one vsync later by the vsync thread's existing
per-tick invalidation.
An integration test opens a window from within an element's paint;
without the deferred clear it reproduces the exact "ArenaRef after its
Arena was cleared" panic seen in the wild. Deferrals are logged so the
diagnosis can be confirmed from user logs.
Closes FR-110
Closes FR-114
Release Notes:
- Fixed a crash on Windows caused by re-entrant window drawing
corrupting UI element memory.
Closes#58270
In remote projects, Markdown previews resolved relative links from the
project root instead of the Markdown file's folder. Links worked for
files in the root but could fail or open the wrong file for files in
subfolders.
Zed now resolves these links from the Markdown file's folder. The fix
updates base path handling in `open_url_or_file`. Only Markdown Preview
passes a base path to this function.
I tested it on macOS with a Linux SSH host and on Windows with WSL.
Release Notes:
- Fixed relative links in Markdown previews for files in subfolders when
using SSH or WSL.
# Objective
Fixes#60612
`workspace::ReopenLastPicker` should open the stashed picker _after_ the
active model is dismissed
## Solution
Queue reopen requests when another modal is active, then reveal the
stashed modal after `hide_modal` clears the layer. Reset queued reveals
when explicitly opening a new modal.
## Testing
Confirmed `ReopenLastPicker` keybind working even when which_key is
enabled with delay=`0ms`. Tested with file_finder and text_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 `workspace::ReopenLastPicker` when `which_key` helper menu is
enabled
Co-authored-by: Yara 🏳️⚧️ <git@yara.blue>
# Objective
- Make runnable task results visible directly in the editor gutter after
running a test or task.
- This makes it easier to see whether the last run passed or failed
without looking at the terminal output.
## Solution
- Track the completion result for scheduled runnable tasks.
- Show the last runnable result in the gutter:
- running task: accent play icon
- successful task: success check icon
- failed/cancelled task: error icon
- Apply the same status update path when running from the gutter play
button and from inline code lens actions such as `Run Test`.
## Testing
- Ran `cargo check -p editor -p workspace`.
- Ran `cargo test -p workspace
test_schedule_resolved_task_with_completion_reports_success`.
- Manually tested running a GPUI test from the gutter play button.
- Manually tested running a GPUI test from the inline `Run Test` code
lens.
- Verified the gutter icon updates after completion in both cases.
## 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="1897" height="691" alt="before"
src="https://github.com/user-attachments/assets/614c2811-ee0a-43c0-8619-d0301836aa62"
/>
After:
<img width="1897" height="691" alt="after"
src="https://github.com/user-attachments/assets/a3db19f2-71e6-4c9b-824d-43a4f020a6b7"
/>
---
Release Notes:
- Improved runnable tasks by showing the last run result in the editor
gutter.
When `active_pane_modifiers.border_size` is set in `settings.json`, both
the active editor pane and the active terminal pane would display a
border simultaneously, making it impossible to tell which pane actually
has focus. The pane opacity dimming also renders simultaneously before
this fix.
1. Before fix: impossible to tell which pane has focus
<img width="901" height="732" alt="image"
src="https://github.com/user-attachments/assets/cbcad798-0d72-420c-9585-2dafa867ff2b"
/>
2. After fix: only one pane has focus
<img width="902" height="731" alt="image"
src="https://github.com/user-attachments/assets/97f2238e-4789-41b3-97e3-98cb9a0c82ef"
/>
The root cause is that both the workspace center and the terminal panel
pass their own `active_pane` to `PaneRenderContext`, so each pane group
unconditionally marks its active pane for border rendering. The fix adds
a focus check so `active_pane_ix` is only set when the pane actually has
keyboard focus, ensuring only the truly focused pane gets the border
(and the inactive_opacity dimming applies correctly to unfocused
groups).
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 active pane border being drawn on both the editor pane and
terminal pane simultaneously
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
When a file has unsaved edits and has also changed on disk, the conflict
prompt offered "Overwrite / Discard / Cancel". Both "Overwrite" and
"Discard" were directionally ambiguous, it wasn't clear whether the disk
contents or the buffer edits would be lost. "Discard Edits" makes it
explicit that the buffer edits are thrown away and the disk version is
reloaded.
Release Notes:
- Improved the file conflict prompt by renaming the "Discard" button to
"Discard Edits" to clarify that unsaved edits are discarded in favor of
the on-disk contents.
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Closes#54951
## Problem
The quick action bar's preview button (markdown, SVG, and CSV behind the
feature flag) resolved everything through `workspace.active_item()` —
the globally *focused* item — instead of the item of the pane the button
sits in. With `A.md` in the left pane and focus in `B.md` in the right
pane:
- Clicking the eye button in **A.md's** toolbar opened a preview of
**B.md**, in the right pane.
- Focusing a non-previewable file (e.g. `B.sh`) in one pane hid the
button in **every** pane's toolbar, making `A.md` unpreviewable by
mouse.
Clicking the button dispatched the `OpenPreview` action, whose
workspace-level handler re-resolved the focused editor — so a click on a
specific pane's toolbar was functionally identical to pressing the
keybinding, discarding the pane the click happened in.
## Fix
Make the flow pane-explicit end to end:
- **Visibility:** each pane's `QuickActionBar` resolves the preview type
from its own `active_item` (set via `set_active_pane_item`) instead of
the workspace's focused item.
- **Click:** no more action dispatch. The handler resolves its pane via
`Workspace::pane_for` and calls new pane-explicit helpers —
`open_preview_in_pane` / `open_preview_to_the_side_of_pane` — extracted
from the action-handler bodies in all three preview crates. Keyboard
actions keep their focus-based semantics and route through the same
helpers with the focused editor and active pane.
- **Alt-click** (open in split) now splits relative to the button's pane
via the new `Workspace::adjacent_pane_of` (the existing `adjacent_pane`
delegates to it).
Notably *not* done: focusing the button's pane and re-dispatching the
action. `workspace.active_pane` only updates when pane focus-in
listeners fire at the end of the next draw, while dispatched actions run
before it — the handler would still read the stale pane.
## Additional changes
- Existing-preview lookup now happens **before** view construction,
instead of building a full preview view (subscriptions, initial parse)
and discarding it when one already exists.
- The `focus` flag now also applies to the activate-existing branch, so
open-to-the-side never steals focus — previously the *first* invocation
left focus in the editor but a *repeat* invocation focused the existing
preview (and cancelled collaborator-following in that pane as a side
effect).
- SVG handlers no longer double-check `is_svg_file`; CSV handlers reuse
`resolve_active_item_as_csv_editor` instead of inlining it;
`is_markdown_file` takes `&App` instead of a needless `&mut Context<V>`.
## Testing
- New regression test
`preview_opens_for_the_given_pane_not_the_focused_editor` reproducing
the issue's setup (two panes, focus in the second, preview invoked for
the first pane's editor), asserting the preview opens in the invoking
pane bound to that pane's editor with the focused pane untouched.
- Markdown/SVG/CSV preview suites and the full `workspace` suite pass;
`./script/clippy` is clean.
Release Notes:
- Fixed the preview button (Markdown/SVG) previewing the focused file
instead of the file in the pane the button belongs to when multiple
panes are open
# Objective
Fixes#59983.
Reducing the Zed window height with the terminal open can clip the
Bottom Dock and terminal content. The dock should shrink to remain
within the workspace instead of extending beyond the window.
## Solution
Restore height clamping for Bottom Dock panels by skipping
`clamp_panel_size` only when a panel actually uses flexible width.
Flexible sizing remains unchanged for the Left and Right Docks, while
Bottom Dock panels once again reduce their stored height to fit the
available workspace.
## Testing
Added a regression test that distinguishes flexible Bottom and Right
Dock behavior. It confirms that the Bottom Dock is clamped while the
flexible-width Right Dock is not. The test failed with the previous
condition and passed with this change.
Manually verified the reported window-resizing scenario locally.
## 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
https://github.com/user-attachments/assets/c56995a8-47c6-45b6-aeb4-b0b56477c737
+ After
https://github.com/user-attachments/assets/97b5ca6f-cf6f-4dd5-b981-e44bd8139490
---
Release Notes:
- Fixed bottom dock clipping when resizing windows.
This is a lot of computation work which otherwise hangs the ui thread
Closes FR-122
Release Notes:
- Fixed a cause for ui hangs when interacting with the agent panel
On Linux with client-side decorations, opening the workspace sidebar
squared off the window corners on the sidebar's side while the rest of
the window stayed rounded:
Before:
<img width="366" height="239" alt="image"
src="https://github.com/user-attachments/assets/e0ee8d28-6143-42ea-bfd2-10d069df5492"
/>
After:
<img width="426" height="219" alt="image"
src="https://github.com/user-attachments/assets/51d2979d-0103-4742-90bd-a97f5837d99b"
/>
Previously, `client_side_decorations` took a `border_radius_tiling`
override that `MultiWorkspace` used to deliberately square the window
shape on the sidebar's side, since the sidebar painted a square
background that would otherwise poke out past the rounded window border.
The title bar and status bar already skip rounding their corners on the
sidebar side, implying the sidebar is expected to own those window
corners — it just never rounded them.
This PR makes the sidebar round its outer corners the same way the title
bar and status bar do (including overlapping the 1px window border on
untiled edges to avoid a transparent gap in the rounded corners), and
removes the now-unneeded `border_radius_tiling` parameter so the window
border and backdrop round purely based on actual tiling state.
Only applies when the window uses client-side decorations, so macOS and
Windows are unaffected.
Fixes#54724
Release Notes:
- Fixed square window corners on the sidebar side of client-decorated
(Linux) windows when the workspace sidebar is open.
---------
Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
# Objective
Allow keybindings to open the file finder with ignored files
pre-included, regardless of the global `file_finder.include_ignored`
setting:
```json
{
"bindings": {
"ctrl-shift-o": ["file_finder::Toggle", { "include_ignored": true }]
}
}
```
Closes https://github.com/zed-industries/zed/discussions/42575
## Solution
- Describe the solution used to achieve the objective above.
## Testing
- Did you test these changes? If so, how?
manually locally and a unit test.
- Are there any parts that need more testing?
no
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
no
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
macOS
## 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>
My super cool demos here
</details>
---
Release Notes:
- Added `include_ignored` parameter to `file_finder::Toggle` action,
allowing keybindings to open the file finder with ignored files
pre-included.
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
# Objective
- Prevent the Zed window height from shrinking to the built-in MacBook
screen's height after macOS screen lock or display sleep in
multi-monitor setups.
- Related to #41246.
## Solution
- Ignore window bounds change events in `observe_window_bounds` if the
window is currently inactive (`!window.is_window_active()`).
- **Explanation**: When the system locks or sleeps, macOS reconfigures
displays (monitors power down, and macOS temporarily treats the built-in
screen as the only primary display). This triggers a resize event on
inactive Zed windows to fit them onto the built-in display. Because the
window was inactive, the `observe_window_bounds` listener still
triggered and scheduled `save_window_bounds`, immediately overwriting
the workspace database with the temporary shrunk dimensions.
- By ignoring bounds updates when the window is inactive, we preserve
the correct original bounds in the database. Since a user-initiated
resize/move always activates/focuses the window first, bounds will still
be correctly persisted for intentional manual updates.
## Testing
- Yes, tested locally on macOS (Sequoia).
- Verified that compiling the `workspace` crate succeeds (`cargo check
-p workspace`).
- Ran all 220 unit tests in the `workspace` crate (`cargo test -p
workspace`), and all passed successfully.
- **How to test**:
1. Open Zed on an external monitor and set it to a large size (or
maximize).
2. Lock the screen (or let the displays sleep).
3. Wake/unlock the screen.
4. Verify that the window recovers and maintains its original height
instead of shrinking.
## 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 an issue where the Zed window would shrink to the built-in
display's height on macOS after screen lock or display sleep in
multi-monitor setups.
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
The earlier editor-only zoom implementation in #32860 rendered the
active pane with padding, a border, rounded corners, and a shadow. In
addition to keeping docks visible, that treatment made the transient
editor zoom mode apparent.
The current `ToggleEditorZoom` implementation (#53911) only omits
sibling panes from the pane group, without any visual indication.
Without a persistent control or decoration, the result can look like an
ordinary single-pane layout, so users cannot tell whether toggling the
command will restore hidden splits.
So this commit renders the maximized pane as an inset card with padding,
a subtle theme border, rounded corners, and a shadow. Keeping this
treatment in `PaneGroup` makes it apply only to editor zoom, leaves
docks untouched, and distinguishes it from `ToggleZoom`'s square
workspace overlay.
## Showcase
<img width="862" height="415" alt="Screenshot 2026-07-15 at 18 51 30"
src="https://github.com/user-attachments/assets/f61c61ce-79b7-4e3a-a9c4-0775931fa90d"
/>
---
Release Notes:
- N/A
---------
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
This is necessary to remove some `util` dependencies from crates, as
well as better sharing for our projects. This also includes the WIP
AbsPath abstraction as well as some bug fixes from internal tooling.
Release Notes:
- N/A or Added/Fixed/Improved ...
# Objective
Closes#55925Closes#59094
When a Python project is opened and a toolchain is selected, Zed
stores/persists this choice in the database. When the project is
reopened later, that saved toolchain should be automatically selected.
However, this recovery mechanism requires the associated worktree to be
loaded first.
In local development, the worktrees are loaded first, after which the
toolchain is restored and activated:
afaef857b9/crates/workspace/src/workspace.rs (L1916-L1955)
But in remote development, the toolchain restoration block runs at the
very beginning of initialization, before any worktrees are loaded:
afaef857b9/crates/workspace/src/workspace.rs (L10381-L10413)
Because the worktree does not exist yet when the toolchain is processed,
`find_worktree` always returns `None`, and the saved toolchain is never
activated. This breaks toolchain persistence for remote workspaces.
## Solution
Move the toolchain activation block in `open_remote_project_inner` so it
runs after the worktrees have been loaded, matching the sequence used in
`new_local`. This ensures the worktree is present in the project when we
perform the ID lookup and activate the toolchain.
## Testing
Tested locally with a Windows client connecting to a remote Linux
server, verifying that the previously selected virtual environment is
correctly restored upon reopening the workspace.
## 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 Python virtual environments not automatically restoring when
reopening a remote development workspace.
Co-authored-by: Lukas Wirth <lukas@zed.dev>
VS Code has a command called "Toggle Maximize Editor Group" (`Cmd+K
Cmd+M`) that expands the active editor pane to fill the entire center
area, hiding editor split panes, but leaving docks and panels visible.
Zed's existing `ToggleZoom` hides all panels and is closer to VS Code's
Zen Mode. VS Code has both — it would be useful for Zed to as well.
This is particularly useful for people working on laptops, and has been
raised before (#32715, #4897, #32860), but the addition of the project
panel alongside the agent panel has made it more relevant. I work with
the editor split vertically, but with the project and agent panels both
visible, on a laptop screen there's really only room for a single editor
pane. This command makes it easy to switch to and from that mode.
**Behavior:**
- New action: `workspace::ToggleEditorZoom`
- When activated, the active editor pane expands to fill 100% of the
center/editor area, hiding sibling split panes
- Docks and panels remain visible and unaffected
- Toggling again restores the previous split layout
- If `ToggleZoom` is active, it unzooms first, then maximizes
Here's a demo:
https://github.com/user-attachments/assets/fcf6748e-6c45-4c4a-8d9f-f106c6cd58ea
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#32715
Release Notes:
- Added `workspace::ToggleEditorZoom` action to maximize the active
editor pane within the center area while keeping panels visible.
Fixes menu a11y, and adds landmarks with `F6`-navigation.
Also fixes a GPUI bug, and adds debug actions for dumping a11y tree
info.
Since `F6` was already in use by the pause debugger keybind, also
tightens up the debugger keybind context so they require an active
debugger session. When there is one active, `F6` stays as pause
debugger. `ctrl-F6` always works to go to the next landmark.
Also adds an "accessible mode" setting. Currently, this only controls
whether we show all menus all the time, but I suspect it will expand
significantly in the future.
Also adds `.aria_keyshortcuts()` API, but it's not wired up within
accesskit adapters, so is not yet reported to screen readers.
---
Release Notes:
- N/A or Added/Fixed/Improved ...
This allows us to build powerful and flexible Input and TextArea
components
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- N/A
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolves https://github.com/zed-industries/zed/issues/55600
This diff fixes `pane::ReopenClosedItem` getting stuck when the
closed-item stack contains entries that cannot be reopened, such as
Project Search, untitled buffers, or Default Settings. Previously,
`Workspace::navigate_history_impl` would pop the newest closed entry and
stop if that item was no longer present in the pane and had no path
recorded for reopening. That made `cmd- shift-t` appear to do nothing
until enough attempts had consumed those unreopenable entries.
With this change, closed-item navigation keeps scanning when it
encounters an entry that cannot be activated or reopened by path. This
preserves the current path-based reopening behavior for normal files,
while avoiding no-op shortcuts caused by non-file items in the closed
stack.
This made me wonder whether or not we'd eventually want full reopen
support for non-traditional items like Project Search or bundled
settings editors. Supporting that properly would require storing
item-specific restoration state, such as search query/options for
Project Search or a bundled-file descriptor for Default Settings, and
teaching closed-item navigation how to recreate those items from that
state. Something definitely out of scope for this PR.
| Before | After |
| --- | --- |
| <video
src="https://github.com/user-attachments/assets/c7044423-4531-4857-84f2-4e9651826c6a"
controls width="500" title="Before"></video> | <video
src="https://github.com/user-attachments/assets/c89dcefb-1796-4cdf-bb21-f165145e678e"
controls width="500" title="After"></video> |
Release Notes:
- Fixed reopening closed tabs getting stuck on closed items that cannot
be reopened.
Summary
- Track whether a worktree root is itself a linked Git worktree.
- Use that metadata when computing project group keys so bare checkout
worktrees group under the repository identity path.
- Propagate the metadata through remote worktree protocols and add
local/remote regression coverage.
Background
Bare checkout layouts can place linked worktrees under the repository
identity directory, e.g. `/monty/.bare` with worktrees like
`/monty/feature-a`. We were treating those linked worktree paths as
separate project identities, which caused the sidebar to move agent
threads under the active worktree instead of the shared repository
group.
We also exclude adding this to collab intentionally, we can open a
different PR for that if we need to.
Closes#59910
Closes AI-431
Test Plan
- `cargo fmt --package project --package worktree --package
remote_server --package workspace --package collab --package proto`
- `git --no-pager diff --check`
- `cargo test -p project test_project_group_key -- --nocapture`
- `cargo test -p remote_server test_remote_root_repo_common_dir --
--nocapture`
- `cargo test -p worktree remote_worktree -- --nocapture`
- `cargo test -p workspace
test_remote_project_root_dir_changes_update_groups -- --nocapture`
- `cargo check -p collab`
Self-Review Checklist:
I've reviewed my own diff for quality, security, and reliability
Unsafe blocks (if any) have justifying comments
The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
Tests cover the new/changed behavior
Performance impact has been considered and is acceptable
Release Notes:
- Fixed agent thread/sidebar grouping for Git worktrees backed by bare
checkouts.
---------
Co-authored-by: Anthony Eid <anthony@zed.dev>
To reproduce:
1. Open a git project with the agent sidebar, ideally with no other
threads in the sidebar.
2. Create a thread in a new git worktree and type into it without
sending.
3. While still in that worktree workspace, hit New Thread. The parked
draft must now be the last activatable entry in the sidebar.
4. Hover the parked draft → click Discard Draft
5. 💥
Release Notes:
- Fixed a panic when discarding a draft workspace.