windows: Make window creation failable (#14395)

Release Notes:

- N/A
This commit is contained in:
张小白 2024-07-15 10:37:46 +08:00 committed by GitHub
parent 70d983abe3
commit ba09eabfba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 33 additions and 28 deletions

View file

@ -288,7 +288,7 @@ impl Platform for WindowsPlatform {
self.icon, self.icon,
self.foreground_executor.clone(), self.foreground_executor.clone(),
lock.current_cursor, lock.current_cursor,
); )?;
drop(lock); drop(lock);
let handle = window.get_raw_handle(); let handle = window.get_raw_handle();
self.raw_window_handles.write().push(handle); self.raw_window_handles.write().push(handle);

View file

@ -11,7 +11,7 @@ use std::{
}; };
use ::util::ResultExt; use ::util::ResultExt;
use anyhow::Context; use anyhow::{Context, Result};
use futures::channel::oneshot::{self, Receiver}; use futures::channel::oneshot::{self, Receiver};
use itertools::Itertools; use itertools::Itertools;
use raw_window_handle as rwh; use raw_window_handle as rwh;
@ -69,7 +69,7 @@ impl WindowsWindowState {
cs: &CREATESTRUCTW, cs: &CREATESTRUCTW,
current_cursor: HCURSOR, current_cursor: HCURSOR,
display: WindowsDisplay, display: WindowsDisplay,
) -> Self { ) -> Result<Self> {
let scale_factor = { let scale_factor = {
let monitor_dpi = unsafe { GetDpiForWindow(hwnd) } as f32; let monitor_dpi = unsafe { GetDpiForWindow(hwnd) } as f32;
monitor_dpi / USER_DEFAULT_SCREEN_DPI as f32 monitor_dpi / USER_DEFAULT_SCREEN_DPI as f32
@ -84,7 +84,7 @@ impl WindowsWindowState {
size: logical_size, size: logical_size,
}; };
let border_offset = WindowBorderOffset::default(); let border_offset = WindowBorderOffset::default();
let renderer = windows_renderer::windows_renderer(hwnd, transparent); let renderer = windows_renderer::windows_renderer(hwnd, transparent)?;
let callbacks = Callbacks::default(); let callbacks = Callbacks::default();
let input_handler = None; let input_handler = None;
let click_state = ClickState::new(); let click_state = ClickState::new();
@ -92,7 +92,7 @@ impl WindowsWindowState {
let nc_button_pressed = None; let nc_button_pressed = None;
let fullscreen = None; let fullscreen = None;
Self { Ok(Self {
origin, origin,
logical_size, logical_size,
fullscreen_restore_bounds, fullscreen_restore_bounds,
@ -108,7 +108,7 @@ impl WindowsWindowState {
display, display,
fullscreen, fullscreen,
hwnd, hwnd,
} })
} }
#[inline] #[inline]
@ -203,23 +203,23 @@ impl WindowsWindowState {
} }
impl WindowsWindowStatePtr { impl WindowsWindowStatePtr {
fn new(context: &WindowCreateContext, hwnd: HWND, cs: &CREATESTRUCTW) -> Rc<Self> { fn new(context: &WindowCreateContext, hwnd: HWND, cs: &CREATESTRUCTW) -> Result<Rc<Self>> {
let state = RefCell::new(WindowsWindowState::new( let state = RefCell::new(WindowsWindowState::new(
hwnd, hwnd,
context.transparent, context.transparent,
cs, cs,
context.current_cursor, context.current_cursor,
context.display, context.display,
)); )?);
Rc::new(Self { Ok(Rc::new(Self {
state, state,
hwnd, hwnd,
handle: context.handle, handle: context.handle,
hide_title_bar: context.hide_title_bar, hide_title_bar: context.hide_title_bar,
is_movable: context.is_movable, is_movable: context.is_movable,
executor: context.executor.clone(), executor: context.executor.clone(),
}) }))
} }
} }
@ -236,7 +236,7 @@ pub(crate) struct Callbacks {
} }
struct WindowCreateContext { struct WindowCreateContext {
inner: Option<Rc<WindowsWindowStatePtr>>, inner: Option<Result<Rc<WindowsWindowStatePtr>>>,
handle: AnyWindowHandle, handle: AnyWindowHandle,
hide_title_bar: bool, hide_title_bar: bool,
display: WindowsDisplay, display: WindowsDisplay,
@ -253,7 +253,7 @@ impl WindowsWindow {
icon: HICON, icon: HICON,
executor: ForegroundExecutor, executor: ForegroundExecutor,
current_cursor: HCURSOR, current_cursor: HCURSOR,
) -> Self { ) -> Result<Self> {
let classname = register_wnd_class(icon); let classname = register_wnd_class(icon);
let hide_title_bar = params let hide_title_bar = params
.titlebar .titlebar
@ -310,15 +310,15 @@ impl WindowsWindow {
lpparam, lpparam,
) )
}; };
let state_ptr = Rc::clone(context.inner.as_ref().unwrap()); let state_ptr = context.inner.take().unwrap()?;
register_drag_drop(state_ptr.clone()); register_drag_drop(state_ptr.clone())?;
unsafe { unsafe {
let mut placement = WINDOWPLACEMENT { let mut placement = WINDOWPLACEMENT {
length: std::mem::size_of::<WINDOWPLACEMENT>() as u32, length: std::mem::size_of::<WINDOWPLACEMENT>() as u32,
..Default::default() ..Default::default()
}; };
GetWindowPlacement(raw_hwnd, &mut placement).log_err(); GetWindowPlacement(raw_hwnd, &mut placement)?;
// the bounds may be not inside the display // the bounds may be not inside the display
let bounds = if display.check_given_bounds(params.bounds) { let bounds = if display.check_given_bounds(params.bounds) {
params.bounds params.bounds
@ -327,14 +327,14 @@ impl WindowsWindow {
}; };
let mut lock = state_ptr.state.borrow_mut(); let mut lock = state_ptr.state.borrow_mut();
let bounds = bounds.to_device_pixels(lock.scale_factor); let bounds = bounds.to_device_pixels(lock.scale_factor);
lock.border_offset.udpate(raw_hwnd).unwrap(); lock.border_offset.udpate(raw_hwnd)?;
placement.rcNormalPosition = calcualte_window_rect(bounds, lock.border_offset); placement.rcNormalPosition = calcualte_window_rect(bounds, lock.border_offset);
drop(lock); drop(lock);
SetWindowPlacement(raw_hwnd, &placement).log_err(); SetWindowPlacement(raw_hwnd, &placement)?;
} }
unsafe { ShowWindow(raw_hwnd, SW_SHOW).ok().log_err() }; unsafe { ShowWindow(raw_hwnd, SW_SHOW).ok()? };
Self(state_ptr) Ok(Self(state_ptr))
} }
} }
@ -921,10 +921,14 @@ unsafe extern "system" fn wnd_proc(
let cs = unsafe { &*cs }; let cs = unsafe { &*cs };
let ctx = cs.lpCreateParams as *mut WindowCreateContext; let ctx = cs.lpCreateParams as *mut WindowCreateContext;
let ctx = unsafe { &mut *ctx }; let ctx = unsafe { &mut *ctx };
let state_ptr = WindowsWindowStatePtr::new(ctx, hwnd, cs); let creation_result = WindowsWindowStatePtr::new(ctx, hwnd, cs);
let weak = Box::new(Rc::downgrade(&state_ptr)); if creation_result.is_err() {
ctx.inner = Some(creation_result);
return LRESULT(0);
}
let weak = Box::new(Rc::downgrade(creation_result.as_ref().unwrap()));
unsafe { set_window_long(hwnd, GWLP_USERDATA, Box::into_raw(weak) as isize) }; unsafe { set_window_long(hwnd, GWLP_USERDATA, Box::into_raw(weak) as isize) };
ctx.inner = Some(state_ptr); ctx.inner = Some(creation_result);
return LRESULT(1); return LRESULT(1);
} }
let ptr = unsafe { get_window_long(hwnd, GWLP_USERDATA) } as *mut Weak<WindowsWindowStatePtr>; let ptr = unsafe { get_window_long(hwnd, GWLP_USERDATA) } as *mut Weak<WindowsWindowStatePtr>;
@ -972,7 +976,7 @@ fn get_module_handle() -> HMODULE {
} }
} }
fn register_drag_drop(state_ptr: Rc<WindowsWindowStatePtr>) { fn register_drag_drop(state_ptr: Rc<WindowsWindowStatePtr>) -> Result<()> {
let window_handle = state_ptr.hwnd; let window_handle = state_ptr.hwnd;
let handler = WindowsDragDropHandler(state_ptr); let handler = WindowsDragDropHandler(state_ptr);
// The lifetime of `IDropTarget` is handled by Windows, it wont release untill // The lifetime of `IDropTarget` is handled by Windows, it wont release untill
@ -981,8 +985,9 @@ fn register_drag_drop(state_ptr: Rc<WindowsWindowStatePtr>) {
let drag_drop_handler: IDropTarget = handler.into(); let drag_drop_handler: IDropTarget = handler.into();
unsafe { unsafe {
RegisterDragDrop(window_handle, &drag_drop_handler) RegisterDragDrop(window_handle, &drag_drop_handler)
.expect("unable to register drag-drop event") .context("unable to register drag-drop event")?;
}; }
Ok(())
} }
fn calcualte_window_rect(bounds: Bounds<DevicePixels>, border_offset: WindowBorderOffset) -> RECT { fn calcualte_window_rect(bounds: Bounds<DevicePixels>, border_offset: WindowBorderOffset) -> RECT {
@ -1045,7 +1050,7 @@ mod windows_renderer {
platform::blade::{BladeRenderer, BladeSurfaceConfig}, platform::blade::{BladeRenderer, BladeSurfaceConfig},
}; };
pub(super) fn windows_renderer(hwnd: HWND, transparent: bool) -> BladeRenderer { pub(super) fn windows_renderer(hwnd: HWND, transparent: bool) -> anyhow::Result<BladeRenderer> {
let raw = RawWindow { hwnd: hwnd.0 }; let raw = RawWindow { hwnd: hwnd.0 };
let gpu: Arc<gpu::Context> = Arc::new( let gpu: Arc<gpu::Context> = Arc::new(
unsafe { unsafe {
@ -1058,14 +1063,14 @@ mod windows_renderer {
}, },
) )
} }
.unwrap(), .map_err(|e| anyhow::anyhow!("{:?}", e))?,
); );
let config = BladeSurfaceConfig { let config = BladeSurfaceConfig {
size: gpu::Extent::default(), size: gpu::Extent::default(),
transparent, transparent,
}; };
BladeRenderer::new(gpu, config) Ok(BladeRenderer::new(gpu, config))
} }
struct RawWindow { struct RawWindow {