diff --git a/crates/gpui/src/platform/test/window.rs b/crates/gpui/src/platform/test/window.rs index b310084fc490de..d5d62e0155513b 100644 --- a/crates/gpui/src/platform/test/window.rs +++ b/crates/gpui/src/platform/test/window.rs @@ -171,7 +171,7 @@ impl PlatformWindow for TestWindow { } fn appearance(&self) -> WindowAppearance { - unimplemented!() + WindowAppearance::Light } fn display(&self) -> std::rc::Rc { @@ -276,9 +276,7 @@ impl PlatformWindow for TestWindow { unimplemented!() } - fn on_appearance_changed(&self, _callback: Box) { - unimplemented!() - } + fn on_appearance_changed(&self, _callback: Box) {} fn is_topmost_for_position(&self, _position: crate::Point) -> bool { unimplemented!() diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs index c1be6925428f30..fbea1ba8dd4948 100644 --- a/crates/gpui/src/window.rs +++ b/crates/gpui/src/window.rs @@ -6,8 +6,8 @@ use crate::{ KeymatchResult, Keystroke, KeystrokeEvent, Model, ModelContext, Modifiers, MouseButton, MouseMoveEvent, MouseUpEvent, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformWindow, Point, PromptLevel, Render, ScaledPixels, SharedString, Size, SubscriberSet, - Subscription, TaffyLayoutEngine, Task, View, VisualContext, WeakView, WindowBounds, - WindowOptions, WindowTextSystem, + Subscription, TaffyLayoutEngine, Task, View, VisualContext, WeakView, WindowAppearance, + WindowBounds, WindowOptions, WindowTextSystem, }; use anyhow::{anyhow, Context as _, Result}; use collections::FxHashSet; @@ -269,6 +269,8 @@ pub struct Window { scale_factor: f32, bounds: WindowBounds, bounds_observers: SubscriberSet<(), AnyObserver>, + appearance: WindowAppearance, + appearance_observers: SubscriberSet<(), AnyObserver>, active: bool, pub(crate) dirty: bool, pub(crate) refreshing: bool, @@ -338,6 +340,7 @@ impl Window { let content_size = platform_window.content_size(); let scale_factor = platform_window.scale_factor(); let bounds = platform_window.bounds(); + let appearance = platform_window.appearance(); let text_system = Arc::new(WindowTextSystem::new(cx.text_system().clone())); platform_window.on_request_frame(Box::new({ @@ -364,6 +367,14 @@ impl Window { .log_err(); } })); + platform_window.on_appearance_changed(Box::new({ + let mut cx = cx.to_async(); + move || { + handle + .update(&mut cx, |_, cx| cx.appearance_changed()) + .log_err(); + } + })); platform_window.on_active_status_change(Box::new({ let mut cx = cx.to_async(); move |active| { @@ -413,6 +424,8 @@ impl Window { scale_factor, bounds, bounds_observers: SubscriberSet::new(), + appearance, + appearance_observers: SubscriberSet::new(), active: false, dirty: false, refreshing: false, @@ -742,6 +755,20 @@ impl<'a> WindowContext<'a> { self.window.bounds } + fn appearance_changed(&mut self) { + self.window.appearance = self.window.platform_window.appearance(); + + self.window + .appearance_observers + .clone() + .retain(&(), |callback| callback(self)); + } + + /// Returns the appearance of the current window. + pub fn appearance(&self) -> WindowAppearance { + self.window.appearance + } + /// Returns the size of the drawable area within the window. pub fn viewport_size(&self) -> Size { self.window.viewport_size @@ -2066,6 +2093,20 @@ impl<'a, V: 'static> ViewContext<'a, V> { subscription } + /// Registers a callback to be invoked when the window appearance changes. + pub fn observe_window_appearance( + &mut self, + mut callback: impl FnMut(&mut V, &mut ViewContext) + 'static, + ) -> Subscription { + let view = self.view.downgrade(); + let (subscription, activate) = self.window.appearance_observers.insert( + (), + Box::new(move |cx| view.update(cx, |view, cx| callback(view, cx)).is_ok()), + ); + activate(); + subscription + } + /// Register a listener to be called when the given focus handle receives focus. /// Returns a subscription and persists until the subscription is dropped. pub fn on_focus(