Skip to content

agent_ui: Fix agent panel stealing focus from modals on workspace restore#49630

Closed
Dnreikronos wants to merge 5 commits intozed-industries:mainfrom
Dnreikronos:fix/agent-panel-focus-stealing-from-modals
Closed

agent_ui: Fix agent panel stealing focus from modals on workspace restore#49630
Dnreikronos wants to merge 5 commits intozed-industries:mainfrom
Dnreikronos:fix/agent-panel-focus-stealing-from-modals

Conversation

@Dnreikronos
Copy link
Copy Markdown
Contributor

@Dnreikronos Dnreikronos commented Feb 19, 2026

When opening a modal (e.g. "Open Recent" via cmd-alt-o) with no active
window, the AgentPanel async thread restoration would call
set_active_view with focus: true, stealing keyboard focus from the
modal. This is a regression of #43180, where the focus guard was lost
during subsequent refactoring.

Thread a focus parameter through external_thread and _external_thread
so that AgentPanel::load() passes false during startup restoration,
while all user-initiated actions continue to pass true.

Closes #49336

Release Notes:

  • N/A

@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Feb 19, 2026
@Dnreikronos
Copy link
Copy Markdown
Contributor Author

Dnreikronos commented Feb 19, 2026

Motivation

Issue #49336 reported a focus-stealing regression on macOS. When a user had no active
window and opened the "Open Recent" modal via Cmd-Alt-O, the modal would appear but
keyboard focus was immediately stolen by the Agent Panel's background thread restoration.
This meant the user couldn't type to filter the recent projects list without first clicking
the window.

