From 64ebbb4afc79d1e5ded55111b6d35232b1101142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=B0=8F=E7=99=BD?= <364772080@qq.com> Date: Tue, 19 Mar 2024 00:49:40 +0800 Subject: [PATCH] Update `display` info when window moved to another monitor (#9360) Release Notes: - N/A --- crates/gpui/src/platform/windows/display.rs | 41 +++++++++++++++------ crates/gpui/src/platform/windows/window.rs | 31 +++++++++++++--- 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/crates/gpui/src/platform/windows/display.rs b/crates/gpui/src/platform/windows/display.rs index 5f766339be6c71..a3784cf83c20ba 100644 --- a/crates/gpui/src/platform/windows/display.rs +++ b/crates/gpui/src/platform/windows/display.rs @@ -11,6 +11,7 @@ use crate::{Bounds, DisplayId, GlobalPixels, PlatformDisplay, Point, Size}; #[derive(Debug)] pub(crate) struct WindowsDisplay { + pub handle: HMONITOR, pub display_id: DisplayId, bounds: Bounds, uuid: Uuid, @@ -28,6 +29,7 @@ impl WindowsDisplay { let uuid = generate_uuid(&info.szDevice); Some(WindowsDisplay { + handle: screen, display_id, bounds: Bounds { origin: Point { @@ -43,12 +45,39 @@ impl WindowsDisplay { }) } + pub fn new_with_handle(monitor: HMONITOR) -> Self { + let info = get_monitor_info(monitor).expect("unable to get monitor info"); + let size = info.monitorInfo.rcMonitor; + let uuid = generate_uuid(&info.szDevice); + let display_id = available_monitors() + .iter() + .position(|handle| handle.0 == monitor.0) + .unwrap(); + + WindowsDisplay { + handle: monitor, + display_id: DisplayId(display_id as _), + bounds: Bounds { + origin: Point { + x: GlobalPixels(size.left as f32), + y: GlobalPixels(size.top as f32), + }, + size: Size { + width: GlobalPixels((size.right - size.left) as f32), + height: GlobalPixels((size.bottom - size.top) as f32), + }, + }, + uuid, + } + } + fn new_with_handle_and_id(handle: HMONITOR, display_id: DisplayId) -> Self { let info = get_monitor_info(handle).expect("unable to get monitor info"); let size = info.monitorInfo.rcMonitor; let uuid = generate_uuid(&info.szDevice); WindowsDisplay { + handle, display_id, bounds: Bounds { origin: Point { @@ -75,17 +104,7 @@ impl WindowsDisplay { ); return None; } - let Some(display_id) = available_monitors() - .iter() - .position(|handle| handle.0 == monitor.0) - else { - return None; - }; - - Some(WindowsDisplay::new_with_handle_and_id( - monitor, - DisplayId(display_id as _), - )) + Some(WindowsDisplay::new_with_handle(monitor)) } pub fn displays() -> Vec> { diff --git a/crates/gpui/src/platform/windows/window.rs b/crates/gpui/src/platform/windows/window.rs index 04939657bb9087..2331179c4aaba4 100644 --- a/crates/gpui/src/platform/windows/window.rs +++ b/crates/gpui/src/platform/windows/window.rs @@ -49,6 +49,7 @@ pub(crate) struct WindowsWindowInner { platform_inner: Rc, pub(crate) handle: AnyWindowHandle, scale_factor: f32, + display: RefCell>, } impl WindowsWindowInner { @@ -57,6 +58,7 @@ impl WindowsWindowInner { cs: &CREATESTRUCTW, platform_inner: Rc, handle: AnyWindowHandle, + display: Rc, ) -> Self { let origin = Cell::new(Point::new((cs.x as f64).into(), (cs.y as f64).into())); let size = Cell::new(Size { @@ -101,6 +103,7 @@ impl WindowsWindowInner { }; let renderer = RefCell::new(BladeRenderer::new(gpu, extent)); let callbacks = RefCell::new(Callbacks::default()); + let display = RefCell::new(display); Self { hwnd, origin, @@ -112,6 +115,7 @@ impl WindowsWindowInner { platform_inner, handle, scale_factor: 1.0, + display, } } @@ -251,6 +255,22 @@ impl WindowsWindowInner { let x = lparam.signed_loword() as f64; let y = lparam.signed_hiword() as f64; self.origin.set(Point::new(x.into(), y.into())); + let size = self.size.get(); + let center_x = x as f32 + size.width.0 / 2.0; + let center_y = y as f32 + size.height.0 / 2.0; + let monitor_bounds = self.display.borrow().bounds(); + if center_x < monitor_bounds.left().0 + || center_x > monitor_bounds.right().0 + || center_y < monitor_bounds.top().0 + || center_y > monitor_bounds.bottom().0 + { + // center of the window may have moved to another monitor + let monitor = unsafe { MonitorFromWindow(self.hwnd, MONITOR_DEFAULTTONULL) }; + if !monitor.is_invalid() && self.display.borrow().handle != monitor { + // we will get the same monitor if we only have one + (*self.display.borrow_mut()) = Rc::new(WindowsDisplay::new_with_handle(monitor)); + } + } let mut callbacks = self.callbacks.borrow_mut(); if let Some(callback) = callbacks.moved.as_mut() { callback() @@ -1015,13 +1035,13 @@ struct Callbacks { pub(crate) struct WindowsWindow { inner: Rc, drag_drop_handler: IDropTarget, - display: Rc, } struct WindowCreateContext { inner: Option>, platform_inner: Rc, handle: AnyWindowHandle, + display: Rc, } impl WindowsWindow { @@ -1051,6 +1071,9 @@ impl WindowsWindow { inner: None, platform_inner: platform_inner.clone(), handle, + // todo(windows) move window to target monitor + // options.display_id + display: Rc::new(WindowsDisplay::primary_monitor().unwrap()), }; let lpparam = Some(&context as *const _ as *const _); unsafe { @@ -1079,12 +1102,9 @@ impl WindowsWindow { }; drag_drop_handler }; - // todo(windows) move window to target monitor - // options.display_id let wnd = Self { inner: context.inner.unwrap(), drag_drop_handler, - display: Rc::new(WindowsDisplay::primary_monitor().unwrap()), }; platform_inner .raw_window_handles @@ -1161,7 +1181,7 @@ impl PlatformWindow for WindowsWindow { } fn display(&self) -> Rc { - self.display.clone() + self.inner.display.borrow().clone() } fn mouse_position(&self) -> Point { @@ -1504,6 +1524,7 @@ unsafe extern "system" fn wnd_proc( cs, ctx.platform_inner.clone(), ctx.handle, + ctx.display.clone(), )); let weak = Box::new(Rc::downgrade(&inner)); unsafe { set_window_long(hwnd, GWLP_USERDATA, Box::into_raw(weak) as isize) };