From 3f844bc953b534d4656a478585e3a47bfdd65df9 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 5 May 2021 11:34:49 -0600 Subject: [PATCH] Fix crash when closing windows --- gpui/src/app.rs | 11 +++++++++++ gpui/src/platform/mac/window.rs | 25 ++++++++++++++++++++++++- gpui/src/platform/mod.rs | 1 + gpui/src/platform/test.rs | 6 ++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/gpui/src/app.rs b/gpui/src/app.rs index ac4c4e69b1782a416f5058025db0eafb974b7e7a..7cda6107f1e122037d8abef4128c9e6e31a61961 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 73196346e351ac823212248f0e5bb05931af81a2..92d0503aeb76d4ad767816897f86a888632c2c6e 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 b98d3a687bcd35a2dc22a4ca6cff600d5fea87ea..0450856950303e91540581ef4abcfe74b3b155a8 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 878449a0216e9a0a95447d9abaef16e089f8672c..2c8876f0c90cc95cf65a638dedb5019f7630073b 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 {