-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
windows: Fix regression introduced by a previous PR #18578
Conversation
zed/crates/gpui/src/platform/windows/window.rs Lines 542 to 550 in 68d6177
Maybe the problem is this:
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setactivewindow#remarks It seems that we need to add a line to this function: unsafe { ShowWindow(hwnd, SW_SHOW).ok().log_err() }; But the Window still not show in the front. |
@huacnlee The issue is much more complicated than that, please see my new comment. |
This bug itself is relatively straightforward to fix, but the associated quality-of-life issues it brings are a bit trickier to address. Here are the approaches I’ve tried for resolving it: Approach 1: Add Approach 2: Use winit’s method of setting additional Approach 3: Use I’ve also experimented with other approaches, but they all seem to run into animation-related issues. From the tests I performed, it seems that the window-opening animation can only be triggered by the initial Given that Zed currently creates windows in a hidden state and then makes them visible by calling
Alternatively, a simpler solution would be to set |
I think moving the boolean into the window params is our preferred solution. If windows needs it to feel right, then that’s what we’ll do :) |
I have tried different ways, but still can't find a suitable solution. It seems that the trouble is that when CreateWindow is called, it cannot be hidden from the beginning. I also tried to remove WS_VISIBLE from the CreateWindow parameter, but it didn't work. |
My Mac is currently at school, and I’m in my dorm, so I’m unable to test these changes on macOS. I’m not sure if the current modifications will have any impact on macOS. Should I use #[cfg(windows)]
show: true,
#[cfg(not(windows))]
show: false, Let me know your thoughts @mikayla-maki |
Yes, if we do want to keep the current |
I did a bit of a review of the code for what this code would change, and it seems like it would cause our window opening to have a lot more pop-in. See https://github.com/zed-industries/zed/blob/main/crates/workspace/src/workspace.rs#L1192-L1223, for how we create the window, then deserialize the state, then activate the window. Given this issue, I think I'd actually prefer switching to option #2 of the ones you've given @JunkuiZhang. That said, could we fake this in GPUI and get the best of all worlds? Essentially, don't create the underlying windows-window until the first 'activate' call, so that we get the proper animation and also don't have issues with workspace code that relies on a Let me know what y'all think. Going with the winit style solution is probably the right choice :D |
This is exactly my concern here, that is the possibility of unintended side effects here if we directly change
In fact, this approach doesn't work as expected. As I mentioned before, using this method causes the window's opening animation to disappear, meaning the window just appears abruptly, which I find quite undesirable. Allow me to explain method #2 in more detail: Under PR #18161, the process for creating an invisible window in Zed is as follows:
While fixing this issue, I noticed that winit creates an invisible window with the following process:
In Zed’s case, the window creation flow is:
Under method #2, to fix this issue, when calling
However, this causes the issue I mentioned earlier—the window’s opening animation disappears.
If we proceed with this approach, it might turn out to be a dead end:
As you can see, this solution introduces some conflicts. For both Case 2 and Case 3, the window creation parameter is Thus, we need to differentiate between these two cases. However, if we make this distinction, there may actually be a simpler solution, as explained below.
After extensive testing, I think the following solutions are feasible:
At present, the latest commit (a8f5e87) in this PR implements the first solution. The next step will be to implement the second approach. |
In the latest changes, I introduced a |
@@ -295,7 +295,7 @@ impl WindowsWindow { | |||
WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX, | |||
) | |||
}; | |||
if !params.show { | |||
if params.display_state == WindowDisplayState::Hidden { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than add this additional optional, could we just remove this minimized state entirely? I'd prefer to keep the two options, Hidden
and Visible
or true
and false
, as this third option doesn't feel quite right yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than add this additional optional, could we just remove this minimized state entirely?
The minimized state here is quite necessary; otherwise, when creating an invisible window, there will be a brief window flash, as shown in the video below.
Screen.Recording.2024-10-03.102803.mp4
I'd prefer to keep the two options,
Hidden
andVisible
ortrue
andfalse
, as this third option doesn't feel quite right yet.
The purpose of the DeferredVisible
option is to distinguish between the following two cases when show = false
is set:
- Creating a hidden window, as demonstrated by clicking the "invisible" button in the video.
- Creating a window that remains hidden until
activate_window
is called, which is how Zed currently handles window creation.
The reason for this distinction is that if we don't make it, when Zed creates a window:
- Create a hidden window
- Zed configures the window
- Show the hidden window
Regardless of how the hidden window is created, in the third step, the window's opening animation will be problematic—it will either suddenly appear on the screen (with no opening animation) or play the animation for restoring from a minimized state.
Therefore, under the DeferredVisible
option, we avoid creating a hidden window, which preserves the window's opening animation. The process becomes:
- Create a normal window
- Zed configures the window
- Show the window
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you do want to keep just two options, true
or false
, we may need to create a new window within the first call of activate_window
.
I've created another PR #18705 which is a better solution I think |
- Closes #18610 This PR addresses the same issue as PR #18578. After a full day of research and testing, I believe I’ve found the best solution to resolve this issue. With this PR, the window creation behavior on Windows becomes more consistent with macOS: - When `params.show` is `true`: The window is created and immediately displayed. - When `params.show` is `false`: The window is created but remains hidden until the first call to `activate_window`. As I mentioned in #18578, `winit` creates hidden windows by setting the window's `exstyle` to `WS_EX_NOACTIVATE | WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_TOOLWINDOW`, which is different from the method used in this PR. Here, the window is created with normal parameters, but we do not call `ShowWindow` so the window is not shown. I'm not sure why `winit` doesn't use a smilliar approach like this PR to create hidden windows. My guess is that `winit` is creating this hidden window to function as a "DispatchWindow" — serving a purpose similar to `WindowsPlatform` in `zed`. To ensure the window stays hidden even if `ShowWindow` is called, they use the `exstyle` approach. With the method used in this PR, my initial tests haven't revealed any issues. Release Notes: - N/A
#18705 closes this one, presumably, as the most tested and working one so far. |
- Closes zed-industries#18610 This PR addresses the same issue as PR zed-industries#18578. After a full day of research and testing, I believe I’ve found the best solution to resolve this issue. With this PR, the window creation behavior on Windows becomes more consistent with macOS: - When `params.show` is `true`: The window is created and immediately displayed. - When `params.show` is `false`: The window is created but remains hidden until the first call to `activate_window`. As I mentioned in zed-industries#18578, `winit` creates hidden windows by setting the window's `exstyle` to `WS_EX_NOACTIVATE | WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_TOOLWINDOW`, which is different from the method used in this PR. Here, the window is created with normal parameters, but we do not call `ShowWindow` so the window is not shown. I'm not sure why `winit` doesn't use a smilliar approach like this PR to create hidden windows. My guess is that `winit` is creating this hidden window to function as a "DispatchWindow" — serving a purpose similar to `WindowsPlatform` in `zed`. To ensure the window stays hidden even if `ShowWindow` is called, they use the `exstyle` approach. With the method used in this PR, my initial tests haven't revealed any issues. Release Notes: - N/A
In the current main branch, Zed refuses to open any windows on Windows. After performing a quick
git bisect
, I found that PR #18161 introduced this regression.I'll provide more detailed information about this PR after I return from dinner.
Release Notes: