From 7336cacf0733967ee711e09ecd466eddab9b9465 Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Sat, 4 Mar 2017 14:04:01 +0100 Subject: [PATCH] wayland: mugrate to new API --- src/platform/linux/mod.rs | 11 +- src/platform/linux/wayland/context.rs | 106 +++++++------ src/platform/linux/wayland/event_loop.rs | 184 +++++++++++++++++++++++ src/platform/linux/wayland/keyboard.rs | 18 +-- src/platform/linux/wayland/mod.rs | 117 +------------- src/platform/linux/wayland/window.rs | 179 ++++++---------------- 6 files changed, 310 insertions(+), 305 deletions(-) create mode 100644 src/platform/linux/wayland/event_loop.rs diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 3669a3ce..fd820225 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -129,7 +129,12 @@ impl Window2 { { match *UNIX_BACKEND { UnixBackend::Wayland(ref ctxt) => { - wayland::Window2::new(events_loop, ctxt.clone(), window).map(Window2::Wayland) + if let EventsLoop::Wayland(ref evlp) = *events_loop { + wayland::Window2::new(evlp, ctxt.clone(), window).map(Window2::Wayland) + } else { + // It is not possible to instanciate an EventsLoop not matching its backend + unreachable!() + } }, UnixBackend::X(ref connec) => { @@ -299,8 +304,8 @@ pub enum EventsLoop { impl EventsLoop { pub fn new() -> EventsLoop { match *UNIX_BACKEND { - UnixBackend::Wayland(_) => { - EventsLoop::Wayland(wayland::EventsLoop::new()) + UnixBackend::Wayland(ref ctxt) => { + EventsLoop::Wayland(wayland::EventsLoop::new(ctxt.clone())) }, UnixBackend::X(_) => { diff --git a/src/platform/linux/wayland/context.rs b/src/platform/linux/wayland/context.rs index 90b4027a..4641f39f 100644 --- a/src/platform/linux/wayland/context.rs +++ b/src/platform/linux/wayland/context.rs @@ -10,7 +10,7 @@ use wayland_client::protocol::{wl_compositor, wl_seat, wl_shell, wl_shm, wl_subc wl_display, wl_registry, wl_output, wl_surface, wl_pointer, wl_keyboard}; -use super::wayland_window; +use super::{wayland_window, EventsLoopSink, make_wid}; use super::wayland_kbd::MappedKeyboard; use super::keyboard::KbdHandler; @@ -27,7 +27,7 @@ wayland_env!(InnerEnv, enum KbdType { Mapped(MappedKeyboard), - Plain(Option>>>) + Plain(Option<(Arc,Arc>)>) } struct WaylandEnv { @@ -35,10 +35,10 @@ struct WaylandEnv { inner: EnvHandler, monitors: Vec, my_id: usize, - windows: Vec<(Arc,Arc>>)>, + windows: Vec<(Arc,Arc>)>, seat: Option, mouse: Option, - mouse_focus: Option>>>, + mouse_focus: Option<(Arc,Arc>)>, mouse_location: (i32, i32), axis_buffer: Option<(f32, f32)>, axis_discrete_buffer: Option<(i32, i32)>, @@ -252,16 +252,15 @@ impl WaylandContext { } } - pub fn create_window(&self) - -> (Arc, Arc>>, wayland_window::DecoratedSurface) + pub fn create_window(&self, sink: Arc>) + -> (Arc, wayland_window::DecoratedSurface) { let mut guard = self.evq.lock().unwrap(); let mut state = guard.state(); let env = state.get_mut_handler::(self.env_id); // this "expect" cannot trigger (see https://github.com/vberger/wayland-client-rs/issues/69) let surface = Arc::new(env.inner.compositor.create_surface().expect("Compositor cannot be dead")); - let eventiter = Arc::new(Mutex::new(VecDeque::new())); - env.windows.push((surface.clone(), eventiter.clone())); + env.windows.push((surface.clone(), sink)); let decorated = wayland_window::DecoratedSurface::new( &*surface, 800, 600, &env.inner.compositor, @@ -271,7 +270,7 @@ impl WaylandContext { env.get_seat(), false ).expect("Failed to create a tmpfile buffer."); - (surface, eventiter, decorated) + (surface, decorated) } pub fn prune_dead_windows(&self) { @@ -397,13 +396,13 @@ impl wl_pointer::Handler for WaylandEnv { surface_y: f64) { self.mouse_location = (surface_x as i32, surface_y as i32); - for &(ref window, ref eviter) in &self.windows { + for &(ref window, ref sink) in &self.windows { if window.equals(surface) { - self.mouse_focus = Some(eviter.clone()); + self.mouse_focus = Some((window.clone(), sink.clone())); let (w, h) = self.mouse_location; - let mut event_queue = eviter.lock().unwrap(); - event_queue.push_back(Event::MouseEntered); - event_queue.push_back(Event::MouseMoved(w, h)); + let mut event_queue = sink.lock().unwrap(); + event_queue.push_event(Event::MouseEntered, make_wid(window)); + event_queue.push_event(Event::MouseMoved(w, h), make_wid(window)); break; } } @@ -416,10 +415,10 @@ impl wl_pointer::Handler for WaylandEnv { surface: &wl_surface::WlSurface) { self.mouse_focus = None; - for &(ref window, ref eviter) in &self.windows { + for &(ref window, ref sink) in &self.windows { if window.equals(surface) { - let mut event_queue = eviter.lock().unwrap(); - event_queue.push_back(Event::MouseLeft); + let mut event_queue = sink.lock().unwrap(); + event_queue.push_event(Event::MouseLeft, make_wid(window)); break; } } @@ -433,10 +432,11 @@ impl wl_pointer::Handler for WaylandEnv { surface_y: f64) { self.mouse_location = (surface_x as i32, surface_y as i32); - if let Some(ref eviter) = self.mouse_focus { + if let Some((ref window, ref sink)) = self.mouse_focus { let (w,h) = self.mouse_location; - eviter.lock().unwrap().push_back( - Event::MouseMoved(w, h) + sink.lock().unwrap().push_event( + Event::MouseMoved(w, h), + make_wid(window) ); } } @@ -449,7 +449,7 @@ impl wl_pointer::Handler for WaylandEnv { button: u32, state: wl_pointer::ButtonState) { - if let Some(ref eviter) = self.mouse_focus { + if let Some((ref window, ref sink)) = self.mouse_focus { let state = match state { wl_pointer::ButtonState::Pressed => ElementState::Pressed, wl_pointer::ButtonState::Released => ElementState::Released @@ -461,8 +461,9 @@ impl wl_pointer::Handler for WaylandEnv { // TODO figure out the translation ? _ => return }; - eviter.lock().unwrap().push_back( - Event::MouseInput(state, button) + sink.lock().unwrap().push_event( + Event::MouseInput(state, button), + make_wid(window) ); } } @@ -492,20 +493,22 @@ impl wl_pointer::Handler for WaylandEnv { { let axis_buffer = self.axis_buffer.take(); let axis_discrete_buffer = self.axis_discrete_buffer.take(); - if let Some(ref eviter) = self.mouse_focus { + if let Some((ref window, ref sink)) = self.mouse_focus { if let Some((x, y)) = axis_discrete_buffer { - eviter.lock().unwrap().push_back( + sink.lock().unwrap().push_event( Event::MouseWheel( MouseScrollDelta::LineDelta(x as f32, y as f32), self.axis_state - ) + ), + make_wid(window) ); } else if let Some((x, y)) = axis_buffer { - eviter.lock().unwrap().push_back( + sink.lock().unwrap().push_event( Event::MouseWheel( MouseScrollDelta::PixelDelta(x as f32, y as f32), self.axis_state - ) + ), + make_wid(window) ); } } @@ -574,24 +577,24 @@ impl wl_keyboard::Handler for WaylandEnv { surface: &wl_surface::WlSurface, keys: Vec) { - let mut opt_eviter = None; - for &(ref window, ref eviter) in &self.windows { + let mut opt_sink = None; + for &(ref window, ref sink) in &self.windows { if window.equals(surface) { - opt_eviter = Some(eviter.clone()); + opt_sink = Some((window.clone(), sink.clone())); break; } } - if let Some(ref eviter) = opt_eviter { + if let Some((ref window, ref sink)) = opt_sink { // send focused event - let mut guard = eviter.lock().unwrap(); - guard.push_back(Event::Focused(true)); + let mut guard = sink.lock().unwrap(); + guard.push_event(Event::Focused(true), make_wid(window)); } match self.kbd_handler { KbdType::Mapped(ref mut h) => { - h.handler().target = opt_eviter; + h.handler().target = opt_sink; h.enter(evqh, proxy, serial, surface, keys); }, - KbdType::Plain(ref mut opt) => { *opt = opt_eviter; } + KbdType::Plain(ref mut opt) => { *opt = opt_sink; } } } @@ -601,17 +604,17 @@ impl wl_keyboard::Handler for WaylandEnv { serial: u32, surface: &wl_surface::WlSurface) { - let opt_eviter = match self.kbd_handler { + let opt_sink = match self.kbd_handler { KbdType::Mapped(ref mut h) => { - let eviter = h.handler().target.take(); + let sink = h.handler().target.take(); h.leave(evqh, proxy, serial, surface); - eviter + sink }, KbdType::Plain(ref mut opt) => opt.take() }; - if let Some(eviter) = opt_eviter { - let mut guard = eviter.lock().unwrap(); - guard.push_back(Event::Focused(false)); + if let Some((ref window, ref sink)) = opt_sink { + let mut guard = sink.lock().unwrap(); + guard.push_event(Event::Focused(false), make_wid(window)); } } @@ -625,12 +628,12 @@ impl wl_keyboard::Handler for WaylandEnv { { match self.kbd_handler { KbdType::Mapped(ref mut h) => h.key(evqh, proxy, serial, time, key, state), - KbdType::Plain(Some(ref eviter)) => { + KbdType::Plain(Some((ref window, ref sink))) => { let state = match state { wl_keyboard::KeyState::Pressed => ElementState::Pressed, wl_keyboard::KeyState::Released => ElementState::Released, }; - let mut guard = eviter.lock().unwrap(); + let mut guard = sink.lock().unwrap(); // This is fallback impl if libxkbcommon was not available // This case should probably never happen, as most wayland // compositors _need_ libxkbcommon anyway... @@ -638,12 +641,15 @@ impl wl_keyboard::Handler for WaylandEnv { // In this case, we don't have the modifiers state information // anyway, as we need libxkbcommon to interpret it (it is // supposed to be serialized by the compositor using libxkbcommon) - guard.push_back(Event::KeyboardInput( - state, - key as u8, - None, - ModifiersState::default() - )); + guard.push_event( + Event::KeyboardInput( + state, + key as u8, + None, + ModifiersState::default() + ), + make_wid(window) + ); }, KbdType::Plain(None) => () } diff --git a/src/platform/linux/wayland/event_loop.rs b/src/platform/linux/wayland/event_loop.rs new file mode 100644 index 00000000..0477d7b9 --- /dev/null +++ b/src/platform/linux/wayland/event_loop.rs @@ -0,0 +1,184 @@ +use std::collections::VecDeque; +use std::sync::{Arc, Mutex}; +use std::sync::atomic::AtomicBool; + +use super::{DecoratedHandler, WindowId, WaylandContext}; + +use wayland_client::EventQueue; +use super::wayland_window::DecoratedSurface; + +pub struct EventsLoopSink { + callback: Option<*mut FnMut(::Event)>, + queue: VecDeque<::Event> +} + +unsafe impl Send for EventsLoopSink { } + +impl EventsLoopSink { + pub fn new() -> EventsLoopSink { + EventsLoopSink { + callback: None, + queue: VecDeque::new() + } + } + + pub fn push_event(&mut self, evt: ::WindowEvent, wid: WindowId) { + let evt = ::Event::WindowEvent { + event: evt, + window_id: ::WindowId(::platform::WindowId::Wayland(wid)) + }; + if let Some(cb) = self.callback { + unsafe { (&mut *cb)(evt) } + } else { + self.queue.push_back(evt) + } + } + + // This function is only safe of the set callback is unset before exclusive + // access to the wayland EventQueue is finished. + // + // The callback also cannot be used any longer as long as it has not been + // cleared from the Sink. + unsafe fn set_callback(&mut self, cb: &mut FnMut(::Event)) { + let cb: &mut FnMut(::Event) = ::std::mem::transmute(cb); + self.callback = Some(cb as *mut _); + } + + fn with_callback(&mut self, f: F) { + if let Some(cb) = self.callback { + f(unsafe {&mut *cb}) + } + } + + fn clear_callback(&mut self) { + self.callback = None + } + + fn drain_queue(&mut self, cb: &mut F) { + for evt in self.queue.drain(..) { + cb(evt) + } + } +} + +pub struct EventsLoop { + ctxt: Arc, + evq: Arc>, + decorated_ids: Mutex>, + sink: Arc>, + interrupted: AtomicBool, +} + +impl EventsLoop { + pub fn new(ctxt: Arc) -> EventsLoop { + let evq = ctxt.display.create_event_queue(); + EventsLoop { + ctxt: ctxt, + evq: Arc::new(Mutex::new(evq)), + decorated_ids: Mutex::new(Vec::new()), + sink: Arc::new(Mutex::new(EventsLoopSink::new())), + interrupted: AtomicBool::new(false) + } + } + + pub fn get_sink(&self) -> Arc> { + self.sink.clone() + } + + pub fn get_event_queue(&self) -> Arc> { + self.evq.clone() + } + + pub fn register_window(&self, decorated_id: usize, wid: WindowId) { + self.decorated_ids.lock().unwrap().push((decorated_id, wid)); + } + + fn process_resize(evq: &mut EventQueue, ids: &[(usize, WindowId)], callback: &mut FnMut(::Event)) + { + let mut state = evq.state(); + for &(decorated_id, window_id) 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)), + event: ::WindowEvent::Resized(w,h) + } + ); + } + } + } + + 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) + { + // send pending requests to the server... + self.ctxt.flush(); + + // first of all, get exclusive access to this event queue + let mut evq_guard = self.evq.lock().unwrap(); + + // dispatch stored events: + self.sink.lock().unwrap().drain_queue(&mut callback); + + // read some events from the socket if some are waiting & queue is empty + if let Some(guard) = evq_guard.prepare_read() { + guard.read_events().expect("Wayland connection unexpectedly lost"); + } + + // set the callback into the sink + unsafe { self.sink.lock().unwrap().set_callback(&mut callback) }; + + // then do the actual dispatching + self.ctxt.dispatch_pending(); + evq_guard.dispatch_pending().expect("Wayland connection unexpectedly lost"); + + let mut sink_guard = self.sink.lock().unwrap(); + + // events where probably dispatched, process resize + let ids_guard = self.decorated_ids.lock().unwrap(); + sink_guard.with_callback( + |cb| Self::process_resize(&mut evq_guard, &ids_guard, cb) + ); + + sink_guard.clear_callback(); + // we must keep callback alive up to this point! + drop(callback); + + } + + pub fn run_forever(&self, mut callback: F) + where F: FnMut(::Event) + { + // send pending requests to the server... + self.ctxt.flush(); + + // first of all, get exclusive access to this event queue + let mut evq_guard = self.evq.lock().unwrap(); + + // dispatch stored events: + self.sink.lock().unwrap().drain_queue(&mut callback); + + // set the callback into the sink + unsafe { self.sink.lock().unwrap().set_callback(&mut callback) }; + + while !self.interrupted.load(::std::sync::atomic::Ordering::Relaxed) { + self.ctxt.dispatch(); + evq_guard.dispatch_pending().expect("Wayland connection unexpectedly lost"); + let ids_guard = self.decorated_ids.lock().unwrap(); + self.sink.lock().unwrap().with_callback( + |cb| Self::process_resize(&mut evq_guard, &ids_guard, cb) + ); + self.ctxt.flush(); + } + + self.sink.lock().unwrap().clear_callback(); + // we must keep callback alive up to this point! + drop(callback) + } +} diff --git a/src/platform/linux/wayland/keyboard.rs b/src/platform/linux/wayland/keyboard.rs index 98b8e1bd..3a73f43a 100644 --- a/src/platform/linux/wayland/keyboard.rs +++ b/src/platform/linux/wayland/keyboard.rs @@ -1,16 +1,15 @@ -use std::collections::VecDeque; use std::sync::{Arc, Mutex}; use {VirtualKeyCode, ElementState, WindowEvent as Event}; use events::ModifiersState; -use super::wayland_kbd; +use super::{wayland_kbd, make_wid, EventsLoopSink}; use wayland_client::EventQueueHandle; -use wayland_client::protocol::wl_keyboard; +use wayland_client::protocol::{wl_keyboard, wl_surface}; pub struct KbdHandler { - pub target: Option>>> + pub target: Option<(Arc,Arc>)> } impl KbdHandler { @@ -31,14 +30,14 @@ impl wayland_kbd::Handler for KbdHandler { state: wl_keyboard::KeyState, utf8: Option) { - if let Some(ref eviter) = self.target { + if let Some((ref window, ref sink)) = self.target { let state = match state { wl_keyboard::KeyState::Pressed => ElementState::Pressed, wl_keyboard::KeyState::Released => ElementState::Released, }; let vkcode = key_to_vkey(rawkey, keysym); - let mut guard = eviter.lock().unwrap(); - guard.push_back( + let mut guard = sink.lock().unwrap(); + guard.push_event( Event::KeyboardInput( state, rawkey as u8, @@ -49,13 +48,14 @@ impl wayland_kbd::Handler for KbdHandler { alt: mods.alt, logo: mods.logo } - ) + ), + make_wid(window) ); // send char event only on key press, not release if let ElementState::Released = state { return } if let Some(txt) = utf8 { for chr in txt.chars() { - guard.push_back(Event::ReceivedCharacter(chr)); + guard.push_event(Event::ReceivedCharacter(chr), make_wid(window)); } } } diff --git a/src/platform/linux/wayland/mod.rs b/src/platform/linux/wayland/mod.rs index c3ab1c4b..1f5a6411 100644 --- a/src/platform/linux/wayland/mod.rs +++ b/src/platform/linux/wayland/mod.rs @@ -1,122 +1,17 @@ #![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))] -use self::window::Window; +pub use self::window::{Window as Window2, WindowId}; +pub use self::event_loop::EventsLoop; pub use self::context::{WaylandContext, MonitorId, get_available_monitors, get_primary_monitor}; +use self::window::{make_wid, DecoratedHandler}; +use self::event_loop::EventsLoopSink; + extern crate wayland_kbd; extern crate wayland_window; -use CreationError; - -use std::sync::Arc; - mod context; +mod event_loop; 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 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(::std::time::Duration::from_millis(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 _); - } - } - } -} diff --git a/src/platform/linux/wayland/window.rs b/src/platform/linux/wayland/window.rs index 9994cf09..76f4c44f 100644 --- a/src/platform/linux/wayland/window.rs +++ b/src/platform/linux/wayland/window.rs @@ -1,141 +1,80 @@ -use std::collections::VecDeque; use std::sync::{Arc, Mutex}; -use wayland_client::{EventQueue, EventQueueHandle, Init}; +use wayland_client::{EventQueue, EventQueueHandle, Init, Proxy}; use wayland_client::protocol::{wl_display,wl_surface,wl_shell_surface}; -use {CreationError, MouseCursor, CursorState, WindowEvent as Event, WindowAttributes}; +use {CreationError, MouseCursor, CursorState, WindowAttributes}; use platform::MonitorId as PlatformMonitorId; -use super::WaylandContext; +use super::{WaylandContext, EventsLoop}; use super::wayland_window; use super::wayland_window::DecoratedSurface; pub struct Window { ctxt: Arc, - evq: Mutex, - eviter: Arc>>, + evq: Arc>, surface: Arc, size: Mutex<(u32, u32)>, - handler_id: usize, decorated_id: usize } -pub struct PollEventsIterator<'a> { - window: &'a Window, -} +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct WindowId(usize); -impl<'a> Iterator for PollEventsIterator<'a> { - type Item = Event; - - fn next(&mut self) -> Option { - self.window.next_event(false) - } +#[inline] +pub fn make_wid(s: &wl_surface::WlSurface) -> WindowId { + WindowId(s.ptr() as usize) } impl Window { - pub fn new(ctxt: Arc, attributes: &WindowAttributes) -> Result + pub fn new(evlp: &EventsLoop, ctxt: Arc, attributes: &WindowAttributes) -> Result { let (width, height) = attributes.dimensions.unwrap_or((800,600)); - let mut evq = ctxt.display.create_event_queue(); - - let (surface, eviter, decorated) = ctxt.create_window::(); + let (surface, decorated) = ctxt.create_window::(evlp.get_sink()); // init DecoratedSurface - let decorated_id = evq.add_handler_with_init(decorated); - { - let mut state = evq.state(); - let decorated = state.get_mut_handler::>(decorated_id); - *(decorated.handler()) = Some(DecoratedHandler::new()); + let evq = evlp.get_event_queue(); + let decorated_id = { + let mut evq_guard = evq.lock().unwrap(); + let decorated_id = evq_guard.add_handler_with_init(decorated); + { + let mut state = evq_guard.state(); + let decorated = state.get_mut_handler::>(decorated_id); + *(decorated.handler()) = Some(DecoratedHandler::new()); - if let Some(PlatformMonitorId::Wayland(ref monitor_id)) = attributes.monitor { - ctxt.with_output(monitor_id.clone(), |output| { - decorated.set_fullscreen( - wl_shell_surface::FullscreenMethod::Default, - 0, - Some(output) - ) - }); - } else if attributes.decorations { - decorated.set_decorate(true); + if let Some(PlatformMonitorId::Wayland(ref monitor_id)) = attributes.monitor { + ctxt.with_output(monitor_id.clone(), |output| { + decorated.set_fullscreen( + wl_shell_surface::FullscreenMethod::Default, + 0, + Some(output) + ) + }); + } else if attributes.decorations { + decorated.set_decorate(true); + } + // Finally, set the decorations size + decorated.resize(width as i32, height as i32); } - // Finally, set the decorations size - decorated.resize(width as i32, height as i32); - } - - // init general handler - let handler = WindowHandler::new(); - let handler_id = evq.add_handler_with_init(handler); - - Ok(Window { + decorated_id + }; + let me = Window { ctxt: ctxt, - evq: Mutex::new(evq), - eviter: eviter, + evq: evq, surface: surface, size: Mutex::new((width, height)), - handler_id: handler_id, decorated_id: decorated_id - }) - } - - fn process_resize(&self) { - let mut evq_guard = self.evq.lock().unwrap(); - let mut state = evq_guard.state(); - let decorated = state.get_mut_handler::>(self.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); - *self.size.lock().unwrap() = (w, h); - self.eviter.lock().unwrap().push_back(Event::Resized(w,h)); - } - } - - fn next_event(&self, block: bool) -> Option { - let mut evt = { - let mut guard = self.eviter.lock().unwrap(); - guard.pop_front() - }; - if evt.is_some() { return evt } - - // There is no event in the queue, we need to fetch more - - // flush the display - self.ctxt.flush(); - - // read some events if some are waiting & queue is empty - if let Some(guard) = self.evq.lock().unwrap().prepare_read() { - guard.read_events().expect("Wayland connection unexpectedly lost"); - } - - // try a pending dispatch - { - self.ctxt.dispatch_pending(); - self.evq.lock().unwrap().dispatch_pending() - .expect("Wayland connection unexpectedly lost"); - // some events were dispatched, need to process a potential resising - self.process_resize(); - } - - evt = { - let mut guard = self.eviter.lock().unwrap(); - guard.pop_front() }; - while block && evt.is_none() { - // no event waiting, need to repopulate! - { - self.ctxt.flush(); - self.ctxt.dispatch(); - self.evq.lock().unwrap().dispatch_pending() - .expect("Wayland connection unexpectedly lost"); - // some events were dispatched, need to process a potential resising - self.process_resize(); - } - // try again - let mut guard = self.eviter.lock().unwrap(); - evt = guard.pop_front(); - } - evt + evlp.register_window(me.decorated_id, me.id()); + + Ok(me) + } + + #[inline] + pub fn id(&self) -> WindowId { + make_wid(&self.surface) } pub fn set_title(&self, title: &str) { @@ -186,13 +125,6 @@ impl Window { decorated.resize(x as i32, y as i32); } - #[inline] - pub fn poll_events(&self) -> PollEventsIterator { - PollEventsIterator { - window: self - } - } - #[inline] pub fn set_cursor(&self, _cursor: MouseCursor) { // TODO @@ -237,13 +169,14 @@ impl Drop for Window { } } -struct DecoratedHandler { +pub struct DecoratedHandler { newsize: Option<(u32, u32)> } impl DecoratedHandler { fn new() -> DecoratedHandler { DecoratedHandler { newsize: None }} - fn take_newsize(&mut self) -> Option<(u32, u32)> { + + pub fn take_newsize(&mut self) -> Option<(u32, u32)> { self.newsize.take() } } @@ -258,21 +191,3 @@ impl wayland_window::Handler for DecoratedHandler { self.newsize = Some((max(width,1) as u32, max(height,1) as u32)); } } - -struct WindowHandler { - my_id: usize, -} - -impl WindowHandler { - fn new() -> WindowHandler { - WindowHandler { - my_id: 0, - } - } -} - -impl Init for WindowHandler { - fn init(&mut self, _evqh: &mut EventQueueHandle, index: usize) { - self.my_id = index; - } -}