diff --git a/crates/gpui/src/platform/windows/platform.rs b/crates/gpui/src/platform/windows/platform.rs index 09e1297262..18b3fae844 100644 --- a/crates/gpui/src/platform/windows/platform.rs +++ b/crates/gpui/src/platform/windows/platform.rs @@ -59,7 +59,7 @@ pub(crate) struct WindowsPlatformInner { text_system: Arc, callbacks: Mutex, pub raw_window_handles: RwLock>, - pub(crate) dispatch_event: HANDLE, + pub(crate) dispatch_event: OwnedHandle, pub(crate) settings: RefCell, } @@ -76,12 +76,6 @@ impl WindowsPlatformInner { } } -impl Drop for WindowsPlatformInner { - fn drop(&mut self) { - unsafe { CloseHandle(self.dispatch_event) }.ok(); - } -} - #[derive(Default)] struct Callbacks { open_urls: Option)>>, @@ -152,8 +146,9 @@ impl WindowsPlatform { OleInitialize(None).expect("unable to initialize Windows OLE"); } let (main_sender, main_receiver) = flume::unbounded::(); - let dispatch_event = unsafe { CreateEventW(None, false, false, None) }.unwrap(); - let dispatcher = Arc::new(WindowsDispatcher::new(main_sender, dispatch_event)); + let dispatch_event = + OwnedHandle::new(unsafe { CreateEventW(None, false, false, None) }.unwrap()); + let dispatcher = Arc::new(WindowsDispatcher::new(main_sender, dispatch_event.to_raw())); let background_executor = BackgroundExecutor::new(dispatcher.clone()); let foreground_executor = ForegroundExecutor::new(dispatcher); let text_system = Arc::new(WindowsTextSystem::new()); @@ -208,14 +203,15 @@ impl Platform for WindowsPlatform { fn run(&self, on_finish_launching: Box) { on_finish_launching(); - let dispatch_event = self.inner.dispatch_event; - let vsync_event = unsafe { CreateEventW(None, false, false, None) }.unwrap(); - let timer_stop_event = unsafe { CreateEventW(None, false, false, None) }.unwrap(); - begin_vsync_timer(vsync_event, timer_stop_event); + let dispatch_event = self.inner.dispatch_event.to_raw(); + let vsync_event = create_event().unwrap(); + let timer_stop_event = create_event().unwrap(); + let raw_timer_stop_event = timer_stop_event.to_raw(); + begin_vsync_timer(vsync_event.to_raw(), timer_stop_event); 'a: loop { let wait_result = unsafe { MsgWaitForMultipleObjects( - Some(&[vsync_event, dispatch_event]), + Some(&[vsync_event.to_raw(), dispatch_event]), false, INFINITE, QS_ALLINPUT, @@ -257,8 +253,7 @@ impl Platform for WindowsPlatform { } } } - end_vsync_timer(timer_stop_event); - unsafe { CloseHandle(dispatch_event) }.log_err(); + end_vsync_timer(raw_timer_stop_event); let mut callbacks = self.inner.callbacks.lock(); if let Some(callback) = callbacks.quit.as_mut() { @@ -737,15 +732,14 @@ unsafe fn show_savefile_dialog(directory: PathBuf) -> Result { Ok(dialog) } -fn begin_vsync_timer(vsync_event: HANDLE, timer_stop_event: HANDLE) { +fn begin_vsync_timer(vsync_event: HANDLE, timer_stop_event: OwnedHandle) { let vsync_fn = select_vsync_fn(); std::thread::spawn(move || { - while vsync_fn(timer_stop_event) { + while vsync_fn(timer_stop_event.to_raw()) { if unsafe { SetEvent(vsync_event) }.log_err().is_none() { break; } } - unsafe { CloseHandle(timer_stop_event) }.log_err(); }); } diff --git a/crates/gpui/src/platform/windows/util.rs b/crates/gpui/src/platform/windows/util.rs index 5fbff4a3ce..d534f4e337 100644 --- a/crates/gpui/src/platform/windows/util.rs +++ b/crates/gpui/src/platform/windows/util.rs @@ -1,4 +1,5 @@ -use windows::Win32::{Foundation::*, UI::WindowsAndMessaging::*}; +use util::ResultExt; +use windows::Win32::{Foundation::*, System::Threading::*, UI::WindowsAndMessaging::*}; pub(crate) trait HiLoWord { fn hiword(&self) -> u16; @@ -69,6 +70,33 @@ pub(crate) unsafe fn set_window_long( } } +pub(crate) struct OwnedHandle(HANDLE); + +impl OwnedHandle { + pub(crate) fn new(handle: HANDLE) -> Self { + Self(handle) + } + + #[inline(always)] + pub(crate) fn to_raw(&self) -> HANDLE { + self.0 + } +} + +impl Drop for OwnedHandle { + fn drop(&mut self) { + if !self.0.is_invalid() { + unsafe { CloseHandle(self.0) }.log_err(); + } + } +} + +pub(crate) fn create_event() -> windows::core::Result { + Ok(OwnedHandle::new(unsafe { + CreateEventW(None, false, false, None)? + })) +} + pub(crate) fn windows_credentials_target_name(url: &str) -> String { format!("zed:url={}", url) }