This was a regression of a previously fixed behavior (originally fixed in #43451 /
#43180). During subsequent refactoring of the Agent Panel, the focus guard that prevented
this was inadvertently lost.

Root cause: During workspace restoration, AgentPanel::load() would asynchronously
restore agent threads by calling set_active_view with focus: true. This unconditionally
grabbed keyboard focus, ripping it away from whatever modal or UI element the user was
actively interacting with.

What the PR Changes

The fix is surgical and contained entirely in crates/agent_ui/src/agent_panel.rs (+29 / -13
lines):

  1. Threads a focus: bool parameter through external_thread() and
    _external_thread(), propagating it down to the set_active_view() call.
  2. Startup restoration passes focus: false — when AgentPanel::load() restores a
    previously active thread on workspace open, it now calls load_agent_thread_inner(..., false, ...), so no focus stealing occurs.
  3. All user-initiated actions pass focus: true — creating a new thread, switching
    agents, loading a thread from history, etc. all explicitly pass true, preserving the
    existing behavior where the panel correctly takes focus when the user actively interacts with
    it.
  4. Introduces a load_agent_thread_inner() helper that wraps the focus parameter, keeping
    the public load_agent_thread() API unchanged (it defaults to focus: true).

Impact

  • User-facing: Modals (Open Recent, file picker, etc.) will no longer lose keyboard focus
    when the Agent Panel restores threads in the background during workspace startup.
  • Scope: The change is narrowly scoped to a single file with no architectural changes —
    it's a classic "thread a parameter to the right place" fix.
  • Risk: Low. All existing user-initiated code paths explicitly pass true, so behavior
    is unchanged except for the one restoration path that now correctly passes false.

@Dnreikronos
Copy link
Copy Markdown
Contributor Author

I'm looking for that erros on the tests now

…tore

When opening a modal (e.g. "Open Recent" via cmd-alt-o) with no active
   window, the AgentPanel async thread restoration would call
   set_active_view with focus: true, stealing keyboard focus from the
   modal. This is a regression of zed-industries#43180, where the focus guard was lost
   during subsequent refactoring.

   Thread a focus parameter through external_thread and _external_thread
   so that AgentPanel::load() passes false during startup restoration,
   while all user-initiated actions continue to pass true.

Closes zed-industries#49336
@Dnreikronos Dnreikronos force-pushed the fix/agent-panel-focus-stealing-from-modals branch from 3ea988d to 0b54d93 Compare February 24, 2026 11:59
@Dnreikronos
Copy link
Copy Markdown
Contributor Author

Hi, @SomeoneToIgnore, good morning!

I adjusted all the errors that was happening on the CI pipeline. If you could take a look and analyze everything, I will appreciate it

Copy link
Copy Markdown
Contributor

@SomeoneToIgnore SomeoneToIgnore left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix does not seem to work for me, when I try this?

Here's the video of what I do: start Zed off the current commit, then close the window with cmd-shift-w, then invoke the cmd-alt-o as requested in the issue.
I have failed to get anything useful out of this state, the focus is not on the modal:

broken_still.mov

@Dnreikronos
Copy link
Copy Markdown
Contributor Author

Dnreikronos commented Feb 26, 2026

The fix does not seem to work for me, when I try this?

Here's the video of what I do: start Zed off the current commit, then close the window with cmd-shift-w, then invoke the cmd-alt-o as requested in the issue. I have failed to get anything useful out of this state, the focus is not on the modal:

broken_still.mov

Hmmm, that's strange!
I will validate that again.

Dnreikronos and others added 2 commits February 26, 2026 13:38
The previous fix only addressed the 'load' path (restoring a saved
thread), but missed the 'set_active' path where dock restoration
activates the panel and creates a new thread with focus: true.
@Dnreikronos
Copy link
Copy Markdown
Contributor Author

Could you test again, @SomeoneToIgnore, please?

I'm testing this on Arch Linux, so the flow is slightly different. I open the built binary with ./target/debug/zed, close it with Ctrl+W (which closes Zed entirely, unlike on macOS where the app stays open), relaunch the binary, and then press Alt+Ctrl+O, and it works correctly.

@Dnreikronos
Copy link
Copy Markdown
Contributor Author

Could you test again, @SomeoneToIgnore, please?

I'm testing this on Arch Linux, so the flow is slightly different. I open the built binary with ./target/debug/zed, close it with Ctrl+W (which closes Zed entirely, unlike on macOS where the app stays open), relaunch the binary, and then press Alt+Ctrl+O, and it works correctly.

That box has to be in focus:

image

So you have to be abble to type there

@SomeoneToIgnore
Copy link
Copy Markdown
Contributor

Now I cannot build it at all...

@Dnreikronos
Copy link
Copy Markdown
Contributor Author

Now I cannot build it at all...

The branch merged main which included commit f900340 that removed hardcoded Gemini variants from the AgentType and ExternalAgent enums (replacing them with the generic Custom { name }
pattern). However, a match arm in agent_panel.rs still referenced AgentType::Gemini and ExternalAgent::Gemini, causing a compilation failure across all CI checks. The fix was removing that
stale match arm.

@SomeoneToIgnore, thanks for the patience.

@SomeoneToIgnore
Copy link
Copy Markdown
Contributor

I've tested it another time with the same result — given the steps in #49336 , we do have to test the fix on macOS (or other OS with a patch that enables a similar behavior which does not quit the app after last window is closed).

The steps from #49630 (comment) are not from mac, ergo do not capture the issue good enough.

I think we can close the PR meanwhile, given the circumstances, but let me know if you're up to another try before.

@Dnreikronos
Copy link
Copy Markdown
Contributor Author

nother time with the same result — given the steps in #49336 , we do have to test the fix on macOS (or other OS with a patch that enables a similar behavior which does not quit the app after last window is closed).

I've tested it another time with the same result — given the steps in #49336 , we do have to test the fix on macOS (or other OS with a patch that enables a similar behavior which does not quit the app after last window is closed).

The steps from #49630 (comment) are not from mac, ergo do not capture the issue good enough.

I think we can close the PR meanwhile, given the circumstances, but let me know if you're up to another try before.

I'll give it another try.
I think I've found the code that controls when Zed closes on Linux.

@Dnreikronos
Copy link
Copy Markdown
Contributor Author

Last chance now, @SomeoneToIgnore.
I think I could managed the same pattern of MacOS

@SomeoneToIgnore
Copy link
Copy Markdown
Contributor

SomeoneToIgnore commented Feb 27, 2026

That's a huge breakthrough and things start to work!

Yet, the next logical thing is to go test all agent interactions that were just altered: and there, it seems that we now can get into state where agent panel is not focused despite being just shown with cmd-shift-/.

My sequence of actions to reproduce this:

  • empty Zed, no panels open
  • close it with cmd-shift-w
  • cmd-alt-o to reopen (gets the focus now, neat!)
  • ESC to hide the modal
  • cmd-shift-/ to open the agent panel

Expected: can type into an agent.
Actual: nothing is focused despite the obvious need.

Notice that consequent cmd-shift-/ calls will focus the input after the first fluke.
I've tried to capture this on a video:

agent_focus_broken.mov

Overall, I feel 0 interest to do constant, repeated, work to test after each submission, this is counter-productive, so I'll close the PR after all.

If you feel like fixing and testing things thoroughly more later, I can review and re-test again on another PR opened.

@Dnreikronos
Copy link
Copy Markdown
Contributor Author

That's a huge breakthrough and things start to work!

Yet, the next logical thing is to go test all agent interactions that were just altered: and there, it seems that we now can get into state where agent panel is not focused despite being just shown with cmd-shift-/.

My sequence of actions to reproduce this:

  • empty Zed, no panels open
  • close it with cmd-shift-w
  • cmd-alt-o to reopen (gets the focus now, neat!)
  • ESC to hide the modal
  • cmd-shift-/ to open the agent panel

Expected: can type into an agent. Actual: nothing is focused despite the obvious need.

Notice that consequent cmd-shift-/ calls will focus the input after the first fluke. I've tried to capture this on a video:

agent_focus_broken.mov
Overall, I feel 0 interest to do constant, repeated, work to test after each submission, this is counter-productive, so I'll close the PR after all.

If you feel like fixing and testing things thoroughly more later, I can review and re-test again on another PR opened.

Thanks for your time invested, @SomeoneToIgnore.
I will adjust the functionallity following the sequence that you said and test it everything local before send a new PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed The user has signed the Contributor License Agreement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Open recent projects (cmd-alt-o) with no active window does not focus

2 participants