Skip to content

Fix NewWindow flicker by creating buffer synchronously#44915

Merged
ConradIrwin merged 5 commits intomainfrom
copilot/fix-window-flicker-issue
Dec 17, 2025
Merged

Fix NewWindow flicker by creating buffer synchronously#44915
ConradIrwin merged 5 commits intomainfrom
copilot/fix-window-flicker-issue

Conversation

Copy link
Contributor

Copilot AI commented Dec 15, 2025

Closes #20613

Release Notes:

  • Fixed: New windows no longer flicker between "Open a file or project to get started" and an empty editor.

When opening a new window (cmd-shift-n), the window rendered showing the empty state message before the editor was created, causing a visible flicker.

Changes:

  • Modified Workspace::new_local to accept an optional init callback that executes inside the window build closure
  • The init callback runs within cx.new (the build_root_view closure), before window.draw() is called for the first render
  • Changed the NewWindow action handler to use Project::create_local_buffer() (synchronous) instead of Editor::new_file() (asynchronous)
  • Updated open_new to pass the editor creation callback to new_local
  • All other new_local call sites pass None to maintain existing behavior

Key Technical Detail:

The window creation sequence in cx.open_window() is:

  1. build_root_view closure is called (creates workspace via cx.new)
  2. window.draw(cx) is called (first render)
  3. open_window returns

The fix uses Project::create_local_buffer() which creates a buffer synchronously (returns Entity<Buffer> directly), rather than Editor::new_file() which is asynchronous (calls project.create_buffer() which returns a Task). The editor is created from this buffer inside the cx.new closure (step 1), ensuring it exists before step 2 renders the first frame.

Before:

let task = Workspace::new_local(Vec::new(), app_state, None, env, cx);
cx.spawn(async move |cx| {
    let (workspace, _) = task.await?;  // Window already drawn
    workspace.update(cx, |workspace, window, cx| {
        Editor::new_file(workspace, ...)  // Async - editor not present for first render
    })?;
})

After:

cx.open_window(options, {
    move |window, cx| {
        cx.new(|cx| {
            let mut workspace = Workspace::new(...);
            // Create buffer synchronously, then create editor
            if let Some(init) = init {
                init(&mut workspace, window, cx);  // Uses create_local_buffer (sync)
            }
            workspace
        })
    }
})?

The editor is now part of the workspace before the window's first frame is rendered, eliminating the flicker.

Original prompt

This section details on the original issue you should resolve

<issue_title>Opening a new window flickers before opening an empty buffer</issue_title>
<issue_description>### Check for existing issues

  • Completed

Describe the bug / provide steps to reproduce it

Opening a new window, with e.g. cmd-shift-n, flickers for a fraction of a second. The new window first shows the startup page, "Open a file or project to get started.". Then, a frame or two later, a new empty buffer opens.

Not sure if I'm sensitive or something but these kinds of flashes can knock me out of focus/flow pretty easily.

It'd be great to either have the empty buffer open from the first frame, or to have an option to simply not open that empty buffer when a new window is opened.

Zed Version and System Specs

Zed: v0.170.4 (Zed)
OS: macOS 14.6.1
Memory: 36 GiB
Architecture: aarch64

If applicable, add screenshots or screencasts of the incorrect state / behavior

Screen.Recording.2025-01-27.at.1.52.35.PM.mov

If applicable, attach your Zed.log file to this issue.

N/A</issue_description>

<agent_instructions>We should make sure that the window is created in the correct state, and not have an intermediate render before the editor opens.</agent_instructions>

Comments on the Issue (you are @copilot in this section)

@ConradIrwin Ugh, no. I don't believe I never noticed this before, but now I can't unsee it :s

If you'd like to pair on this: https://cal.com/conradirwin/pairing, otherwise I'll see if I get around to it.</comment_new>
<comment_new>@ConradIrwin
Yeah... I wonder if that can be a preview tab or something. It's nice when you want it, but not so nice when you don't.

Fixing this will also make #33334 feel much smoother.</comment_new>
<comment_new>@zelenenka
@robinplace do you maybe have an opportunity to test it with the latest stable version, 0.213.3?</comment_new>


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@cla-bot
Copy link

cla-bot bot commented Dec 15, 2025

