From 3ff9eb08e8e370da6505c0560c53233b0399edaa Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Fri, 10 Mar 2017 23:40:31 +0100 Subject: [PATCH] wayland: cleanup signal to prune dead windows --- src/platform/linux/wayland/event_loop.rs | 42 +++++++++++++++++------- src/platform/linux/wayland/window.rs | 6 +++- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/platform/linux/wayland/event_loop.rs b/src/platform/linux/wayland/event_loop.rs index 9cdcc33f..ea86dd58 100644 --- a/src/platform/linux/wayland/event_loop.rs +++ b/src/platform/linux/wayland/event_loop.rs @@ -1,7 +1,5 @@ use {WindowEvent as Event, ElementState, MouseButton, MouseScrollDelta, TouchPhase, ModifiersState}; -use std::cell::UnsafeCell; -use std::collections::VecDeque; use std::sync::{Arc, Mutex}; use std::sync::atomic::AtomicBool; @@ -54,9 +52,10 @@ impl EventsLoopSink { pub struct EventsLoop { ctxt: Arc, evq: Arc>, - decorated_ids: Mutex>, + decorated_ids: Mutex)>>, sink: Arc>, interrupted: AtomicBool, + cleanup_needed: Arc, hid: usize } @@ -71,31 +70,32 @@ impl EventsLoop { decorated_ids: Mutex::new(Vec::new()), sink: sink, interrupted: AtomicBool::new(false), + cleanup_needed: Arc::new(AtomicBool::new(false)), hid: hid } } - pub fn get_event_queue(&self) -> Arc> { - self.evq.clone() + pub fn get_window_init(&self) -> (Arc>, Arc) { + (self.evq.clone(), self.cleanup_needed.clone()) } pub fn register_window(&self, decorated_id: usize, surface: Arc) { - self.decorated_ids.lock().unwrap().push((decorated_id, make_wid(&surface))); + self.decorated_ids.lock().unwrap().push((decorated_id, surface.clone())); let mut guard = self.evq.lock().unwrap(); let mut state = guard.state(); state.get_mut_handler::(self.hid).windows.push(surface); } - fn process_resize(evq: &mut EventQueue, ids: &[(usize, WindowId)], callback: &mut FnMut(::Event)) + fn process_resize(evq: &mut EventQueue, ids: &[(usize, Arc)], callback: &mut FnMut(::Event)) { let mut state = evq.state(); - for &(decorated_id, window_id) in ids { + for &(decorated_id, ref window) in ids { let decorated = state.get_mut_handler::>(decorated_id); if let Some((w, h)) = decorated.handler().as_mut().and_then(|h| h.take_newsize()) { decorated.resize(w as i32, h as i32); callback( ::Event::WindowEvent { - window_id: ::WindowId(::platform::WindowId::Wayland(window_id)), + window_id: ::WindowId(::platform::WindowId::Wayland(make_wid(&window))), event: ::WindowEvent::Resized(w,h) } ); @@ -107,7 +107,20 @@ impl EventsLoop { self.interrupted.store(true, ::std::sync::atomic::Ordering::Relaxed); } - pub fn poll_events(&self, mut callback: F) + fn prune_dead_windows(&self) { + self.decorated_ids.lock().unwrap().retain(|&(_, ref w)| w.is_alive()); + let mut evq_guard = self.evq.lock().unwrap(); + let mut state = evq_guard.state(); + let handler = state.get_mut_handler::(self.hid); + handler.windows.retain(|w| w.is_alive()); + if let Some(w) = handler.mouse_focus.take() { + if w.is_alive() { + handler.mouse_focus = Some(w) + } + } + } + + pub fn poll_events(&self, callback: F) where F: FnMut(::Event) { // send pending requests to the server... @@ -142,9 +155,12 @@ impl EventsLoop { // replace the old noop callback unsafe { self.sink.lock().unwrap().set_callback(old_cb) }; + if self.cleanup_needed.swap(false, ::std::sync::atomic::Ordering::Relaxed) { + self.prune_dead_windows() + } } - pub fn run_forever(&self, mut callback: F) + pub fn run_forever(&self, callback: F) where F: FnMut(::Event) { // send pending requests to the server... @@ -171,6 +187,10 @@ impl EventsLoop { // replace the old noop callback unsafe { self.sink.lock().unwrap().set_callback(old_cb) }; + + if self.cleanup_needed.swap(false, ::std::sync::atomic::Ordering::Relaxed) { + self.prune_dead_windows() + } } } diff --git a/src/platform/linux/wayland/window.rs b/src/platform/linux/wayland/window.rs index af07adbd..30d192b4 100644 --- a/src/platform/linux/wayland/window.rs +++ b/src/platform/linux/wayland/window.rs @@ -1,4 +1,5 @@ use std::sync::{Arc, Mutex}; +use std::sync::atomic::AtomicBool; use wayland_client::{EventQueue, EventQueueHandle, Proxy}; use wayland_client::protocol::{wl_display,wl_surface,wl_shell_surface}; @@ -13,6 +14,7 @@ use super::wayland_window::DecoratedSurface; pub struct Window { ctxt: Arc, evq: Arc>, + cleanup_signal: Arc, surface: Arc, size: Mutex<(u32, u32)>, decorated_id: usize @@ -34,7 +36,7 @@ impl Window { let (surface, decorated) = ctxt.create_window::(); // init DecoratedSurface - let evq = evlp.get_event_queue(); + let (evq, cleanup_signal) = evlp.get_window_init(); let decorated_id = { let mut evq_guard = evq.lock().unwrap(); let decorated_id = evq_guard.add_handler_with_init(decorated); @@ -62,6 +64,7 @@ impl Window { let me = Window { ctxt: ctxt, evq: evq, + cleanup_signal: cleanup_signal, surface: surface, size: Mutex::new((width, height)), decorated_id: decorated_id @@ -165,6 +168,7 @@ impl Window { impl Drop for Window { fn drop(&mut self) { self.surface.destroy(); + self.cleanup_signal.store(true, ::std::sync::atomic::Ordering::Relaxed); } }