@@ -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<GlobalPixels>,
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<Rc<dyn PlatformDisplay>> {
@@ -49,6 +49,7 @@ pub(crate) struct WindowsWindowInner {
platform_inner: Rc<WindowsPlatformInner>,
pub(crate) handle: AnyWindowHandle,
scale_factor: f32,
+ display: RefCell<Rc<WindowsDisplay>>,
}
impl WindowsWindowInner {
@@ -57,6 +58,7 @@ impl WindowsWindowInner {
cs: &CREATESTRUCTW,
platform_inner: Rc<WindowsPlatformInner>,
handle: AnyWindowHandle,
+ display: Rc<WindowsDisplay>,
) -> 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<WindowsWindowInner>,
drag_drop_handler: IDropTarget,
- display: Rc<WindowsDisplay>,
}
struct WindowCreateContext {
inner: Option<Rc<WindowsWindowInner>>,
platform_inner: Rc<WindowsPlatformInner>,
handle: AnyWindowHandle,
+ display: Rc<WindowsDisplay>,
}
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<dyn PlatformDisplay> {
- self.display.clone()
+ self.inner.display.borrow().clone()
}
fn mouse_position(&self) -> Point<Pixels> {
@@ -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) };