Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update display info when window moved to another monitor #9360

Merged
merged 3 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 30 additions & 11 deletions crates/gpui/src/platform/windows/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -28,6 +29,7 @@ impl WindowsDisplay {
let uuid = generate_uuid(&info.szDevice);

Some(WindowsDisplay {
handle: screen,
display_id,
bounds: Bounds {
origin: Point {
Expand All @@ -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 {
Expand All @@ -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>> {
Expand Down
31 changes: 26 additions & 5 deletions crates/gpui/src/platform/windows/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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,
Expand All @@ -112,6 +115,7 @@ impl WindowsWindowInner {
platform_inner,
handle,
scale_factor: 1.0,
display,
}
}

Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -1012,13 +1032,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 {
Expand Down Expand Up @@ -1048,6 +1068,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 {
Expand Down Expand Up @@ -1076,12 +1099,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
Expand Down Expand Up @@ -1158,7 +1178,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> {
Expand Down Expand Up @@ -1501,6 +1521,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) };
Expand Down
Loading