From 1593b1e13d3a842fcb115873c5bd25f85c929bfe Mon Sep 17 00:00:00 2001 From: Kay Simmons Date: Thu, 26 Jan 2023 16:35:00 -0800 Subject: [PATCH] window position restoration working --- crates/gpui/src/platform/mac/geometry.rs | 38 +++++++++++----------- crates/gpui/src/platform/mac/window.rs | 21 +++++++------ crates/workspace/src/workspace.rs | 40 +++++++++++++++++++++--- 3 files changed, 66 insertions(+), 33 deletions(-) diff --git a/crates/gpui/src/platform/mac/geometry.rs b/crates/gpui/src/platform/mac/geometry.rs index a59d72a796..0f3b1f6fce 100644 --- a/crates/gpui/src/platform/mac/geometry.rs +++ b/crates/gpui/src/platform/mac/geometry.rs @@ -42,31 +42,16 @@ impl RectFExt for RectF { } fn to_ns_rect(&self) -> NSRect { - dbg!(&self); NSRect::new( NSPoint::new( - dbg!(self.origin_x() as f64), - dbg!(-(self.origin_y() - self.height()) as f64), + self.origin_x() as f64, + -(self.origin_y() + self.height()) as f64, ), NSSize::new(self.width() as f64, self.height() as f64), ) } } -pub trait NSPointExt { - /// Converts self to a Vector2F with y axis pointing down. - /// Also takes care of converting from window scaled coordinates to screen coordinates - fn to_window_vector2f(&self, native_window: id) -> Vector2F; -} -impl NSPointExt for NSPoint { - fn to_window_vector2f(&self, native_window: id) -> Vector2F { - unsafe { - let point: NSPoint = msg_send![native_window, convertPointFromScreen: self]; - vec2f(point.x as f32, -point.y as f32) - } - } -} - pub trait NSRectExt { /// Converts self to a RectF with y axis pointing down. /// The resulting RectF will have an origin at the top left of the rectangle. @@ -77,11 +62,13 @@ pub trait NSRectExt { /// The resulting RectF will have an origin at the top left of the rectangle. /// Unlike to_screen_ns_rect, coordinates are not converted and are assumed to already be in screen scale fn to_rectf(&self) -> RectF; + + fn intersects(&self, other: Self) -> bool; } impl NSRectExt for NSRect { fn to_window_rectf(&self, native_window: id) -> RectF { unsafe { - dbg!(self.origin.x); + self.origin.x; let rect: NSRect = native_window.convertRectFromScreen_(*self); rect.to_rectf() } @@ -90,10 +77,21 @@ impl NSRectExt for NSRect { fn to_rectf(&self) -> RectF { RectF::new( vec2f( - dbg!(self.origin.x as f32), - dbg!(-(self.origin.y - self.size.height) as f32), + self.origin.x as f32, + -(self.origin.y + self.size.height) as f32, ), vec2f(self.size.width as f32, self.size.height as f32), ) } + + fn intersects(&self, other: Self) -> bool { + self.size.width > 0. + && self.size.height > 0. + && other.size.width > 0. + && other.size.height > 0. + && self.origin.x <= other.origin.x + other.size.width + && self.origin.x + self.size.width >= other.origin.x + && self.origin.y <= other.origin.y + other.size.height + && self.origin.y + self.size.height >= other.origin.y + } } diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index ecea0604f5..bc934703be 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -371,14 +371,8 @@ impl WindowState { return WindowBounds::Fullscreen; } - let screen_frame = self - .native_window - .screen() - .visibleFrame() - .to_window_rectf(self.native_window); let window_frame = self.frame(); - - if screen_frame == window_frame { + if window_frame == self.native_window.screen().visibleFrame().to_rectf() { WindowBounds::Maximized } else { WindowBounds::Fixed(window_frame) @@ -388,7 +382,10 @@ impl WindowState { // Returns the window bounds in window coordinates fn frame(&self) -> RectF { - unsafe { NSWindow::frame(self.native_window).to_window_rectf(self.native_window) } + unsafe { + let ns_frame = NSWindow::frame(self.native_window); + ns_frame.to_rectf() + } } fn content_size(&self) -> Vector2F { @@ -474,7 +471,13 @@ impl Window { native_window.setFrame_display_(screen.visibleFrame(), YES); } WindowBounds::Fixed(rect) => { - native_window.setFrame_display_(rect.to_screen_ns_rect(native_window), YES); + let screen_frame = screen.visibleFrame(); + let ns_rect = rect.to_ns_rect(); + if ns_rect.intersects(screen_frame) { + native_window.setFrame_display_(ns_rect, YES); + } else { + native_window.setFrame_display_(screen_frame, YES); + } } } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 4602e498f1..80c52e0bc8 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -682,10 +682,28 @@ impl Workspace { DB.next_id().await.unwrap_or(0) }; - let (bounds, display) = dbg!(serialized_workspace + let (bounds, display) = serialized_workspace .as_ref() .and_then(|sw| sw.bounds.zip(sw.display)) - .unzip()); + .and_then(|(mut bounds, display)| { + // Stored bounds are relative to the containing display. So convert back to global coordinates if that screen still exists + if let WindowBounds::Fixed(mut window_bounds) = bounds { + if let Some(screen) = cx.platform().screen_by_id(display) { + let screen_bounds = screen.bounds(); + window_bounds + .set_origin_x(window_bounds.origin_x() + screen_bounds.origin_x()); + window_bounds + .set_origin_y(window_bounds.origin_y() + screen_bounds.origin_y()); + bounds = WindowBounds::Fixed(window_bounds); + } else { + // Screen no longer exists. Return none here. + return None; + } + } + + Some((bounds, display)) + }) + .unzip(); // Use the serialized workspace to construct the new window let (_, workspace) = cx.add_window( @@ -699,9 +717,23 @@ impl Workspace { cx, ); (app_state.initialize_workspace)(&mut workspace, &app_state, cx); - cx.observe_window_bounds(move |_, bounds, display, cx| { + cx.observe_window_bounds(move |_, mut bounds, display, cx| { + // Transform fixed bounds to be stored in terms of the containing display + if let WindowBounds::Fixed(mut window_bounds) = bounds { + if let Some(screen) = cx.platform().screen_by_id(display) { + let screen_bounds = screen.bounds(); + window_bounds.set_origin_x( + window_bounds.origin_x() - screen_bounds.origin_x(), + ); + window_bounds.set_origin_y( + window_bounds.origin_y() - screen_bounds.origin_y(), + ); + bounds = WindowBounds::Fixed(window_bounds); + } + } + cx.background() - .spawn(DB.set_window_bounds(workspace_id, dbg!(bounds), dbg!(display))) + .spawn(DB.set_window_bounds(workspace_id, bounds, display)) .detach_and_log_err(cx); }) .detach();