@@ -20,7 +20,7 @@ use objc2_app_kit::{
2020 NSTrackingAreaOptions , NSView , NSWindow ,
2121} ;
2222use objc2_foundation:: { NSArray , NSNotification , NSPoint , NSRect , NSSize , NSString } ;
23- use std:: cell:: { Cell , OnceCell } ;
23+ use std:: cell:: { Cell , RefCell } ;
2424use std:: rc:: Rc ;
2525
2626pub enum ViewParentingType {
@@ -31,7 +31,7 @@ pub enum ViewParentingType {
3131pub ( crate ) struct BaseviewView {
3232 pub ( crate ) state : Rc < WindowSharedState > ,
3333 pub ( crate ) mtm : MainThreadMarker ,
34- window_handler : OnceCell < Box < dyn WindowHandler > > ,
34+ window_handler : WindowHandlerContainer ,
3535
3636 frame_timer : Cell < Option < TimerHandle > > ,
3737 notification_center_observer : Cell < Option < NotificationCenterObserver > > ,
@@ -41,7 +41,7 @@ pub(crate) struct BaseviewView {
4141 parenting : ViewParentingType ,
4242
4343 #[ cfg( feature = "opengl" ) ]
44- pub ( crate ) gl_context : OnceCell < super :: gl:: GlContext > ,
44+ pub ( crate ) gl_context : std :: cell :: OnceCell < super :: gl:: GlContext > ,
4545}
4646
4747impl BaseviewView {
@@ -60,12 +60,12 @@ impl BaseviewView {
6060
6161 keyboard_state : KeyboardState :: new ( ) ,
6262 frame_timer : None . into ( ) ,
63- window_handler : OnceCell :: new ( ) ,
63+ window_handler : WindowHandlerContainer :: new ( ) ,
6464 notification_center_observer : None . into ( ) ,
6565 parenting,
6666
6767 #[ cfg( feature = "opengl" ) ]
68- gl_context : OnceCell :: new ( ) ,
68+ gl_context : std :: cell :: OnceCell :: new ( ) ,
6969 } ;
7070
7171 let view = View :: new ( view_rect, inner, |view| {
@@ -95,7 +95,7 @@ impl BaseviewView {
9595 let handler = builder. build ( crate :: WindowContext :: new ( context) ) ;
9696
9797 // Initialize handler
98- let Ok ( ( ) ) = view. window_handler . set ( handler) else { unreachable ! ( ) } ;
98+ view. window_handler . set ( handler) ;
9999
100100 // Set up anything that might trigger events to the handler
101101
@@ -129,6 +129,9 @@ impl BaseviewView {
129129 pub fn close ( this : ViewRef < Self > ) {
130130 this. state . closed . set ( true ) ;
131131 this. view . removeFromSuperview ( ) ;
132+ this. notification_center_observer . take ( ) ;
133+ this. frame_timer . take ( ) ;
134+ this. window_handler . destroy ( ) ;
132135
133136 if let ViewParentingType :: Windowed { owned_window : parent_window, running_app } =
134137 & this. parenting
@@ -171,17 +174,11 @@ impl BaseviewView {
171174
172175 /// Trigger the event immediately and return the event status.
173176 fn trigger_event ( this : ViewRef < Self > , event : Event ) -> EventStatus {
174- let Some ( handler) = this. window_handler . get ( ) else {
175- return EventStatus :: Ignored ;
176- } ;
177-
178- handler. on_event ( event)
177+ this. window_handler . use_handler ( |h| h. on_event ( event) ) . unwrap_or ( EventStatus :: Ignored )
179178 }
180179
181180 fn trigger_frame ( this : ViewRef < Self > ) {
182- let Some ( handler) = this. window_handler . get ( ) else { return } ;
183-
184- handler. on_frame ( ) ;
181+ this. window_handler . use_handler ( |h| h. on_frame ( ) ) ;
185182 }
186183}
187184
@@ -228,9 +225,9 @@ impl ViewImpl for BaseviewView {
228225 this. state . size . set ( current_size) ;
229226 this. state . scale_factor . set ( current_scale_factor) ;
230227
231- if let Some ( handler ) = this. window_handler . get ( ) {
232- handler . resized ( WindowSize :: from_logical ( current_size, current_scale_factor) )
233- }
228+ this. window_handler . use_handler ( |h| {
229+ h . resized ( WindowSize :: from_logical ( current_size, current_scale_factor) )
230+ } ) ;
234231 }
235232 }
236233
@@ -619,3 +616,41 @@ fn on_event(this: ViewRef<BaseviewView>, event: MouseEvent) -> NSDragOperation {
619616 _ => NSDragOperation :: None ,
620617 }
621618}
619+
620+ pub struct WindowHandlerContainer {
621+ inner : RefCell < Option < Box < dyn WindowHandler > > > ,
622+ must_be_destroyed : Cell < bool > ,
623+ }
624+
625+ impl WindowHandlerContainer {
626+ pub fn new ( ) -> WindowHandlerContainer {
627+ Self { inner : RefCell :: new ( None ) , must_be_destroyed : false . into ( ) }
628+ }
629+
630+ pub fn use_handler < T > ( & self , user : impl FnOnce ( & dyn WindowHandler ) -> T ) -> Option < T > {
631+ let returned = {
632+ let inner = self . inner . try_borrow ( ) . ok ( ) ?;
633+ user ( inner. as_ref ( ) ?. as_ref ( ) )
634+ } ;
635+
636+ if self . must_be_destroyed . get ( ) {
637+ if let Ok ( mut inner) = self . inner . try_borrow_mut ( ) {
638+ * inner = None ;
639+ }
640+ }
641+
642+ Some ( returned)
643+ }
644+
645+ pub fn set ( & self , handler : Box < dyn WindowHandler > ) {
646+ self . inner . replace ( Some ( handler) ) ;
647+ self . must_be_destroyed . set ( false ) ;
648+ }
649+
650+ pub fn destroy ( & self ) {
651+ match self . inner . try_borrow_mut ( ) {
652+ Ok ( mut inner) => * inner = None ,
653+ Err ( _) => self . must_be_destroyed . set ( true ) ,
654+ }
655+ }
656+ }
0 commit comments