diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs index f6d9be68ab0773ca14e99a2f42bde3cb88d031c2..ef7a720e7f6f06f61a885424139b010e106fb341 100644 --- a/crates/gpui/src/window.rs +++ b/crates/gpui/src/window.rs @@ -918,26 +918,85 @@ pub(crate) struct ElementStateBox { } fn default_bounds(display_id: Option, cx: &mut App) -> Bounds { - const DEFAULT_WINDOW_OFFSET: Point = point(px(0.), px(35.)); - - // TODO, BUG: if you open a window with the currently active window - // on the stack, this will erroneously select the 'unwrap_or_else' - // code path - cx.active_window() - .and_then(|w| w.update(cx, |_, window, _| window.bounds()).ok()) - .map(|mut bounds| { - bounds.origin += DEFAULT_WINDOW_OFFSET; - bounds - }) - .unwrap_or_else(|| { - let display = display_id - .map(|id| cx.find_display(id)) - .unwrap_or_else(|| cx.primary_display()); - - display - .map(|display| display.default_bounds()) - .unwrap_or_else(|| Bounds::new(point(px(0.), px(0.)), DEFAULT_WINDOW_SIZE)) - }) + #[cfg(target_os = "macos")] + { + const CASCADE_OFFSET: f32 = 25.0; + + let display = display_id + .map(|id| cx.find_display(id)) + .unwrap_or_else(|| cx.primary_display()); + + let display_bounds = display + .as_ref() + .map(|d| d.bounds()) + .unwrap_or_else(|| Bounds::new(point(px(0.), px(0.)), DEFAULT_WINDOW_SIZE)); + + // TODO, BUG: if you open a window with the currently active window + // on the stack, this will erroneously select the 'unwrap_or_else' + // code path + let (base_origin, base_size) = cx + .active_window() + .and_then(|w| { + w.update(cx, |_, window, _| { + let bounds = window.bounds(); + (bounds.origin, bounds.size) + }) + .ok() + }) + .unwrap_or_else(|| { + let default_bounds = display + .as_ref() + .map(|d| d.default_bounds()) + .unwrap_or_else(|| Bounds::new(point(px(0.), px(0.)), DEFAULT_WINDOW_SIZE)); + (default_bounds.origin, default_bounds.size) + }); + + let cascade_offset = point(px(CASCADE_OFFSET), px(CASCADE_OFFSET)); + let proposed_origin = base_origin + cascade_offset; + let proposed_bounds = Bounds::new(proposed_origin, base_size); + + let display_right = display_bounds.origin.x + display_bounds.size.width; + let display_bottom = display_bounds.origin.y + display_bounds.size.height; + let window_right = proposed_bounds.origin.x + proposed_bounds.size.width; + let window_bottom = proposed_bounds.origin.y + proposed_bounds.size.height; + + let fits_horizontally = window_right <= display_right; + let fits_vertically = window_bottom <= display_bottom; + + let final_origin = match (fits_horizontally, fits_vertically) { + (true, true) => proposed_origin, + (false, true) => point(display_bounds.origin.x, base_origin.y), + (true, false) => point(base_origin.x, display_bounds.origin.y), + (false, false) => display_bounds.origin, + }; + + Bounds::new(final_origin, base_size) + } + + #[cfg(not(target_os = "macos"))] + { + const DEFAULT_WINDOW_OFFSET: Point = point(px(0.), px(35.)); + + // TODO, BUG: if you open a window with the currently active window + // on the stack, this will erroneously select the 'unwrap_or_else' + // code path + cx.active_window() + .and_then(|w| w.update(cx, |_, window, _| window.bounds()).ok()) + .map(|mut bounds| { + bounds.origin += DEFAULT_WINDOW_OFFSET; + bounds + }) + .unwrap_or_else(|| { + let display = display_id + .map(|id| cx.find_display(id)) + .unwrap_or_else(|| cx.primary_display()); + + display + .as_ref() + .map(|display| display.default_bounds()) + .unwrap_or_else(|| Bounds::new(point(px(0.), px(0.)), DEFAULT_WINDOW_SIZE)) + }) + } } impl Window {