diff --git a/gpui/src/app.rs b/gpui/src/app.rs index ac4c4e69b1..7cda6107f1 100644 --- a/gpui/src/app.rs +++ b/gpui/src/app.rs @@ -758,6 +758,10 @@ impl MutableAppContext { (window_id, root_handle) } + pub fn remove_window(&mut self, window_id: usize) { + self.presenters_and_platform_windows.remove(&window_id); + } + fn open_platform_window(&mut self, window_id: usize) { let mut window = self.platform.open_window( window_id, @@ -814,6 +818,13 @@ impl MutableAppContext { })); } + { + let mut app = self.upgrade(); + window.on_close(Box::new(move || { + app.update(|ctx| ctx.remove_window(window_id)); + })); + } + self.presenters_and_platform_windows .insert(window_id, (presenter.clone(), window)); diff --git a/gpui/src/platform/mac/window.rs b/gpui/src/platform/mac/window.rs index 73196346e3..92d0503aeb 100644 --- a/gpui/src/platform/mac/window.rs +++ b/gpui/src/platform/mac/window.rs @@ -61,6 +61,7 @@ unsafe fn build_classes() { sel!(sendEvent:), send_event as extern "C" fn(&Object, Sel, id), ); + decl.add_method(sel!(close), close_window as extern "C" fn(&Object, Sel)); decl.register() }; @@ -125,6 +126,7 @@ struct WindowState { native_window: id, event_callback: Option>, resize_callback: Option>, + close_callback: Option>, synthetic_drag_counter: usize, executor: Rc, scene_to_render: Option, @@ -184,6 +186,7 @@ impl Window { native_window, event_callback: None, resize_callback: None, + close_callback: None, synthetic_drag_counter: 0, executor, scene_to_render: Default::default(), @@ -262,6 +265,10 @@ impl platform::Window for Window { fn on_resize(&mut self, callback: Box) { self.0.as_ref().borrow_mut().resize_callback = Some(callback); } + + fn on_close(&mut self, callback: Box) { + self.0.as_ref().borrow_mut().close_callback = Some(callback); + } } impl platform::WindowContext for Window { @@ -310,7 +317,7 @@ unsafe fn get_window_state(object: &Object) -> Rc> { unsafe fn drop_window_state(object: &Object) { let raw: *mut c_void = *object.get_ivar(WINDOW_STATE_IVAR); - Rc::from_raw(raw as *mut WindowState); + Rc::from_raw(raw as *mut RefCell); } extern "C" fn yes(_: &Object, _: Sel) -> BOOL { @@ -371,6 +378,22 @@ extern "C" fn send_event(this: &Object, _: Sel, native_event: id) { } } +extern "C" fn close_window(this: &Object, _: Sel) { + unsafe { + let window_state = get_window_state(this); + let close_callback = window_state + .as_ref() + .try_borrow_mut() + .ok() + .and_then(|mut window_state| window_state.close_callback.take()); + if let Some(callback) = close_callback { + callback(); + } + + let () = msg_send![super(this, class!(NSWindow)), close]; + } +} + extern "C" fn make_backing_layer(this: &Object, _: Sel) -> id { let window_state = unsafe { get_window_state(this) }; let window_state = window_state.as_ref().borrow(); diff --git a/gpui/src/platform/mod.rs b/gpui/src/platform/mod.rs index b98d3a687b..0450856950 100644 --- a/gpui/src/platform/mod.rs +++ b/gpui/src/platform/mod.rs @@ -59,6 +59,7 @@ pub trait Dispatcher: Send + Sync { pub trait Window: WindowContext { fn on_event(&mut self, callback: Box); fn on_resize(&mut self, callback: Box); + fn on_close(&mut self, callback: Box); } pub trait WindowContext { diff --git a/gpui/src/platform/test.rs b/gpui/src/platform/test.rs index 878449a021..2c8876f0c9 100644 --- a/gpui/src/platform/test.rs +++ b/gpui/src/platform/test.rs @@ -16,6 +16,7 @@ pub struct Window { current_scene: Option, event_handlers: Vec>, resize_handlers: Vec>, + close_handlers: Vec>, } impl Platform { @@ -92,6 +93,7 @@ impl Window { size, event_handlers: Vec::new(), resize_handlers: Vec::new(), + close_handlers: Vec::new(), scale_factor: 1.0, current_scene: None, } @@ -130,6 +132,10 @@ impl super::Window for Window { fn on_resize(&mut self, callback: Box) { self.resize_handlers.push(callback); } + + fn on_close(&mut self, callback: Box) { + self.close_handlers.push(callback); + } } pub fn platform() -> impl super::Platform {