#![deny(unsafe_op_in_unsafe_fn)] use std::{ cell::RefCell, num::NonZeroIsize, path::PathBuf, rc::{Rc, Weak}, str::FromStr, sync::{Arc, Once}, time::{Duration, Instant},}; use ::util::ResultExt;use anyhow::{Context as _, Result};use async_task::Runnable;use futures::channel::oneshot::{self, Receiver};use raw_window_handle as rwh;use smallvec::SmallVec;use windows::{ core::*, Win32::{ Foundation::*, Graphics::Gdi::*, System::{Com::*, LibraryLoader::*, Ole::*, SystemServices::*}, UI::{Controls::*, HiDpi::*, Input::KeyboardAndMouse::*, Shell::*, WindowsAndMessaging::*}, },}; use crate::platform::blade::{BladeContext, BladeRenderer};use crate::*; pub(crate) struct WindowsWindow(pub Rc<WindowsWindowStatePtr>); pub struct WindowsWindowState { pub origin: Point<Pixels>, pub logical_size: Size<Pixels>, pub fullscreen_restore_bounds: Bounds<Pixels>, pub border_offset: WindowBorderOffset, pub scale_factor: f32, pub restore_from_minimized: Option<Box<dyn FnMut(RequestFrameOptions)>>, pub callbacks: Callbacks, pub input_handler: Option<PlatformInputHandler>, pub system_key_handled: bool, pub hovered: bool, pub renderer: BladeRenderer, pub click_state: ClickState, pub system_settings: WindowsSystemSettings, pub current_cursor: HCURSOR, pub nc_button_pressed: Option<u32>, pub display: WindowsDisplay, fullscreen: Option<StyleAndBounds>, 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, pub(crate) is_movable: bool, pub(crate) executor: ForegroundExecutor, pub(crate) windows_version: WindowsVersion, pub(crate) validation_number: usize, pub(crate) main_receiver: flume::Receiver<Runnable>, pub(crate) main_thread_id_win32: u32,} impl WindowsWindowState { fn new( hwnd: HWND, transparent: bool, cs: &CREATESTRUCTW, current_cursor: HCURSOR, display: WindowsDisplay, gpu_context: &BladeContext, ) -> Result<Self> { let scale_factor = { let monitor_dpi = unsafe { GetDpiForWindow(hwnd) } as f32; monitor_dpi / USER_DEFAULT_SCREEN_DPI as f32 }; let origin = logical_point(cs.x as f32, cs.y as f32, scale_factor); let logical_size = { let physical_size = size(DevicePixels(cs.cx), DevicePixels(cs.cy)); physical_size.to_pixels(scale_factor) }; let fullscreen_restore_bounds = Bounds { origin, size: logical_size, }; let border_offset = WindowBorderOffset::default(); let restore_from_minimized = None; let renderer = windows_renderer::init(gpu_context, hwnd, transparent)?; let callbacks = Callbacks::default(); let input_handler = None; let system_key_handled = false; let hovered = false; let click_state = ClickState::new(); let system_settings = WindowsSystemSettings::new(display); let nc_button_pressed = None; let fullscreen = None; let initial_placement = None; Ok(Self { origin, logical_size, fullscreen_restore_bounds, border_offset, scale_factor, restore_from_minimized, callbacks, input_handler, system_key_handled, hovered, renderer, click_state, system_settings, current_cursor, nc_button_pressed, display, fullscreen, initial_placement, hwnd, }) } #[inline] pub(crate) fn is_fullscreen(&self) -> bool { self.fullscreen.is_some() } pub(crate) fn is_maximized(&self) -> bool { !self.is_fullscreen() && unsafe { IsZoomed(self.hwnd) }.as_bool() } fn bounds(&self) -> Bounds<Pixels> { Bounds { origin: self.origin, size: self.logical_size, } } // Calculate the bounds used for saving and whether the window is maximized. fn calculate_window_bounds(&self) -> (Bounds<Pixels>, bool) { let placement = unsafe { let mut placement = WINDOWPLACEMENT { length: std::mem::size_of::<WINDOWPLACEMENT>() as u32, ..Default::default() }; GetWindowPlacement(self.hwnd, &mut placement).log_err(); placement }; ( calculate_client_rect( placement.rcNormalPosition, self.border_offset, self.scale_factor, ), placement.showCmd == SW_SHOWMAXIMIZED.0 as u32, ) } fn window_bounds(&self) -> WindowBounds { let (bounds, maximized) = self.calculate_window_bounds(); if self.is_fullscreen() { WindowBounds::Fullscreen(self.fullscreen_restore_bounds) } else if maximized { WindowBounds::Maximized(bounds) } else { WindowBounds::Windowed(bounds) } } /// get the logical size of the app's drawable area. /// /// Currently, GPUI uses the logical size of the app to handle mouse interactions (such as /// whether the mouse collides with other elements of GPUI). fn content_size(&self) -> Size<Pixels> { self.logical_size } fn title_bar_padding(&self) -> Pixels { // using USER_DEFAULT_SCREEN_DPI because GPUI handles the scale with the scale factor let padding = unsafe { GetSystemMetricsForDpi(SM_CXPADDEDBORDER, USER_DEFAULT_SCREEN_DPI) }; px(padding as f32) } fn title_bar_top_offset(&self) -> Pixels { if self.is_maximized() { self.title_bar_padding() * 2 } else { px(0.) } } fn title_bar_height(&self) -> Pixels { // todo(windows) this is hardcoded to match the ui title bar // in the future the ui title bar component will report the size px(32.) + self.title_bar_top_offset() } pub(crate) fn caption_button_width(&self) -> Pixels { // todo(windows) this is hardcoded to match the ui title bar // in the future the ui title bar component will report the size px(36.) } pub(crate) fn get_titlebar_rect(&self) -> anyhow::Result<RECT> { let height = self.title_bar_height(); let mut rect = RECT::default(); unsafe { GetClientRect(self.hwnd, &mut rect) }?; rect.bottom = rect.top + ((height.0 * self.scale_factor).round() as i32); Ok(rect) }} impl WindowsWindowStatePtr { fn new(context: &WindowCreateContext, hwnd: HWND, cs: &CREATESTRUCTW) -> Result<Rc<Self>> { let state = RefCell::new(WindowsWindowState::new( hwnd, context.transparent, cs, context.current_cursor, context.display, context.gpu_context, )?); 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, executor: context.executor.clone(), windows_version: context.windows_version, validation_number: context.validation_number, main_receiver: context.main_receiver.clone(), main_thread_id_win32: context.main_thread_id_win32, })) } 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(open_status) = self.state.borrow_mut().initial_placement.take() else { return Ok(()); }; 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(()) }} #[derive(Default)]pub(crate) struct Callbacks { pub(crate) request_frame: Option<Box<dyn FnMut(RequestFrameOptions)>>, pub(crate) input: Option<Box<dyn FnMut(crate::PlatformInput) -> DispatchEventResult>>, pub(crate) active_status_change: Option<Box<dyn FnMut(bool)>>, pub(crate) hovered_status_change: Option<Box<dyn FnMut(bool)>>, pub(crate) resize: Option<Box<dyn FnMut(Size<Pixels>, f32)>>, pub(crate) moved: Option<Box<dyn FnMut()>>, pub(crate) should_close: Option<Box<dyn FnMut() -> bool>>, pub(crate) close: Option<Box<dyn FnOnce()>>, pub(crate) appearance_changed: Option<Box<dyn FnMut()>>,} struct WindowCreateContext<'a> { inner: Option<Result<Rc<WindowsWindowStatePtr>>>, handle: AnyWindowHandle, hide_title_bar: bool, display: WindowsDisplay, transparent: bool, is_movable: bool, executor: ForegroundExecutor, current_cursor: HCURSOR, windows_version: WindowsVersion, validation_number: usize, main_receiver: flume::Receiver<Runnable>, gpu_context: &'a BladeContext, main_thread_id_win32: u32,} impl WindowsWindow { pub(crate) fn new( handle: AnyWindowHandle, params: WindowParams, creation_info: WindowCreationInfo, gpu_context: &BladeContext, ) -> Result<Self> { let WindowCreationInfo { icon, executor, current_cursor, windows_version, validation_number, main_receiver, main_thread_id_win32, } = creation_info; let classname = register_wnd_class(icon); let hide_title_bar = params .titlebar .as_ref() .map(|titlebar| titlebar.appears_transparent) .unwrap_or(true); let windowname = HSTRING::from( params .titlebar .as_ref() .and_then(|titlebar| titlebar.title.as_ref()) .map(|title| title.as_ref()) .unwrap_or(""), ); let (dwexstyle, mut dwstyle) = if params.kind == WindowKind::PopUp { (WS_EX_TOOLWINDOW, WINDOW_STYLE(0x0)) } else { ( WS_EX_APPWINDOW, WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX, ) }; let hinstance = get_module_handle(); let display = if let Some(display_id) = params.display_id { // if we obtain a display_id, then this ID must be valid. WindowsDisplay::new(display_id).unwrap() } else { WindowsDisplay::primary_monitor().unwrap() }; let mut context = WindowCreateContext { inner: None, handle, hide_title_bar, display, transparent: true, is_movable: params.is_movable, executor, current_cursor, windows_version, validation_number, main_receiver, gpu_context, main_thread_id_win32, }; let lpparam = Some(&context as *const _ as *const _); let creation_result = unsafe { CreateWindowExW( dwexstyle, classname, &windowname, dwstyle, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, None, None, hinstance, lpparam, ) }; // We should call `?` on state_ptr first, then call `?` on hwnd. // Or, we will lose the error info reported by `WindowsWindowState::new` let state_ptr = context.inner.take().unwrap()?; let hwnd = creation_result?; register_drag_drop(state_ptr.clone())?; configure_dwm_dark_mode(hwnd); state_ptr.state.borrow_mut().border_offset.update(hwnd)?; let placement = retrieve_window_placement( hwnd, display, params.bounds, state_ptr.state.borrow().scale_factor, state_ptr.state.borrow().border_offset, )?; if params.show { unsafe { SetWindowPlacement(hwnd, &placement)? }; } else { state_ptr.state.borrow_mut().initial_placement = Some(WindowOpenStatus { placement, state: WindowOpenState::Windowed, }); } Ok(Self(state_ptr)) }} impl rwh::HasWindowHandle for WindowsWindow { fn window_handle(&self) -> std::result::Result<rwh::WindowHandle<'_>, rwh::HandleError> { let raw = rwh::Win32WindowHandle::new(unsafe { NonZeroIsize::new_unchecked(self.0.hwnd.0 as isize) }) .into(); Ok(unsafe { rwh::WindowHandle::borrow_raw(raw) }) }} // todo(windows)impl rwh::HasDisplayHandle for WindowsWindow { fn display_handle(&self) -> std::result::Result<rwh::DisplayHandle<'_>, rwh::HandleError> { unimplemented!() }} impl Drop for WindowsWindow { fn drop(&mut self) { self.0.state.borrow_mut().renderer.destroy(); // clone this `Rc` to prevent early release of the pointer let this = self.0.clone(); self.0 .executor .spawn(async move { let handle = this.hwnd; unsafe { RevokeDragDrop(handle).log_err(); DestroyWindow(handle).log_err(); } }) .detach(); }}Lines 1–500 of 1355. Load more
#![deny(unsafe_op_in_unsafe_fn)] use std::{ cell::RefCell, num::NonZeroIsize, path::PathBuf, rc::{Rc, Weak}, str::FromStr, sync::{Arc, Once}, time::{Duration, Instant}, }; use ::util::ResultExt; use anyhow::{Context as _, Result}; use async_task::Runnable; use futures::channel::oneshot::{self, Receiver}; use raw_window_handle as rwh; use smallvec::SmallVec; use windows::{ core::*, Win32::{ Foundation::*, Graphics::Gdi::*, System::{Com::*, LibraryLoader::*, Ole::*, SystemServices::*}, UI::{Controls::*, HiDpi::*, Input::KeyboardAndMouse::*, Shell::*, WindowsAndMessaging::*}, }, }; use crate::platform::blade::{BladeContext, BladeRenderer}; use crate::*; pub(crate) struct WindowsWindow(pub Rc<WindowsWindowStatePtr>); pub struct WindowsWindowState { pub origin: Point<Pixels>, pub logical_size: Size<Pixels>, pub fullscreen_restore_bounds: Bounds<Pixels>, pub border_offset: WindowBorderOffset, pub scale_factor: f32, pub restore_from_minimized: Option<Box<dyn FnMut(RequestFrameOptions)>>, pub callbacks: Callbacks, pub input_handler: Option<PlatformInputHandler>, pub system_key_handled: bool, pub hovered: bool, pub renderer: BladeRenderer, pub click_state: ClickState, pub system_settings: WindowsSystemSettings, pub current_cursor: HCURSOR, pub nc_button_pressed: Option<u32>, pub display: WindowsDisplay, fullscreen: Option<StyleAndBounds>, 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, pub(crate) is_movable: bool, pub(crate) executor: ForegroundExecutor, pub(crate) windows_version: WindowsVersion, pub(crate) validation_number: usize, pub(crate) main_receiver: flume::Receiver<Runnable>, pub(crate) main_thread_id_win32: u32, } impl WindowsWindowState { fn new( hwnd: HWND, transparent: bool, cs: &CREATESTRUCTW, current_cursor: HCURSOR, display: WindowsDisplay, gpu_context: &BladeContext, ) -> Result<Self> { let scale_factor = { let monitor_dpi = unsafe { GetDpiForWindow(hwnd) } as f32; monitor_dpi / USER_DEFAULT_SCREEN_DPI as f32 }; let origin = logical_point(cs.x as f32, cs.y as f32, scale_factor); let logical_size = { let physical_size = size(DevicePixels(cs.cx), DevicePixels(cs.cy)); physical_size.to_pixels(scale_factor) }; let fullscreen_restore_bounds = Bounds { origin, size: logical_size, }; let border_offset = WindowBorderOffset::default(); let restore_from_minimized = None; let renderer = windows_renderer::init(gpu_context, hwnd, transparent)?; let callbacks = Callbacks::default(); let input_handler = None; let system_key_handled = false; let hovered = false; let click_state = ClickState::new(); let system_settings = WindowsSystemSettings::new(display); let nc_button_pressed = None; let fullscreen = None; let initial_placement = None; Ok(Self { origin, logical_size, fullscreen_restore_bounds, border_offset, scale_factor, restore_from_minimized, callbacks, input_handler, system_key_handled, hovered, renderer, click_state, system_settings, current_cursor, nc_button_pressed, display, fullscreen, initial_placement, hwnd, }) } #[inline] pub(crate) fn is_fullscreen(&self) -> bool { self.fullscreen.is_some() } pub(crate) fn is_maximized(&self) -> bool { !self.is_fullscreen() && unsafe { IsZoomed(self.hwnd) }.as_bool() } fn bounds(&self) -> Bounds<Pixels> { Bounds { origin: self.origin, size: self.logical_size, } } // Calculate the bounds used for saving and whether the window is maximized. fn calculate_window_bounds(&self) -> (Bounds<Pixels>, bool) { let placement = unsafe { let mut placement = WINDOWPLACEMENT { length: std::mem::size_of::<WINDOWPLACEMENT>() as u32, ..Default::default() }; GetWindowPlacement(self.hwnd, &mut placement).log_err(); placement }; ( calculate_client_rect( placement.rcNormalPosition, self.border_offset, self.scale_factor, ), placement.showCmd == SW_SHOWMAXIMIZED.0 as u32, ) } fn window_bounds(&self) -> WindowBounds { let (bounds, maximized) = self.calculate_window_bounds(); if self.is_fullscreen() { WindowBounds::Fullscreen(self.fullscreen_restore_bounds) } else if maximized { WindowBounds::Maximized(bounds) } else { WindowBounds::Windowed(bounds) } } /// get the logical size of the app's drawable area. /// /// Currently, GPUI uses the logical size of the app to handle mouse interactions (such as /// whether the mouse collides with other elements of GPUI). fn content_size(&self) -> Size<Pixels> { self.logical_size } fn title_bar_padding(&self) -> Pixels { // using USER_DEFAULT_SCREEN_DPI because GPUI handles the scale with the scale factor let padding = unsafe { GetSystemMetricsForDpi(SM_CXPADDEDBORDER, USER_DEFAULT_SCREEN_DPI) }; px(padding as f32) } fn title_bar_top_offset(&self) -> Pixels { if self.is_maximized() { self.title_bar_padding() * 2 } else { px(0.) } } fn title_bar_height(&self) -> Pixels { // todo(windows) this is hardcoded to match the ui title bar // in the future the ui title bar component will report the size px(32.) + self.title_bar_top_offset() } pub(crate) fn caption_button_width(&self) -> Pixels { // todo(windows) this is hardcoded to match the ui title bar // in the future the ui title bar component will report the size px(36.) } pub(crate) fn get_titlebar_rect(&self) -> anyhow::Result<RECT> { let height = self.title_bar_height(); let mut rect = RECT::default(); unsafe { GetClientRect(self.hwnd, &mut rect) }?; rect.bottom = rect.top + ((height.0 * self.scale_factor).round() as i32); Ok(rect) } } impl WindowsWindowStatePtr { fn new(context: &WindowCreateContext, hwnd: HWND, cs: &CREATESTRUCTW) -> Result<Rc<Self>> { let state = RefCell::new(WindowsWindowState::new( hwnd, context.transparent, cs, context.current_cursor, context.display, context.gpu_context, )?); 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, executor: context.executor.clone(), windows_version: context.windows_version, validation_number: context.validation_number, main_receiver: context.main_receiver.clone(), main_thread_id_win32: context.main_thread_id_win32, })) } 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(open_status) = self.state.borrow_mut().initial_placement.take() else { return Ok(()); }; 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(()) } } #[derive(Default)] pub(crate) struct Callbacks { pub(crate) request_frame: Option<Box<dyn FnMut(RequestFrameOptions)>>, pub(crate) input: Option<Box<dyn FnMut(crate::PlatformInput) -> DispatchEventResult>>, pub(crate) active_status_change: Option<Box<dyn FnMut(bool)>>, pub(crate) hovered_status_change: Option<Box<dyn FnMut(bool)>>, pub(crate) resize: Option<Box<dyn FnMut(Size<Pixels>, f32)>>, pub(crate) moved: Option<Box<dyn FnMut()>>, pub(crate) should_close: Option<Box<dyn FnMut() -> bool>>, pub(crate) close: Option<Box<dyn FnOnce()>>, pub(crate) appearance_changed: Option<Box<dyn FnMut()>>, } struct WindowCreateContext<'a> { inner: Option<Result<Rc<WindowsWindowStatePtr>>>, handle: AnyWindowHandle, hide_title_bar: bool, display: WindowsDisplay, transparent: bool, is_movable: bool, executor: ForegroundExecutor, current_cursor: HCURSOR, windows_version: WindowsVersion, validation_number: usize, main_receiver: flume::Receiver<Runnable>, gpu_context: &'a BladeContext, main_thread_id_win32: u32, } impl WindowsWindow { pub(crate) fn new( handle: AnyWindowHandle, params: WindowParams, creation_info: WindowCreationInfo, gpu_context: &BladeContext, ) -> Result<Self> { let WindowCreationInfo { icon, executor, current_cursor, windows_version, validation_number, main_receiver, main_thread_id_win32, } = creation_info; let classname = register_wnd_class(icon); let hide_title_bar = params .titlebar .as_ref() .map(|titlebar| titlebar.appears_transparent) .unwrap_or(true); let windowname = HSTRING::from( params .titlebar .as_ref() .and_then(|titlebar| titlebar.title.as_ref()) .map(|title| title.as_ref()) .unwrap_or(""), ); let (dwexstyle, mut dwstyle) = if params.kind == WindowKind::PopUp { (WS_EX_TOOLWINDOW, WINDOW_STYLE(0x0)) } else { ( WS_EX_APPWINDOW, WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX, ) }; let hinstance = get_module_handle(); let display = if let Some(display_id) = params.display_id { // if we obtain a display_id, then this ID must be valid. WindowsDisplay::new(display_id).unwrap() } else { WindowsDisplay::primary_monitor().unwrap() }; let mut context = WindowCreateContext { inner: None, handle, hide_title_bar, display, transparent: true, is_movable: params.is_movable, executor, current_cursor, windows_version, validation_number, main_receiver, gpu_context, main_thread_id_win32, }; let lpparam = Some(&context as *const _ as *const _); let creation_result = unsafe { CreateWindowExW( dwexstyle, classname, &windowname, dwstyle, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, None, None, hinstance, lpparam, ) }; // We should call `?` on state_ptr first, then call `?` on hwnd. // Or, we will lose the error info reported by `WindowsWindowState::new` let state_ptr = context.inner.take().unwrap()?; let hwnd = creation_result?; register_drag_drop(state_ptr.clone())?; configure_dwm_dark_mode(hwnd); state_ptr.state.borrow_mut().border_offset.update(hwnd)?; let placement = retrieve_window_placement( hwnd, display, params.bounds, state_ptr.state.borrow().scale_factor, state_ptr.state.borrow().border_offset, )?; if params.show { unsafe { SetWindowPlacement(hwnd, &placement)? }; } else { state_ptr.state.borrow_mut().initial_placement = Some(WindowOpenStatus { placement, state: WindowOpenState::Windowed, }); } Ok(Self(state_ptr)) } } impl rwh::HasWindowHandle for WindowsWindow { fn window_handle(&self) -> std::result::Result<rwh::WindowHandle<'_>, rwh::HandleError> { let raw = rwh::Win32WindowHandle::new(unsafe { NonZeroIsize::new_unchecked(self.0.hwnd.0 as isize) }) .into(); Ok(unsafe { rwh::WindowHandle::borrow_raw(raw) }) } } // todo(windows) impl rwh::HasDisplayHandle for WindowsWindow { fn display_handle(&self) -> std::result::Result<rwh::DisplayHandle<'_>, rwh::HandleError> { unimplemented!() } } impl Drop for WindowsWindow { fn drop(&mut self) { self.0.state.borrow_mut().renderer.destroy(); // clone this `Rc` to prevent early release of the pointer let this = self.0.clone(); self.0 .executor .spawn(async move { let handle = this.hwnd; unsafe { RevokeDragDrop(handle).log_err(); DestroyWindow(handle).log_err(); } }) .detach(); } }