mirror of
https://github.com/zed-industries/zed.git
synced 2024-10-23 14:59:50 +00:00
windows: Fix window not displaying correctly on launch (#19124)
Closes #18705 (comment) This PR fixes the issue where the Zed window was not displaying correctly on launch. Now, when Zed is closed in a maximized state, it will reopen in a maximized state. On macOS, when a window is created but not yet visible, calling `zoom` or `toggle_fullscreen` will still affect the hidden window. However, this behavior is different on Windows, so special handling is required. Also, since #18705 hasn't been reviewed yet, I'm not sure if this PR should be merged now or if it should wait until #18705 is reviewed first. Release Notes: - N/A
This commit is contained in:
parent
879a2ea06f
commit
338bf3fd28
1 changed files with 109 additions and 65 deletions
|
@ -52,12 +52,13 @@ pub struct WindowsWindowState {
|
|||
|
||||
pub display: WindowsDisplay,
|
||||
fullscreen: Option<StyleAndBounds>,
|
||||
initial_placement: Option<WINDOWPLACEMENT>,
|
||||
initial_placement: Option<WindowOpenStatus>,
|
||||
hwnd: HWND,
|
||||
}
|
||||
|
||||
pub(crate) struct WindowsWindowStatePtr {
|
||||
hwnd: HWND,
|
||||
this: Weak<Self>,
|
||||
pub(crate) state: RefCell<WindowsWindowState>,
|
||||
pub(crate) handle: AnyWindowHandle,
|
||||
pub(crate) hide_title_bar: bool,
|
||||
|
@ -222,9 +223,10 @@ impl WindowsWindowStatePtr {
|
|||
context.display,
|
||||
)?);
|
||||
|
||||
Ok(Rc::new(Self {
|
||||
state,
|
||||
Ok(Rc::new_cyclic(|this| Self {
|
||||
hwnd,
|
||||
this: this.clone(),
|
||||
state,
|
||||
handle: context.handle,
|
||||
hide_title_bar: context.hide_title_bar,
|
||||
is_movable: context.is_movable,
|
||||
|
@ -235,11 +237,86 @@ impl WindowsWindowStatePtr {
|
|||
}))
|
||||
}
|
||||
|
||||
fn toggle_fullscreen(&self) {
|
||||
let Some(state_ptr) = self.this.upgrade() else {
|
||||
log::error!("Unable to toggle fullscreen: window has been dropped");
|
||||
return;
|
||||
};
|
||||
self.executor
|
||||
.spawn(async move {
|
||||
let mut lock = state_ptr.state.borrow_mut();
|
||||
let StyleAndBounds {
|
||||
style,
|
||||
x,
|
||||
y,
|
||||
cx,
|
||||
cy,
|
||||
} = if let Some(state) = lock.fullscreen.take() {
|
||||
state
|
||||
} else {
|
||||
let (window_bounds, _) = lock.calculate_window_bounds();
|
||||
lock.fullscreen_restore_bounds = window_bounds;
|
||||
let style =
|
||||
WINDOW_STYLE(unsafe { get_window_long(state_ptr.hwnd, GWL_STYLE) } as _);
|
||||
let mut rc = RECT::default();
|
||||
unsafe { GetWindowRect(state_ptr.hwnd, &mut rc) }.log_err();
|
||||
let _ = lock.fullscreen.insert(StyleAndBounds {
|
||||
style,
|
||||
x: rc.left,
|
||||
y: rc.top,
|
||||
cx: rc.right - rc.left,
|
||||
cy: rc.bottom - rc.top,
|
||||
});
|
||||
let style = style
|
||||
& !(WS_THICKFRAME
|
||||
| WS_SYSMENU
|
||||
| WS_MAXIMIZEBOX
|
||||
| WS_MINIMIZEBOX
|
||||
| WS_CAPTION);
|
||||
let physical_bounds = lock.display.physical_bounds();
|
||||
StyleAndBounds {
|
||||
style,
|
||||
x: physical_bounds.left().0,
|
||||
y: physical_bounds.top().0,
|
||||
cx: physical_bounds.size.width.0,
|
||||
cy: physical_bounds.size.height.0,
|
||||
}
|
||||
};
|
||||
drop(lock);
|
||||
unsafe { set_window_long(state_ptr.hwnd, GWL_STYLE, style.0 as isize) };
|
||||
unsafe {
|
||||
SetWindowPos(
|
||||
state_ptr.hwnd,
|
||||
HWND::default(),
|
||||
x,
|
||||
y,
|
||||
cx,
|
||||
cy,
|
||||
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER,
|
||||
)
|
||||
}
|
||||
.log_err();
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn set_window_placement(&self) -> Result<()> {
|
||||
let Some(placement) = self.state.borrow_mut().initial_placement.take() else {
|
||||
let Some(open_status) = self.state.borrow_mut().initial_placement.take() else {
|
||||
return Ok(());
|
||||
};
|
||||
unsafe { SetWindowPlacement(self.hwnd, &placement)? };
|
||||
match open_status.state {
|
||||
WindowOpenState::Maximized => unsafe {
|
||||
SetWindowPlacement(self.hwnd, &open_status.placement)?;
|
||||
ShowWindowAsync(self.hwnd, SW_MAXIMIZE).ok()?;
|
||||
},
|
||||
WindowOpenState::Fullscreen => {
|
||||
unsafe { SetWindowPlacement(self.hwnd, &open_status.placement)? };
|
||||
self.toggle_fullscreen();
|
||||
}
|
||||
WindowOpenState::Windowed => unsafe {
|
||||
SetWindowPlacement(self.hwnd, &open_status.placement)?;
|
||||
},
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -361,7 +438,10 @@ impl WindowsWindow {
|
|||
if params.show {
|
||||
unsafe { SetWindowPlacement(hwnd, &placement)? };
|
||||
} else {
|
||||
state_ptr.state.borrow_mut().initial_placement = Some(placement);
|
||||
state_ptr.state.borrow_mut().initial_placement = Some(WindowOpenStatus {
|
||||
placement,
|
||||
state: WindowOpenState::Windowed,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(Self(state_ptr))
|
||||
|
@ -579,68 +659,21 @@ impl PlatformWindow for WindowsWindow {
|
|||
}
|
||||
|
||||
fn zoom(&self) {
|
||||
unsafe { ShowWindowAsync(self.0.hwnd, SW_MAXIMIZE).ok().log_err() };
|
||||
unsafe {
|
||||
if IsWindowVisible(self.0.hwnd).as_bool() {
|
||||
ShowWindowAsync(self.0.hwnd, SW_MAXIMIZE).ok().log_err();
|
||||
} else if let Some(status) = self.0.state.borrow_mut().initial_placement.as_mut() {
|
||||
status.state = WindowOpenState::Maximized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn toggle_fullscreen(&self) {
|
||||
let state_ptr = self.0.clone();
|
||||
self.0
|
||||
.executor
|
||||
.spawn(async move {
|
||||
let mut lock = state_ptr.state.borrow_mut();
|
||||
let StyleAndBounds {
|
||||
style,
|
||||
x,
|
||||
y,
|
||||
cx,
|
||||
cy,
|
||||
} = if let Some(state) = lock.fullscreen.take() {
|
||||
state
|
||||
} else {
|
||||
let (window_bounds, _) = lock.calculate_window_bounds();
|
||||
lock.fullscreen_restore_bounds = window_bounds;
|
||||
let style =
|
||||
WINDOW_STYLE(unsafe { get_window_long(state_ptr.hwnd, GWL_STYLE) } as _);
|
||||
let mut rc = RECT::default();
|
||||
unsafe { GetWindowRect(state_ptr.hwnd, &mut rc) }.log_err();
|
||||
let _ = lock.fullscreen.insert(StyleAndBounds {
|
||||
style,
|
||||
x: rc.left,
|
||||
y: rc.top,
|
||||
cx: rc.right - rc.left,
|
||||
cy: rc.bottom - rc.top,
|
||||
});
|
||||
let style = style
|
||||
& !(WS_THICKFRAME
|
||||
| WS_SYSMENU
|
||||
| WS_MAXIMIZEBOX
|
||||
| WS_MINIMIZEBOX
|
||||
| WS_CAPTION);
|
||||
let physical_bounds = lock.display.physical_bounds();
|
||||
StyleAndBounds {
|
||||
style,
|
||||
x: physical_bounds.left().0,
|
||||
y: physical_bounds.top().0,
|
||||
cx: physical_bounds.size.width.0,
|
||||
cy: physical_bounds.size.height.0,
|
||||
}
|
||||
};
|
||||
drop(lock);
|
||||
unsafe { set_window_long(state_ptr.hwnd, GWL_STYLE, style.0 as isize) };
|
||||
unsafe {
|
||||
SetWindowPos(
|
||||
state_ptr.hwnd,
|
||||
HWND::default(),
|
||||
x,
|
||||
y,
|
||||
cx,
|
||||
cy,
|
||||
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER,
|
||||
)
|
||||
}
|
||||
.log_err();
|
||||
})
|
||||
.detach();
|
||||
if unsafe { IsWindowVisible(self.0.hwnd).as_bool() } {
|
||||
self.0.toggle_fullscreen();
|
||||
} else if let Some(status) = self.0.state.borrow_mut().initial_placement.as_mut() {
|
||||
status.state = WindowOpenState::Fullscreen;
|
||||
}
|
||||
}
|
||||
|
||||
fn is_fullscreen(&self) -> bool {
|
||||
|
@ -925,6 +958,17 @@ impl WindowBorderOffset {
|
|||
}
|
||||
}
|
||||
|
||||
struct WindowOpenStatus {
|
||||
placement: WINDOWPLACEMENT,
|
||||
state: WindowOpenState,
|
||||
}
|
||||
|
||||
enum WindowOpenState {
|
||||
Maximized,
|
||||
Fullscreen,
|
||||
Windowed,
|
||||
}
|
||||
|
||||
fn register_wnd_class(icon_handle: HICON) -> PCWSTR {
|
||||
const CLASS_NAME: PCWSTR = w!("Zed::Window");
|
||||
|
||||
|
|
Loading…
Reference in a new issue