wayland: cleanup signal to prune dead windows

This commit is contained in:
Victor Berger 2017-03-10 23:40:31 +01:00
parent 17fde48ed7
commit 3ff9eb08e8
2 changed files with 36 additions and 12 deletions

View file

@ -1,7 +1,5 @@
use {WindowEvent as Event, ElementState, MouseButton, MouseScrollDelta, TouchPhase, ModifiersState}; 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::{Arc, Mutex};
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
@ -54,9 +52,10 @@ impl EventsLoopSink {
pub struct EventsLoop { pub struct EventsLoop {
ctxt: Arc<WaylandContext>, ctxt: Arc<WaylandContext>,
evq: Arc<Mutex<EventQueue>>, evq: Arc<Mutex<EventQueue>>,
decorated_ids: Mutex<Vec<(usize, WindowId)>>, decorated_ids: Mutex<Vec<(usize, Arc<wl_surface::WlSurface>)>>,
sink: Arc<Mutex<EventsLoopSink>>, sink: Arc<Mutex<EventsLoopSink>>,
interrupted: AtomicBool, interrupted: AtomicBool,
cleanup_needed: Arc<AtomicBool>,
hid: usize hid: usize
} }
@ -71,31 +70,32 @@ impl EventsLoop {
decorated_ids: Mutex::new(Vec::new()), decorated_ids: Mutex::new(Vec::new()),
sink: sink, sink: sink,
interrupted: AtomicBool::new(false), interrupted: AtomicBool::new(false),
cleanup_needed: Arc::new(AtomicBool::new(false)),
hid: hid hid: hid
} }
} }
pub fn get_event_queue(&self) -> Arc<Mutex<EventQueue>> { pub fn get_window_init(&self) -> (Arc<Mutex<EventQueue>>, Arc<AtomicBool>) {
self.evq.clone() (self.evq.clone(), self.cleanup_needed.clone())
} }
pub fn register_window(&self, decorated_id: usize, surface: Arc<wl_surface::WlSurface>) { pub fn register_window(&self, decorated_id: usize, surface: Arc<wl_surface::WlSurface>) {
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 guard = self.evq.lock().unwrap();
let mut state = guard.state(); let mut state = guard.state();
state.get_mut_handler::<InputHandler>(self.hid).windows.push(surface); state.get_mut_handler::<InputHandler>(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<wl_surface::WlSurface>)], callback: &mut FnMut(::Event))
{ {
let mut state = evq.state(); 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::<DecoratedSurface<DecoratedHandler>>(decorated_id); let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(decorated_id);
if let Some((w, h)) = decorated.handler().as_mut().and_then(|h| h.take_newsize()) { if let Some((w, h)) = decorated.handler().as_mut().and_then(|h| h.take_newsize()) {
decorated.resize(w as i32, h as i32); decorated.resize(w as i32, h as i32);
callback( callback(
::Event::WindowEvent { ::Event::WindowEvent {
window_id: ::WindowId(::platform::WindowId::Wayland(window_id)), window_id: ::WindowId(::platform::WindowId::Wayland(make_wid(&window))),
event: ::WindowEvent::Resized(w,h) event: ::WindowEvent::Resized(w,h)
} }
); );
@ -107,7 +107,20 @@ impl EventsLoop {
self.interrupted.store(true, ::std::sync::atomic::Ordering::Relaxed); self.interrupted.store(true, ::std::sync::atomic::Ordering::Relaxed);
} }
pub fn poll_events<F>(&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::<InputHandler>(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<F>(&self, callback: F)
where F: FnMut(::Event) where F: FnMut(::Event)
{ {
// send pending requests to the server... // send pending requests to the server...
@ -142,9 +155,12 @@ impl EventsLoop {
// replace the old noop callback // replace the old noop callback
unsafe { self.sink.lock().unwrap().set_callback(old_cb) }; 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<F>(&self, mut callback: F) pub fn run_forever<F>(&self, callback: F)
where F: FnMut(::Event) where F: FnMut(::Event)
{ {
// send pending requests to the server... // send pending requests to the server...
@ -171,6 +187,10 @@ impl EventsLoop {
// replace the old noop callback // replace the old noop callback
unsafe { self.sink.lock().unwrap().set_callback(old_cb) }; unsafe { self.sink.lock().unwrap().set_callback(old_cb) };
if self.cleanup_needed.swap(false, ::std::sync::atomic::Ordering::Relaxed) {
self.prune_dead_windows()
}
} }
} }

View file

@ -1,4 +1,5 @@
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::sync::atomic::AtomicBool;
use wayland_client::{EventQueue, EventQueueHandle, Proxy}; use wayland_client::{EventQueue, EventQueueHandle, Proxy};
use wayland_client::protocol::{wl_display,wl_surface,wl_shell_surface}; use wayland_client::protocol::{wl_display,wl_surface,wl_shell_surface};
@ -13,6 +14,7 @@ use super::wayland_window::DecoratedSurface;
pub struct Window { pub struct Window {
ctxt: Arc<WaylandContext>, ctxt: Arc<WaylandContext>,
evq: Arc<Mutex<EventQueue>>, evq: Arc<Mutex<EventQueue>>,
cleanup_signal: Arc<AtomicBool>,
surface: Arc<wl_surface::WlSurface>, surface: Arc<wl_surface::WlSurface>,
size: Mutex<(u32, u32)>, size: Mutex<(u32, u32)>,
decorated_id: usize decorated_id: usize
@ -34,7 +36,7 @@ impl Window {
let (surface, decorated) = ctxt.create_window::<DecoratedHandler>(); let (surface, decorated) = ctxt.create_window::<DecoratedHandler>();
// init DecoratedSurface // init DecoratedSurface
let evq = evlp.get_event_queue(); let (evq, cleanup_signal) = evlp.get_window_init();
let decorated_id = { let decorated_id = {
let mut evq_guard = evq.lock().unwrap(); let mut evq_guard = evq.lock().unwrap();
let decorated_id = evq_guard.add_handler_with_init(decorated); let decorated_id = evq_guard.add_handler_with_init(decorated);
@ -62,6 +64,7 @@ impl Window {
let me = Window { let me = Window {
ctxt: ctxt, ctxt: ctxt,
evq: evq, evq: evq,
cleanup_signal: cleanup_signal,
surface: surface, surface: surface,
size: Mutex::new((width, height)), size: Mutex::new((width, height)),
decorated_id: decorated_id decorated_id: decorated_id
@ -165,6 +168,7 @@ impl Window {
impl Drop for Window { impl Drop for Window {
fn drop(&mut self) { fn drop(&mut self) {
self.surface.destroy(); self.surface.destroy();
self.cleanup_signal.store(true, ::std::sync::atomic::Ordering::Relaxed);
} }
} }