11use core:: sync:: atomic:: Ordering ;
22use std:: sync:: atomic:: AtomicBool ;
3- use std:: sync:: { Arc , Mutex } ;
3+ use std:: sync:: { Arc , Mutex , Weak } ;
44
55use dpi:: { LogicalPosition , PhysicalInsets , PhysicalPosition , PhysicalSize , Position , Size } ;
66use rwh_06:: RawWindowHandle ;
@@ -35,7 +35,10 @@ pub struct Popup {
3535 popup : SctkPopup ,
3636
3737 /// The state of the popup.
38- popup_state : Arc < Mutex < WindowState > > ,
38+ /// The only single truth of the state is stored
39+ /// in the event loop state, because if the server decides to destroy the popup
40+ /// we cannot use it anymore
41+ popup_state : Weak < Mutex < WindowState > > ,
3942
4043 /// Window id.
4144 window_id : WindowId ,
@@ -201,7 +204,7 @@ impl Popup {
201204
202205 Ok ( Self {
203206 popup,
204- popup_state,
207+ popup_state : Arc :: downgrade ( & popup_state ) ,
205208 window_id,
206209 display : event_loop_window_target. handle . connection . display ( ) . clone ( ) ,
207210 handles : Handles {
@@ -241,11 +244,13 @@ impl CoreWindow for Popup {
241244
242245 #[ inline]
243246 fn title ( & self ) -> String {
244- self . popup_state . lock ( ) . unwrap ( ) . title ( ) . to_owned ( )
247+ let Some ( s) = self . popup_state . upgrade ( ) else { return String :: new ( ) } ;
248+ s. lock ( ) . unwrap ( ) . title ( ) . to_owned ( )
245249 }
246250
247251 fn pre_present_notify ( & self ) {
248- self . popup_state . lock ( ) . unwrap ( ) . request_frame_callback ( ) ;
252+ let Some ( s) = self . popup_state . upgrade ( ) else { return } ;
253+ s. lock ( ) . unwrap ( ) . request_frame_callback ( ) ;
249254 }
250255
251256 fn reset_dead_keys ( & self ) {
@@ -262,7 +267,8 @@ impl CoreWindow for Popup {
262267 }
263268
264269 fn set_outer_position ( & self , position : Position ) {
265- let state = self . popup_state . lock ( ) . unwrap ( ) ;
270+ let Some ( s) = self . popup_state . upgrade ( ) else { return } ;
271+ let state = s. lock ( ) . unwrap ( ) ;
266272 if let WindowType :: Popup { popup, positioner, .. } = & state. window {
267273 let position = position. to_logical ( state. scale_factor ( ) ) ;
268274 positioner. set_offset ( position. x , position. y ) ;
@@ -271,20 +277,23 @@ impl CoreWindow for Popup {
271277 }
272278
273279 fn surface_size ( & self ) -> PhysicalSize < u32 > {
274- let popup_state = self . popup_state . lock ( ) . unwrap ( ) ;
280+ let Some ( s) = self . popup_state . upgrade ( ) else { return PhysicalSize :: default ( ) } ;
281+ let popup_state = s. lock ( ) . unwrap ( ) ;
275282 let scale_factor = popup_state. scale_factor ( ) ;
276283 super :: logical_to_physical_rounded ( popup_state. surface_size ( ) , scale_factor)
277284 }
278285
279286 fn request_surface_size ( & self , size : Size ) -> Option < PhysicalSize < u32 > > {
280- let mut popup_state = self . popup_state . lock ( ) . unwrap ( ) ;
287+ let Some ( s) = self . popup_state . upgrade ( ) else { return None } ;
288+ let mut popup_state = s. lock ( ) . unwrap ( ) ;
281289 popup_state. request_surface_size ( size) ;
282290 self . request_redraw ( ) ;
283291 Some ( size. to_physical ( popup_state. scale_factor ( ) ) )
284292 }
285293
286294 fn outer_size ( & self ) -> PhysicalSize < u32 > {
287- let popup_state = self . popup_state . lock ( ) . unwrap ( ) ;
295+ let Some ( s) = self . popup_state . upgrade ( ) else { return PhysicalSize :: default ( ) } ;
296+ let popup_state = s. lock ( ) . unwrap ( ) ;
288297 let scale_factor = popup_state. scale_factor ( ) ;
289298 super :: logical_to_physical_rounded ( popup_state. outer_size ( ) , scale_factor)
290299 }
@@ -296,7 +305,8 @@ impl CoreWindow for Popup {
296305 fn set_min_surface_size ( & self , min_size : Option < Size > ) {
297306 let scale_factor = self . scale_factor ( ) ;
298307 let min_size = min_size. map ( |size| size. to_logical ( scale_factor) ) ;
299- self . popup_state . lock ( ) . unwrap ( ) . set_min_surface_size ( min_size) ;
308+ let Some ( s) = self . popup_state . upgrade ( ) else { return } ;
309+ s. lock ( ) . unwrap ( ) . set_min_surface_size ( min_size) ;
300310 // NOTE: Requires commit to be applied.
301311 self . request_redraw ( ) ;
302312 }
@@ -306,33 +316,38 @@ impl CoreWindow for Popup {
306316 fn set_max_surface_size ( & self , max_size : Option < Size > ) {
307317 let scale_factor = self . scale_factor ( ) ;
308318 let max_size = max_size. map ( |size| size. to_logical ( scale_factor) ) ;
309- self . popup_state . lock ( ) . unwrap ( ) . set_max_surface_size ( max_size) ;
319+ let Some ( s) = self . popup_state . upgrade ( ) else { return } ;
320+ s. lock ( ) . unwrap ( ) . set_max_surface_size ( max_size) ;
310321 // NOTE: Requires commit to be applied.
311322 self . request_redraw ( ) ;
312323 }
313324
314325 fn surface_resize_increments ( & self ) -> Option < PhysicalSize < u32 > > {
315- let popup_state = self . popup_state . lock ( ) . unwrap ( ) ;
326+ let Some ( s) = self . popup_state . upgrade ( ) else { return None } ;
327+ let popup_state = s. lock ( ) . unwrap ( ) ;
316328 let scale_factor = popup_state. scale_factor ( ) ;
317329 popup_state
318330 . resize_increments ( )
319331 . map ( |size| super :: logical_to_physical_rounded ( size, scale_factor) )
320332 }
321333
322334 fn set_surface_resize_increments ( & self , increments : Option < Size > ) {
323- let mut popup_state = self . popup_state . lock ( ) . unwrap ( ) ;
335+ let Some ( s) = self . popup_state . upgrade ( ) else { return } ;
336+ let mut popup_state = s. lock ( ) . unwrap ( ) ;
324337 let scale_factor = popup_state. scale_factor ( ) ;
325338 let increments = increments. map ( |size| size. to_logical ( scale_factor) ) ;
326339 popup_state. set_resize_increments ( increments) ;
327340 }
328341
329342 fn set_title ( & self , title : & str ) {
330- self . popup_state . lock ( ) . unwrap ( ) . set_title ( title. to_owned ( ) ) ;
343+ let Some ( s) = self . popup_state . upgrade ( ) else { return } ;
344+ s. lock ( ) . unwrap ( ) . set_title ( title. to_owned ( ) ) ;
331345 }
332346
333347 #[ inline]
334348 fn set_transparent ( & self , transparent : bool ) {
335- self . popup_state . lock ( ) . unwrap ( ) . set_transparent ( transparent) ;
349+ let Some ( s) = self . popup_state . upgrade ( ) else { return } ;
350+ s. lock ( ) . unwrap ( ) . set_transparent ( transparent) ;
336351 }
337352
338353 fn set_visible ( & self , _visible : bool ) {
@@ -389,12 +404,14 @@ impl CoreWindow for Popup {
389404
390405 #[ inline]
391406 fn scale_factor ( & self ) -> f64 {
392- self . popup_state . lock ( ) . unwrap ( ) . scale_factor ( )
407+ let Some ( s) = self . popup_state . upgrade ( ) else { return 1.0 } ;
408+ s. lock ( ) . unwrap ( ) . scale_factor ( )
393409 }
394410
395411 #[ inline]
396412 fn set_blur ( & self , blur : bool ) {
397- if self . popup_state . lock ( ) . unwrap ( ) . set_blur ( blur) {
413+ let Some ( s) = self . popup_state . upgrade ( ) else { return } ;
414+ if s. lock ( ) . unwrap ( ) . set_blur ( blur) {
398415 self . request_redraw ( ) ;
399416 }
400417 }
@@ -420,7 +437,8 @@ impl CoreWindow for Popup {
420437
421438 #[ inline]
422439 fn request_ime_update ( & self , request : ImeRequest ) -> Result < ( ) , ImeRequestError > {
423- let state_changed = self . popup_state . lock ( ) . unwrap ( ) . request_ime_update ( request) ?;
440+ let Some ( s) = self . popup_state . upgrade ( ) else { return Ok ( ( ) ) } ;
441+ let state_changed = s. lock ( ) . unwrap ( ) . request_ime_update ( request) ?;
424442
425443 if let Some ( allowed) = state_changed {
426444 let event = WindowEvent :: Ime ( if allowed { Ime :: Enabled } else { Ime :: Disabled } ) ;
@@ -432,13 +450,15 @@ impl CoreWindow for Popup {
432450
433451 #[ inline]
434452 fn ime_capabilities ( & self ) -> Option < ImeCapabilities > {
435- self . popup_state . lock ( ) . unwrap ( ) . ime_allowed ( )
453+ let Some ( s) = self . popup_state . upgrade ( ) else { return None } ;
454+ s. lock ( ) . unwrap ( ) . ime_allowed ( )
436455 }
437456
438457 fn focus_window ( & self ) { }
439458
440459 fn has_focus ( & self ) -> bool {
441- self . popup_state . lock ( ) . unwrap ( ) . has_focus ( )
460+ let Some ( s) = self . popup_state . upgrade ( ) else { return false } ;
461+ s. lock ( ) . unwrap ( ) . has_focus ( )
442462 }
443463
444464 fn request_user_attention ( & self , request_type : Option < UserAttentionType > ) {
@@ -457,31 +477,33 @@ impl CoreWindow for Popup {
457477 fn set_content_protected ( & self , _protected : bool ) { }
458478
459479 fn set_cursor ( & self , cursor : Cursor ) {
460- let popup_state = & mut self . popup_state . lock ( ) . unwrap ( ) ;
461-
480+ let Some ( s ) = self . popup_state . upgrade ( ) else { return } ;
481+ let mut popup_state = s . lock ( ) . unwrap ( ) ;
462482 match cursor {
463483 Cursor :: Icon ( icon) => popup_state. set_cursor ( icon) ,
464484 Cursor :: Custom ( cursor) => popup_state. set_custom_cursor ( cursor) ,
465485 }
466486 }
467487
468488 fn set_cursor_position ( & self , position : Position ) -> Result < ( ) , RequestError > {
469- let scale_factor = self . scale_factor ( ) ;
489+ let Some ( s) = self . popup_state . upgrade ( ) else { return Err ( RequestError :: Ignored ) } ;
490+ let scale_factor = s. lock ( ) . unwrap ( ) . scale_factor ( ) ;
470491 let position = position. to_logical ( scale_factor) ;
471- self . popup_state
472- . lock ( )
492+ s. lock ( )
473493 . unwrap ( )
474494 . set_cursor_position ( position)
475495 // Request redraw on success, since the state is double buffered.
476496 . map ( |_| self . request_redraw ( ) )
477497 }
478498
479499 fn set_cursor_grab ( & self , mode : CursorGrabMode ) -> Result < ( ) , RequestError > {
480- self . popup_state . lock ( ) . unwrap ( ) . set_cursor_grab ( mode)
500+ let Some ( s) = self . popup_state . upgrade ( ) else { return Err ( RequestError :: Ignored ) } ;
501+ s. lock ( ) . unwrap ( ) . set_cursor_grab ( mode)
481502 }
482503
483504 fn set_cursor_visible ( & self , visible : bool ) {
484- self . popup_state . lock ( ) . unwrap ( ) . set_cursor_visible ( visible) ;
505+ let Some ( s) = self . popup_state . upgrade ( ) else { return } ;
506+ s. lock ( ) . unwrap ( ) . set_cursor_visible ( visible) ;
485507 }
486508
487509 fn drag_window ( & self ) -> Result < ( ) , RequestError > {
@@ -539,9 +561,11 @@ impl Drop for Popup {
539561
540562impl rwh_06:: HasWindowHandle for Popup {
541563 fn window_handle ( & self ) -> Result < rwh_06:: WindowHandle < ' _ > , rwh_06:: HandleError > {
564+ if self . popup_state . upgrade ( ) . is_none ( ) {
565+ return Err ( rwh_06:: HandleError :: Unavailable ) ;
566+ } ;
542567 let raw = rwh_06:: WaylandWindowHandle :: new ( {
543- let state = self . popup_state . lock ( ) . unwrap ( ) ;
544- let ptr = state. window . wl_surface ( ) . id ( ) . as_ptr ( ) ;
568+ let ptr = self . popup . wl_surface ( ) . id ( ) . as_ptr ( ) ;
545569 std:: ptr:: NonNull :: new ( ptr as * mut _ ) . expect ( "wl_surface will never be null" )
546570 } ) ;
547571
@@ -551,6 +575,9 @@ impl rwh_06::HasWindowHandle for Popup {
551575
552576impl rwh_06:: HasDisplayHandle for Popup {
553577 fn display_handle ( & self ) -> Result < rwh_06:: DisplayHandle < ' _ > , rwh_06:: HandleError > {
578+ if self . popup_state . upgrade ( ) . is_none ( ) {
579+ return Err ( rwh_06:: HandleError :: Unavailable ) ;
580+ } ;
554581 let raw = rwh_06:: WaylandDisplayHandle :: new ( {
555582 let ptr = self . display . id ( ) . as_ptr ( ) ;
556583 std:: ptr:: NonNull :: new ( ptr as * mut _ ) . expect ( "wl_proxy should never be null" )
0 commit comments