#![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))] pub use self::window::{PollEventsIterator, WaitEventsIterator, Window, WindowProxy}; pub use self::context::{WaylandContext, MonitorId, get_available_monitors, get_primary_monitor}; extern crate wayland_kbd; extern crate wayland_window; use platform::PlatformSpecificWindowBuilderAttributes; use CreationError; use std::sync::Arc; mod context; mod keyboard; mod window; // API TRANSITION // // We don't use the gen_api_transistion!() macro but rather do the expansion manually: // // As this module is nested into platform/linux, its code is not _exactly_ the same as // the one generated by the macro. pub struct EventsLoop { windows: ::std::sync::Mutex>>, interrupted: ::std::sync::atomic::AtomicBool, } impl EventsLoop { pub fn new() -> EventsLoop { EventsLoop { windows: ::std::sync::Mutex::new(vec![]), interrupted: ::std::sync::atomic::AtomicBool::new(false), } } pub fn interrupt(&self) { self.interrupted.store(true, ::std::sync::atomic::Ordering::Relaxed); } pub fn poll_events(&self, mut callback: F) where F: FnMut(::Event) { let mut windows = self.windows.lock().unwrap(); for window in windows.iter() { for event in window.poll_events() { callback(::Event::WindowEvent { window_id: ::WindowId(::platform::WindowId::Wayland(WindowId(&**window as *const Window as usize))), event: event, }) } } } pub fn run_forever(&self, mut callback: F) where F: FnMut(::Event) { self.interrupted.store(false, ::std::sync::atomic::Ordering::Relaxed); // Yeah that's a very bad implementation. loop { self.poll_events(|e| callback(e)); ::std::thread::sleep_ms(5); if self.interrupted.load(::std::sync::atomic::Ordering::Relaxed) { break; } } } } #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct WindowId(usize); pub struct Window2 { pub window: ::std::sync::Arc, events_loop: ::std::sync::Weak<::platform::EventsLoop>, } impl ::std::ops::Deref for Window2 { type Target = Window; #[inline] fn deref(&self) -> &Window { &*self.window } } impl Window2 { pub fn new(events_loop: ::std::sync::Arc<::platform::EventsLoop>, ctxt: Arc, window: &::WindowAttributes) -> Result { let win = ::std::sync::Arc::new(try!(Window::new(ctxt, window))); if let ::platform::EventsLoop::Wayland(ref ev) = *events_loop { ev.windows.lock().unwrap().push(win.clone()); } else { // It should not be possible to create an eventloop not matching the backend // in use unreachable!() } Ok(Window2 { window: win, events_loop: ::std::sync::Arc::downgrade(&events_loop), }) } #[inline] pub fn id(&self) -> WindowId { WindowId(&*self.window as *const Window as usize) } } impl Drop for Window2 { fn drop(&mut self) { if let Some(ev) = self.events_loop.upgrade() { if let ::platform::EventsLoop::Wayland(ref ev) = *ev { let mut windows = ev.windows.lock().unwrap(); windows.retain(|w| &**w as *const Window != &*self.window as *const _); } } } }