diff --git a/crates/gpui/src/platform/windows/dispatcher.rs b/crates/gpui/src/platform/windows/dispatcher.rs index 575e844051d9b7502f1efa5a0ac7406ec47b2c8a..e7d337116b71f80dc9dbf95218ed7d08b4e4f894 100644 --- a/crates/gpui/src/platform/windows/dispatcher.rs +++ b/crates/gpui/src/platform/windows/dispatcher.rs @@ -15,29 +15,37 @@ use windows::{ ThreadPool, ThreadPoolTimer, TimerElapsedHandler, WorkItemHandler, WorkItemOptions, WorkItemPriority, }, - Win32::{Foundation::HANDLE, System::Threading::SetEvent}, + Win32::{ + Foundation::{LPARAM, WPARAM}, + UI::WindowsAndMessaging::PostThreadMessageW, + }, }; -use crate::{PlatformDispatcher, SafeHandle, TaskLabel}; +use crate::{PlatformDispatcher, TaskLabel, WM_ZED_EVENT_DISPATCHED_ON_MAIN_THREAD}; pub(crate) struct WindowsDispatcher { main_sender: Sender, - dispatch_event: SafeHandle, parker: Mutex, main_thread_id: ThreadId, + main_thread_id_win32: u32, + validation_number: usize, } impl WindowsDispatcher { - pub(crate) fn new(main_sender: Sender, dispatch_event: HANDLE) -> Self { - let dispatch_event = dispatch_event.into(); + pub(crate) fn new( + main_sender: Sender, + main_thread_id_win32: u32, + validation_number: usize, + ) -> Self { let parker = Mutex::new(Parker::new()); let main_thread_id = current().id(); WindowsDispatcher { main_sender, - dispatch_event, parker, main_thread_id, + main_thread_id_win32, + validation_number, } } @@ -87,11 +95,23 @@ impl PlatformDispatcher for WindowsDispatcher { } fn dispatch_on_main_thread(&self, runnable: Runnable) { - self.main_sender + if self + .main_sender .send(runnable) .context("Dispatch on main thread failed") - .log_err(); - unsafe { SetEvent(*self.dispatch_event).log_err() }; + .log_err() + .is_some() + { + unsafe { + PostThreadMessageW( + self.main_thread_id_win32, + WM_ZED_EVENT_DISPATCHED_ON_MAIN_THREAD, + WPARAM(self.validation_number), + LPARAM(0), + ) + .log_err(); + } + } } fn dispatch_after(&self, duration: Duration, runnable: Runnable) { diff --git a/crates/gpui/src/platform/windows/events.rs b/crates/gpui/src/platform/windows/events.rs index efaf7a148acef67849482cfb05b33042b08678fa..2362683e2bbe99df2f9c22f68a7caaac18bd96b1 100644 --- a/crates/gpui/src/platform/windows/events.rs +++ b/crates/gpui/src/platform/windows/events.rs @@ -16,8 +16,9 @@ use windows::Win32::{ use crate::*; -pub(crate) const CURSOR_STYLE_CHANGED: u32 = WM_USER + 1; -pub(crate) const CLOSE_ONE_WINDOW: u32 = WM_USER + 2; +pub(crate) const WM_ZED_CURSOR_STYLE_CHANGED: u32 = WM_USER + 1; +pub(crate) const WM_ZED_CLOSE_ONE_WINDOW: u32 = WM_USER + 2; +pub(crate) const WM_ZED_EVENT_DISPATCHED_ON_MAIN_THREAD: u32 = WM_USER + 3; const SIZE_MOVE_LOOP_TIMER_ID: usize = 1; const AUTO_HIDE_TASKBAR_THICKNESS_PX: i32 = 1; @@ -89,7 +90,7 @@ pub(crate) fn handle_msg( WM_SETCURSOR => handle_set_cursor(lparam, state_ptr), WM_SETTINGCHANGE => handle_system_settings_changed(handle, state_ptr), WM_DWMCOLORIZATIONCOLORCHANGED => handle_system_theme_changed(state_ptr), - CURSOR_STYLE_CHANGED => handle_cursor_changed(lparam, state_ptr), + WM_ZED_CURSOR_STYLE_CHANGED => handle_cursor_changed(lparam, state_ptr), _ => None, }; if let Some(n) = handled { @@ -243,9 +244,9 @@ fn handle_destroy_msg(handle: HWND, state_ptr: Rc) -> Opt callback(); } unsafe { - PostMessageW( - None, - CLOSE_ONE_WINDOW, + PostThreadMessageW( + state_ptr.main_thread_id_win32, + WM_ZED_CLOSE_ONE_WINDOW, WPARAM(state_ptr.validation_number), LPARAM(handle.0 as isize), ) diff --git a/crates/gpui/src/platform/windows/platform.rs b/crates/gpui/src/platform/windows/platform.rs index 16d298dc66468c480cd1f8c618f2d4c60288efb1..e9877e29b004abcd33b8d7164113533728897b8a 100644 --- a/crates/gpui/src/platform/windows/platform.rs +++ b/crates/gpui/src/platform/windows/platform.rs @@ -37,13 +37,13 @@ pub(crate) struct WindowsPlatform { // The below members will never change throughout the entire lifecycle of the app. icon: HICON, main_receiver: flume::Receiver, - dispatch_event: HANDLE, background_executor: BackgroundExecutor, foreground_executor: ForegroundExecutor, text_system: Arc, windows_version: WindowsVersion, bitmap_factory: ManuallyDrop, validation_number: usize, + main_thread_id_win32: u32, } pub(crate) struct WindowsPlatformState { @@ -82,8 +82,13 @@ 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 main_thread_id_win32 = unsafe { GetCurrentThreadId() }; + let validation_number = rand::random::(); + let dispatcher = Arc::new(WindowsDispatcher::new( + main_sender, + main_thread_id_win32, + validation_number, + )); let background_executor = BackgroundExecutor::new(dispatcher.clone()); let foreground_executor = ForegroundExecutor::new(dispatcher); let bitmap_factory = ManuallyDrop::new(unsafe { @@ -99,7 +104,6 @@ impl WindowsPlatform { let raw_window_handles = RwLock::new(SmallVec::new()); let gpu_context = BladeContext::new().expect("Unable to init GPU context"); let windows_version = WindowsVersion::new().expect("Error retrieve windows version"); - let validation_number = rand::random::(); Self { state, @@ -107,13 +111,13 @@ impl WindowsPlatform { gpu_context, icon, main_receiver, - dispatch_event, background_executor, foreground_executor, text_system, windows_version, bitmap_factory, validation_number, + main_thread_id_win32, } } @@ -150,16 +154,7 @@ impl WindowsPlatform { }); } - fn close_one_window( - &self, - target_window: HWND, - validation_number: usize, - msg: *const MSG, - ) -> bool { - if validation_number != self.validation_number { - unsafe { DispatchMessageW(msg) }; - return false; - } + fn close_one_window(&self, target_window: HWND) -> bool { let mut lock = self.raw_window_handles.write(); let index = lock .iter() @@ -171,8 +166,8 @@ impl WindowsPlatform { } #[inline] - fn run_foreground_tasks(&self) { - for runnable in self.main_receiver.drain() { + fn run_foreground_task(&self) { + if let Ok(runnable) = self.main_receiver.try_recv() { runnable.run(); } } @@ -185,7 +180,54 @@ impl WindowsPlatform { windows_version: self.windows_version, validation_number: self.validation_number, main_receiver: self.main_receiver.clone(), + main_thread_id_win32: self.main_thread_id_win32, + } + } + + fn handle_events(&self) -> bool { + let mut msg = MSG::default(); + unsafe { + while PeekMessageW(&mut msg, None, 0, 0, PM_REMOVE).as_bool() { + match msg.message { + WM_QUIT => return true, + WM_ZED_CLOSE_ONE_WINDOW | WM_ZED_EVENT_DISPATCHED_ON_MAIN_THREAD => { + if self.handle_zed_evnets(msg.message, msg.wParam, msg.lParam, &msg) { + return true; + } + } + _ => { + // todo(windows) + // crate `windows 0.56` reports true as Err + TranslateMessage(&msg).as_bool(); + DispatchMessageW(&msg); + } + } + } } + false + } + + fn handle_zed_evnets( + &self, + message: u32, + wparam: WPARAM, + lparam: LPARAM, + msg: *const MSG, + ) -> bool { + if wparam.0 != self.validation_number { + unsafe { DispatchMessageW(msg) }; + return false; + } + match message { + WM_ZED_CLOSE_ONE_WINDOW => { + if self.close_one_window(HWND(lparam.0 as _)) { + return true; + } + } + WM_ZED_EVENT_DISPATCHED_ON_MAIN_THREAD => self.run_foreground_task(), + _ => unreachable!(), + } + false } } @@ -216,46 +258,17 @@ impl Platform for WindowsPlatform { begin_vsync(*vsync_event); 'a: loop { let wait_result = unsafe { - MsgWaitForMultipleObjects( - Some(&[*vsync_event, self.dispatch_event]), - false, - INFINITE, - QS_ALLINPUT, - ) + MsgWaitForMultipleObjects(Some(&[*vsync_event]), false, INFINITE, QS_ALLINPUT) }; match wait_result { // compositor clock ticked so we should draw a frame WAIT_EVENT(0) => self.redraw_all(), - // foreground tasks are dispatched - WAIT_EVENT(1) => self.run_foreground_tasks(), // Windows thread messages are posted - WAIT_EVENT(2) => { - let mut msg = MSG::default(); - unsafe { - while PeekMessageW(&mut msg, None, 0, 0, PM_REMOVE).as_bool() { - match msg.message { - WM_QUIT => break 'a, - CLOSE_ONE_WINDOW => { - if self.close_one_window( - HWND(msg.lParam.0 as _), - msg.wParam.0, - &msg, - ) { - break 'a; - } - } - _ => { - // todo(windows) - // crate `windows 0.56` reports true as Err - TranslateMessage(&msg).as_bool(); - DispatchMessageW(&msg); - } - } - } + WAIT_EVENT(1) => { + if self.handle_events() { + break 'a; } - // foreground tasks may have been queued in the message handlers - self.run_foreground_tasks(); } _ => { log::error!("Something went wrong while waiting {:?}", wait_result); @@ -492,7 +505,11 @@ impl Platform for WindowsPlatform { let hcursor = load_cursor(style); let mut lock = self.state.borrow_mut(); if lock.current_cursor.0 != hcursor.0 { - self.post_message(CURSOR_STYLE_CHANGED, WPARAM(0), LPARAM(hcursor.0 as isize)); + self.post_message( + WM_ZED_CURSOR_STYLE_CHANGED, + WPARAM(0), + LPARAM(hcursor.0 as isize), + ); lock.current_cursor = hcursor; } } @@ -598,6 +615,7 @@ pub(crate) struct WindowCreationInfo { pub(crate) windows_version: WindowsVersion, pub(crate) validation_number: usize, pub(crate) main_receiver: flume::Receiver, + pub(crate) main_thread_id_win32: u32, } fn open_target(target: &str) { diff --git a/crates/gpui/src/platform/windows/window.rs b/crates/gpui/src/platform/windows/window.rs index e2389f0dba443f193844392b2c8dc5acec40f955..cee6459371fb19192ffa34bbdf01f26ff74cebfa 100644 --- a/crates/gpui/src/platform/windows/window.rs +++ b/crates/gpui/src/platform/windows/window.rs @@ -69,6 +69,7 @@ pub(crate) struct WindowsWindowStatePtr { pub(crate) windows_version: WindowsVersion, pub(crate) validation_number: usize, pub(crate) main_receiver: flume::Receiver, + pub(crate) main_thread_id_win32: u32, } impl WindowsWindowState { @@ -242,6 +243,7 @@ impl WindowsWindowStatePtr { 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, })) } @@ -355,6 +357,7 @@ struct WindowCreateContext<'a> { validation_number: usize, main_receiver: flume::Receiver, gpu_context: &'a BladeContext, + main_thread_id_win32: u32, } impl WindowsWindow { @@ -371,6 +374,7 @@ impl WindowsWindow { windows_version, validation_number, main_receiver, + main_thread_id_win32, } = creation_info; let classname = register_wnd_class(icon); let hide_title_bar = params @@ -415,6 +419,7 @@ impl WindowsWindow { validation_number, main_receiver, gpu_context, + main_thread_id_win32, }; let lpparam = Some(&context as *const _ as *const _); let creation_result = unsafe {