init

Junkui Zhang created

Change summary

crates/gpui/src/platform/windows/platform.rs | 60 +++++++++++++++------
crates/gpui/src/platform/windows/wrapper.rs  | 33 +++++++++++
2 files changed, 75 insertions(+), 18 deletions(-)

Detailed changes

crates/gpui/src/platform/windows/platform.rs 🔗

@@ -18,6 +18,7 @@ use windows::{
     Win32::{
         Foundation::*,
         Graphics::{
+            DirectComposition::DCompositionWaitForCompositorClock,
             Gdi::*,
             Imaging::{CLSID_WICImagingFactory, IWICImagingFactory},
         },
@@ -32,7 +33,7 @@ use crate::*;
 
 pub(crate) struct WindowsPlatform {
     state: RefCell<WindowsPlatformState>,
-    raw_window_handles: RwLock<SmallVec<[HWND; 4]>>,
+    raw_window_handles: Arc<RwLock<SmallVec<[SafeHwnd; 4]>>>,
     // The below members will never change throughout the entire lifecycle of the app.
     icon: HICON,
     main_receiver: flume::Receiver<Runnable>,
@@ -109,7 +110,7 @@ impl WindowsPlatform {
         };
         let icon = load_icon().unwrap_or_default();
         let state = RefCell::new(WindowsPlatformState::new());
-        let raw_window_handles = RwLock::new(SmallVec::new());
+        let raw_window_handles = Arc::new(RwLock::new(SmallVec::new()));
         let windows_version = WindowsVersion::new().context("Error retrieve windows version")?;
 
         Ok(Self {
@@ -128,10 +129,27 @@ impl WindowsPlatform {
         })
     }
 
+    fn begin_vsync_thread(&self) {
+        let raw_window_handles = self.raw_window_handles.clone();
+        std::thread::spawn(move || {
+            loop {
+                unsafe {
+                    DCompositionWaitForCompositorClock(None, INFINITE);
+                    for handle in raw_window_handles.read().iter() {
+                        RedrawWindow(Some(**handle), None, None, RDW_INVALIDATE)
+                            .ok()
+                            .log_err();
+                        // PostMessageW(Some(**handle), WM_GPUI_FORCE_DRAW_WINDOW, WPARAM(0), LPARAM(0)).log_err();
+                    }
+                }
+            }
+        });
+    }
+
     fn redraw_all(&self) {
         for handle in self.raw_window_handles.read().iter() {
             unsafe {
-                RedrawWindow(Some(*handle), None, None, RDW_INVALIDATE | RDW_UPDATENOW)
+                RedrawWindow(Some(**handle), None, None, RDW_INVALIDATE | RDW_UPDATENOW)
                     .ok()
                     .log_err();
             }
@@ -142,8 +160,8 @@ impl WindowsPlatform {
         self.raw_window_handles
             .read()
             .iter()
-            .find(|entry| *entry == &hwnd)
-            .and_then(|hwnd| try_get_window_inner(*hwnd))
+            .find(|entry| ***entry == hwnd)
+            .and_then(|hwnd| try_get_window_inner(**hwnd))
     }
 
     #[inline]
@@ -152,7 +170,7 @@ impl WindowsPlatform {
             .read()
             .iter()
             .for_each(|handle| unsafe {
-                PostMessageW(Some(*handle), message, wparam, lparam).log_err();
+                PostMessageW(Some(**handle), message, wparam, lparam).log_err();
             });
     }
 
@@ -160,7 +178,7 @@ impl WindowsPlatform {
         let mut lock = self.raw_window_handles.write();
         let index = lock
             .iter()
-            .position(|handle| *handle == target_window)
+            .position(|handle| **handle == target_window)
             .unwrap();
         lock.remove(index);
 
@@ -223,7 +241,8 @@ impl WindowsPlatform {
     fn handle_events(&self) -> bool {
         let mut msg = MSG::default();
         unsafe {
-            while PeekMessageW(&mut msg, None, 0, 0, PM_REMOVE).as_bool() {
+            // while PeekMessageW(&mut msg, None, 0, 0, PM_REMOVE).as_bool() {
+            while GetMessageW(&mut msg, None, 0, 0).as_bool() {
                 match msg.message {
                     WM_QUIT => return true,
                     WM_INPUTLANGCHANGE
@@ -305,11 +324,17 @@ impl WindowsPlatform {
         if active_window_hwnd.is_invalid() {
             return None;
         }
-        self.raw_window_handles
+        if self
+            .raw_window_handles
             .read()
             .iter()
-            .find(|&&hwnd| hwnd == active_window_hwnd)
-            .copied()
+            .find(|&&hwnd| *hwnd == active_window_hwnd)
+            .is_some()
+        {
+            Some(active_window_hwnd)
+        } else {
+            None
+        }
     }
 }
 
@@ -340,12 +365,13 @@ impl Platform for WindowsPlatform {
 
     fn run(&self, on_finish_launching: Box<dyn 'static + FnOnce()>) {
         on_finish_launching();
-        loop {
-            if self.handle_events() {
-                break;
-            }
-            self.redraw_all();
+        self.begin_vsync_thread();
+        // loop {
+        if self.handle_events() {
+            // break;
         }
+        //     self.redraw_all();
+        // }
 
         if let Some(ref mut callback) = self.state.borrow_mut().callbacks.quit {
             callback();
@@ -438,7 +464,7 @@ impl Platform for WindowsPlatform {
     ) -> Result<Box<dyn PlatformWindow>> {
         let window = WindowsWindow::new(handle, options, self.generate_creation_info())?;
         let handle = window.get_raw_handle();
-        self.raw_window_handles.write().push(handle);
+        self.raw_window_handles.write().push(handle.into());
 
         Ok(Box::new(window))
     }

crates/gpui/src/platform/windows/wrapper.rs 🔗

@@ -1,6 +1,9 @@
 use std::ops::Deref;
 
-use windows::Win32::{Foundation::HANDLE, UI::WindowsAndMessaging::HCURSOR};
+use windows::Win32::{
+    Foundation::{HANDLE, HWND},
+    UI::WindowsAndMessaging::HCURSOR,
+};
 
 #[derive(Debug, Clone, Copy)]
 pub(crate) struct SafeHandle {
@@ -45,3 +48,31 @@ impl Deref for SafeCursor {
         &self.raw
     }
 }
+
+#[derive(Clone, Copy)]
+pub(crate) struct SafeHwnd {
+    raw: HWND,
+}
+
+unsafe impl Send for SafeHwnd {}
+unsafe impl Sync for SafeHwnd {}
+
+impl From<HWND> for SafeHwnd {
+    fn from(value: HWND) -> Self {
+        SafeHwnd { raw: value }
+    }
+}
+
+impl From<SafeHwnd> for HWND {
+    fn from(value: SafeHwnd) -> Self {
+        value.raw
+    }
+}
+
+impl Deref for SafeHwnd {
+    type Target = HWND;
+
+    fn deref(&self) -> &Self::Target {
+        &self.raw
+    }
+}