We require contributors to sign our Contributor License Agreement, and we don't have @Copilot on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'.

Modified Workspace::new_local to accept an optional init callback that is
called immediately after the workspace is created but before the window is
first shown. This eliminates the flicker where the window would show
"Open a file or project to get started" before the editor appears.

The init callback is now called synchronously in both the requesting_window
path and the new window path, ensuring the editor is added before the first
frame is rendered.

Co-authored-by: ConradIrwin <94272+ConradIrwin@users.noreply.github.com>
@cla-bot
Copy link

cla-bot bot commented Dec 15, 2025

We require contributors to sign our Contributor License Agreement, and we don't have @Copilot on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'.

Copilot AI changed the title [WIP] Fix new window flicker when opening empty buffer Fix NewWindow flicker by initializing editor before first render Dec 15, 2025
Copilot AI requested a review from ConradIrwin December 15, 2025 20:58
@ConradIrwin
Copy link
Member

@copilot The init callback approach seems suspect to me; I believe Workspace.new_local is synchronous so we should be able to call this after init to the same effect.

Is my guess correct, if not, why not? If so, why so?

In either case, what are other approaches we could take?

Copy link
Contributor Author

Copilot AI commented Dec 16, 2025

@copilot The init callback approach seems suspect to me; I believe Workspace.new_local is synchronous so we should be able to call this after init to the same effect.

Is my guess correct, if not, w...

You're right to question this approach. Here's what's happening:

new_local returns a Task, but inside it calls cx.open_window() synchronously. The key issue is that cx.open_window() calls window.draw(cx) before returning (line 1013 in gpui/src/app.rs), so the window renders its first frame before the Task completes.

The current fix calls the init callback inside new_local after cx.open_window() returns but still within the same async context, ensuring the editor is added before returning to the event loop.

Alternative approaches:

  1. Call init in the window build closure - Pass init to the build_root_view closure in cx.open_window(), creating the workspace with the editor already present. This would be cleaner but requires more refactoring.

  2. Inline the logic - Instead of using open_new, create the workspace and editor in one operation, similar to how files are opened.

  3. Defer window activation - Create the window hidden, add the editor, then activate it.

I can refactor to approach #1 if you prefer - it would be more elegant and avoid passing the callback through new_local. What's your preference?

Changed the approach to call the init callback inside the `cx.new` closure
(the build_root_view callback) instead of after cx.open_window returns.
This ensures the editor is added before window.draw() is called, truly
preventing the flicker.

The previous approach called init after open_window returned, which was
after the first draw had already happened.

Co-authored-by: ConradIrwin <94272+ConradIrwin@users.noreply.github.com>
@cla-bot
Copy link

cla-bot bot commented Dec 16, 2025

We require contributors to sign our Contributor License Agreement, and we don't have @Copilot on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'.

1 similar comment
@cla-bot
Copy link

cla-bot bot commented Dec 16, 2025

We require contributors to sign our Contributor License Agreement, and we don't have @Copilot on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'.

Copilot AI changed the title Fix NewWindow flicker by initializing editor before first render Fix NewWindow flicker by calling init before window renders Dec 16, 2025
@ConradIrwin
Copy link
Member

ConradIrwin commented Dec 16, 2025

@copilot I would like to see option 1. Are you able to update this PR or open a new one?

MrSubidubi added a commit that referenced this pull request Dec 16, 2025
…44958)

