Skip to content

Commit 6921e91

Browse files
committed
Always force-close windows when dropping WindowHandle (#288)
1 parent 9014a9e commit 6921e91

8 files changed

Lines changed: 105 additions & 67 deletions

File tree

src/platform/macos/context.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ impl WindowContext {
2929

3030
pub fn request_close(&self) {
3131
let Some(view) = self.view.load() else { return };
32-
BaseviewView::close(view.inner_ref());
32+
let Some(view) = view.inner_ref() else { return };
33+
BaseviewView::close(view);
3334
}
3435

3536
pub fn has_focus(&self) -> bool {
@@ -58,7 +59,7 @@ impl WindowContext {
5859

5960
pub fn resize(&self, size: Size) {
6061
let Some(view) = self.view.load() else { return };
61-
let view = view.inner_ref();
62+
let Some(view) = view.inner_ref() else { return };
6263
if view.inner.state.closed.get() {
6364
return;
6465
}
@@ -82,7 +83,7 @@ impl WindowContext {
8283

8384
#[cfg(feature = "opengl")]
8485
pub fn gl_context(&self) -> Option<crate::gl::GlContext> {
85-
Some(crate::gl::GlContext::new(self.view.load()?.inner().gl_context.get()?.clone()))
86+
Some(crate::gl::GlContext::new(self.view.load()?.inner()?.gl_context.get()?.clone()))
8687
}
8788

8889
pub fn window_handle(&self) -> Option<raw_window_handle::WindowHandle<'_>> {

src/platform/macos/view.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,18 @@ impl BaseviewView {
106106
let timer_view = Weak::new(view.view);
107107
view.frame_timer.set(TimerHandle::new(0.015, move || {
108108
if let Some(view) = timer_view.load() {
109-
Self::trigger_frame(view.inner_ref());
109+
if let Some(view) = view.inner_ref() {
110+
Self::trigger_frame(view);
111+
}
110112
}
111113
}));
112114

113115
let notifier_view = Weak::new(view.view);
114116
let observer = NotificationCenterObserver::register_window_key_change(move |n| {
115117
if let Some(view) = notifier_view.load() {
116-
BaseviewView::handle_notification(view.inner_ref(), n);
118+
if let Some(view) = view.inner_ref() {
119+
BaseviewView::handle_notification(view, n);
120+
}
117121
}
118122
});
119123
view.notification_center_observer.set(Some(observer));

src/platform/macos/window.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ pub struct WindowHandle {
1818
state: Rc<WindowSharedState>,
1919
}
2020

21+
impl Drop for WindowHandle {
22+
fn drop(&mut self) {
23+
let Some(view) = self.view.load() else { return };
24+
let Some(view) = view.inner_ref() else { return };
25+
26+
BaseviewView::close(view);
27+
}
28+
}
29+
2130
impl WindowHandle {
2231
pub fn create_window(mut options: WindowOpenOptions, handler: WindowHandlerBuilder) -> Self {
2332
autoreleasepool(|_| {
@@ -75,14 +84,6 @@ impl WindowHandle {
7584
NSApplication::sharedApplication(self.mtm).run();
7685
}
7786

78-
pub fn close(&self) {
79-
let Some(view) = self.view.load() else {
80-
return;
81-
};
82-
83-
BaseviewView::close(view.inner_ref());
84-
}
85-
8687
pub fn is_open(&self) -> bool {
8788
self.state.closed.get()
8889
}

src/platform/win/window.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
use windows_core::{ComObject, Result, HSTRING};
22
use windows_sys::Win32::{
3-
Foundation::{HWND, LPARAM, LRESULT, RECT, WPARAM},
3+
Foundation::{LPARAM, LRESULT, RECT, WPARAM},
44
UI::{
55
Controls::WM_MOUSELEAVE,
66
WindowsAndMessaging::{
7-
PostMessageW, HTCLIENT, WHEEL_DELTA, WM_CHAR, WM_CLOSE, WM_DPICHANGED,
8-
WM_INPUTLANGCHANGE, WM_KEYDOWN, WM_KEYUP, WM_KILLFOCUS, WM_LBUTTONDOWN, WM_LBUTTONUP,
9-
WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEHWHEEL, WM_MOUSEMOVE, WM_MOUSEWHEEL,
10-
WM_RBUTTONDOWN, WM_RBUTTONUP, WM_SETCURSOR, WM_SETFOCUS, WM_SIZE, WM_SYSCHAR,
11-
WM_SYSKEYDOWN, WM_SYSKEYUP, WM_TIMER, WM_USER, WM_XBUTTONDOWN, WM_XBUTTONUP,
7+
HTCLIENT, WHEEL_DELTA, WM_CHAR, WM_CLOSE, WM_DPICHANGED, WM_INPUTLANGCHANGE,
8+
WM_KEYDOWN, WM_KEYUP, WM_KILLFOCUS, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN,
9+
WM_MBUTTONUP, WM_MOUSEHWHEEL, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_RBUTTONDOWN,
10+
WM_RBUTTONUP, WM_SETCURSOR, WM_SETFOCUS, WM_SIZE, WM_SYSCHAR, WM_SYSKEYDOWN,
11+
WM_SYSKEYUP, WM_TIMER, WM_USER, WM_XBUTTONDOWN, WM_XBUTTONUP,
1212
},
1313
},
1414
};
@@ -59,19 +59,19 @@ impl WindowHandle {
5959
run_thread_message_loop_until(|| !self.is_open()).unwrap();
6060
}
6161

62-
pub fn close(&self) {
63-
if let Some(hwnd) = self.hwnd.take() {
64-
unsafe {
65-
PostMessageW(hwnd.as_raw(), BV_WINDOW_MUST_CLOSE, 0, 0);
66-
}
67-
}
68-
}
69-
7062
pub fn is_open(&self) -> bool {
7163
self.is_open.get()
7264
}
7365
}
7466

67+
impl Drop for WindowHandle {
68+
fn drop(&mut self) {
69+
if let Some(hwnd) = self.hwnd.take() {
70+
let _ = hwnd.destroy();
71+
}
72+
}
73+
}
74+
7575
struct ParentHandle {
7676
is_open: Rc<Cell<bool>>,
7777
}

src/platform/x11/window.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,18 @@ impl WindowHandle {
5151
});
5252
}
5353

54-
pub fn close(&self) {
54+
pub fn is_open(&self) -> bool {
55+
self.is_open.load(Ordering::Relaxed)
56+
}
57+
}
58+
59+
impl Drop for WindowHandle {
60+
fn drop(&mut self) {
5561
self.close_requested.store(true, Ordering::Relaxed);
5662
if let Some(event_loop) = self.event_loop_handle.take() {
5763
let _ = event_loop.join();
5864
}
5965
}
60-
61-
pub fn is_open(&self) -> bool {
62-
self.is_open.load(Ordering::Relaxed)
63-
}
6466
}
6567

6668
pub(crate) struct ParentHandle {

src/window.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ impl WindowHandle {
2020
}
2121

2222
/// Close the window
23-
pub fn close(&self) {
24-
self.window_handle.close();
23+
pub fn close(self) {
24+
drop(self)
2525
}
2626

2727
/// Returns `true` if the window is still open, and returns `false`

src/wrappers/appkit/view.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl<V: ViewImpl> View<V> {
5151

5252
let view: Retained<View<V>> = unsafe { msg_send![view, initWithFrame: frame] };
5353

54-
init(view.inner_ref());
54+
init(view.inner_ref().unwrap());
5555

5656
view
5757
}
@@ -68,23 +68,28 @@ impl<V: ViewImpl> View<V> {
6868
let ivar = class.instance_variable(BASEVIEW_STATE_IVAR).unwrap();
6969
let ivar = unsafe { ivar.load_ptr::<*mut c_void>(this) };
7070
let raw = unsafe { ivar.read() };
71+
72+
if raw.is_null() {
73+
return;
74+
}
75+
7176
let inner = unsafe { Box::<ViewInner<V>>::from_raw(raw.cast()) };
7277
unsafe { ivar.write(core::ptr::null_mut()) };
7378
drop(inner);
7479
}
7580

76-
fn get_inner(&self) -> &ViewInner<V> {
81+
fn get_inner(&self) -> Option<&ViewInner<V>> {
7782
let ivar = self.class().instance_variable(BASEVIEW_STATE_IVAR).unwrap();
7883
let ivar = unsafe { ivar.load::<*mut c_void>(self) };
79-
unsafe { ivar.cast::<ViewInner<V>>().as_ref() }.unwrap()
84+
unsafe { ivar.cast::<ViewInner<V>>().as_ref() }
8085
}
8186

82-
pub fn inner(&self) -> &V {
83-
&self.get_inner().inner
87+
pub fn inner(&self) -> Option<&V> {
88+
Some(&self.get_inner()?.inner)
8489
}
8590

86-
pub fn inner_ref(&self) -> ViewRef<'_, V> {
87-
ViewRef { view: self, inner: self.inner() }
91+
pub fn inner_ref(&self) -> Option<ViewRef<'_, V>> {
92+
Some(ViewRef { view: self, inner: self.inner()? })
8893
}
8994

9095
pub fn window_handle_from_weak(this: &Weak<Self>) -> Option<WindowHandle<'_>> {

src/wrappers/appkit/view/implementation.rs

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -162,125 +162,150 @@ extern "C-unwind" fn accepts_first_mouse(_this: &NSView, _sel: Sel, _event: &NSE
162162
}
163163

164164
extern "C-unwind" fn become_first_responder<V: ViewImpl>(this: &View<V>, _sel: Sel) -> Bool {
165-
V::become_first_responder(this.inner_ref()).into()
165+
let Some(inner) = this.inner_ref() else { return false.into() };
166+
V::become_first_responder(inner).into()
166167
}
167168

168169
extern "C-unwind" fn resign_first_responder<V: ViewImpl>(this: &View<V>, _sel: Sel) -> Bool {
169-
V::resign_first_responder(this.inner_ref()).into()
170+
let Some(inner) = this.inner_ref() else { return true.into() };
171+
V::resign_first_responder(inner).into()
170172
}
171173

172174
extern "C-unwind" fn window_should_close<V: ViewImpl>(
173175
this: &View<V>, _: Sel, _sender: &AnyObject,
174176
) -> Bool {
175-
V::window_should_close(this.inner_ref()).into()
177+
let Some(inner) = this.inner_ref() else { return true.into() };
178+
V::window_should_close(inner).into()
176179
}
177180

178181
extern "C-unwind" fn view_did_change_backing_properties<V: ViewImpl>(
179182
this: &View<V>, _: Sel, _: &AnyObject,
180183
) {
181-
V::view_did_change_backing_properties(this.inner_ref());
184+
let Some(inner) = this.inner_ref() else { return };
185+
V::view_did_change_backing_properties(inner);
182186
}
183187

184188
extern "C-unwind" fn hit_test<V: ViewImpl>(
185189
this: &View<V>, _sel: Sel, point: NSPoint,
186190
) -> Option<&NSView> {
187-
V::hit_test(this.inner_ref(), point)
191+
V::hit_test(this.inner_ref()?, point)
188192
}
189193

190194
extern "C-unwind" fn view_will_move_to_window<V: ViewImpl>(
191195
this: &View<V>, _self: Sel, new_window: Option<&NSWindow>,
192196
) {
193-
V::view_will_move_to_window(this.inner_ref(), new_window);
197+
let Some(inner) = this.inner_ref() else { return };
198+
V::view_will_move_to_window(inner, new_window);
194199
}
195200

196201
extern "C-unwind" fn update_tracking_areas<V: ViewImpl>(this: &View<V>, _self: Sel, _: &AnyObject) {
197-
V::update_tracking_areas(this.inner_ref());
202+
let Some(inner) = this.inner_ref() else { return };
203+
V::update_tracking_areas(inner);
198204
}
199205

200206
extern "C-unwind" fn mouse_moved<V: ViewImpl>(this: &View<V>, _sel: Sel, event: &NSEvent) {
201-
V::mouse_moved(this.inner_ref(), event);
207+
let Some(inner) = this.inner_ref() else { return };
208+
V::mouse_moved(inner, event);
202209
}
203210

204211
extern "C-unwind" fn scroll_wheel<V: ViewImpl>(this: &View<V>, _: Sel, event: &NSEvent) {
205-
V::scroll_wheel(this.inner_ref(), event);
212+
let Some(inner) = this.inner_ref() else { return };
213+
V::scroll_wheel(inner, event);
206214
}
207215

208216
extern "C-unwind" fn dragging_entered<V: ViewImpl>(
209217
this: &View<V>, _sel: Sel, sender: Option<&ProtocolObject<dyn NSDraggingInfo>>,
210218
) -> NSDragOperation {
211-
V::dragging_entered(this.inner_ref(), sender)
219+
let Some(inner) = this.inner_ref() else { return NSDragOperation::None };
220+
V::dragging_entered(inner, sender)
212221
}
213222

214223
extern "C-unwind" fn dragging_updated<V: ViewImpl>(
215224
this: &View<V>, _sel: Sel, sender: Option<&ProtocolObject<dyn NSDraggingInfo>>,
216225
) -> NSDragOperation {
217-
V::dragging_updated(this.inner_ref(), sender)
226+
let Some(inner) = this.inner_ref() else { return NSDragOperation::None };
227+
V::dragging_updated(inner, sender)
218228
}
219229

220230
extern "C-unwind" fn prepare_for_drag_operation<V: ViewImpl>(
221231
this: &View<V>, _sel: Sel, sender: Option<&ProtocolObject<dyn NSDraggingInfo>>,
222232
) -> Bool {
223-
V::prepare_for_drag_operation(this.inner_ref(), sender).into()
233+
let Some(inner) = this.inner_ref() else { return false.into() };
234+
V::prepare_for_drag_operation(inner, sender).into()
224235
}
225236

226237
extern "C-unwind" fn perform_drag_operation<V: ViewImpl>(
227238
this: &View<V>, _sel: Sel, sender: Option<&ProtocolObject<dyn NSDraggingInfo>>,
228239
) -> Bool {
229-
V::perform_drag_operation(this.inner_ref(), sender).into()
240+
let Some(inner) = this.inner_ref() else { return false.into() };
241+
V::perform_drag_operation(inner, sender).into()
230242
}
231243

232244
extern "C-unwind" fn dragging_exited<V: ViewImpl>(
233245
this: &View<V>, _sel: Sel, sender: Option<&ProtocolObject<dyn NSDraggingInfo>>,
234246
) {
235-
V::dragging_exited(this.inner_ref(), sender)
247+
let Some(inner) = this.inner_ref() else { return };
248+
V::dragging_exited(inner, sender)
236249
}
237250

238251
extern "C-unwind" fn handle_notification<V: ViewImpl>(
239252
this: &View<V>, _cmd: Sel, notification: &NSNotification,
240253
) {
241-
V::handle_notification(this.inner_ref(), notification)
254+
let Some(inner) = this.inner_ref() else { return };
255+
V::handle_notification(inner, notification)
242256
}
243257

244258
extern "C-unwind" fn mouse_entered<V: ViewImpl>(this: &View<V>, _: Sel, _: &AnyObject) {
245-
V::mouse_entered(this.inner_ref());
259+
let Some(inner) = this.inner_ref() else { return };
260+
V::mouse_entered(inner);
246261
}
247262

248263
extern "C-unwind" fn mouse_exited<V: ViewImpl>(this: &View<V>, _: Sel, _: &AnyObject) {
249-
V::mouse_exited(this.inner_ref());
264+
let Some(inner) = this.inner_ref() else { return };
265+
V::mouse_exited(inner);
250266
}
251267

252268
extern "C-unwind" fn key_down<V: ViewImpl>(this: &View<V>, _: Sel, event: &NSEvent) {
253-
V::key_down(this.inner_ref(), event);
269+
let Some(inner) = this.inner_ref() else { return };
270+
V::key_down(inner, event);
254271
}
255272

256273
extern "C-unwind" fn key_up<V: ViewImpl>(this: &View<V>, _: Sel, event: &NSEvent) {
257-
V::key_up(this.inner_ref(), event);
274+
let Some(inner) = this.inner_ref() else { return };
275+
V::key_up(inner, event);
258276
}
259277

260278
extern "C-unwind" fn flags_changed<V: ViewImpl>(this: &View<V>, _: Sel, event: &NSEvent) {
261-
V::flags_changed(this.inner_ref(), event);
279+
let Some(inner) = this.inner_ref() else { return };
280+
V::flags_changed(inner, event);
262281
}
263282

264283
extern "C-unwind" fn mouse_down<V: ViewImpl>(this: &View<V>, _sel: Sel, event: &NSEvent) {
265-
V::mouse_down(this.inner_ref(), event);
284+
let Some(inner) = this.inner_ref() else { return };
285+
V::mouse_down(inner, event);
266286
}
267287

268288
extern "C-unwind" fn mouse_up<V: ViewImpl>(this: &View<V>, _sel: Sel, event: &NSEvent) {
269-
V::mouse_up(this.inner_ref(), event);
289+
let Some(inner) = this.inner_ref() else { return };
290+
V::mouse_up(inner, event);
270291
}
271292

272293
extern "C-unwind" fn right_mouse_down<V: ViewImpl>(this: &View<V>, _sel: Sel, event: &NSEvent) {
273-
V::right_mouse_down(this.inner_ref(), event);
294+
let Some(inner) = this.inner_ref() else { return };
295+
V::right_mouse_down(inner, event);
274296
}
275297

276298
extern "C-unwind" fn right_mouse_up<V: ViewImpl>(this: &View<V>, _sel: Sel, event: &NSEvent) {
277-
V::right_mouse_up(this.inner_ref(), event);
299+
let Some(inner) = this.inner_ref() else { return };
300+
V::right_mouse_up(inner, event);
278301
}
279302

280303
extern "C-unwind" fn other_mouse_down<V: ViewImpl>(this: &View<V>, _sel: Sel, event: &NSEvent) {
281-
V::other_mouse_down(this.inner_ref(), event);
304+
let Some(inner) = this.inner_ref() else { return };
305+
V::other_mouse_down(inner, event);
282306
}
283307

284308
extern "C-unwind" fn other_mouse_up<V: ViewImpl>(this: &View<V>, _sel: Sel, event: &NSEvent) {
285-
V::other_mouse_up(this.inner_ref(), event);
309+
let Some(inner) = this.inner_ref() else { return };
310+
V::other_mouse_up(inner, event);
286311
}

0 commit comments

Comments
 (0)