@@ -401,9 +401,12 @@ impl TestAppContext {
T: View,
F: FnOnce(&mut ViewContext<T>) -> T,
{
- self.cx
+ let (window_id, view) = self
+ .cx
.borrow_mut()
- .add_window(Default::default(), build_root_view)
+ .add_window(Default::default(), build_root_view);
+ self.simulate_window_activation(Some(window_id));
+ (window_id, view)
}
pub fn window_ids(&self) -> Vec<usize> {
@@ -551,6 +554,35 @@ impl TestAppContext {
}
}
+ pub fn simulate_window_activation(&self, to_activate: Option<usize>) {
+ let mut handlers = BTreeMap::new();
+ {
+ let mut cx = self.cx.borrow_mut();
+ for (window_id, (_, window)) in &mut cx.presenters_and_platform_windows {
+ let window = window
+ .as_any_mut()
+ .downcast_mut::<platform::test::Window>()
+ .unwrap();
+ handlers.insert(
+ *window_id,
+ mem::take(&mut window.active_status_change_handlers),
+ );
+ }
+ };
+ let mut handlers = handlers.into_iter().collect::<Vec<_>>();
+ handlers.sort_unstable_by_key(|(window_id, _)| Some(*window_id) == to_activate);
+
+ for (window_id, mut window_handlers) in handlers {
+ for window_handler in &mut window_handlers {
+ window_handler(Some(window_id) == to_activate);
+ }
+
+ self.window_mut(window_id)
+ .active_status_change_handlers
+ .extend(window_handlers);
+ }
+ }
+
pub fn is_window_edited(&self, window_id: usize) -> bool {
self.window_mut(window_id).edited
}
@@ -6992,4 +7024,81 @@ mod tests {
);
assert_eq!(presenter.borrow().rendered_views.len(), 1);
}
+
+ #[crate::test(self)]
+ async fn test_window_activation(cx: &mut TestAppContext) {
+ struct View(&'static str);
+
+ impl super::Entity for View {
+ type Event = ();
+ }
+
+ impl super::View for View {
+ fn ui_name() -> &'static str {
+ "test view"
+ }
+
+ fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
+ Empty::new().boxed()
+ }
+ }
+
+ let events = Rc::new(RefCell::new(Vec::new()));
+ let (window_1, _) = cx.add_window(|cx: &mut ViewContext<View>| {
+ cx.observe_window_activation({
+ let events = events.clone();
+ move |this, active, _| events.borrow_mut().push((this.0, active))
+ })
+ .detach();
+ View("window 1")
+ });
+ assert_eq!(mem::take(&mut *events.borrow_mut()), [("window 1", true)]);
+
+ let (window_2, _) = cx.add_window(|cx: &mut ViewContext<View>| {
+ cx.observe_window_activation({
+ let events = events.clone();
+ move |this, active, _| events.borrow_mut().push((this.0, active))
+ })
+ .detach();
+ View("window 2")
+ });
+ assert_eq!(
+ mem::take(&mut *events.borrow_mut()),
+ [("window 1", false), ("window 2", true)]
+ );
+
+ let (window_3, _) = cx.add_window(|cx: &mut ViewContext<View>| {
+ cx.observe_window_activation({
+ let events = events.clone();
+ move |this, active, _| events.borrow_mut().push((this.0, active))
+ })
+ .detach();
+ View("window 3")
+ });
+ assert_eq!(
+ mem::take(&mut *events.borrow_mut()),
+ [("window 2", false), ("window 3", true)]
+ );
+
+ cx.simulate_window_activation(Some(window_2));
+ assert_eq!(
+ mem::take(&mut *events.borrow_mut()),
+ [("window 3", false), ("window 2", true)]
+ );
+
+ cx.simulate_window_activation(Some(window_1));
+ assert_eq!(
+ mem::take(&mut *events.borrow_mut()),
+ [("window 2", false), ("window 1", true)]
+ );
+
+ cx.simulate_window_activation(Some(window_3));
+ assert_eq!(
+ mem::take(&mut *events.borrow_mut()),
+ [("window 1", false), ("window 3", true)]
+ );
+
+ cx.simulate_window_activation(Some(window_3));
+ assert_eq!(mem::take(&mut *events.borrow_mut()), []);
+ }
}
@@ -37,6 +37,7 @@ pub struct Window {
event_handlers: Vec<Box<dyn FnMut(super::Event) -> bool>>,
resize_handlers: Vec<Box<dyn FnMut()>>,
close_handlers: Vec<Box<dyn FnOnce()>>,
+ pub(crate) active_status_change_handlers: Vec<Box<dyn FnMut(bool)>>,
pub(crate) should_close_handler: Option<Box<dyn FnMut() -> bool>>,
pub(crate) title: Option<String>,
pub(crate) edited: bool,
@@ -191,6 +192,7 @@ impl Window {
resize_handlers: Default::default(),
close_handlers: Default::default(),
should_close_handler: Default::default(),
+ active_status_change_handlers: Default::default(),
scale_factor: 1.0,
current_scene: None,
title: None,
@@ -241,7 +243,9 @@ impl super::Window for Window {
self.event_handlers.push(callback);
}
- fn on_active_status_change(&mut self, _: Box<dyn FnMut(bool)>) {}
+ fn on_active_status_change(&mut self, callback: Box<dyn FnMut(bool)>) {
+ self.active_status_change_handlers.push(callback);
+ }
fn on_resize(&mut self, callback: Box<dyn FnMut()>) {
self.resize_handlers.push(callback);