Commit Graph
39151 Commits
Author SHA1 Message Date
John Tur 0c51c7fd24 Reduce overdraw for border-only quads (#61274)
Restore an optimization that I mistakenly removed in
https://github.com/zed-industries/zed/pull/54728.

Drawing a quad with a border but no fill color will run the quad
fragment shader for every transparent interior pixel, which is
especially costly when the quad is large. Instead, split these quads
into four non-overlapping strips that cover the regions where borders
are painted. The side strips own the straight left and right edges,
while the top and bottom strips own the horizontal edges and the rounded
corners.

Previously, this optimization only applied to borders drawn by the Taffy
layout. I've decided to reinstate the logic directly in `paint_quad` so
that the optimization can be applied more generally... though if this
feels like too much policy, we can move it back.

This reduces the GPU time spent painting a representative Zed scene by
about 20% or so.

Release Notes:

- N/A
2026-07-19 06:52:53 +00:00
Miguel Raz Guzmán Macedo ac5538b723 Fix several small performance inefficiencies in hot paths (#61275)
# Objective

Land five small, independent performance fixes found during an audit of
hot paths (anchor resolution, line shaping, worktree scanning, and
sorting in multibuffers).

## Solution

Each fix is its own commit, so **this PR is best reviewed
commit-by-commit** — every commit message contains the full reasoning
for that change:

- `text`: Avoid redundant rope traversal in `Anchor → usize` conversion
— call `offset_for_anchor` directly instead of `summary_for_anchor`,
which recomputed the same byte offset with ~4 extra O(log n) tree walks.
This is the hottest anchor-resolution path.
- `editor`: Avoid double allocation per shaped line —
`line.as_str().into()` instead of `line.clone().into()`, which allocated
twice per visible line, every frame.
- `text`: Use `sort_unstable_by_key` in operation queue insertion —
Lamport timestamps are unique keys and duplicates are deduped right
after, so stability buys nothing.
- `multi_buffer`: Sort with an explicit comparator instead of
`sort_unstable_by_key`, which cloned a `PathKey` (`Arc` refcount bump)
on every comparison.
- `worktree`: Replace O(n²) `Vec::remove` in the deferred-directory pass
with an O(1) `None` assignment — the vec is already
`Vec<Option<ScanJob>>` and is consumed with `.flatten()`.

## Testing

- No behavior changes intended; all changes are mechanical and tests
affected crates pass: `text`, `editor`, `multi_buffer`, `worktree`.

## 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 editor performance through several micro-optimizations in
anchor resolution, line shaping, and worktree scanning.
2026-07-19 05:36:35 +00:00
Yifeng Xu f032f4d433 agent_ui: Show controls after every agent message (#61245)
# Objective

Fixes #61244 

In the Agent Panel, after a multi-turn conversation, the action buttons
("Copy this Agent response", "Scroll to User Message", and "Scroll to
top") were only shown after the last assistant response. This was
inconvenient for users who wanted to copy or navigate from earlier
responses.

Additionally, the "Scroll to User Message" button always jumped to the
most recent user message in the entire thread, even when clicked from a
historical assistant response.

This PR addresses both issues by rendering the controls after every
non-blank assistant response, and by making "Scroll to User Message"
jump to the user prompt associated with that specific response.

## Solution

- Refactored `render_thread_controls` in
`crates/agent_ui/src/conversation_view/thread_view.rs` to accept an
explicit `entry_ix`, `copy_response_index`, `is_thread_bottom`, and
`user_message_index`, making it reusable per assistant message.
- Rendered the control bar after each non-blank `AssistantMessage`
entry, not just the last entry.
- Made button IDs unique by using tuple IDs like `("name", entry_ix)`,
matching the existing style in this file and avoiding `format!`
allocations.
- Keyed the copy button ID by the control bar location (`entry_ix`)
while still copying `response_index`'s content, so the bottom fallback
bar doesn't duplicate IDs with the per-response bar.
- Gated the generation/confirmation early return to `is_thread_bottom`,
so historical controls remain accessible while the thread is generating
or waiting for confirmation.
- Gated turn stats and thread feedback buttons to the bottom of the
thread so they only appear on the last response.
- Replaced `scroll_to_most_recent_user_prompt` with a more general
`scroll_to_user_message_index` that takes an optional target user
message index.
- For each per-response button, computed the associated user message
index as the most recent user message before that assistant response.
- For the bottom fallback (when the last entry is not an assistant
message), passed `None` so the button still scrolls to the most recent
user message.
- Updated the tooltip from "Scroll to Most Recent User Message" to
"Scroll to User Message".
- Updated existing tests and added assertions for
`scroll_to_user_message_index(Some(ix), cx)`.

## Testing

- `cargo check -p agent_ui`
- `./script/clippy -p agent_ui`
- `cargo test -p agent_ui --lib` (399 passed)
- Added assertions in `test_scroll_to_most_recent_user_prompt` to verify
`scroll_to_user_message_index(Some(0), cx)` and
`scroll_to_user_message_index(Some(2), cx)` scroll to the correct user
message indices.
- Manual testing recommended: open the Agent Panel, send multiple
messages, and verify that each assistant response has the three buttons
and that "Scroll to User Message" jumps to the corresponding user
prompt.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments (no unsafe blocks)
- [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: Only the last assistant response in the Agent Panel showed the
"Copy this Agent response", "Scroll to User Message", and "Scroll to
top" buttons. Clicking "Scroll to User Message" always jumped to the
most recent user message.

After: Every non-blank assistant response displays these buttons.
Clicking "Scroll to User Message" on a historical response scrolls to
the user prompt that triggered that specific response.


https://github.com/user-attachments/assets/46e02bcc-8bed-4cf3-a08a-9ef91a206d08

---

Release Notes:

- Added "Copy this Agent response", "Scroll to User Message", and
"Scroll to top" buttons to every agent response in the Agent Panel.
- Fixed "Scroll to User Message" so it jumps to the user prompt
associated with the current response, rather than the most recent user
message.
2026-07-18 22:40:55 +00:00
Xiaobo LiuandCole Miller edeaf598c7 project: Add remote support for adding paths to .gitignore (#56368)
Release Notes:

- Fixed remote support for adding paths to .gitignore



The problem solved by this PR is: when opening a remote project,
right-clicking a new file in the git panel and clicking "Add to
.gitignore" does not work.

---------

Co-authored-by: Cole Miller <cole@zed.dev>
2026-07-18 21:39:15 +00:00
aa0923404f git_ui: Disable commit actions during commit message generation (#51727)
Release Notes:

- Add disable commit actions during commit message generation

---------

Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com>
Co-authored-by: Cole Miller <cole@zed.dev>
Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
2026-07-18 20:06:31 +00:00
victorandCole Miller 80a1add64b git: Add possibility to open specific line in a diff using the CLI (#45499)
this pr enables opening a specific line in a diff using zed's cli

Release Notes:
- refactor: add possibility to open specific line in a diff using the
cli

---------

Co-authored-by: Cole Miller <cole@zed.dev>
2026-07-18 19:56:01 +00:00
Sathwik Chirivelli 54fdf58d3a git_panel: Show staged and unstaged diff stats (#60815)
# Objective

- Show accurate diff stats for each staged and unstaged projection of a
partially staged file in the Git panel.
- This was originally considered for
https://github.com/zed-industries/zed/pull/59884, but was scoped out of
that already-large PR and is being submitted separately as discussed
there.

## Solution

- Collect HEAD-to-index and index-to-worktree diff stats alongside the
existing combined HEAD-to-worktree stats.
- Carry the staged and unstaged stats through repository status
snapshots and remote status serialization.
- Use the stat matching the projected Git panel section while preserving
the combined stat for the other grouping modes.
- Update the fake Git repository and add regression coverage with
deliberately different staged and unstaged counts.

## Testing

- `cargo check -p git_ui`
- `cargo check -p collab`
- `cargo test -p git_ui
test_group_by_staging_section_membership_and_order --lib`
- `cargo test -p project --lib --no-run`
- `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

---

Release Notes:

- Fixed diff stats for partially staged files in the Git panel
2026-07-18 19:02:25 +00:00
Jake AbendrothandCole Miller eb962794a3 buffer_diff: Canonicalize ambiguous hunk placement to fix staging corruption (#60584)
Closes #60424

## Problem

With the repro from #60424, staging the first deletion hunk marked the
second deletion as staged in the UI even though git still had it
unstaged, and clicking the (incorrectly shown) Unstage button inserted a
duplicate copy of the hunk's contents into the git index on every click.

The root cause is ambiguous hunk placement. The committed text contains
repeated `end\n\n` line runs, so the deletion hunks can "slide": more
than one placement produces a minimal diff. The uncommitted diff (HEAD
vs worktree) anchored the remaining deletion at one row while the
unstaged diff (index vs worktree), recomputed after the partial stage,
anchored the same logical deletion at a different row. Everything that
correlates hunks across those two diffs assumes they agree on positions:

- the secondary-status matching in `hunks_intersecting_range_impl` found
no unstaged hunk at the uncommitted hunk's rows and reported it as
staged (`NoSecondaryHunk`);
- the worktree→index projection in `compute_uncommitted_index_edits`
treated the hunk's position as unchanged text and, on unstage, inserted
the hunk's HEAD content at an index position that already contained it,
duplicating it on every request.

## Fix

Upgrade `imara-diff` from 0.1.8 to 0.2.0 and run
`Diff::postprocess_lines` (imara-diff's port of git's xdiff
slider/indent heuristic) after computing hunks in `buffer_diff`. This
canonicalizes the placement of ambiguous hunks based only on their local
content, so diffs of the same buffer against different base texts anchor
the same logical change at the same rows. A bonus is that Zed's hunk
placement now matches `git diff`'s output for such cases (git has used
the indent heuristic by default since 2.11).

As defense in depth, `compute_uncommitted_index_edits` now drops a
pure-insertion index edit whose content is already present at the target
position, so a stale secondary status can no longer duplicate index
content.

The imara-diff 0.2 API removed the `Sink` trait and the top-level
`diff()` function, so the other call sites (`language/text_diff.rs`,
`zeta_prompt/udiff.rs`, `edit_prediction_metrics/reversal.rs`) are
migrated mechanically to `Diff::compute` + `hunks()` with unchanged
behavior (0.2 also renamed `lines_with_terminator` to `lines` and
changed the default `&str` tokenization to include terminators; the
unified-diff builders keep terminator-less tokens via `str::lines()`).

## Testing

- New regression test `test_staging_hunks_with_ambiguous_placement`
replays the exact repro from #60424 (same file contents): stages the
first deletion, asserts the remaining hunks keep their unstaged status
and the index matches exactly, then issues repeated unstage requests for
the unstaged hunk and asserts the index is unchanged. Before the fix
this test showed the second hunk flipping to staged and the index
growing by one copy of the deleted block per unstage request.
- `buffer_diff`, `language`, `zeta_prompt`, `edit_prediction_metrics`,
`multi_buffer`, `git_ui`, `editor`, and the `project` integration suite
pass.
- One test expectation updated: `editor::test_fold_function_bodies`
asserted the old placement of an ambiguous deletion (blank line before
comment); the canonicalized placement (comment before blank line)
matches what `git diff` produces for the same texts.

Release Notes:

- Fixed staging a hunk sometimes marking a different hunk as staged (and
subsequent unstaging corrupting the git index) when the diff contained
repeated lines
([#60424](https://github.com/zed-industries/zed/issues/60424)).

---------

Co-authored-by: Cole Miller <cole@zed.dev>
2026-07-18 18:48:49 +00:00
saberoueslati 2118a7c53a editor: Fix Shift-click selection after cursor movement (#61045)
## Context

Shift-click sometimes extended a selection from an earlier word boundary
after double-clicking a word and moving the cursor with the arrow keys.
Cursor movement changed the selection but left the word or line
selection mode active, so the next Shift-click reused stale selection
bounds. Selection movement now resets the mode to character mode
whenever it changes the selection, while preserving valid empty line
selections that have not been moved.

Closes #59913.

Behavior before the fix :

[Screencast from 2026-07-15
13-21-51.webm](https://github.com/user-attachments/assets/c126adfe-f9db-4a04-91c2-6db6e8070182)

Behavior after the fix :

[Screencast from 2026-07-15
13-19-38.webm](https://github.com/user-attachments/assets/19c9f5b6-aaf8-4e8b-b4c5-70327411d1b9)


## How to Review

**`crates/editor/src/selections_collection.rs`**:
`MutableSelectionsCollection::move_with` now resets the selection mode
to character mode when movement changes a selection.

**`crates/editor/src/editor_tests.rs`**: Regression tests cover
Shift-click after collapsing a word selection and confirm that a valid
empty line selection retains line-wise extension behavior.

## Self-Review Checklist

- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the UI/UX checklist
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- Fixed Shift-click sometimes extending selections from a previous word
or line boundary.
2026-07-18 15:51:21 +00:00
Lukas Wirth ab234b1946 workspace: Run possible_open_target logic on the background (#61257)
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
2026-07-18 14:45:31 +00:00
Kevin Bravo c9e8e611db lsp: Set workspace folder names (#60938)
# Objective

Fixes #60518.

Zed sends an empty `name` for entries in
`initialize.params.workspaceFolders`. Language servers such as
basedpyright use this field to identify workspace service instances,
resulting in an unnamed instance.

## Solution

Derive each workspace folder name from its URI, preferring the decoded
filesystem basename. For basename-less URIs, fall back to a non-empty
path, URI path segment, or the full URI.

Use the same construction for initialization parameters, dynamic
workspace-folder notifications, and `workspace/workspaceFolders`
responses so all LSP messages remain consistent.

## Testing

- `cargo fmt --all -- --check`
- `cargo test -p lsp`
- `cargo check -p project --all-targets --all-features`
- `./script/clippy -p lsp`
- `./script/clippy -p project`

Reproduced with basedpyright 1.39.9 over an LSP stdio session. Before
this change it logged:

```text
Starting service instance ""
```

With a derived workspace folder name it logged:

```text
Starting service instance "zed-60518-project"
```

Tested on 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

Release Notes:

- Fixed language servers receiving empty workspace folder names.
2026-07-18 08:04:17 +00:00
Eric HolkandDanilo Leal 9d7ab04436 Round window corners on the sidebar side on Linux (#61229)
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>
2026-07-17 23:58:06 +00:00
John Tur 7eb8af27a6 gpui: Remove ExitProcess shutdown workaround (#61219)
The issue with aws-lc that necessitated this workaround has been fixed
upstream: https://github.com/aws/aws-lc/issues/3197.

Release Notes:

- N/A
2026-07-17 19:16:49 +00:00
Lukas WirthandJohn Tur de827bce2f gpui: Add system notification platform APIs (#61189)
Release Notes:

- N/A or Added/Fixed/Improved ...

---------

Co-authored-by: John Tur <john-tur@outlook.com>
2026-07-17 18:52:23 +00:00
Jason WilliamsandAnthony Eid 858d3172a8 debugger: Don't eagerly fetch variables for expensive DAP scopes (#61144)
# Objective

Zed eagerly fetches variables for every scope returned by a DAP `scopes`
response, including scopes the adapter marked `expensive: true`.

Per the [DAP
spec](https://microsoft.github.io/debug-adapter-protocol/specification#Types_Scope),
`expensive` means "the number of variables in this scope is large or
expensive to retrieve... recommended for UIs to not automatically expand
and evaluate the scope. Some debug adapters (e.g. `vscode-js-debug`,
used for JavaScript/Chrome debugging) mark scopes like "Global" as
expensive because resolving them can hang forever. VS Code honors this
and leaves the scope collapsed until the user opts in by expanding it;
Zed did not, so any session with a hanging expensive scope would freeze
the entire debug session (including Resume) with no user action at all.

Fixes #61105

## Solution

- `Session::scopes()` in `crates/project/src/debugger/session.rs`
[unconditionally called
`this.variables(...)`](https://github.com/zed-industries/zed/blob/058f01fa93503491a735bfded53e77bfaa276148/crates/project/src/debugger/session.rs#L2538)
for every scope in the `scopes` response.
- `VariableList::build_entries()` in
`crates/debugger_ui/src/session/running/variable_list.rs` also called
`session.variables(...)` [on every
scope](https://github.com/zed-industries/zed/blob/058f01fa93503491a735bfded53e77bfaa276148/crates/debugger_ui/src/session/running/variable_list.rs#L291-L304),
as a side effect of checking whether it was empty (used to decide
whether to hide it from the tree). Fixing only the first call site
wasn't enough, since this one would still trigger the fetch on the very
next render.
  
Both now skip the fetch for `expensive` scopes. Expensive scopes still
show up in the variable list, collapsed, so the user can expand them
manually (which fetches lazily via the existing on-toggle path). Also
hardened the auto-expand heuristic (e.g. "expand the only scope if it's
not Locals") to never auto-expand an expensive scope, even in adapters
where it happens to be the sole or "Locals"-named scope.

## Testing

- Added `test_expensive_scope_is_not_eagerly_fetched` in
`crates/debugger_ui/src/tests/variable_list.rs`, asserting the DAP
`variables` request is never sent for an
`expensive: true` scope until the user expands it, and that expanding it
does trigger the fetch. Verified this test fails on the old code and
passes with the fix.
  - Ran the full `debugger_ui` test suite, all pass, no regressions.
- Manually reproduced and verified the fix using the minimal repro at
https://github.com/jasonwilliams/zed-dap-repro

## 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/7a3ead7e-aece-4726-883d-d60d49c83b7c
Here you can see that once the break has happened Zed has crashed,
resuming doesn't help, i effectively need to kill the whole debug
session.

After:

https://github.com/user-attachments/assets/7a36cbb0-f22b-4782-9326-9ccab9297fc7
Here you can see the Global scope is closed and clicking resume carries
on without any crashes

Release Notes:

- Fixed debugger eagerly fetching expensive variable scopes

---------

Co-authored-by: Anthony Eid <anthony@zed.dev>
2026-07-17 14:42:46 +00:00
tidely f1280b64a4 gpui: Unify raw-window-handle dependency (#61193)
Just something I noticed while skimming through dependencies

Release Notes:

- N/A or Added/Fixed/Improved ...
2026-07-17 13:41:05 +00:00
Smit Barmase 2a983bca86 git: Fix operations timing out and commit-msg hook being skipped (#61185)
Closes #44926
Closes #43157
Closes #29903

We have an askpass 17s timeout that races against Git operations and
results in "Connecting to host timed out". It came along in #25953 when
we extracted askpass out of remoting, where it was used for SSH.

I think, for SSH connection, no prompt and no connection after 17
seconds means the host is unreachable, so the timeout is a reliable
signal there. But for Git, silence is pretty normal. Cases like hook
running, pack transferring, an ssh-agent waiting on a fingerprint are
all senarios where we should not be dependent on timeout which kills
these healthy operations.

#43285 worked around this for commits by running the pre-commit hook
manually and passing `--no-verify` to `git commit`. But, there are more
problems to address, which I reproduced on my machine:

1. A slow `post-commit` hook fails, since `--no-verify` doesn't skip it.
2. A slow `pre-push` hook fails too, and a workaround like #43285 needs
a lot more handling. See
https://github.com/zed-industries/zed/pull/42946#issuecomment-3550570438.
3. This is the tough one: due to `--no-verify`, we are also skipping the
`commit-msg` hook. There is no direct way to call that hook since, Git
hands this hook its in-progress message file, commits whatever the hook
leaves in it, and aborts if the hook exits non-zero. Reproducing that
outside `git commit` means reimplementing that.
4. An ssh-agent waiting for user approval fails after the timeout, like
if you have 1Password set up.
5. It doesn't solve large fetches. Fetching
`git@github.com:torvalds/linux.git` just dies at the 17s timeout
mid-download.

This PR fix keep the timeout only on the SSH transport and drop it for
Git, which is less of a behavior change and more of a restoring its
original scope. If Git in a terminal doesn't time out, we shouldn't
either. This way, we let Git handle all types of hooks, which solves the
hooks issue along with the timeout issue. _This follows how VS Code does
it. It does not have any kind of timeout on git child process, and hooks
are handled by Git itself._

Edit: I also think working towards way to cancel long going operations
is better way forward. See
https://github.com/microsoft/vscode/issues/171353.

Hooks still don't run for untrusted repositories, the existing
`core.hooksPath=/dev/null` clamp covers that. The `RunGitHook` proto
handler is kept for compatibility with older remote clients.




Release Notes:

- Fixed git operations failing with a misleading "Connecting to host
timed out" error when they took longer than 17 seconds (large fetches,
slow hooks, or waiting on agent-based authentication like 1Password
Touch ID).
- Fixed `commit-msg` hooks being silently skipped on commit.
2026-07-17 13:38:09 +00:00
ᴀᴍᴛᴏᴀᴇʀandTom Houlé 5079b33d65 gpui_linux: Fix unbounded memory growth when composing text with Fcitx5 under KWin/Wayland (#61079)
# Objective

Close #61034.

Fix unbounded memory growth when composing text with Fcitx5 under
KWin/Wayland.

While a non-empty preedit is cached, KWin resends it whenever it
receives a text-input-v3 `commit()` ([relevant KWin
code](https://github.com/KDE/kwin/blob/0e473e87a64d5d404c2fecf5516a9a5c3cf17d91/src/wayland/textinput_v3.cpp#L444-L504)).

Zed handles the replayed preedit as a buffer edit. This invalidates the
IME character coordinates, causing Zed to submit the same cursor
rectangle and call `commit()` on the next frame. That commit makes KWin
replay the cached preedit again, forming an infinite feedback loop.

The observed memory growth is caused by retained CRDT state accumulating
indefinitely.

## Solution

Following [SDL's solution to the same
problem](https://github.com/libsdl-org/SDL/commit/81479d8784d0e1a61eafb3a444dd3865ad762fb2),
cache the last submitted cursor rectangle and compare it with the new
rectangle before calling `set_cursor_rectangle()`.

If the rectangles are equal, skip both the rectangle update and its
associated `commit()`. The initial cursor rectangle and actual rectangle
changes during an active composition are still submitted, preserving the
candidate-window positioning behavior introduced by #59911.

## Testing

Manually tested on KDE Plasma with `fcitx5-chinese-addons`. 

Before the fix, memory usage grew continuously while preedit text was
present, with `WAYLAND_DEBUG=client` showing text-input events repeating
indefinitely.

After the fix, the repeated events stopped and memory usage remained
stable.

No automated test was added because reproducing the feedback loop
requires compositor-specific KWin text-input-v3 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)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable


---

Release Notes:

- Fixed excessive memory usage when composing text with Fcitx5 on KDE
Wayland.

---------

Co-authored-by: Tom Houlé <tom@tomhoule.com>
2026-07-17 13:10:42 +00:00
d0 1d2a4b3f7f outline: Add preview pane to buffer symbols (#61069)
# Objective

- Implement preview pane for buffer symbols, similar to #59863 

## Showcase
### Before 
<img width="4512" height="2980" alt="CleanShot 2026-07-15 at 23 25
19@2x"
src="https://github.com/user-attachments/assets/443f150a-bb67-4bac-ba4a-f8f299554470"
/>

### After
<img width="4512" height="2980" alt="CleanShot 2026-07-15 at 23 19
09@2x"
src="https://github.com/user-attachments/assets/0fd4be89-d25e-4052-8de0-3a9a5a5908f9"
/>


---

Release Notes:

- Added a preview pane to the buffer symbols picker
2026-07-17 11:41:08 +00:00
Ibrahim Khan df9321ec81 agent_ui: Fix project rule pluralization in context usage popover (#61184)
The agent panel's context usage popover showed "1 project rules" when
exactly one project rule (e.g. `.rules`) was loaded, because the
project-rules button used an unconditional `format!("{} project rules",
...)`.

Reuse the existing `pluralize` helper (already used for diagnostics
labels in the same crate) so a single rule renders as "1 project rule"
and multiple rules render as "N project rules". The sibling "1 global
rule" label is intentionally left unchanged, since there is only ever
one global rule.

Closes #57759

Release Notes:

- Fixed the agent panel context usage popover showing "1 project rules"
instead of "1 project rule" when a single project rule is loaded.
2026-07-17 11:36:37 +00:00
Danilo Leal fd013f7f56 git_graph: Remove commit preview on row hover (#61191)
This PR removes the commit preview popover when hovering over rows in
the git graph. In my humble opinion, I've been finding that having the
hover preview damages the usability/readability of the graph. I can't
properly read each row's content and understand its place on the graph
if everywhere I rest my cursor in a popover appears... Moreover, almost
all of the information we display in the commit preview is already
displayed in the row itsself, and if you'd like to drill down into the
commit description and whatnot, clicking the row opens the commit drawer
and gives you that and even more information (e.g., set of changed
files, etc.).

Release Notes:

- N/A
2026-07-17 11:32:07 +00:00
Kirill Bulatov 31ceaf7908 Bump taffy (#61183)
Follow-up to https://github.com/zed-industries/zed/pull/60721

Release Notes:

- N/A
2026-07-17 09:45:16 +00:00
Kirill Bulatov dde45ff092 Mimic macOS bundling behavior for Windows builds (#61180)
Rei-mplements the logic from
https://github.com/zed-industries/zed/blob/9552acc2bc242d45342fa9b5a987d43868aee1ec/script/bundle-mac#L120-L123
for Windows bundling so that `run-bundling` label in CI can build
unsigned Windows binaries properly.

Release Notes:

- N/A
2026-07-17 09:01:06 +00:00
Lukas Wirth 6d66d5749d git_graph: Fix commit message overflowing into changed files section (#61177)
This regressed in https://github.com/zed-industries/zed/pull/59674

Closes FR-125

Release Notes:

- Fixed an issue where the commit message in the git panel could overlap
other content
2026-07-17 08:57:46 +00:00
Lukas Wirth c7148c8190 project: Fix agent hanging indefinitely when pulling workspace diagnostics (#61176)
The agent's diagnostics tool waits on pull_workspace_diagnostics_once,
which enqueues a completion signal into the background workspace
diagnostics refresh loop. When a language server failed to answer
workspace/diagnostic requests, that signal could be stranded, leaving
the agent stuck on 'Check project diagnostics' (reported with logs full
of 'Timeout during workspace diagnostics pull' and requests cancelled
after 120s).

Three hang paths in lsp_workspace_diagnostics_refresh:

1. Timeouts never resolved the completion signal. On
ConnectionResult::Timeout the loop just retried, holding the waiter
through up to 50 attempts x 120s each (~100 minutes) before the sender
was finally dropped.

2. Waiters could queue behind an already-hanging request. The refresh
channel has capacity 1; if the loop was mid-retry (e.g. the initial pull
at server startup was timing out), a newly enqueued waiter sat
unreceived until the entire retry cycle ended.

3. The request timeout was permanently disabled after the first partial
result. The timer raced progress_rx.recv() once and became pending()
forever if progress won, so a server that streamed one chunk and then
stalled hung the request indefinitely.

Fixes:

- On timeout, release all pending waiters (including ones that queued
mid-flight) with refreshed = false, so callers fall back to cached
diagnostics after at most one timeout period while the background loop
keeps retrying.

- Carry waiters as a Vec and absorb refresh requests queued during
backoff/in-flight requests into the current attempt instead of
serializing them behind it.

- Restart the timeout whenever a partial result arrives, turning it into
an inactivity timeout: streaming servers get unlimited total time while
they keep making progress, but a stalled stream now times out instead of
hanging forever.

Adds a regression test with a fake server that never answers workspace
diagnostic pulls, verifying the waiter resolves after the timeout; it
fails with 'Parking forbidden' (infinite hang) without the fix.

Closes FR-124

Release Notes:

- Fixed agents hanging indefinitely if an LSP server never responds to
diagnostics requests
2026-07-17 08:45:02 +00:00
Shuhei Kadowaki 94e59ce2f8 git_graph: Fix long commit message overflow in detail panel (#61163)
Follow-up to zed-industries/zed#60721.

The Taffy 0.12 upgrade exposed that the message height limit was applied
to its grid parent while percentage-sized children retained the Markdown
content's intrinsic height. Long messages therefore painted over the
changed-files summary instead of scrolling.

Move the height limit to the scroll container itself, matching the
commit view. Add a GPUI regression test that verifies the viewport stays
bounded, remains scrollable, and does not overlap the changed-files
list.

> On `main`:
<img width="697" height="873" alt="Screenshot 2026-07-17 at 14 59 21"
src="https://github.com/user-attachments/assets/51e6cc0e-aeac-4ad1-a6af-2120efcef901"
/>

---

Release Notes:

- N/A
2026-07-17 08:43:11 +00:00
saberoueslati 9552acc2bc gpui: Apply EXIF orientation when decoding static images (#61017)
## Context

Static images decoded by GPUI ignored their EXIF `Orientation` tag, so
JPEGs that rely on it (photos from phones and cameras) rendered rotated
or flipped in image preview, Markdown preview, and other `ImageSource`
consumers. The `image` crate only exposes orientation through
`ImageDecoder::orientation()`, which must be read before the decoder is
consumed; `DynamicImage::from_decoder` does not apply it. The old path
went straight through `image::load_from_memory_with_format`, so the
metadata was never read.

Closes #60844.

Video of manual test below :

[Screencast from 2026-07-15
02-14-41.webm](https://github.com/user-attachments/assets/002b0324-44f8-4ddb-acbd-8c3e070d5248)


## How to Review

**Cargo.toml**
Raises the workspace `image` dependency minimum from `0.25.1` to
`0.25.4`, the first release exposing `orientation()` and
`apply_orientation()`. The lockfile already resolves to `0.25.10`, so no
lock change is required.

**crates/gpui/src/platform.rs**
Adds two crate-private helpers. `decode_static_image_from_decoder` reads
`orientation()`, decodes to a `DynamicImage`, applies the orientation,
then converts RGBA to GPUI's BGRA. `decode_static_image` builds a format
decoder from bytes and delegates to it. `Image::to_image_data` now
routes its static formats through these helpers instead of
`image::load_from_memory_with_format`. Adds
`test_image_to_image_data_applies_exif_orientation`, which decodes a
16x32 fixture stored upside down with EXIF Orientation 3 and asserts the
corner pixels were flipped upright; the test fails if orientation is
dropped.

**crates/gpui/src/elements/img.rs**
Routes `ImageAssetLoader` (Markdown paths, URLs, embedded resources)
through the same helpers, including the static WebP branch. GIF and
animated-WebP frame handling are left unchanged, since animated
orientation is out of scope.

## Self-Review Checklist

- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the UI/UX checklist
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- Fixed static images ignoring their EXIF orientation, which caused some
JPEGs to render rotated or flipped in image and Markdown preview.
2026-07-17 08:29:17 +00:00
Kirill Bulatov aa42d3adce Render nested tabstops correctly (#61130)
Closes https://github.com/zed-industries/zed/issues/61112

Now behaves similar to VSCode: 

<img width="857" height="552" alt="1"
src="https://github.com/user-attachments/assets/bed95600-c75c-4b1d-a750-17b9eb35db92"
/>

<img width="601" height="243" alt="2"
src="https://github.com/user-attachments/assets/b2e839a5-6ca3-4e3a-8e5f-bc8b3e9a565f"
/>

Release Notes:

- Fixed rust-analyzer's macro with nested tabstops causing panics when
completed
2026-07-17 07:42:28 +00:00
Kirill Bulatov a3f6ef252b Add more parameter colors to the theme (#61134)
Follow-up to https://github.com/zed-industries/zed/pull/60949 based on
https://github.com/zed-industries/zed/pull/60949#issuecomment-4994719726


`basedpyright` sends the token we lack the theme element for

<img width="1141" height="599" alt="before"
src="https://github.com/user-attachments/assets/47fd6375-507d-4419-810b-04e69251fe90"
/>

supports that in theme definitions:

<img width="385" height="244" alt="after"
src="https://github.com/user-attachments/assets/edfe3866-4bdb-480d-9bbd-b76c1366d311"
/>


---

Release Notes:

- Added `variable.parameter` theme color
2026-07-17 07:41:28 +00:00
Smit Barmase c7ee116ead vtsls: Fix invalid tsserver install error in TypeScript 7 projects (#61126)
Closes #60761

Follow-up to #60970, which fixed this for `typescript-language-server`.
`vtsls` had the same problem, we only checked that the workspace tsdk
directory exists, but TypeScript 7 ships it without `tsserver.js`,
causing vtsls to error on startup.

Now we do the same `tsserver.js` check, so vtsls silently falls back to
its bundled TypeScript (see #60951).

Release Notes:

- Fixed vtsls showing a "doesn't point to a valid tsserver install"
error on startup in projects using TypeScript 7. For full TypeScript 7
support, install the `tsgo` extension to use TypeScript's native
language server.
2026-07-17 05:59:19 +00:00
Smit Barmase 058f01fa93 gpui: Fix clicks on window prompts dismissing popovers behind them (#61136)
I noticed that when Zed renders prompts in-window (Linux, or
`use_system_prompts: false`), clicking a prompt button also dismisses
the popover behind it. Native macOS dialogs don't have this problem
since the click goes to the OS dialog and the window never sees it.

For example, in the worktree picker:
1. Delete a dirty worktree.
2. Confirm "Force Delete".
3. Mouse down dismissed the picker, which aborted the confirmed
deletion.

This PR makes GPUI-rendered prompts behave the same way as native. If
someone actually wants to observe mouse downs during a prompt, the raw
`window.on_mouse_event` API still sees every event.

macOS:


https://github.com/user-attachments/assets/9f85622f-c0d1-44f2-83f9-8378d9d7d13b


Before GPUI prompt:


https://github.com/user-attachments/assets/d1845ba1-9886-4733-8cf6-ab32424416e1

After GPUI prompt:


https://github.com/user-attachments/assets/27936aca-8de5-4da8-88be-d88dbc1259d8

Release Notes:

- Fixed confirmation dialog buttons dismissing the popover underneath
them on click when using Zed-rendered prompts.
2026-07-16 19:45:21 +00:00
Oleksandr Kholiavko f688bee4fe csv_preview: Add single-line row displaying mode (#61127)
### Changes

Adds a checkbox to toggle between multiline cells (current behavior) and
single-line rows that clip overflow, so wide CSVs stay compact when full
cell content isn't needed at a glance.

#### Demo
| Before | After |
| --- | --- |
| No single line mode | <img width="662" height="316" alt="image"
src="https://github.com/user-attachments/assets/3f2a9673-557c-4539-b755-9ff2633de2d7"
/> |
| <img width="666" height="287" alt="image"
src="https://github.com/user-attachments/assets/703f7214-a722-4fa5-9125-f043439e21b2"
/> | <img width="660" height="317" alt="image"
src="https://github.com/user-attachments/assets/be6ca912-e686-44da-90eb-58f09fab51f1"
/> |

### Testing

- Toggle "Display multiline rows" off: cells clip to one line with
ellipsis instead of wrapping
- Toggle it back on: cells wrap and grow to show full content
- Resize the window / change font size: single-line clip height tracks
the actual text line height instead of a stale hardcoded value

Release Notes:

-  N/A
2026-07-16 19:28:22 +00:00
Daan De Meyer ae3bbdeb2d gpui: Avoid redundant group hover redraws (#61118)
Anonymous elements with group hover styles have no persistent hover
state. The
prepaint mouse handler treated missing state as unhovered and notified
the
current view for every pointer movement within the group. This made
controls
such as switches redraw continuously while the pointer moved over them.

Let anonymous elements use the existing paint-time hover transition
handler.
Only elements with persistent hover state now update that state and
notify from
prepaint. Add regression coverage for entering, moving within, and
leaving an
anonymous hover group.

Signed-off-by: Daan De Meyer <daan@amutable.com>

Release Notes:

- N/A

Signed-off-by: Daan De Meyer <daan@amutable.com>
2026-07-16 19:26:49 +00:00
Kirill Bulatov b05f40c554 Fix post-taffy-bump layouting issues (#61107)
Follow-up to https://github.com/zed-industries/zed/pull/60721

Before:
<img width="564" height="470" alt="before"
src="https://github.com/user-attachments/assets/d825464d-f8d9-4fa1-bee3-42b5f615d4ba"
/>

<img width="745" height="221" alt="image"
src="https://github.com/user-attachments/assets/18139bec-6778-491a-9aa5-0112bd121723"
/>


After:
<img width="576" height="472" alt="after"
src="https://github.com/user-attachments/assets/4c3c37cf-12c4-421e-98e9-cc6e40aa099d"
/>

<img width="812" height="275" alt="image"
src="https://github.com/user-attachments/assets/407e06b4-101f-4984-8d5b-4e33895b5ae9"
/>


### Bug 1 — constraint-blind text layout cache (the collapse)

`TextLayout`'s measure closure is stateful (each call overwrites the
shared element state used for painting), and its cache check served
cached sizes to unconstrained probes regardless of the constraints they
were computed under:

1. `uniform_list::measure_item` lays an item out at `(MinContent,
MinContent)`; the row's `min_w_0` lets it shrink to ~0, so labels get
truncated at a tiny width — and that tiny size lands in the element
state.
2. The real layout probes the label's flex base size with
`available_space.width = MaxContent` (taffy maps Definite → MaxContent).
Truncated labels are `whitespace_nowrap`, so both `wrap_width` and
`truncate_width` were `None` → the cache check passed → the poisoned
tiny size became the flex basis → labels rendered at ~5 chars.

**Fix**: record `truncate_width` in `TextLayoutInner` and never serve a
cached layout that was computed *with* truncation to an unconstrained
probe; the honest intrinsic size is recomputed instead, and the final
`PerformLayout` call re-truncates against the real resolved width.

### Bug 2 — truncation width math disagrees with shaping (the ~2-char
loss)

After fix 1, rows got their full width, but exact-fit strings like
`Cargo.toml` still lost ~2 chars:

- Sizing measures via `shape_text` (real shaping with kerning); the
element gets exactly `ceil(shaped_width)`.
- The truncation decision (`LineWrapper::should_truncate_line_middle`
etc.) sums **per-character advances** — no kerning — with zero
tolerance, overestimating width for some glyph sequences. Text sitting
in a box of exactly its own measured width got truncated, losing ~2
chars to fit the `…`. String-dependent (kerning pairs), hence
`Cargo.toml` broke while `Cargo.lock` didn't.
- Previously masked because taffy 0.10 usually skipped the final measure
invocation, so the truncation path rarely ran with an exact-fit width.

**Fix**: before truncating (nowrap case, `wrap_width.is_none()`), shape
the untruncated text and skip truncation if the *shaped* width fits —
matching CSS `text-overflow`, which only activates on actual overflow.
Cheap: the shaping result is a `line_layout_cache` hit from the earlier
untruncated sizing probe.

### Bug 3 — `MinContent` used instead of `MaxContent` that caused over
truncation of certain labels

Release Notes:

- N/A
2026-07-16 17:23:49 +00:00
Lena a0bb97cad5 Guild board automation: fix In Progress status moves (#61115)
Release Notes:

- N/A
2026-07-16 16:17:01 +00:00
Oleksandr Kholiavko 0b94192ebd csv_preview: Refine table styling and header button visibility (#60995)
Cleans up table cell/row styling and reworks column header filter/sort
buttons so they stay out of the way until needed, with a gradient fade
instead of a hard clip when the header label is truncated.

### Summary

Improved CSV preview column headers to only show filter/sort actions on
hover, with a gradient fade for truncated labels

### Demo (todo)

| Before | After |
| --- | --- |
| <img width="771" height="626" alt="image"
src="https://github.com/user-attachments/assets/76dcf7b9-ed4a-444f-91f7-57f2acd16934"
/> | <img width="774" height="603" alt="image"
src="https://github.com/user-attachments/assets/aeda6693-ff37-41e6-a849-780874e23286"
/> |

### Testing

- Hover over a data column header: filter/sort buttons fade in, label
truncates behind a gradient rather than a hard edge
- Apply a filter or sort on a column: its buttons stay visible without
hovering
- Toggle row identifier / cell vertical alignment setting between top
and center: alignment applies consistently to both row identifiers and
cells
- Confirm table renders without the previous striping (only bottom
borders)

Release Notes:

-  N/A
2026-07-16 16:02:18 +00:00
Dino 819fe33799 project_panel: Avoid recording record excluded files changes (#61106)
# Objective

Fix error shown when attempting to undo/redo operations on excluded
files, for example, undoing a creation of a file in an excluded path.

## Solution

Since `worktree::Snapshot::entry_for_path` always returns `None` for
excluded files, these changes will simply avoid calling
`UndoManager::record` in `ProjectPanel::confirm_edit` if the created
entry is excluded. This can be confusing if the user is renaming a file
to another path that is excluded, as that will not be recorded and can't
be undone but we accept it as a limitation for now and will document
that.

In the future we can potentially support undoing of operations for
excluded file paths but that would mean not only introducing new methods
that operate directly on the absolute path instead of the entry id, as
well as changes to the proto messages, in order to ensure it's also
fixed in remote and collab.

## Testing

Tested manually, as shown in the "Showcase" section below and also
introduced a test for this –
`project_panel::tests::undo::excluded_create_is_not_recorded` .

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] 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
- [ ] Performance impact has been considered and is acceptable

## Showcase

<details>
  <summary>Before</summary>


https://github.com/user-attachments/assets/7f8fca3e-2716-40bb-95db-c7119bb39b83

</details>

<details>
  <summary>After</summary>
  

https://github.com/user-attachments/assets/47b0322e-a323-4648-8a56-6e96266888d3

</details>

---

Release Notes:

- N/A
2026-07-16 12:07:35 +00:00
Dino 68b165e450 project_panel: Disable undo and redo on read-only projects (#61104)
# Objective

Users in a read-only project should have no permission to create,
rename, move, trash or delete files, as such, they should also have no
way to undo or redo these actions. These changes ensure that the
listeners for both `project_panel::Undo` and `project_panel::Redo` are
only registered if the project is not read-only.

## Solution

The `ProjectPanel` listeners for both the `Undo` and `Redo` actions were
not gated behind the existing `!Project::is_read_only` call, on
`ProjectPanel::render`, so these changes move the listeners inside that
check.

## Testing

Currently, there isn't an easy way to manually test this, as these
actions were already disabled in collab and the easiest way to get into
a read-only project is connect as a collab guest. However, in order to
ensure this continues being asserted once we remove the collab
restriction, the
`project_panel::tests::undo::undo_redo_unavailable_for_read_only_collab_guest`
test has been added.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] 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
- [ ] Performance impact has been considered and is acceptable

---

Release Notes:

- N/A
2026-07-16 11:45:03 +00:00
Daan De Meyer 7d07d39f19 editor: Blink cursors only in the focused editor (#61086)
Every editor associated with a window observed window activation. The
handler enabled the blink manager for every editor, including hidden and
unfocused editors. Their independent 500 ms timers invalidated the
window out of phase and caused redundant full-window presents.

Window activation and deactivation are already represented as focus
transitions by GPUI: an inactive window has an empty effective focus
path. Remove the redundant activation observer and rely on the editor
focus and blur handlers to stop blinking on deactivation and restart it
only for the editor that owns focus on activation.

In a 40-second idle diagnostic run before this change, the steady-state
tail repeatedly contained invalidations from one or two editors per
frame. After the change, no unfocused-editor invalidations appeared.
Bounded scrollbar fades and visible activity animations remain
unchanged.

Add a regression test with focused and unfocused editors that covers
activation, deactivation, and reactivation.

Release Notes:

- Fixed cursors blinking in unfocused editors, reducing idle redraws.

---------

Signed-off-by: Daan De Meyer <daan@amutable.com>
2026-07-16 11:43:27 +00:00
Josh Kent 27ff74540b agent_ui: Match ACP boolean option label colors (#61103)
# Objective

ACP boolean config option labels use the default text color, while
select option labels use the muted text color. This makes boolean
options such as Fast Mode look visually inconsistent with adjacent
configuration controls.

## Solution

Add a label color override to `Switch` while retaining `Color::Default`
for existing callers. Apply `Color::Muted` only when `agent_ui` renders
ACP boolean config options, leaving all other switches unchanged.

## Testing

Manually verified on macOS in the light theme.

## 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 (verified visually)
- [x] Performance impact has been considered and is acceptable

## Showcase

### Before

<img width="449" height="37" alt="image"
src="https://github.com/user-attachments/assets/1abe3e39-b243-47b3-8a62-67a0b5a17b43"
/>

### After

<img width="445" height="39" alt="image"
src="https://github.com/user-attachments/assets/e134378c-84cb-4c72-92d1-98eecc2137e4"
/>

---

Release Notes:

- Fixed ACP boolean option labels to match other agent configuration
controls.
2026-07-16 11:32:43 +00:00
ian 625b29d243 Fix focus handling in ProjectSearchBar. (#61093)
# Objective

Fix #61023

When project search is already open and focused, pressing the project
search shortcut again (`cmd-shift-f` / `ctrl-shift-f`) only re-focused
the query editor and did not select the existing query text. That made
it hard to quickly retype a search term—especially after a no-results
search, when focus stays in the search bar.

This aligns project search behavior with buffer search, where
`FocusSearch` focuses and selects the query.

## Solution

In `ProjectSearchBar::focus_search`, call `focus_query_editor` instead
of only focusing the query editor. `focus_query_editor` already focuses
the field and selects all text (same path used by `DeploySearch`).

## Testing

- [ ] Manual: open project search → type a non-matching query → Enter →
press project search shortcut again → query text should be selected so
typing replaces it
- [ ] Manual: same flow after a search that returns matches
- [ ] Manual: compare with buffer search (`cmd-f` / `ctrl-f`) to confirm
consistent “refocus selects query” behavior
- Platforms: tested / to be tested on macOS; Linux/Windows should behave
the same via the shared `FocusSearch` action

No automated test added yet; a `gpui::test` that deploys project search,
dispatches `FocusSearch`, and asserts the query editor selection would
be a good follow-up.

## 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:

- N/A
2026-07-16 11:07:07 +00:00
Daniel StrobuschandSmit Barmase 93b846b2a6 file_finder: Add include_ignored parameter to Toggle action (#59568)
# 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>
2026-07-16 10:30:16 +00:00
Noah Hüsser 53a3874a32 Relax core-foundation pin from =0.10.0 to 0.10 (#61089)
This PR relaxes the workspace `core-foundation` pin from an exact
`=0.10.0` to `0.10`.

I am not sure why this is pinned - digging a bit did not turn up any
specific reason so I have to assume it was not on purpose. At the moment
you cannot use gpui with nusb 0.2 (which is muuuuuch improved over 0.1,
it's not a cosmetic update) for example because of this restriction.

I would much appreciate if this relaxation was in the realm of
possibilities :)

Release Notes:

- N/A
2026-07-16 10:27:44 +00:00
i18uandKirill Bulatov 40102ee7c2 workspace: Prevent overwriting window bounds when window is not active (#60950)
# 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>
2026-07-16 10:06:41 +00:00
DinoandYara b562439e93 project_panel: Add remote support for undo/redo system (#59709)
# Objective

Add remote (SSH) and collaboration support for trashing and restoring
files in the project panel, which in turn enables undo/redo of trash
operations against remote and collab projects.

Relates to #5039.

## Solution

- Updated the project panel undo system to carry `TrashId` instead of
`TrashedEntry`.
- Using `TrashedEntry` could get hairy, as it includes paths, which
wouldn't play too nicely when using, for exapmle, macOS as the client
and Windows as the host. Using a simple identifier is much easier in
this regard and simplifies implementation.
- Enabled the Trash action and context-menu entry on remote projects,
and removed the command palette filter in `ProjectPanel::new` that was
still hiding the action on remote.
- As far as I can tell, there isn't a reliable way to detect whether a
given remote actually supports the OS trash, so we expose the action
everywhere rather than guessing. On a remote without trash support the
action will fail when invoked but this is a conscious tradeoff until we
find a better way to handle this.
- `fs` now tracks trashed files in a `SlotMap<TrashId, TrashedEntry>` on
each `Fs` implementation. Trashed files are referenced by an opaque
`TrashId` instead of passing a `TrashedEntry` around, which avoids
serializing filesystem paths in remote messages.
- Split the old `delete_entry(trash: bool)` API into distinct
`trash_entry`/`trash_file` (returning a `TrashId`) and
`delete_entry`/`delete_file` across `Project`, `Worktree`,
`LocalWorktree` and `RemoteWorktree`.
- This lets us drop the optional trash result (`Option<TrashedEntry>`)
from the delete path and require a `TrashId` from the trash path.
- Added new proto messages (`TrashProjectEntry`,
`TrashProjectEntryResponse`, `RestoreProjectEntry`,
`RestoreProjectEntryResponse`) to let clients request the host to trash
or restore entries.
- This deprecates `DeleteProjectEntry::use_trash`, but the host still
honors it. An older collab peer may request trashing via that flag
instead of the newer `TrashProjectEntry`. If the host ignored it, a
newer host would permanently delete a file the user meant to send to the
trash. The field will be removed in a later PR once all supported peers
use `TrashProjectEntry`.

## Testing

The following tests were introduced to ensure the new behavior is
correctly tested:

* `remote_server::remote_editing_tests::test_remote_trash_restore` –
Tests trashing a project entry in remote
*
`remote_server::remote_editing_tests::test_remote_delete_project_entry_with_trash`
– Test to ensure we continue respecting `DeleteProjectEntry::use_trash`
until it is fully removed
* `project_panel::tests::undo::trash_directory_undo_redo` – Not related
to these changes but a nice to have as we were missing a test ensuring
that trashing and then undoing and redoing it for a directory works as
expected

Besides these, the following scenarios were manually tested against a
remote session on the same machine (macOS):

- Trashing → Undo (Restore) → Redo (Trashing)
- Batch Trashing → Undo (Batch Restore) → Redo (Batch Trashing)
- Rename → Undo (Rename) → Redo (Rename)
- Move → Undo (Move) → Redo (Move)
- Batch Move → Undo (Batch Move) → Redo (Batch Move)

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [ ] 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
- [ ] Performance impact has been considered and is acceptable

Release Notes:

- N/A

---------

Co-authored-by: Yara <git@yara.blue>
2026-07-16 09:41:21 +00:00
Kirill Bulatov bf14327c27 Remove the 3rd party section (#61087)
See
https://github.com/zed-industries/zed/pull/60909#issuecomment-4987200706
and
https://github.com/ghostty-org/website/commit/d840266a668149495b41322d22f1f8d8f7747690

Release Notes:

- N/A
2026-07-16 07:51:58 +00:00
Jiby Jose 86751c2aad agent: Add GPT 5.6 Luna for ChatGPT subscription (#61083)
GPT 5.6 Luna now passes properly though the codex backend 

---

Release Notes:

- agent: Added GPT 5.6 Luna support for ChatGPT subscription
2026-07-16 07:43:30 +00:00
Apoorva VermaandNathan Sobo 1a246efd7e Fix auto-indent for braceless if/for/while in TypeScript (#60708)
type `if (true)`, hit enter, nothing indents. same for for/while.

12aa270 commented these out to stop allman braces over-indenting
(#24976). fixed that, broke this. put them back with an optional `@end`
on the `{}` body so braced blocks stop before the brace and braceless
ones indent. same in tsx.

Fixes #60371.

Release Notes:

- Fixed TypeScript and TSX not auto-indenting the body of a braceless
`if`, `for`, or `while`

---------

Co-authored-by: Nathan Sobo <nathan@zed.dev>
2026-07-15 23:29:16 +00:00
Shuhei KadowakiandDanilo Leal 367cd75963 workspace: Add visual indicator for editor zoom (#61039)
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>
2026-07-15 23:21:16 +00:00
Aliaksandr ZhyburtovichandNathan Sobo 9dfdaa62b7 editor: Preserve non-breaking whitespace during rewrap (#59893)
## Objective

Prevent rewrap from breaking at whitespace that Unicode classifies as
non-breaking.

The original approach, prompted by #59664, treated every non-ASCII
whitespace character as unbreakable. Unicode classifies `U+2009 THIN
SPACE` as breakable and `U+202F NARROW NO-BREAK SPACE` as its
non-breaking counterpart.

## Solution

- Treat `U+00A0 NO-BREAK SPACE`, `U+2007 FIGURE SPACE`, and `U+202F
NARROW NO-BREAK SPACE` as part of the surrounding word
- Keep thin spaces, em spaces, and other Unicode breaking spaces as
line-break opportunities
- Cover all three non-breaking whitespace variants in tokenizer and
wrapping tests

## Testing

- `cargo test -p editor rewrap::tests`

Release Notes:

- Fixed rewrap breaking lines at non-breaking spaces.

---------

Co-authored-by: Nathan Sobo <nathan@zed.dev>
2026-07-15 22:17:51 +00:00