diff --git a/Cargo.toml b/Cargo.toml index 1e4c2bcd55..041c3214a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -343,17 +343,6 @@ features = [ "Win32_Globalization", "Win32_Graphics_DirectComposition", "Win32_Graphics_Gdi", - "Win32_UI_Controls", - "Win32_Graphics_DirectWrite", - "Win32_UI_WindowsAndMessaging", - "Win32_UI_Input_KeyboardAndMouse", - "Win32_UI_Shell", - "Win32_System_Com", - "Win32_UI_HiDpi", - "Win32_UI_Controls", - "Win32_System_SystemInformation", - "Win32_System_SystemServices", - "Win32_System_Time", "Win32_Security", "Win32_Storage_FileSystem", "Win32_System_Com", diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 0bc3d91a95..f2aa5c1184 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -13,12 +13,12 @@ use rpc::proto; use std::sync::Arc; use theme::ActiveTheme; use ui::{ - h_flex, platform_titlebar, popover_menu, prelude::*, Avatar, AvatarAudioStatusIndicator, - Button, ButtonLike, ButtonStyle, ContextMenu, Icon, IconButton, IconName, TintColor, Tooltip, + h_flex, popover_menu, prelude::*, Avatar, AvatarAudioStatusIndicator, Button, ButtonLike, + ButtonStyle, ContextMenu, Icon, IconButton, IconName, TintColor, Tooltip, }; use util::ResultExt; use vcs_menu::{build_branch_list, BranchList, OpenRecent as ToggleVcsMenu}; -use workspace::{notifications::NotifyResultExt, Workspace}; +use workspace::{notifications::NotifyResultExt, titlebar_height, Workspace}; const MAX_PROJECT_NAME_LENGTH: usize = 40; const MAX_BRANCH_NAME_LENGTH: usize = 40; @@ -58,18 +58,26 @@ impl Render for CollabTitlebarItem { let project_id = self.project.read(cx).remote_id(); let workspace = self.workspace.upgrade(); - platform_titlebar("collab-titlebar") - .titlebar_bg(cx.theme().colors().title_bar_background) - // note: on windows titlebar behaviour is handled by the platform implementation - .when(cfg!(not(windows)), |this| { - this.on_click(|event, cx| { - if event.up.click_count == 2 { - cx.zoom_window(); - } - }) - }) - .px_2() + h_flex() + .id("titlebar") .justify_between() + .w_full() + .h(titlebar_height(cx)) + .map(|this| { + if cx.is_fullscreen() { + this.pl_2() + } else { + // Use pixels here instead of a rem-based size because the macOS traffic + // lights are a static size, and don't scale with the rest of the UI. + this.pl(px(80.)) + } + }) + .bg(cx.theme().colors().title_bar_background) + .on_click(|event, cx| { + if event.up.click_count == 2 { + cx.zoom_window(); + } + }) // left side .child( h_flex() diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index 73a41f74e3..ecebbd2849 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -22,10 +22,10 @@ mod test; mod windows; use crate::{ - Action, AnyWindowHandle, AsyncWindowContext, BackgroundExecutor, Bounds, DevicePixels, - DispatchEventResult, Font, FontId, FontMetrics, FontRun, ForegroundExecutor, GlobalPixels, - GlyphId, Keymap, LineLayout, Pixels, PlatformInput, Point, RenderGlyphParams, - RenderImageParams, RenderSvgParams, Scene, SharedString, Size, Task, TaskLabel, WindowContext, + Action, AnyWindowHandle, AsyncWindowContext, BackgroundExecutor, Bounds, DevicePixels, Font, + FontId, FontMetrics, FontRun, ForegroundExecutor, GlobalPixels, GlyphId, Keymap, LineLayout, + Pixels, PlatformInput, Point, RenderGlyphParams, RenderImageParams, RenderSvgParams, Scene, + SharedString, Size, Task, TaskLabel, WindowContext, }; use anyhow::Result; use async_task::Runnable; @@ -168,7 +168,6 @@ unsafe impl Send for DisplayId {} pub(crate) trait PlatformWindow: HasWindowHandle + HasDisplayHandle { fn bounds(&self) -> Bounds; - fn is_maximized(&self) -> bool; fn content_size(&self) -> Size; fn scale_factor(&self) -> f32; fn titlebar_height(&self) -> Pixels; @@ -195,7 +194,7 @@ pub(crate) trait PlatformWindow: HasWindowHandle + HasDisplayHandle { fn toggle_fullscreen(&self); fn is_fullscreen(&self) -> bool; fn on_request_frame(&self, callback: Box); - fn on_input(&self, callback: Box DispatchEventResult>); + fn on_input(&self, callback: Box bool>); fn on_active_status_change(&self, callback: Box); fn on_resize(&self, callback: Box, f32)>); fn on_fullscreen(&self, callback: Box); diff --git a/crates/gpui/src/platform/linux/wayland/window.rs b/crates/gpui/src/platform/linux/wayland/window.rs index 6c11c250fd..897a32a420 100644 --- a/crates/gpui/src/platform/linux/wayland/window.rs +++ b/crates/gpui/src/platform/linux/wayland/window.rs @@ -29,7 +29,7 @@ use crate::{ #[derive(Default)] pub(crate) struct Callbacks { request_frame: Option>, - input: Option crate::DispatchEventResult>>, + input: Option bool>>, active_status_change: Option>, resize: Option, f32)>>, fullscreen: Option>, @@ -237,7 +237,7 @@ impl WaylandWindowState { pub fn handle_input(&self, input: PlatformInput) { if let Some(ref mut fun) = self.callbacks.borrow_mut().input { - if !fun(input.clone()).propagate { + if fun(input.clone()) { return; } } @@ -279,11 +279,6 @@ impl PlatformWindow for WaylandWindow { unimplemented!() } - // todo(linux) - fn is_maximized(&self) -> bool { - unimplemented!() - } - fn content_size(&self) -> Size { let inner = self.0.inner.borrow_mut(); Size { @@ -383,7 +378,7 @@ impl PlatformWindow for WaylandWindow { self.0.callbacks.borrow_mut().request_frame = Some(callback); } - fn on_input(&self, callback: Box crate::DispatchEventResult>) { + fn on_input(&self, callback: Box bool>) { self.0.callbacks.borrow_mut().input = Some(callback); } diff --git a/crates/gpui/src/platform/linux/x11/window.rs b/crates/gpui/src/platform/linux/x11/window.rs index 9078aa3a9e..3b07b5c587 100644 --- a/crates/gpui/src/platform/linux/x11/window.rs +++ b/crates/gpui/src/platform/linux/x11/window.rs @@ -31,7 +31,7 @@ use super::X11Display; #[derive(Default)] struct Callbacks { request_frame: Option>, - input: Option crate::DispatchEventResult>>, + input: Option bool>>, active_status_change: Option>, resize: Option, f32)>>, fullscreen: Option>, @@ -303,7 +303,7 @@ impl X11WindowState { pub fn handle_input(&self, input: PlatformInput) { if let Some(ref mut fun) = self.callbacks.borrow_mut().input { - if !fun(input.clone()).propagate { + if fun(input.clone()) { return; } } @@ -333,11 +333,6 @@ impl PlatformWindow for X11Window { .map(|v| GlobalPixels(v as f32)) } - // todo(linux) - fn is_maximized(&self) -> bool { - unimplemented!() - } - fn content_size(&self) -> Size { self.0.inner.borrow_mut().content_size() } @@ -456,7 +451,7 @@ impl PlatformWindow for X11Window { self.0.callbacks.borrow_mut().request_frame = Some(callback); } - fn on_input(&self, callback: Box crate::DispatchEventResult>) { + fn on_input(&self, callback: Box bool>) { self.0.callbacks.borrow_mut().input = Some(callback); } diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index 04f3873e10..8240b21101 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -324,7 +324,7 @@ struct MacWindowState { renderer: renderer::Renderer, kind: WindowKind, request_frame_callback: Option>, - event_callback: Option crate::DispatchEventResult>>, + event_callback: Option bool>>, activate_callback: Option>, resize_callback: Option, f32)>>, fullscreen_callback: Option>, @@ -411,14 +411,6 @@ impl MacWindowState { self.display_link = None; } - fn is_maximized(&self) -> bool { - unsafe { - let bounds = self.bounds(); - let screen_size = self.native_window.screen().visibleFrame().into(); - bounds.size == screen_size - } - } - fn is_fullscreen(&self) -> bool { unsafe { let style_mask = self.native_window.styleMask(); @@ -724,10 +716,6 @@ impl PlatformWindow for MacWindow { self.0.as_ref().lock().bounds() } - fn is_maximized(&self) -> bool { - self.0.as_ref().lock().is_maximized() - } - fn content_size(&self) -> Size { self.0.as_ref().lock().content_size() } @@ -980,7 +968,7 @@ impl PlatformWindow for MacWindow { self.0.as_ref().lock().request_frame_callback = Some(callback); } - fn on_input(&self, callback: Box crate::DispatchEventResult>) { + fn on_input(&self, callback: Box bool>) { self.0.as_ref().lock().event_callback = Some(callback); } @@ -1203,7 +1191,7 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent: window_state.lock().previous_keydown_inserted_text = Some(text.clone()); if let Some(callback) = callback.as_mut() { event.keystroke.ime_key = Some(text.clone()); - handled = !callback(PlatformInput::KeyDown(event)).propagate; + handled = callback(PlatformInput::KeyDown(event)); } } } @@ -1216,7 +1204,7 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent: let is_held = event.is_held; if let Some(callback) = callback.as_mut() { - handled = !callback(PlatformInput::KeyDown(event)).propagate; + handled = callback(PlatformInput::KeyDown(event)); } if !handled && is_held { diff --git a/crates/gpui/src/platform/test/window.rs b/crates/gpui/src/platform/test/window.rs index 7cc1900d76..f9150b409a 100644 --- a/crates/gpui/src/platform/test/window.rs +++ b/crates/gpui/src/platform/test/window.rs @@ -1,7 +1,7 @@ use crate::{ - AnyWindowHandle, AtlasKey, AtlasTextureId, AtlasTile, Bounds, DispatchEventResult, - GlobalPixels, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, - PlatformWindow, Point, Size, TestPlatform, TileId, WindowAppearance, WindowParams, + AnyWindowHandle, AtlasKey, AtlasTextureId, AtlasTile, Bounds, GlobalPixels, Pixels, + PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point, + Size, TestPlatform, TileId, WindowAppearance, WindowParams, }; use collections::HashMap; use parking_lot::Mutex; @@ -20,7 +20,7 @@ pub(crate) struct TestWindowState { platform: Weak, sprite_atlas: Arc, pub(crate) should_close_handler: Option bool>>, - input_callback: Option DispatchEventResult>>, + input_callback: Option bool>>, active_status_change_callback: Option>, resize_callback: Option, f32)>>, moved_callback: Option>, @@ -102,7 +102,7 @@ impl TestWindow { drop(lock); let result = callback(event); self.0.lock().input_callback = Some(callback); - !result.propagate + result } } @@ -111,10 +111,6 @@ impl PlatformWindow for TestWindow { self.0.lock().bounds } - fn is_maximized(&self) -> bool { - unimplemented!() - } - fn content_size(&self) -> Size { self.bounds().size.into() } @@ -124,7 +120,7 @@ impl PlatformWindow for TestWindow { } fn titlebar_height(&self) -> Pixels { - 32.0.into() + unimplemented!() } fn appearance(&self) -> WindowAppearance { @@ -212,7 +208,7 @@ impl PlatformWindow for TestWindow { fn on_request_frame(&self, _callback: Box) {} - fn on_input(&self, callback: Box DispatchEventResult>) { + fn on_input(&self, callback: Box bool>) { self.0.lock().input_callback = Some(callback) } diff --git a/crates/gpui/src/platform/windows/display.rs b/crates/gpui/src/platform/windows/display.rs index 6eff3c7870..5c67cb80b3 100644 --- a/crates/gpui/src/platform/windows/display.rs +++ b/crates/gpui/src/platform/windows/display.rs @@ -1,6 +1,7 @@ +use std::rc::Rc; + use itertools::Itertools; use smallvec::SmallVec; -use std::rc::Rc; use uuid::Uuid; use windows::Win32::{Foundation::*, Graphics::Gdi::*}; diff --git a/crates/gpui/src/platform/windows/text_system.rs b/crates/gpui/src/platform/windows/text_system.rs index f68c74c7f7..7f6c356d0a 100644 --- a/crates/gpui/src/platform/windows/text_system.rs +++ b/crates/gpui/src/platform/windows/text_system.rs @@ -5,9 +5,9 @@ use crate::{ }; use anyhow::{anyhow, Context, Ok, Result}; use collections::HashMap; -use cosmic_text::Font as CosmicTextFont; use cosmic_text::{ - fontdb::Query, Attrs, AttrsList, BufferLine, CacheKey, Family, FontSystem, SwashCache, + fontdb::Query, Attrs, AttrsList, BufferLine, CacheKey, Family, Font as CosmicTextFont, + FontSystem, SwashCache, }; use parking_lot::{RwLock, RwLockUpgradableReadGuard}; use pathfinder_geometry::{ @@ -31,6 +31,10 @@ struct WindowsTextSystemState { impl WindowsTextSystem { pub(crate) fn new() -> Self { let mut font_system = FontSystem::new(); + + // todo(windows) make font loading non-blocking + font_system.db_mut().load_system_fonts(); + Self(RwLock::new(WindowsTextSystemState { font_system, swash_cache: SwashCache::new(), @@ -218,11 +222,10 @@ impl WindowsTextSystemState { .get_font_matches(Attrs::new().family(cosmic_text::Family::Name(name))); for font in family.as_ref() { let font = self.font_system.get_font(*font).unwrap(); - // TODO: figure out why this is causing fluent icons from loading - // if font.as_swash().charmap().map('m') == 0 { - // self.font_system.db_mut().remove_face(font.id()); - // continue; - // }; + if font.as_swash().charmap().map('m') == 0 { + self.font_system.db_mut().remove_face(font.id()); + continue; + }; let font_id = FontId(self.fonts.len()); font_ids.push(font_id); diff --git a/crates/gpui/src/platform/windows/util.rs b/crates/gpui/src/platform/windows/util.rs index 7093f564ca..e310965577 100644 --- a/crates/gpui/src/platform/windows/util.rs +++ b/crates/gpui/src/platform/windows/util.rs @@ -42,29 +42,3 @@ impl HiLoWord for LPARAM { (self.0 & 0xFFFF) as i16 } } - -pub(crate) unsafe fn get_window_long(hwnd: HWND, nindex: WINDOW_LONG_PTR_INDEX) -> isize { - #[cfg(target_pointer_width = "64")] - unsafe { - GetWindowLongPtrW(hwnd, nindex) - } - #[cfg(target_pointer_width = "32")] - unsafe { - GetWindowLongW(hwnd, nindex) as isize - } -} - -pub(crate) unsafe fn set_window_long( - hwnd: HWND, - nindex: WINDOW_LONG_PTR_INDEX, - dwnewlong: isize, -) -> isize { - #[cfg(target_pointer_width = "64")] - unsafe { - SetWindowLongPtrW(hwnd, nindex, dwnewlong) - } - #[cfg(target_pointer_width = "32")] - unsafe { - SetWindowLongW(hwnd, nindex, dwnewlong as i32) as isize - } -} diff --git a/crates/gpui/src/platform/windows/window.rs b/crates/gpui/src/platform/windows/window.rs index b491a8d174..cbb0a472a6 100644 --- a/crates/gpui/src/platform/windows/window.rs +++ b/crates/gpui/src/platform/windows/window.rs @@ -1,4 +1,6 @@ #![deny(unsafe_op_in_unsafe_fn)] +// todo(windows): remove +#![allow(unused_variables)] use std::{ any::Any, @@ -12,7 +14,6 @@ use std::{ sync::{Arc, Once}, }; -use ::util::ResultExt; use blade_graphics as gpu; use futures::channel::oneshot::{self, Receiver}; use itertools::Itertools; @@ -27,7 +28,6 @@ use windows::{ System::{Com::*, Ole::*, SystemServices::*}, UI::{ Controls::*, - HiDpi::*, Input::{Ime::*, KeyboardAndMouse::*}, Shell::*, WindowsAndMessaging::*, @@ -48,7 +48,6 @@ pub(crate) struct WindowsWindowInner { callbacks: RefCell, platform_inner: Rc, handle: AnyWindowHandle, - scale_factor: f32, } impl WindowsWindowInner { @@ -111,48 +110,9 @@ impl WindowsWindowInner { callbacks, platform_inner, handle, - scale_factor: 1.0, } } - fn is_maximized(&self) -> bool { - let mut placement = WINDOWPLACEMENT::default(); - placement.length = std::mem::size_of::() as u32; - if unsafe { GetWindowPlacement(self.hwnd, &mut placement) }.is_ok() { - return placement.showCmd == SW_SHOWMAXIMIZED.0 as u32; - } - return false; - } - - fn get_titlebar_rect(&self) -> anyhow::Result { - let top_and_bottom_borders = 2; - let theme = unsafe { OpenThemeData(self.hwnd, w!("WINDOW")) }; - let title_bar_size = unsafe { - GetThemePartSize( - theme, - HDC::default(), - WP_CAPTION.0, - CS_ACTIVE.0, - None, - TS_TRUE, - ) - }?; - unsafe { CloseThemeData(theme) }?; - - let mut height = - (title_bar_size.cy as f32 * self.scale_factor).round() as i32 + top_and_bottom_borders; - - if self.is_maximized() { - let dpi = unsafe { GetDpiForWindow(self.hwnd) }; - height += unsafe { (GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi) * 2) as i32 }; - } - - let mut rect = RECT::default(); - unsafe { GetClientRect(self.hwnd, &mut rect) }?; - rect.bottom = rect.top + height; - Ok(rect) - } - fn is_virtual_key_pressed(&self, vkey: VIRTUAL_KEY) -> bool { unsafe { GetKeyState(vkey.0 as i32) < 0 } } @@ -176,30 +136,12 @@ impl WindowsWindowInner { fn handle_msg(&self, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT { log::debug!("msg: {msg}, wparam: {}, lparam: {}", wparam.0, lparam.0); match msg { - WM_ACTIVATE => self.handle_activate_msg(msg, wparam, lparam), - WM_CREATE => self.handle_create_msg(lparam), WM_MOVE => self.handle_move_msg(lparam), WM_SIZE => self.handle_size_msg(lparam), - WM_NCCALCSIZE => self.handle_calc_client_size(msg, wparam, lparam), - WM_DPICHANGED => self.handle_dpi_changed_msg(msg, wparam, lparam), - WM_NCHITTEST => self.handle_hit_test_msg(msg, wparam, lparam), WM_PAINT => self.handle_paint_msg(), WM_CLOSE => self.handle_close_msg(msg, wparam, lparam), WM_DESTROY => self.handle_destroy_msg(), WM_MOUSEMOVE => self.handle_mouse_move_msg(lparam, wparam), - WM_NCMOUSEMOVE => self.handle_nc_mouse_move_msg(msg, wparam, lparam), - WM_NCLBUTTONDOWN => { - self.handle_nc_mouse_down_msg(MouseButton::Left, msg, wparam, lparam) - } - WM_NCRBUTTONDOWN => { - self.handle_nc_mouse_down_msg(MouseButton::Right, msg, wparam, lparam) - } - WM_NCMBUTTONDOWN => { - self.handle_nc_mouse_down_msg(MouseButton::Middle, msg, wparam, lparam) - } - WM_NCLBUTTONUP => self.handle_nc_mouse_up_msg(MouseButton::Left, msg, wparam, lparam), - WM_NCRBUTTONUP => self.handle_nc_mouse_up_msg(MouseButton::Right, msg, wparam, lparam), - WM_NCMBUTTONUP => self.handle_nc_mouse_up_msg(MouseButton::Middle, msg, wparam, lparam), WM_LBUTTONDOWN => self.handle_mouse_down_msg(MouseButton::Left, lparam), WM_RBUTTONDOWN => self.handle_mouse_down_msg(MouseButton::Right, lparam), WM_MBUTTONDOWN => self.handle_mouse_down_msg(MouseButton::Middle, lparam), @@ -282,7 +224,7 @@ impl WindowsWindowInner { fn handle_paint_msg(&self) -> LRESULT { let mut paint_struct = PAINTSTRUCT::default(); - let _hdc = unsafe { BeginPaint(self.hwnd, &mut paint_struct) }; + let hdc = unsafe { BeginPaint(self.hwnd, &mut paint_struct) }; let mut callbacks = self.callbacks.borrow_mut(); if let Some(request_frame) = callbacks.request_frame.as_mut() { request_frame(); @@ -349,7 +291,7 @@ impl WindowsWindowInner { pressed_button, modifiers: self.current_modifiers(), }; - if callback(PlatformInput::MouseMove(event)).default_prevented { + if callback(PlatformInput::MouseMove(event)) { return LRESULT(0); } } @@ -475,7 +417,7 @@ impl WindowsWindowInner { keystroke, is_held: lparam.0 & (0x1 << 30) > 0, }; - if func(PlatformInput::KeyDown(event)).default_prevented { + if func(PlatformInput::KeyDown(event)) { self.invalidate_client_area(); return LRESULT(0); } @@ -492,14 +434,14 @@ impl WindowsWindowInner { return unsafe { DefWindowProcW(self.hwnd, message, wparam, lparam) }; }; let event = KeyUpEvent { keystroke }; - if func(PlatformInput::KeyUp(event)).default_prevented { + if func(PlatformInput::KeyUp(event)) { self.invalidate_client_area(); return LRESULT(0); } unsafe { DefWindowProcW(self.hwnd, message, wparam, lparam) } } - fn handle_keydown_msg(&self, _msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT { + fn handle_keydown_msg(&self, message: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT { let Some(keystroke) = self.parse_keydown_msg_keystroke(wparam) else { return LRESULT(1); }; @@ -510,14 +452,14 @@ impl WindowsWindowInner { keystroke, is_held: lparam.0 & (0x1 << 30) > 0, }; - if func(PlatformInput::KeyDown(event)).default_prevented { + if func(PlatformInput::KeyDown(event)) { self.invalidate_client_area(); return LRESULT(0); } LRESULT(1) } - fn handle_keyup_msg(&self, _msg: u32, wparam: WPARAM) -> LRESULT { + fn handle_keyup_msg(&self, message: u32, wparam: WPARAM) -> LRESULT { let Some(keystroke) = self.parse_keydown_msg_keystroke(wparam) else { return LRESULT(1); }; @@ -525,14 +467,14 @@ impl WindowsWindowInner { return LRESULT(1); }; let event = KeyUpEvent { keystroke }; - if func(PlatformInput::KeyUp(event)).default_prevented { + if func(PlatformInput::KeyUp(event)) { self.invalidate_client_area(); return LRESULT(0); } LRESULT(1) } - fn handle_char_msg(&self, _msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT { + fn handle_char_msg(&self, message: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT { let Some(keystroke) = self.parse_char_msg_keystroke(wparam) else { return LRESULT(1); }; @@ -545,7 +487,7 @@ impl WindowsWindowInner { keystroke, is_held: lparam.0 & (0x1 << 30) > 0, }; - if func(PlatformInput::KeyDown(event)).default_prevented { + if func(PlatformInput::KeyDown(event)) { self.invalidate_client_area(); return LRESULT(0); } @@ -573,7 +515,7 @@ impl WindowsWindowInner { modifiers: self.current_modifiers(), click_count: 1, }; - if callback(PlatformInput::MouseDown(event)).default_prevented { + if callback(PlatformInput::MouseDown(event)) { return LRESULT(0); } } @@ -591,7 +533,7 @@ impl WindowsWindowInner { modifiers: self.current_modifiers(), click_count: 1, }; - if callback(PlatformInput::MouseUp(event)).default_prevented { + if callback(PlatformInput::MouseUp(event)) { return LRESULT(0); } } @@ -636,7 +578,7 @@ impl WindowsWindowInner { modifiers: self.current_modifiers(), touch_phase: TouchPhase::Moved, }; - if callback(PlatformInput::ScrollWheel(event)).default_prevented { + if callback(PlatformInput::ScrollWheel(event)) { return LRESULT(0); } } @@ -743,237 +685,12 @@ impl WindowsWindowInner { }; func(input); } - - /// SEE: https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-nccalcsize - fn handle_calc_client_size(&self, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT { - if wparam.0 == 0 { - return unsafe { DefWindowProcW(self.hwnd, msg, wparam, lparam) }; - } - - let dpi = unsafe { GetDpiForWindow(self.hwnd) }; - - let frame_x = unsafe { GetSystemMetricsForDpi(SM_CXFRAME, dpi) }; - let frame_y = unsafe { GetSystemMetricsForDpi(SM_CYFRAME, dpi) }; - let padding = unsafe { GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi) }; - - // wparam is TRUE so lparam points to an NCCALCSIZE_PARAMS structure - let mut params = lparam.0 as *mut NCCALCSIZE_PARAMS; - let mut requested_client_rect = unsafe { &mut ((*params).rgrc) }; - - requested_client_rect[0].right -= frame_x + padding; - requested_client_rect[0].left += frame_x + padding; - requested_client_rect[0].bottom -= frame_y + padding; - - LRESULT(0) - } - - fn handle_activate_msg(&self, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT { - if let Some(titlebar_rect) = self.get_titlebar_rect().log_err() { - unsafe { InvalidateRect(self.hwnd, Some(&titlebar_rect), FALSE) }; - } - return unsafe { DefWindowProcW(self.hwnd, msg, wparam, lparam) }; - } - - fn handle_create_msg(&self, _lparam: LPARAM) -> LRESULT { - let mut size_rect = RECT::default(); - unsafe { GetWindowRect(self.hwnd, &mut size_rect).log_err() }; - let width = size_rect.right - size_rect.left; - let height = size_rect.bottom - size_rect.top; - - self.size.set(Size { - width: GlobalPixels::from(width as f64), - height: GlobalPixels::from(height as f64), - }); - - // Inform the application of the frame change to force redrawing with the new - // client area that is extended into the title bar - unsafe { - SetWindowPos( - self.hwnd, - HWND::default(), - size_rect.left, - size_rect.top, - width, - height, - SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE, - ) - .log_err() - }; - LRESULT(0) - } - - fn handle_dpi_changed_msg(&self, _msg: u32, _wparam: WPARAM, _lparam: LPARAM) -> LRESULT { - LRESULT(1) - } - - fn handle_hit_test_msg(&self, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT { - // default handler for resize areas - let hit = unsafe { DefWindowProcW(self.hwnd, msg, wparam, lparam) }; - if matches!( - hit.0 as u32, - HTNOWHERE - | HTRIGHT - | HTLEFT - | HTTOPLEFT - | HTTOP - | HTTOPRIGHT - | HTBOTTOMRIGHT - | HTBOTTOM - | HTBOTTOMLEFT - ) { - return hit; - } - - let dpi = unsafe { GetDpiForWindow(self.hwnd) }; - let frame_y = unsafe { GetSystemMetricsForDpi(SM_CYFRAME, dpi) }; - let padding = unsafe { GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi) }; - - let mut cursor_point = POINT { - x: lparam.signed_loword().into(), - y: lparam.signed_hiword().into(), - }; - unsafe { ScreenToClient(self.hwnd, &mut cursor_point) }; - if cursor_point.y > 0 && cursor_point.y < frame_y + padding { - return LRESULT(HTTOP as _); - } - - let titlebar_rect = self.get_titlebar_rect(); - if let Ok(titlebar_rect) = titlebar_rect { - if cursor_point.y < titlebar_rect.bottom { - let caption_btn_width = unsafe { GetSystemMetricsForDpi(SM_CXSIZE, dpi) }; - if cursor_point.x >= titlebar_rect.right - caption_btn_width { - return LRESULT(HTCLOSE as _); - } else if cursor_point.x >= titlebar_rect.right - caption_btn_width * 2 { - return LRESULT(HTMAXBUTTON as _); - } else if cursor_point.x >= titlebar_rect.right - caption_btn_width * 3 { - return LRESULT(HTMINBUTTON as _); - } - - return LRESULT(HTCAPTION as _); - } - } - - LRESULT(HTCLIENT as _) - } - - fn handle_nc_mouse_move_msg(&self, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT { - let mut cursor_point = POINT { - x: lparam.signed_loword().into(), - y: lparam.signed_hiword().into(), - }; - unsafe { ScreenToClient(self.hwnd, &mut cursor_point) }; - let x = Pixels::from(cursor_point.x as f32); - let y = Pixels::from(cursor_point.y as f32); - self.mouse_position.set(Point { x, y }); - let mut callbacks = self.callbacks.borrow_mut(); - if let Some(callback) = callbacks.input.as_mut() { - let event = MouseMoveEvent { - position: Point { x, y }, - pressed_button: None, - modifiers: self.current_modifiers(), - }; - if callback(PlatformInput::MouseMove(event)).default_prevented { - return LRESULT(0); - } - } - drop(callbacks); - unsafe { DefWindowProcW(self.hwnd, msg, wparam, lparam) } - } - - fn handle_nc_mouse_down_msg( - &self, - button: MouseButton, - msg: u32, - wparam: WPARAM, - lparam: LPARAM, - ) -> LRESULT { - let mut callbacks = self.callbacks.borrow_mut(); - if let Some(callback) = callbacks.input.as_mut() { - let mut cursor_point = POINT { - x: lparam.signed_loword().into(), - y: lparam.signed_hiword().into(), - }; - unsafe { ScreenToClient(self.hwnd, &mut cursor_point) }; - let x = Pixels::from(cursor_point.x as f32); - let y = Pixels::from(cursor_point.y as f32); - let event = MouseDownEvent { - button: button.clone(), - position: Point { x, y }, - modifiers: self.current_modifiers(), - click_count: 1, - }; - if callback(PlatformInput::MouseDown(event)).default_prevented { - return LRESULT(0); - } - } - drop(callbacks); - - match wparam.0 as u32 { - // Since these are handled in handle_nc_mouse_up_msg we must prevent the default window proc - HTMINBUTTON | HTMAXBUTTON | HTCLOSE => LRESULT(0), - _ => unsafe { DefWindowProcW(self.hwnd, msg, wparam, lparam) }, - } - } - - fn handle_nc_mouse_up_msg( - &self, - button: MouseButton, - msg: u32, - wparam: WPARAM, - lparam: LPARAM, - ) -> LRESULT { - let mut callbacks = self.callbacks.borrow_mut(); - if let Some(callback) = callbacks.input.as_mut() { - let mut cursor_point = POINT { - x: lparam.signed_loword().into(), - y: lparam.signed_hiword().into(), - }; - unsafe { ScreenToClient(self.hwnd, &mut cursor_point) }; - let x = Pixels::from(cursor_point.x as f32); - let y = Pixels::from(cursor_point.y as f32); - let event = MouseUpEvent { - button, - position: Point { x, y }, - modifiers: self.current_modifiers(), - click_count: 1, - }; - if callback(PlatformInput::MouseUp(event)).default_prevented { - return LRESULT(0); - } - } - drop(callbacks); - - if button == MouseButton::Left { - match wparam.0 as u32 { - HTMINBUTTON => unsafe { - ShowWindowAsync(self.hwnd, SW_MINIMIZE); - return LRESULT(0); - }, - HTMAXBUTTON => unsafe { - if self.is_maximized() { - ShowWindowAsync(self.hwnd, SW_NORMAL); - } else { - ShowWindowAsync(self.hwnd, SW_MAXIMIZE); - } - return LRESULT(0); - }, - HTCLOSE => unsafe { - PostMessageW(self.hwnd, WM_CLOSE, WPARAM::default(), LPARAM::default()) - .log_err(); - return LRESULT(0); - }, - _ => {} - }; - } - - unsafe { DefWindowProcW(self.hwnd, msg, wparam, lparam) } - } } #[derive(Default)] struct Callbacks { request_frame: Option>, - input: Option DispatchEventResult>>, + input: Option bool>>, active_status_change: Option>, resize: Option, f32)>>, fullscreen: Option>, @@ -1001,6 +718,7 @@ impl WindowsWindow { handle: AnyWindowHandle, options: WindowParams, ) -> Self { + let dwexstyle = WINDOW_EX_STYLE::default(); let classname = register_wnd_class(); let windowname = HSTRING::from( options @@ -1010,7 +728,7 @@ impl WindowsWindow { .map(|title| title.as_ref()) .unwrap_or(""), ); - let dwstyle = WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; + let dwstyle = WS_OVERLAPPEDWINDOW & !WS_VISIBLE; let x = options.bounds.origin.x.0 as i32; let y = options.bounds.origin.y.0 as i32; let nwidth = options.bounds.size.width.0 as i32; @@ -1026,7 +744,7 @@ impl WindowsWindow { let lpparam = Some(&context as *const _ as *const _); unsafe { CreateWindowExW( - WS_EX_APPWINDOW, + dwexstyle, classname, &windowname, dwstyle, @@ -1067,7 +785,7 @@ impl WindowsWindow { } fn maximize(&self) { - unsafe { ShowWindowAsync(self.inner.hwnd, SW_MAXIMIZE) }; + unsafe { ShowWindow(self.inner.hwnd, SW_MAXIMIZE) }; } } @@ -1108,10 +826,6 @@ impl PlatformWindow for WindowsWindow { } } - fn is_maximized(&self) -> bool { - self.inner.is_maximized() - } - // todo(windows) fn content_size(&self) -> Size { let size = self.inner.size.get(); @@ -1123,12 +837,12 @@ impl PlatformWindow for WindowsWindow { // todo(windows) fn scale_factor(&self) -> f32 { - self.inner.scale_factor + 1.0 } + // todo(windows) fn titlebar_height(&self) -> Pixels { - let titlebar_rect = self.inner.get_titlebar_rect().unwrap(); - ((titlebar_rect.bottom - titlebar_rect.top) as f64).into() + 20.0.into() } // todo(windows) @@ -1238,9 +952,8 @@ impl PlatformWindow for WindowsWindow { Some(done_rx) } - fn activate(&self) { - unsafe { ShowWindowAsync(self.inner.hwnd, SW_NORMAL) }; - } + // todo(windows) + fn activate(&self) {} // todo(windows) fn set_title(&mut self, title: &str) { @@ -1250,18 +963,16 @@ impl PlatformWindow for WindowsWindow { } // todo(windows) - fn set_edited(&mut self, _edited: bool) {} + fn set_edited(&mut self, edited: bool) {} // todo(windows) fn show_character_palette(&self) {} - fn minimize(&self) { - unsafe { ShowWindowAsync(self.inner.hwnd, SW_MINIMIZE) }; - } + // todo(windows) + fn minimize(&self) {} - fn zoom(&self) { - unsafe { ShowWindowAsync(self.inner.hwnd, SW_MAXIMIZE) }; - } + // todo(windows) + fn zoom(&self) {} // todo(windows) fn toggle_fullscreen(&self) {} @@ -1277,7 +988,7 @@ impl PlatformWindow for WindowsWindow { } // todo(windows) - fn on_input(&self, callback: Box DispatchEventResult>) { + fn on_input(&self, callback: Box bool>) { self.inner.callbacks.borrow_mut().input = Some(callback); } @@ -1317,7 +1028,7 @@ impl PlatformWindow for WindowsWindow { } // todo(windows) - fn is_topmost_for_position(&self, _position: Point) -> bool { + fn is_topmost_for_position(&self, position: Point) -> bool { true } @@ -1335,7 +1046,6 @@ impl PlatformWindow for WindowsWindow { #[implement(IDropTarget)] struct WindowsDragDropHandler(pub Rc); -#[allow(non_snake_case)] impl IDropTarget_Impl for WindowsDragDropHandler { fn DragEnter( &self, @@ -1449,7 +1159,6 @@ fn register_wnd_class() -> PCWSTR { lpfnWndProc: Some(wnd_proc), hCursor: unsafe { LoadCursorW(None, IDC_ARROW).ok().unwrap() }, lpszClassName: PCWSTR(CLASS_NAME.as_ptr()), - style: CS_HREDRAW | CS_VREDRAW, ..Default::default() }; unsafe { RegisterClassW(&wc) }; @@ -1507,6 +1216,28 @@ pub(crate) fn try_get_window_inner(hwnd: HWND) -> Option> } } +unsafe fn get_window_long(hwnd: HWND, nindex: WINDOW_LONG_PTR_INDEX) -> isize { + #[cfg(target_pointer_width = "64")] + unsafe { + GetWindowLongPtrW(hwnd, nindex) + } + #[cfg(target_pointer_width = "32")] + unsafe { + GetWindowLongW(hwnd, nindex) as isize + } +} + +unsafe fn set_window_long(hwnd: HWND, nindex: WINDOW_LONG_PTR_INDEX, dwnewlong: isize) -> isize { + #[cfg(target_pointer_width = "64")] + unsafe { + SetWindowLongPtrW(hwnd, nindex, dwnewlong) + } + #[cfg(target_pointer_width = "32")] + unsafe { + SetWindowLongW(hwnd, nindex, dwnewlong as i32) as isize + } +} + fn basic_vkcode_to_string(code: u16, modifiers: Modifiers) -> Option { match code { // VK_0 - VK_9 diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs index fe1500ed6c..e6591e291d 100644 --- a/crates/gpui/src/window.rs +++ b/crates/gpui/src/window.rs @@ -520,7 +520,7 @@ impl Window { handle .update(&mut cx, |_, cx| cx.dispatch_event(event)) .log_err() - .unwrap_or(DispatchEventResult::default()) + .unwrap_or(false) }) }); @@ -574,12 +574,6 @@ impl Window { } } -#[derive(Clone, Debug, Default, PartialEq, Eq)] -pub(crate) struct DispatchEventResult { - pub propagate: bool, - pub default_prevented: bool, -} - /// Indicates which region of the window is visible. Content falling outside of this mask will not be /// rendered. Currently, only rectangular content masks are supported, but we give the mask its own type /// to leave room to support more complex shapes in the future. @@ -693,17 +687,6 @@ impl<'a> WindowContext<'a> { style } - /// Get the platform window titlebar height - pub fn titlebar_height(&self) -> Pixels { - self.window.platform_window.titlebar_height() - } - - /// Check if the platform window is maximized - /// On some platforms (namely Windows) this is different than the bounds being the size of the display - pub fn is_maximized(&self) -> bool { - self.window.platform_window.is_maximized() - } - /// Dispatch the given action on the currently focused element. pub fn dispatch_action(&mut self, action: Box) { let focus_handle = self.focused(); @@ -1104,11 +1087,10 @@ impl<'a> WindowContext<'a> { /// You can create a keystroke with Keystroke::parse(""). pub fn dispatch_keystroke(&mut self, keystroke: Keystroke) -> bool { let keystroke = keystroke.with_simulated_ime(); - let result = self.dispatch_event(PlatformInput::KeyDown(KeyDownEvent { + if self.dispatch_event(PlatformInput::KeyDown(KeyDownEvent { keystroke: keystroke.clone(), is_held: false, - })); - if !result.propagate { + })) { return true; } @@ -1141,7 +1123,7 @@ impl<'a> WindowContext<'a> { /// Dispatch a mouse or keyboard event on the window. #[profiling::function] - pub fn dispatch_event(&mut self, event: PlatformInput) -> DispatchEventResult { + pub fn dispatch_event(&mut self, event: PlatformInput) -> bool { self.window.last_input_timestamp.set(Instant::now()); // Handlers may set this to false by calling `stop_propagation`. self.app.propagate_event = true; @@ -1229,10 +1211,7 @@ impl<'a> WindowContext<'a> { self.dispatch_key_event(any_key_event); } - DispatchEventResult { - propagate: self.app.propagate_event, - default_prevented: self.window.default_prevented, - } + !self.app.propagate_event } fn dispatch_mouse_event(&mut self, event: &dyn Any) { diff --git a/crates/ui/src/components.rs b/crates/ui/src/components.rs index c78774f2b8..0848ac74df 100644 --- a/crates/ui/src/components.rs +++ b/crates/ui/src/components.rs @@ -9,7 +9,6 @@ mod indicator; mod keybinding; mod label; mod list; -mod platform_titlebar; mod popover; mod popover_menu; mod right_click_menu; @@ -32,7 +31,6 @@ pub use indicator::*; pub use keybinding::*; pub use label::*; pub use list::*; -pub use platform_titlebar::*; pub use popover::*; pub use popover_menu::*; pub use right_click_menu::*; diff --git a/crates/ui/src/components/platform_titlebar.rs b/crates/ui/src/components/platform_titlebar.rs deleted file mode 100644 index c89d7d8f4e..0000000000 --- a/crates/ui/src/components/platform_titlebar.rs +++ /dev/null @@ -1,226 +0,0 @@ -// allowing due to multiple platform conditional code -#![allow(unused_imports)] - -use gpui::{ - div, - prelude::FluentBuilder, - px, AnyElement, Div, Element, ElementId, Fill, InteractiveElement, Interactivity, IntoElement, - ParentElement, Pixels, RenderOnce, Rgba, Stateful, StatefulInteractiveElement, StyleRefinement, - Styled, - WindowAppearance::{Dark, Light, VibrantDark, VibrantLight}, - WindowContext, -}; -use smallvec::SmallVec; - -use crate::h_flex; - -pub enum PlatformStyle { - Linux, - Windows, - MacOs, -} - -impl PlatformStyle { - pub fn platform() -> Self { - if cfg!(windows) { - Self::Windows - } else if cfg!(macos) { - Self::MacOs - } else { - Self::Linux - } - } - - pub fn windows(&self) -> bool { - matches!(self, Self::Windows) - } - - pub fn macos(&self) -> bool { - matches!(self, Self::MacOs) - } -} - -#[derive(IntoElement)] -pub struct PlatformTitlebar { - platform: PlatformStyle, - titlebar_bg: Option, - content: Stateful
, - children: SmallVec<[AnyElement; 2]>, -} - -impl Styled for PlatformTitlebar { - fn style(&mut self) -> &mut StyleRefinement { - self.content.style() - } -} - -impl PlatformTitlebar { - /// Change the platform style used - pub fn with_platform_style(self, style: PlatformStyle) -> Self { - Self { - platform: style, - ..self - } - } - - fn titlebar_top_padding(&self, cx: &WindowContext) -> Pixels { - if self.platform.windows() && cx.is_maximized() { - // todo(windows): get padding from win32 api, need HWND from window context somehow - // should be GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi) * 2 - px(8.0) - } else { - px(0.0) - } - } - - fn windows_caption_button_width(_cx: &WindowContext) -> Pixels { - // todo(windows): get padding from win32 api, need HWND from window context somehow - // should be GetSystemMetricsForDpi(SM_CXSIZE, dpi) - px(36.0) - } - - fn render_window_controls_right(&self, cx: &mut WindowContext) -> impl Element { - if self.platform.windows() { - let btn_height = cx.titlebar_height() - self.titlebar_top_padding(cx); - let close_btn_hover_color = Rgba { - r: 232.0 / 255.0, - g: 17.0 / 255.0, - b: 32.0 / 255.0, - a: 1.0, - }; - - let btn_hover_color = match cx.appearance() { - Light | VibrantLight => Rgba { - r: 0.1, - g: 0.1, - b: 0.1, - a: 0.2, - }, - Dark | VibrantDark => Rgba { - r: 0.9, - g: 0.9, - b: 0.9, - a: 0.1, - }, - }; - - fn windows_caption_btn( - id: &'static str, - icon_text: &'static str, - hover_color: Rgba, - cx: &WindowContext, - ) -> Stateful
{ - let mut active_color = hover_color; - active_color.a *= 0.2; - h_flex() - .id(id) - .h_full() - .justify_center() - .content_center() - .items_center() - .w(PlatformTitlebar::windows_caption_button_width(cx)) - .hover(|style| style.bg(hover_color)) - .active(|style| style.bg(active_color)) - .child(icon_text) - } - - div() - .id("caption-buttons-windows") - .flex() - .flex_row() - .justify_center() - .content_stretch() - .max_h(btn_height) - .min_h(btn_height) - .font("Segoe Fluent Icons") - .text_size(gpui::Pixels(10.0)) - .children(vec![ - windows_caption_btn("minimize", "\u{e921}", btn_hover_color, cx), // minimize icon - windows_caption_btn( - "maximize", - if cx.is_maximized() { - "\u{e923}" // restore icon - } else { - "\u{e922}" // maximize icon - }, - btn_hover_color, - cx, - ), - windows_caption_btn("close", "\u{e8bb}", close_btn_hover_color, cx), // close icon - ]) - } else { - div().id("caption-buttons-windows") - } - } - - /// Sets the background color of titlebar. - pub fn titlebar_bg(mut self, fill: F) -> Self - where - F: Into, - Self: Sized, - { - self.titlebar_bg = Some(fill.into()); - self - } -} - -pub fn platform_titlebar(id: impl Into) -> PlatformTitlebar { - let id = id.into(); - PlatformTitlebar { - platform: PlatformStyle::platform(), - titlebar_bg: None, - content: div().id(id.clone()), - children: SmallVec::new(), - } -} - -impl RenderOnce for PlatformTitlebar { - fn render(self, cx: &mut WindowContext) -> impl IntoElement { - let titlebar_height = cx.titlebar_height(); - let titlebar_top_padding = self.titlebar_top_padding(cx); - let window_controls_right = self.render_window_controls_right(cx); - let macos = self.platform.macos(); - h_flex() - .id("titlebar") - .w_full() - .pt(titlebar_top_padding) - .max_h(titlebar_height) - .min_h(titlebar_height) - .map(|mut this| { - this.style().background = self.titlebar_bg; - - if macos { - if !cx.is_fullscreen() { - // Use pixels here instead of a rem-based size because the macOS traffic - // lights are a static size, and don't scale with the rest of the UI. - return this.pl(px(80.)); - } - } - - this - }) - .content_stretch() - .child( - self.content - .flex() - .flex_row() - .w_full() - .id("titlebar-content") - .children(self.children), - ) - .child(window_controls_right) - } -} - -impl InteractiveElement for PlatformTitlebar { - fn interactivity(&mut self) -> &mut Interactivity { - self.content.interactivity() - } -} -impl StatefulInteractiveElement for PlatformTitlebar {} - -impl ParentElement for PlatformTitlebar { - fn extend(&mut self, elements: impl Iterator) { - self.children.extend(elements) - } -} diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 50be0bc0ac..5cafb9846d 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -72,7 +72,7 @@ use task::SpawnInTerminal; use theme::{ActiveTheme, SystemAppearance, ThemeSettings}; pub use toolbar::{Toolbar, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView}; pub use ui; -use ui::Label; +use ui::{px, Label}; use util::ResultExt; use uuid::Uuid; pub use workspace_settings::{AutosaveSetting, WorkspaceSettings}; @@ -4753,6 +4753,10 @@ fn parse_pixel_size_env_var(value: &str) -> Option> { Some(size((width as f64).into(), (height as f64).into())) } +pub fn titlebar_height(cx: &mut WindowContext) -> Pixels { + (1.75 * cx.rem_size()).max(px(32.)) +} + struct DisconnectedOverlay; impl Element for DisconnectedOverlay { @@ -4766,7 +4770,7 @@ impl Element for DisconnectedOverlay { .bg(background) .absolute() .left_0() - .top(cx.titlebar_height()) + .top(titlebar_height(cx)) .size_full() .flex() .items_center()