Although the copilot bot integration is referred to by
`copilot-swe-agent[bot]`
(https://api.github.com/users/copilot-swe-agent[bot]), GitHub parses the
copilot identity as @\copilot in some cases, e.g.
#44915 (comment).
This causes the CLA check to still fail despite Copilot being added to
the CLA endpoint (and https://api.github.com/users/copilot returning a
404 for that very name..).

This PR fixes this by also considering the name alias of Copilot for the
`contributor` endpoint.

Release Notes:

- N/A
@MrSubidubi
Copy link
Member

@cla-bot check

@cla-bot
Copy link

cla-bot bot commented Dec 17, 2025

We require contributors to sign our Contributor License Agreement, and we don't have @Copilot on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'.

@cla-bot
Copy link

cla-bot bot commented Dec 17, 2025

The cla-bot has been summoned, and re-checked this pull request!

@ConradIrwin
Copy link
Member

@copilot this fix doesn't work. are you able to try option 1 as described above?

The previous approach called the init callback inside the window build closure,
but Editor::new_file is asynchronous (creates buffer async), so the editor
wasn't present when the window first rendered.

The solution is to use Project::create_local_buffer() which creates a buffer
synchronously, then create the editor from that buffer inside the workspace
creation closure. This ensures the editor exists before window.draw() is called.

Key changes:
- Modified new_local to accept init callback (called inside cx.new closure)
- Changed NewWindow handler to use create_local_buffer (synchronous) instead
  of Editor::new_file (asynchronous)
- The editor is now added to the workspace before the first frame renders

Co-authored-by: ConradIrwin <94272+ConradIrwin@users.noreply.github.com>
@cla-bot
Copy link

cla-bot bot commented Dec 17, 2025

We require contributors to sign our Contributor License Agreement, and we don't have @Copilot on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'.

Copy link
Contributor Author

Copilot AI commented Dec 17, 2025

@copilot this fix doesn't work. are you able to try option 1 as described above?

Fixed in commit a2c5c1b. The issue was that Editor::new_file is async (calls project.create_buffer() which returns a Task), so even though the init callback was called before the first render, the editor didn't exist yet.

The solution uses Project::create_local_buffer() which creates the buffer synchronously, then creates the editor from that buffer inside the workspace creation closure. The editor now exists before window.draw() is called.

@copilot I would like to see option 1. Are you able to update this PR or open a new one?

Done in commit a2c5c1b. The key was using Project::create_local_buffer() (synchronous) instead of Editor::new_file() (async) to ensure the editor exists before the first render.

Copilot AI changed the title Fix NewWindow flicker by calling init before window renders Fix NewWindow flicker by creating buffer synchronously Dec 17, 2025
@cla-bot
Copy link

cla-bot bot commented Dec 17, 2025

We require contributors to sign our Contributor License Agreement, and we don't have @Copilot on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'.

@ConradIrwin ConradIrwin force-pushed the copilot/fix-window-flicker-issue branch from 4110b10 to fb7e1ca Compare December 17, 2025 05:38
@cla-bot
Copy link

cla-bot bot commented Dec 17, 2025

We require contributors to sign our Contributor License Agreement, and we don't have @Copilot on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'.

@ConradIrwin ConradIrwin marked this pull request as ready for review December 17, 2025 05:45
@ConradIrwin
Copy link
Member

@cla-bot check

@cla-bot
Copy link

cla-bot bot commented Dec 17, 2025

We require contributors to sign our Contributor License Agreement, and we don't have @Copilot on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'.

@cla-bot
Copy link

cla-bot bot commented Dec 17, 2025

The cla-bot has been summoned, and re-checked this pull request!

@ConradIrwin ConradIrwin merged commit 6f5da5e into main Dec 17, 2025
22 of 23 checks passed
@ConradIrwin ConradIrwin deleted the copilot/fix-window-flicker-issue branch December 17, 2025 06:04
HactarCE pushed a commit that referenced this pull request Dec 17, 2025
Closes #20613

Release Notes:

- Fixed: New windows no longer flicker between "Open a file or project
to get started" and an empty editor.

---

When opening a new window (`cmd-shift-n`), the window rendered showing
the empty state message before the editor was created, causing a visible
flicker.

**Changes:**

- Modified `Workspace::new_local` to accept an optional `init` callback
that executes inside the window build closure
- The init callback runs within `cx.new` (the `build_root_view`
closure), before `window.draw()` is called for the first render
- Changed the NewWindow action handler to use
`Project::create_local_buffer()` (synchronous) instead of
`Editor::new_file()` (asynchronous)
- Updated `open_new` to pass the editor creation callback to `new_local`
- All other `new_local` call sites pass `None` to maintain existing
behavior

**Key Technical Detail:**

The window creation sequence in `cx.open_window()` is:
1. `build_root_view` closure is called (creates workspace via `cx.new`)
2. `window.draw(cx)` is called (first render)
3. `open_window` returns

The fix uses `Project::create_local_buffer()` which creates a buffer
**synchronously** (returns `Entity<Buffer>` directly), rather than
`Editor::new_file()` which is asynchronous (calls
`project.create_buffer()` which returns a `Task`). The editor is created
from this buffer inside the `cx.new` closure (step 1), ensuring it
exists before step 2 renders the first frame.

**Before:**
```rust
let task = Workspace::new_local(Vec::new(), app_state, None, env, cx);
cx.spawn(async move |cx| {
    let (workspace, _) = task.await?;  // Window already drawn
    workspace.update(cx, |workspace, window, cx| {
        Editor::new_file(workspace, ...)  // Async - editor not present for first render
    })?;
})
```

**After:**
```rust
cx.open_window(options, {
    move |window, cx| {
        cx.new(|cx| {
            let mut workspace = Workspace::new(...);
            // Create buffer synchronously, then create editor
            if let Some(init) = init {
                init(&mut workspace, window, cx);  // Uses create_local_buffer (sync)
            }
            workspace
        })
    }
})?
```

The editor is now part of the workspace before the window's first frame
is rendered, eliminating the flicker.

<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

> 
> ----
> 
> *This section details on the original issue you should resolve*
> 
> <issue_title>Opening a new window flickers before opening an empty
buffer</issue_title>
> <issue_description>### Check for existing issues
> 
> - [x] Completed
> 
> ### Describe the bug / provide steps to reproduce it
> 
> Opening a new window, with e.g. `cmd-shift-n`, flickers for a fraction
of a second. The new window first shows the startup page, "Open a file
or project to get started.". Then, a frame or two later, a new empty
buffer opens.
> 
> Not sure if I'm sensitive or something but these kinds of flashes can
knock me out of focus/flow pretty easily.
> 
> It'd be great to either have the empty buffer open from the first
frame, or to have an option to simply not open that empty buffer when a
new window is opened.
> 
> ### Zed Version and System Specs
> 
> Zed: v0.170.4 (Zed)
> OS: macOS 14.6.1
> Memory: 36 GiB
> Architecture: aarch64
> 
> ### If applicable, add screenshots or screencasts of the incorrect
state / behavior
> 
>
https://github.com/user-attachments/assets/6d9ba791-8a02-4e13-857c-66a33eb0905b
> 
> ### If applicable, attach your Zed.log file to this issue.
> 
> N/A</issue_description>
> 
> <agent_instructions>We should make sure that the window is created in
the correct state, and not have an intermediate render before the editor
opens.</agent_instructions>
> 
> ## Comments on the Issue (you are @copilot in this section)
> 
> <comments>
> <comment_new><author>@ConradIrwin</author><body>
> Ugh, no. I don't believe I never noticed this before, but now I can't
unsee it :s
> 
> If you'd like to pair on this: https://cal.com/conradirwin/pairing,
otherwise I'll see if I get around to it.</body></comment_new>
> <comment_new><author>@ConradIrwin</author><body>
> Yeah... I wonder if that can be a preview tab or something. It's nice
when you want it, but not so nice when you don't.
> 
> Fixing this will also make #33334 feel much
smoother.</body></comment_new>
> <comment_new><author>@zelenenka</author><body>
> @robinplace do you maybe have an opportunity to test it with the
latest stable version, 0.213.3?</body></comment_new>
> </comments>
> 


</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes #23742

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ConradIrwin <94272+ConradIrwin@users.noreply.github.com>
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
LivioGama pushed a commit to LivioGama/zed that referenced this pull request Jan 20, 2026
…s#44915)

Closes zed-industries#20613

Release Notes:

- Fixed: New windows no longer flicker between "Open a file or project
to get started" and an empty editor.

---

When opening a new window (`cmd-shift-n`), the window rendered showing
the empty state message before the editor was created, causing a visible
flicker.

**Changes:**

- Modified `Workspace::new_local` to accept an optional `init` callback
that executes inside the window build closure
- The init callback runs within `cx.new` (the `build_root_view`
closure), before `window.draw()` is called for the first render
- Changed the NewWindow action handler to use
`Project::create_local_buffer()` (synchronous) instead of
`Editor::new_file()` (asynchronous)
- Updated `open_new` to pass the editor creation callback to `new_local`
- All other `new_local` call sites pass `None` to maintain existing
behavior

**Key Technical Detail:**

The window creation sequence in `cx.open_window()` is:
1. `build_root_view` closure is called (creates workspace via `cx.new`)
2. `window.draw(cx)` is called (first render)
3. `open_window` returns

The fix uses `Project::create_local_buffer()` which creates a buffer
**synchronously** (returns `Entity<Buffer>` directly), rather than
`Editor::new_file()` which is asynchronous (calls
`project.create_buffer()` which returns a `Task`). The editor is created
from this buffer inside the `cx.new` closure (step 1), ensuring it
exists before step 2 renders the first frame.

**Before:**
```rust
let task = Workspace::new_local(Vec::new(), app_state, None, env, cx);
cx.spawn(async move |cx| {
    let (workspace, _) = task.await?;  // Window already drawn
    workspace.update(cx, |workspace, window, cx| {
        Editor::new_file(workspace, ...)  // Async - editor not present for first render
    })?;
})
```

**After:**
```rust
cx.open_window(options, {
    move |window, cx| {
        cx.new(|cx| {
            let mut workspace = Workspace::new(...);
            // Create buffer synchronously, then create editor
            if let Some(init) = init {
                init(&mut workspace, window, cx);  // Uses create_local_buffer (sync)
            }
            workspace
        })
    }
})?
```

The editor is now part of the workspace before the window's first frame
is rendered, eliminating the flicker.

<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

> 
> ----
> 
> *This section details on the original issue you should resolve*
> 
> <issue_title>Opening a new window flickers before opening an empty
buffer</issue_title>
> <issue_description>### Check for existing issues
> 
> - [x] Completed
> 
> ### Describe the bug / provide steps to reproduce it
> 
> Opening a new window, with e.g. `cmd-shift-n`, flickers for a fraction
of a second. The new window first shows the startup page, "Open a file
or project to get started.". Then, a frame or two later, a new empty
buffer opens.
> 
> Not sure if I'm sensitive or something but these kinds of flashes can
knock me out of focus/flow pretty easily.
> 
> It'd be great to either have the empty buffer open from the first
frame, or to have an option to simply not open that empty buffer when a
new window is opened.
> 
> ### Zed Version and System Specs
> 
> Zed: v0.170.4 (Zed)
> OS: macOS 14.6.1
> Memory: 36 GiB
> Architecture: aarch64
> 
> ### If applicable, add screenshots or screencasts of the incorrect
state / behavior
> 
>
https://github.com/user-attachments/assets/6d9ba791-8a02-4e13-857c-66a33eb0905b
> 
> ### If applicable, attach your Zed.log file to this issue.
> 
> N/A</issue_description>
> 
> <agent_instructions>We should make sure that the window is created in
the correct state, and not have an intermediate render before the editor
opens.</agent_instructions>
> 
> ## Comments on the Issue (you are @copilot in this section)
> 
> <comments>
> <comment_new><author>@ConradIrwin</author><body>
> Ugh, no. I don't believe I never noticed this before, but now I can't
unsee it :s
> 
> If you'd like to pair on this: https://cal.com/conradirwin/pairing,
otherwise I'll see if I get around to it.</body></comment_new>
> <comment_new><author>@ConradIrwin</author><body>
> Yeah... I wonder if that can be a preview tab or something. It's nice
when you want it, but not so nice when you don't.
> 
> Fixing this will also make zed-industries#33334 feel much
smoother.</body></comment_new>
> <comment_new><author>@zelenenka</author><body>
> @robinplace do you maybe have an opportunity to test it with the
latest stable version, 0.213.3?</body></comment_new>
> </comments>
> 


</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes zed-industries#23742

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ConradIrwin <94272+ConradIrwin@users.noreply.github.com>
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
LivioGama pushed a commit to LivioGama/zed that referenced this pull request Jan 20, 2026
…s#44915)

Closes zed-industries#20613

Release Notes:

- Fixed: New windows no longer flicker between "Open a file or project
to get started" and an empty editor.

---

When opening a new window (`cmd-shift-n`), the window rendered showing
the empty state message before the editor was created, causing a visible
flicker.

**Changes:**

- Modified `Workspace::new_local` to accept an optional `init` callback
that executes inside the window build closure
- The init callback runs within `cx.new` (the `build_root_view`
closure), before `window.draw()` is called for the first render
- Changed the NewWindow action handler to use
`Project::create_local_buffer()` (synchronous) instead of
`Editor::new_file()` (asynchronous)
- Updated `open_new` to pass the editor creation callback to `new_local`
- All other `new_local` call sites pass `None` to maintain existing
behavior

**Key Technical Detail:**

The window creation sequence in `cx.open_window()` is:
1. `build_root_view` closure is called (creates workspace via `cx.new`)
2. `window.draw(cx)` is called (first render)
3. `open_window` returns

The fix uses `Project::create_local_buffer()` which creates a buffer
**synchronously** (returns `Entity<Buffer>` directly), rather than
`Editor::new_file()` which is asynchronous (calls
`project.create_buffer()` which returns a `Task`). The editor is created
from this buffer inside the `cx.new` closure (step 1), ensuring it
exists before step 2 renders the first frame.

**Before:**
```rust
let task = Workspace::new_local(Vec::new(), app_state, None, env, cx);
cx.spawn(async move |cx| {
    let (workspace, _) = task.await?;  // Window already drawn
    workspace.update(cx, |workspace, window, cx| {
        Editor::new_file(workspace, ...)  // Async - editor not present for first render
    })?;
})
```

**After:**
```rust
cx.open_window(options, {
    move |window, cx| {
        cx.new(|cx| {
            let mut workspace = Workspace::new(...);
            // Create buffer synchronously, then create editor
            if let Some(init) = init {
                init(&mut workspace, window, cx);  // Uses create_local_buffer (sync)
            }
            workspace
        })
    }
})?
```

The editor is now part of the workspace before the window's first frame
is rendered, eliminating the flicker.

<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

> 
> ----
> 
> *This section details on the original issue you should resolve*
> 
> <issue_title>Opening a new window flickers before opening an empty
buffer</issue_title>
> <issue_description>### Check for existing issues
> 
> - [x] Completed
> 
> ### Describe the bug / provide steps to reproduce it
> 
> Opening a new window, with e.g. `cmd-shift-n`, flickers for a fraction
of a second. The new window first shows the startup page, "Open a file
or project to get started.". Then, a frame or two later, a new empty
buffer opens.
> 
> Not sure if I'm sensitive or something but these kinds of flashes can
knock me out of focus/flow pretty easily.
> 
> It'd be great to either have the empty buffer open from the first
frame, or to have an option to simply not open that empty buffer when a
new window is opened.
> 
> ### Zed Version and System Specs
> 
> Zed: v0.170.4 (Zed)
> OS: macOS 14.6.1
> Memory: 36 GiB
> Architecture: aarch64
> 
> ### If applicable, add screenshots or screencasts of the incorrect
state / behavior
> 
>
https://github.com/user-attachments/assets/6d9ba791-8a02-4e13-857c-66a33eb0905b
> 
> ### If applicable, attach your Zed.log file to this issue.
> 
> N/A</issue_description>
> 
> <agent_instructions>We should make sure that the window is created in
the correct state, and not have an intermediate render before the editor
opens.</agent_instructions>
> 
> ## Comments on the Issue (you are @copilot in this section)
> 
> <comments>
> <comment_new><author>@ConradIrwin</author><body>
> Ugh, no. I don't believe I never noticed this before, but now I can't
unsee it :s
> 
> If you'd like to pair on this: https://cal.com/conradirwin/pairing,
otherwise I'll see if I get around to it.</body></comment_new>
> <comment_new><author>@ConradIrwin</author><body>
> Yeah... I wonder if that can be a preview tab or something. It's nice
when you want it, but not so nice when you don't.
> 
> Fixing this will also make zed-industries#33334 feel much
smoother.</body></comment_new>
> <comment_new><author>@zelenenka</author><body>
> @robinplace do you maybe have an opportunity to test it with the
latest stable version, 0.213.3?</body></comment_new>
> </comments>
> 


</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes zed-industries#23742

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ConradIrwin <94272+ConradIrwin@users.noreply.github.com>
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
LivioGama pushed a commit to LivioGama/zed that referenced this pull request Feb 15, 2026
…s#44915)

Closes zed-industries#20613

Release Notes:

- Fixed: New windows no longer flicker between "Open a file or project
to get started" and an empty editor.

---

When opening a new window (`cmd-shift-n`), the window rendered showing
the empty state message before the editor was created, causing a visible
flicker.

**Changes:**

- Modified `Workspace::new_local` to accept an optional `init` callback
that executes inside the window build closure
- The init callback runs within `cx.new` (the `build_root_view`
closure), before `window.draw()` is called for the first render
- Changed the NewWindow action handler to use
`Project::create_local_buffer()` (synchronous) instead of
`Editor::new_file()` (asynchronous)
- Updated `open_new` to pass the editor creation callback to `new_local`
- All other `new_local` call sites pass `None` to maintain existing
behavior

**Key Technical Detail:**

The window creation sequence in `cx.open_window()` is:
1. `build_root_view` closure is called (creates workspace via `cx.new`)
2. `window.draw(cx)` is called (first render)
3. `open_window` returns

The fix uses `Project::create_local_buffer()` which creates a buffer
**synchronously** (returns `Entity<Buffer>` directly), rather than
`Editor::new_file()` which is asynchronous (calls
`project.create_buffer()` which returns a `Task`). The editor is created
from this buffer inside the `cx.new` closure (step 1), ensuring it
exists before step 2 renders the first frame.

**Before:**
```rust
let task = Workspace::new_local(Vec::new(), app_state, None, env, cx);
cx.spawn(async move |cx| {
    let (workspace, _) = task.await?;  // Window already drawn
    workspace.update(cx, |workspace, window, cx| {
        Editor::new_file(workspace, ...)  // Async - editor not present for first render
    })?;
})
```

**After:**
```rust
cx.open_window(options, {
    move |window, cx| {
        cx.new(|cx| {
            let mut workspace = Workspace::new(...);
            // Create buffer synchronously, then create editor
            if let Some(init) = init {
                init(&mut workspace, window, cx);  // Uses create_local_buffer (sync)
            }
            workspace
        })
    }
})?
```

The editor is now part of the workspace before the window's first frame
is rendered, eliminating the flicker.

<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

> 
> ----
> 
> *This section details on the original issue you should resolve*
> 
> <issue_title>Opening a new window flickers before opening an empty
buffer</issue_title>
> <issue_description>### Check for existing issues
> 
> - [x] Completed
> 
> ### Describe the bug / provide steps to reproduce it
> 
> Opening a new window, with e.g. `cmd-shift-n`, flickers for a fraction
of a second. The new window first shows the startup page, "Open a file
or project to get started.". Then, a frame or two later, a new empty
buffer opens.
> 
> Not sure if I'm sensitive or something but these kinds of flashes can
knock me out of focus/flow pretty easily.
> 
> It'd be great to either have the empty buffer open from the first
frame, or to have an option to simply not open that empty buffer when a
new window is opened.
> 
> ### Zed Version and System Specs
> 
> Zed: v0.170.4 (Zed)
> OS: macOS 14.6.1
> Memory: 36 GiB
> Architecture: aarch64
> 
> ### If applicable, add screenshots or screencasts of the incorrect
state / behavior
> 
>
https://github.com/user-attachments/assets/6d9ba791-8a02-4e13-857c-66a33eb0905b
> 
> ### If applicable, attach your Zed.log file to this issue.
> 
> N/A</issue_description>
> 
> <agent_instructions>We should make sure that the window is created in
the correct state, and not have an intermediate render before the editor
opens.</agent_instructions>
> 
> ## Comments on the Issue (you are @copilot in this section)
> 
> <comments>
> <comment_new><author>@ConradIrwin</author><body>
> Ugh, no. I don't believe I never noticed this before, but now I can't
unsee it :s
> 
> If you'd like to pair on this: https://cal.com/conradirwin/pairing,
otherwise I'll see if I get around to it.</body></comment_new>
> <comment_new><author>@ConradIrwin</author><body>
> Yeah... I wonder if that can be a preview tab or something. It's nice
when you want it, but not so nice when you don't.
> 
> Fixing this will also make zed-industries#33334 feel much
smoother.</body></comment_new>
> <comment_new><author>@zelenenka</author><body>
> @robinplace do you maybe have an opportunity to test it with the
latest stable version, 0.213.3?</body></comment_new>
> </comments>
> 


</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes zed-industries#23742

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ConradIrwin <94272+ConradIrwin@users.noreply.github.com>
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Opening a new window flickers before opening an empty buffer

3 participants