diff --git a/crates/gpui/src/platform/windows/events.rs b/crates/gpui/src/platform/windows/events.rs index d7205580cdc133fccbf97f1287651521ff7bb06b..a43fdc097f24a5c30544817f60c992829dbc831a 100644 --- a/crates/gpui/src/platform/windows/events.rs +++ b/crates/gpui/src/platform/windows/events.rs @@ -93,7 +93,7 @@ pub(crate) fn handle_msg( WM_IME_STARTCOMPOSITION => handle_ime_position(handle, state_ptr), WM_IME_COMPOSITION => handle_ime_composition(handle, lparam, state_ptr), WM_SETCURSOR => handle_set_cursor(handle, lparam, state_ptr), - WM_SETTINGCHANGE => handle_system_settings_changed(handle, lparam, state_ptr), + WM_SETTINGCHANGE => handle_system_settings_changed(handle, wparam, lparam, state_ptr), WM_INPUTLANGCHANGE => handle_input_language_changed(lparam, state_ptr), WM_GPUI_CURSOR_STYLE_CHANGED => handle_cursor_changed(lparam, state_ptr), _ => None, @@ -1152,37 +1152,23 @@ fn handle_set_cursor( fn handle_system_settings_changed( handle: HWND, + wparam: WPARAM, lparam: LPARAM, state_ptr: Rc, ) -> Option { - let mut lock = state_ptr.state.borrow_mut(); - let display = lock.display; - // system settings - lock.system_settings.update(display); - // mouse double click - lock.click_state.system_update(); - // window border offset - lock.border_offset.update(handle).log_err(); - drop(lock); - - // lParam is a pointer to a string that indicates the area containing the system parameter - // that was changed. - let parameter = PCWSTR::from_raw(lparam.0 as _); - if unsafe { !parameter.is_null() && !parameter.is_empty() } { - if let Some(parameter_string) = unsafe { parameter.to_string() }.log_err() { - log::info!("System settings changed: {}", parameter_string); - match parameter_string.as_str() { - "ImmersiveColorSet" => { - handle_system_theme_changed(handle, state_ptr); - } - _ => {} - } - } - } - + if wparam.0 != 0 { + let mut lock = state_ptr.state.borrow_mut(); + let display = lock.display; + lock.system_settings.update(display, wparam.0); + lock.click_state.system_update(wparam.0); + lock.border_offset.update(handle).log_err(); + } else { + handle_system_theme_changed(handle, lparam, state_ptr)?; + }; // Force to trigger WM_NCCALCSIZE event to ensure that we handle auto hide // taskbar correctly. notify_frame_changed(handle); + Some(0) } @@ -1199,17 +1185,34 @@ fn handle_system_command(wparam: WPARAM, state_ptr: Rc) - fn handle_system_theme_changed( handle: HWND, + lparam: LPARAM, state_ptr: Rc, ) -> Option { - let mut callback = state_ptr - .state - .borrow_mut() - .callbacks - .appearance_changed - .take()?; - callback(); - state_ptr.state.borrow_mut().callbacks.appearance_changed = Some(callback); - configure_dwm_dark_mode(handle); + // lParam is a pointer to a string that indicates the area containing the system parameter + // that was changed. + let parameter = PCWSTR::from_raw(lparam.0 as _); + if unsafe { !parameter.is_null() && !parameter.is_empty() } { + if let Some(parameter_string) = unsafe { parameter.to_string() }.log_err() { + log::info!("System settings changed: {}", parameter_string); + match parameter_string.as_str() { + "ImmersiveColorSet" => { + let new_appearance = system_appearance() + .context("unable to get system appearance when handling ImmersiveColorSet") + .log_err()?; + let mut lock = state_ptr.state.borrow_mut(); + if new_appearance != lock.appearance { + lock.appearance = new_appearance; + let mut callback = lock.callbacks.appearance_changed.take()?; + drop(lock); + callback(); + state_ptr.state.borrow_mut().callbacks.appearance_changed = Some(callback); + configure_dwm_dark_mode(handle, new_appearance); + } + } + _ => {} + } + } + } Some(0) } diff --git a/crates/gpui/src/platform/windows/system_settings.rs b/crates/gpui/src/platform/windows/system_settings.rs index d8e3513b3c33da556a9258810cf86d8da9fe43a3..b2bd289cd00979541f0176a4ccea6a52143b9ddd 100644 --- a/crates/gpui/src/platform/windows/system_settings.rs +++ b/crates/gpui/src/platform/windows/system_settings.rs @@ -32,14 +32,32 @@ pub(crate) struct MouseWheelSettings { impl WindowsSystemSettings { pub(crate) fn new(display: WindowsDisplay) -> Self { let mut settings = Self::default(); - settings.update(display); + settings.init(display); settings } - pub(crate) fn update(&mut self, display: WindowsDisplay) { + fn init(&mut self, display: WindowsDisplay) { self.mouse_wheel_settings.update(); self.auto_hide_taskbar_position = AutoHideTaskbarPosition::new(display).log_err().flatten(); } + + pub(crate) fn update(&mut self, display: WindowsDisplay, wparam: usize) { + match wparam { + // SPI_SETWORKAREA + 47 => self.update_taskbar_position(display), + // SPI_GETWHEELSCROLLLINES, SPI_GETWHEELSCROLLCHARS + 104 | 108 => self.update_mouse_wheel_settings(), + _ => {} + } + } + + fn update_mouse_wheel_settings(&mut self) { + self.mouse_wheel_settings.update(); + } + + fn update_taskbar_position(&mut self, display: WindowsDisplay) { + self.auto_hide_taskbar_position = AutoHideTaskbarPosition::new(display).log_err().flatten(); + } } impl MouseWheelSettings { diff --git a/crates/gpui/src/platform/windows/util.rs b/crates/gpui/src/platform/windows/util.rs index bf9e390ba893d6f885f7a576f13d4e229b036d03..5fb8febe3b9b0b71e5d63ff4070f81b95c3dabf7 100644 --- a/crates/gpui/src/platform/windows/util.rs +++ b/crates/gpui/src/platform/windows/util.rs @@ -144,8 +144,8 @@ pub(crate) fn load_cursor(style: CursorStyle) -> Option { } /// This function is used to configure the dark mode for the window built-in title bar. -pub(crate) fn configure_dwm_dark_mode(hwnd: HWND) { - let dark_mode_enabled: BOOL = match system_appearance().log_err().unwrap_or_default() { +pub(crate) fn configure_dwm_dark_mode(hwnd: HWND, appearance: WindowAppearance) { + let dark_mode_enabled: BOOL = match appearance { WindowAppearance::Dark | WindowAppearance::VibrantDark => true.into(), WindowAppearance::Light | WindowAppearance::VibrantLight => false.into(), }; diff --git a/crates/gpui/src/platform/windows/window.rs b/crates/gpui/src/platform/windows/window.rs index 27c843932bb2a38f37f3b01b354a7eed7f8354fe..5c7dd07c4857c8d99dd8dcde294942cd33bf0573 100644 --- a/crates/gpui/src/platform/windows/window.rs +++ b/crates/gpui/src/platform/windows/window.rs @@ -37,6 +37,7 @@ pub struct WindowsWindowState { pub min_size: Option>, pub fullscreen_restore_bounds: Bounds, pub border_offset: WindowBorderOffset, + pub appearance: WindowAppearance, pub scale_factor: f32, pub restore_from_minimized: Option>, @@ -84,6 +85,7 @@ impl WindowsWindowState { display: WindowsDisplay, gpu_context: &BladeContext, min_size: Option>, + appearance: WindowAppearance, ) -> Result { let scale_factor = { let monitor_dpi = unsafe { GetDpiForWindow(hwnd) } as f32; @@ -118,6 +120,7 @@ impl WindowsWindowState { logical_size, fullscreen_restore_bounds, border_offset, + appearance, scale_factor, restore_from_minimized, min_size, @@ -206,6 +209,7 @@ impl WindowsWindowStatePtr { context.display, context.gpu_context, context.min_size, + context.appearance, )?); Ok(Rc::new_cyclic(|this| Self { @@ -338,6 +342,7 @@ struct WindowCreateContext<'a> { main_receiver: flume::Receiver, gpu_context: &'a BladeContext, main_thread_id_win32: u32, + appearance: WindowAppearance, } impl WindowsWindow { @@ -387,6 +392,7 @@ impl WindowsWindow { } else { WindowsDisplay::primary_monitor().unwrap() }; + let appearance = system_appearance().unwrap_or_default(); let mut context = WindowCreateContext { inner: None, handle, @@ -403,6 +409,7 @@ impl WindowsWindow { main_receiver, gpu_context, main_thread_id_win32, + appearance, }; let lpparam = Some(&context as *const _ as *const _); let creation_result = unsafe { @@ -426,7 +433,7 @@ impl WindowsWindow { let state_ptr = context.inner.take().unwrap()?; let hwnd = creation_result?; register_drag_drop(state_ptr.clone())?; - configure_dwm_dark_mode(hwnd); + configure_dwm_dark_mode(hwnd, appearance); state_ptr.state.borrow_mut().border_offset.update(hwnd)?; let placement = retrieve_window_placement( hwnd, @@ -543,7 +550,7 @@ impl PlatformWindow for WindowsWindow { } fn appearance(&self) -> WindowAppearance { - system_appearance().log_err().unwrap_or_default() + self.0.state.borrow().appearance } fn display(&self) -> Option> { @@ -951,7 +958,7 @@ impl IDropTarget_Impl for WindowsDragDropHandler_Impl { } } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub(crate) struct ClickState { button: MouseButton, last_click: Instant, @@ -993,10 +1000,25 @@ impl ClickState { self.current_count } - pub fn system_update(&mut self) { - self.double_click_spatial_tolerance_width = unsafe { GetSystemMetrics(SM_CXDOUBLECLK) }; - self.double_click_spatial_tolerance_height = unsafe { GetSystemMetrics(SM_CYDOUBLECLK) }; - self.double_click_interval = Duration::from_millis(unsafe { GetDoubleClickTime() } as u64); + pub fn system_update(&mut self, wparam: usize) { + match wparam { + // SPI_SETDOUBLECLKWIDTH + 29 => { + self.double_click_spatial_tolerance_width = + unsafe { GetSystemMetrics(SM_CXDOUBLECLK) } + } + // SPI_SETDOUBLECLKHEIGHT + 30 => { + self.double_click_spatial_tolerance_height = + unsafe { GetSystemMetrics(SM_CYDOUBLECLK) } + } + // SPI_SETDOUBLECLICKTIME + 32 => { + self.double_click_interval = + Duration::from_millis(unsafe { GetDoubleClickTime() } as u64) + } + _ => {} + } } #[inline]