use super::glutin_runtime::*;
use super::glutin_thread_event::*;
use ::desync::*;
use glutin::event_loop::{EventLoop, EventLoopProxy};
use std::mem;
use std::sync::*;
use std::sync::mpsc;
use std::thread;
use std::collections::{HashMap};
lazy_static! {
static ref GLUTIN_THREAD: Desync<Option<Arc<GlutinThread>>> = Desync::new(None);
}
pub struct GlutinThread {
event_proxy: Desync<EventLoopProxy<GlutinThreadEvent>>
}
impl GlutinThread {
pub fn send_event(&self, event: GlutinThreadEvent) {
self.event_proxy.desync(move |proxy| { proxy.send_event(event).ok(); });
}
}
pub fn glutin_thread() -> Arc<GlutinThread> {
GLUTIN_THREAD.sync(|thread| {
if let Some(thread) = thread {
Arc::clone(thread)
} else {
let new_thread = create_glutin_thread();
*thread = Some(Arc::clone(&new_thread));
new_thread
}
})
}
struct StopGlutinWhenDropped;
impl Drop for StopGlutinWhenDropped {
fn drop(&mut self) {
glutin_thread().send_event(GlutinThreadEvent::StopWhenAllWindowsClosed);
}
}
pub fn with_2d_graphics<TAppFn: 'static+Send+FnOnce() -> ()>(app_fn: TAppFn) {
let (send_proxy, recv_proxy) = mpsc::channel();
thread::Builder::new()
.name("Application thread".into())
.spawn(move || {
GLUTIN_THREAD.sync(move |thread| {
let proxy = recv_proxy.recv().expect("Glutin thread will send us a proxy after initialising");
*thread = Some(Arc::new(GlutinThread {
event_proxy: Desync::new(proxy)
}));
});
let stop_glutin = StopGlutinWhenDropped;
app_fn();
mem::drop(stop_glutin);
})
.expect("Application thread is running");
run_glutin_thread(send_proxy);
}
fn create_glutin_thread() -> Arc<GlutinThread> {
let (send_proxy, recv_proxy) = mpsc::channel();
thread::Builder::new()
.name("Glutin event thread".into())
.spawn(move || {
run_glutin_thread(send_proxy)
})
.expect("Glutin thread is running");
let proxy = recv_proxy.recv().expect("Glutin thread will send us a proxy after initialising");
Arc::new(GlutinThread {
event_proxy: Desync::new(proxy)
})
}
fn run_glutin_thread(send_proxy: mpsc::Sender<EventLoopProxy<GlutinThreadEvent>>) {
let event_loop = EventLoop::with_user_event();
let proxy = event_loop.create_proxy();
send_proxy.send(proxy).expect("Main thread is waiting to receive its proxy");
let mut runtime = GlutinRuntime {
window_events: HashMap::new(),
futures: HashMap::new(),
will_stop_when_no_windows: false,
will_exit: false,
pointer_id: HashMap::new(),
pointer_state: HashMap::new()
};
event_loop.run(move |event, window_target, control_flow| {
runtime.handle_event(event, window_target, control_flow);
});
}