diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 0712469f..6e12ffe1 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -5,9 +5,7 @@ use std::sync::Arc; use CreationError; use CursorState; -use WindowEvent as Event; use MouseCursor; -use WindowAttributes; use libc; use self::x11::XConnection; @@ -49,7 +47,7 @@ pub enum Window2 { #[doc(hidden)] X(x11::Window2), #[doc(hidden)] - Wayland(wayland::Window2) + Wayland(wayland::Window) } #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -131,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::Window::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) => { @@ -301,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 c767056a..1c3ca7eb 100644 --- a/src/platform/linux/wayland/context.rs +++ b/src/platform/linux/wayland/context.rs @@ -1,18 +1,11 @@ -use {WindowEvent as Event, ElementState, MouseButton, MouseScrollDelta, TouchPhase}; - -use events::ModifiersState; - use std::collections::VecDeque; use std::sync::{Arc, Mutex}; use wayland_client::{EnvHandler, default_connect, EventQueue, EventQueueHandle, Init, Proxy}; use wayland_client::protocol::{wl_compositor, wl_seat, wl_shell, wl_shm, wl_subcompositor, - wl_display, wl_registry, wl_output, wl_surface, wl_pointer, - wl_keyboard}; + wl_display, wl_registry, wl_output, wl_surface}; use super::wayland_window; -use super::wayland_kbd::MappedKeyboard; -use super::keyboard::KbdHandler; /* * Registry and globals handling @@ -25,26 +18,11 @@ wayland_env!(InnerEnv, subcompositor: wl_subcompositor::WlSubcompositor ); -enum KbdType { - Mapped(MappedKeyboard), - Plain(Option>>>) -} - struct WaylandEnv { registry: wl_registry::WlRegistry, inner: EnvHandler, monitors: Vec, my_id: usize, - windows: Vec<(Arc,Arc>>)>, - seat: Option, - mouse: Option, - mouse_focus: Option>>>, - mouse_location: (i32, i32), - axis_buffer: Option<(f32, f32)>, - axis_discrete_buffer: Option<(i32, i32)>, - axis_state: TouchPhase, - kbd: Option, - kbd_handler: KbdType } struct OutputInfo { @@ -69,32 +47,20 @@ impl OutputInfo { impl WaylandEnv { fn new(registry: wl_registry::WlRegistry) -> WaylandEnv { - let kbd_handler = match MappedKeyboard::new(KbdHandler::new()) { - Ok(h) => KbdType::Mapped(h), - Err(_) => KbdType::Plain(None) - }; WaylandEnv { registry: registry, inner: EnvHandler::new(), monitors: Vec::new(), my_id: 0, - windows: Vec::new(), - seat: None, - mouse: None, - mouse_focus: None, - mouse_location: (0,0), - axis_buffer: None, - axis_discrete_buffer: None, - axis_state: TouchPhase::Started, - kbd: None, - kbd_handler: kbd_handler } } fn get_seat(&self) -> Option { for &(name, ref interface, version) in self.inner.globals() { if interface == "wl_seat" { - // this "expect" cannot trigger (see https://github.com/vberger/wayland-client-rs/issues/69) + if version < 5 { + panic!("Winit requires at least version 5 of the wl_seat global."); + } let seat = self.registry.bind::(5, name).expect("Seat cannot be destroyed"); return Some(seat) } @@ -125,14 +91,6 @@ impl wl_registry::Handler for WaylandEnv { .expect("Registry cannot be dead"); evqh.register::<_, WaylandEnv>(&output, self.my_id); self.monitors.push(OutputInfo::new(output, name)); - } else if interface == "wl_seat" && self.seat.is_none() { - // Only grab the first seat - // TODO: Handle multi-seat-setup? - assert!(version >= 5, "Version 5 of seat interface is needed by glutin."); - let seat = self.registry.bind::(5, name) - .expect("Registry cannot be dead"); - evqh.register::<_, WaylandEnv>(&seat, self.my_id); - self.seat = Some(seat); } self.inner.global(evqh, registry, name, interface, version); } @@ -209,7 +167,7 @@ impl WaylandContext { // this handles both "no libwayland" and "no compositor" cases let (display, mut event_queue) = match default_connect() { Ok(ret) => ret, - Err(e) => return None + Err(_) => return None }; // this "expect" cannot trigger (see https://github.com/vberger/wayland-client-rs/issues/69) @@ -237,7 +195,13 @@ impl WaylandContext { } pub fn flush(&self) { - self.display.flush(); + let _ = self.display.flush(); + } + + pub fn get_seat(&self) -> Option { + let mut guard = self.evq.lock().unwrap(); + let state = guard.state(); + state.get_handler::(self.env_id).get_seat() } pub fn with_output(&self, id: MonitorId, f: F) where F: FnOnce(&wl_output::WlOutput) { @@ -251,15 +215,13 @@ impl WaylandContext { } pub fn create_window(&self) - -> (Arc, Arc>>, wayland_window::DecoratedSurface) + -> (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())); let decorated = wayland_window::DecoratedSurface::new( &*surface, 800, 600, &env.inner.compositor, @@ -269,14 +231,7 @@ impl WaylandContext { env.get_seat(), false ).expect("Failed to create a tmpfile buffer."); - (surface, eventiter, decorated) - } - - pub fn prune_dead_windows(&self) { - let mut guard = self.evq.lock().unwrap(); - let mut state = guard.state(); - let env = state.get_mut_handler::(self.env_id); - env.windows.retain(|w| w.0.is_alive()); + (surface, decorated) } } @@ -341,339 +296,3 @@ impl MonitorId { (0,0) } } - -/* - * Input Handling - */ - -impl wl_seat::Handler for WaylandEnv { - fn capabilities(&mut self, - evqh: &mut EventQueueHandle, - seat: &wl_seat::WlSeat, - capabilities: wl_seat::Capability) - { - // create pointer if applicable - if capabilities.contains(wl_seat::Pointer) && self.mouse.is_none() { - let pointer = seat.get_pointer().expect("Seat is not dead"); - evqh.register::<_, WaylandEnv>(&pointer, self.my_id); - self.mouse = Some(pointer); - } - // destroy pointer if applicable - if !capabilities.contains(wl_seat::Pointer) { - if let Some(pointer) = self.mouse.take() { - pointer.release(); - } - } - // create keyboard if applicable - if capabilities.contains(wl_seat::Keyboard) && self.kbd.is_none() { - let kbd = seat.get_keyboard().expect("Seat is not dead"); - evqh.register::<_, WaylandEnv>(&kbd, self.my_id); - self.kbd = Some(kbd); - } - // destroy keyboard if applicable - if !capabilities.contains(wl_seat::Keyboard) { - if let Some(kbd) = self.kbd.take() { - kbd.release(); - } - } - } -} - -declare_handler!(WaylandEnv, wl_seat::Handler, wl_seat::WlSeat); - -/* - * Pointer Handling - */ - -impl wl_pointer::Handler for WaylandEnv { - fn enter(&mut self, - _evqh: &mut EventQueueHandle, - _proxy: &wl_pointer::WlPointer, - _serial: u32, - surface: &wl_surface::WlSurface, - surface_x: f64, - surface_y: f64) - { - self.mouse_location = (surface_x as i32, surface_y as i32); - for &(ref window, ref eviter) in &self.windows { - if window.equals(surface) { - self.mouse_focus = Some(eviter.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)); - break; - } - } - } - - fn leave(&mut self, - _evqh: &mut EventQueueHandle, - _proxy: &wl_pointer::WlPointer, - _serial: u32, - surface: &wl_surface::WlSurface) - { - self.mouse_focus = None; - for &(ref window, ref eviter) in &self.windows { - if window.equals(surface) { - let mut event_queue = eviter.lock().unwrap(); - event_queue.push_back(Event::MouseLeft); - break; - } - } - } - - fn motion(&mut self, - _evqh: &mut EventQueueHandle, - _proxy: &wl_pointer::WlPointer, - _time: u32, - surface_x: f64, - surface_y: f64) - { - self.mouse_location = (surface_x as i32, surface_y as i32); - if let Some(ref eviter) = self.mouse_focus { - let (w,h) = self.mouse_location; - eviter.lock().unwrap().push_back( - Event::MouseMoved(w, h) - ); - } - } - - fn button(&mut self, - _evqh: &mut EventQueueHandle, - _proxy: &wl_pointer::WlPointer, - _serial: u32, - _time: u32, - button: u32, - state: wl_pointer::ButtonState) - { - if let Some(ref eviter) = self.mouse_focus { - let state = match state { - wl_pointer::ButtonState::Pressed => ElementState::Pressed, - wl_pointer::ButtonState::Released => ElementState::Released - }; - let button = match button { - 0x110 => MouseButton::Left, - 0x111 => MouseButton::Right, - 0x112 => MouseButton::Middle, - // TODO figure out the translation ? - _ => return - }; - eviter.lock().unwrap().push_back( - Event::MouseInput(state, button) - ); - } - } - - fn axis(&mut self, - _evqh: &mut EventQueueHandle, - _proxy: &wl_pointer::WlPointer, - _time: u32, - axis: wl_pointer::Axis, - value: f64) - { - let (mut x, mut y) = self.axis_buffer.unwrap_or((0.0, 0.0)); - match axis { - wl_pointer::Axis::VerticalScroll => y += value as f32, - wl_pointer::Axis::HorizontalScroll => x += value as f32 - } - self.axis_buffer = Some((x,y)); - self.axis_state = match self.axis_state { - TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved, - _ => TouchPhase::Started - } - } - - fn frame(&mut self, - _evqh: &mut EventQueueHandle, - _proxy: &wl_pointer::WlPointer) - { - 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((x, y)) = axis_discrete_buffer { - eviter.lock().unwrap().push_back( - Event::MouseWheel( - MouseScrollDelta::LineDelta(x as f32, y as f32), - self.axis_state - ) - ); - } else if let Some((x, y)) = axis_buffer { - eviter.lock().unwrap().push_back( - Event::MouseWheel( - MouseScrollDelta::PixelDelta(x as f32, y as f32), - self.axis_state - ) - ); - } - } - } - - fn axis_source(&mut self, - _evqh: &mut EventQueueHandle, - _proxy: &wl_pointer::WlPointer, - axis_source: wl_pointer::AxisSource) - { - } - - fn axis_stop(&mut self, - _evqh: &mut EventQueueHandle, - _proxy: &wl_pointer::WlPointer, - _time: u32, - axis: wl_pointer::Axis) - { - self.axis_state = TouchPhase::Ended; - } - - fn axis_discrete(&mut self, - _evqh: &mut EventQueueHandle, - _proxy: &wl_pointer::WlPointer, - axis: wl_pointer::Axis, - discrete: i32) - { - let (mut x, mut y) = self.axis_discrete_buffer.unwrap_or((0,0)); - match axis { - wl_pointer::Axis::VerticalScroll => y += discrete, - wl_pointer::Axis::HorizontalScroll => x += discrete - } - self.axis_discrete_buffer = Some((x,y)); - self.axis_state = match self.axis_state { - TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved, - _ => TouchPhase::Started - } - } -} - -declare_handler!(WaylandEnv, wl_pointer::Handler, wl_pointer::WlPointer); - -/* - * Keyboard Handling - */ - -impl wl_keyboard::Handler for WaylandEnv { - // mostly pass-through - fn keymap(&mut self, - evqh: &mut EventQueueHandle, - proxy: &wl_keyboard::WlKeyboard, - format: wl_keyboard::KeymapFormat, - fd: ::std::os::unix::io::RawFd, - size: u32) - { - match self.kbd_handler { - KbdType::Mapped(ref mut h) => h.keymap(evqh, proxy, format, fd, size), - _ => () - } - } - - fn enter(&mut self, - evqh: &mut EventQueueHandle, - proxy: &wl_keyboard::WlKeyboard, - serial: u32, - surface: &wl_surface::WlSurface, - keys: Vec) - { - let mut opt_eviter = None; - for &(ref window, ref eviter) in &self.windows { - if window.equals(surface) { - opt_eviter = Some(eviter.clone()); - break; - } - } - if let Some(ref eviter) = opt_eviter { - // send focused event - let mut guard = eviter.lock().unwrap(); - guard.push_back(Event::Focused(true)); - } - match self.kbd_handler { - KbdType::Mapped(ref mut h) => { - h.handler().target = opt_eviter; - h.enter(evqh, proxy, serial, surface, keys); - }, - KbdType::Plain(ref mut opt) => { *opt = opt_eviter; } - } - } - - fn leave(&mut self, - evqh: &mut EventQueueHandle, - proxy: &wl_keyboard::WlKeyboard, - serial: u32, - surface: &wl_surface::WlSurface) - { - let opt_eviter = match self.kbd_handler { - KbdType::Mapped(ref mut h) => { - let eviter = h.handler().target.take(); - h.leave(evqh, proxy, serial, surface); - eviter - }, - 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)); - } - } - - fn key(&mut self, - evqh: &mut EventQueueHandle, - proxy: &wl_keyboard::WlKeyboard, - serial: u32, - time: u32, - key: u32, - state: wl_keyboard::KeyState) - { - match self.kbd_handler { - KbdType::Mapped(ref mut h) => h.key(evqh, proxy, serial, time, key, state), - KbdType::Plain(Some(ref eviter)) => { - let state = match state { - wl_keyboard::KeyState::Pressed => ElementState::Pressed, - wl_keyboard::KeyState::Released => ElementState::Released, - }; - let mut guard = eviter.lock().unwrap(); - // This is fallback impl if libxkbcommon was not available - // This case should probably never happen, as most wayland - // compositors _need_ libxkbcommon anyway... - // - // 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() - )); - }, - KbdType::Plain(None) => () - } - } - - fn modifiers(&mut self, - evqh: &mut EventQueueHandle, - proxy: &wl_keyboard::WlKeyboard, - serial: u32, - mods_depressed: u32, - mods_latched: u32, - mods_locked: u32, - group: u32) - { - match self.kbd_handler { - KbdType::Mapped(ref mut h) => h.modifiers(evqh, proxy, serial, mods_depressed, - mods_latched, mods_locked, group), - _ => () - } - } - - fn repeat_info(&mut self, - evqh: &mut EventQueueHandle, - proxy: &wl_keyboard::WlKeyboard, - rate: i32, - delay: i32) - { - match self.kbd_handler { - KbdType::Mapped(ref mut h) => h.repeat_info(evqh, proxy, rate, delay), - _ => () - } - } -} - -declare_handler!(WaylandEnv, wl_keyboard::Handler, wl_keyboard::WlKeyboard); diff --git a/src/platform/linux/wayland/event_loop.rs b/src/platform/linux/wayland/event_loop.rs new file mode 100644 index 00000000..efc9411d --- /dev/null +++ b/src/platform/linux/wayland/event_loop.rs @@ -0,0 +1,592 @@ +use {WindowEvent as Event, ElementState, MouseButton, MouseScrollDelta, TouchPhase, ModifiersState}; + +use std::sync::{Arc, Mutex}; +use std::sync::atomic::AtomicBool; + +use super::{DecoratedHandler, WindowId, WaylandContext}; + + +use wayland_client::{EventQueue, EventQueueHandle, Init, Proxy}; +use wayland_client::protocol::{wl_seat, wl_surface, wl_pointer, wl_keyboard}; + +use super::make_wid; +use super::wayland_window::DecoratedSurface; +use super::wayland_kbd::MappedKeyboard; +use super::keyboard::KbdHandler; + +/// This struct is used as a holder for the callback +/// during the dispatching of events. +/// +/// The proper ay to use it is: +/// - set a callback in it (and retrieve the noop one it contains) +/// - dispatch the EventQueue +/// - put back the noop callback in it +/// +/// Failure to do so is unsafeā„¢ +pub struct EventsLoopSink { + callback: Box +} + +unsafe impl Send for EventsLoopSink { } + +impl EventsLoopSink { + pub fn new() -> EventsLoopSink { + EventsLoopSink { + callback: Box::new(|_| {}), + } + } + + pub fn send_event(&mut self, evt: ::WindowEvent, wid: WindowId) { + let evt = ::Event::WindowEvent { + event: evt, + window_id: ::WindowId(::platform::WindowId::Wayland(wid)) + }; + (self.callback)(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: Box) -> Box { + ::std::mem::replace(&mut self.callback, cb) + } + + fn with_callback(&mut self, f: F) { + f(&mut *self.callback) + } +} + +pub struct EventsLoop { + // the global wayland context + ctxt: Arc, + // our EventQueue + evq: Arc>, + // ids of the DecoratedHandlers of the surfaces we know + decorated_ids: Mutex)>>, + // our sink, receiver of callbacks, shared with some handlers + sink: Arc>, + // trigger interruption of the run + interrupted: AtomicBool, + // trigger cleanup of the dead surfaces + cleanup_needed: Arc, + hid: usize +} + +impl EventsLoop { + pub fn new(ctxt: Arc) -> EventsLoop { + let mut evq = ctxt.display.create_event_queue(); + let sink = Arc::new(Mutex::new(EventsLoopSink::new())); + let hid = evq.add_handler_with_init(InputHandler::new(&ctxt, sink.clone())); + EventsLoop { + ctxt: ctxt, + evq: Arc::new(Mutex::new(evq)), + decorated_ids: Mutex::new(Vec::new()), + sink: sink, + interrupted: AtomicBool::new(false), + cleanup_needed: Arc::new(AtomicBool::new(false)), + hid: hid + } + } + + // some internals that Window needs access to + 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, 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, Arc)], callback: &mut FnMut(::Event)) + { + let mut state = evq.state(); + 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(make_wid(&window))), + event: ::WindowEvent::Resized(w,h) + } + ); + } + } + } + + pub fn interrupt(&self) { + self.interrupted.store(true, ::std::sync::atomic::Ordering::Relaxed); + } + + 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... + self.ctxt.flush(); + + // first of all, get exclusive access to this event queue + let mut evq_guard = self.evq.lock().unwrap(); + + // 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 + // we extend the lifetime of the closure to 'static to be able to put it in + // the sink, but we'll explicitly drop it at the end of this function, so it's fine + let static_cb = unsafe { ::std::mem::transmute(Box::new(callback) as Box) }; + let old_cb = unsafe { self.sink.lock().unwrap().set_callback(static_cb) }; + + // 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) + ); + + // 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, 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(); + + // set the callback into the sink + // we extend the lifetime of the closure to 'static to be able to put it in + // the sink, but we'll explicitly drop it at the end of this function, so it's fine + let static_cb = unsafe { ::std::mem::transmute(Box::new(callback) as Box) }; + let old_cb = unsafe { self.sink.lock().unwrap().set_callback(static_cb) }; + + 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(); + + if self.cleanup_needed.swap(false, ::std::sync::atomic::Ordering::Relaxed) { + self.prune_dead_windows() + } + } + + // replace the old noop callback + unsafe { self.sink.lock().unwrap().set_callback(old_cb) }; + } +} + +enum KbdType { + Mapped(MappedKeyboard), + Plain(Option) +} + +struct InputHandler { + my_id: usize, + windows: Vec>, + seat: Option, + mouse: Option, + mouse_focus: Option>, + mouse_location: (i32, i32), + axis_buffer: Option<(f32, f32)>, + axis_discrete_buffer: Option<(i32, i32)>, + axis_state: TouchPhase, + kbd: Option, + kbd_handler: KbdType, + callback: Arc> +} + +impl InputHandler { + fn new(ctxt: &WaylandContext, sink: Arc>) -> InputHandler { + let kbd_handler = match MappedKeyboard::new(KbdHandler::new(sink.clone())) { + Ok(h) => KbdType::Mapped(h), + Err(_) => KbdType::Plain(None) + }; + InputHandler { + my_id: 0, + windows: Vec::new(), + seat: ctxt.get_seat(), + mouse: None, + mouse_focus: None, + mouse_location: (0,0), + axis_buffer: None, + axis_discrete_buffer: None, + axis_state: TouchPhase::Started, + kbd: None, + kbd_handler: kbd_handler, + callback: sink + } + } +} + +impl Init for InputHandler { + fn init(&mut self, evqh: &mut EventQueueHandle, index: usize) { + if let Some(ref seat) = self.seat { + evqh.register::<_, InputHandler>(seat, index); + } + self.my_id = index; + } +} + +impl wl_seat::Handler for InputHandler { + fn capabilities(&mut self, + evqh: &mut EventQueueHandle, + seat: &wl_seat::WlSeat, + capabilities: wl_seat::Capability) + { + // create pointer if applicable + if capabilities.contains(wl_seat::Pointer) && self.mouse.is_none() { + let pointer = seat.get_pointer().expect("Seat is not dead"); + evqh.register::<_, InputHandler>(&pointer, self.my_id); + self.mouse = Some(pointer); + } + // destroy pointer if applicable + if !capabilities.contains(wl_seat::Pointer) { + if let Some(pointer) = self.mouse.take() { + pointer.release(); + } + } + // create keyboard if applicable + if capabilities.contains(wl_seat::Keyboard) && self.kbd.is_none() { + let kbd = seat.get_keyboard().expect("Seat is not dead"); + evqh.register::<_, InputHandler>(&kbd, self.my_id); + self.kbd = Some(kbd); + } + // destroy keyboard if applicable + if !capabilities.contains(wl_seat::Keyboard) { + if let Some(kbd) = self.kbd.take() { + kbd.release(); + } + } + } +} + +declare_handler!(InputHandler, wl_seat::Handler, wl_seat::WlSeat); + +/* + * Pointer Handling + */ + +impl wl_pointer::Handler for InputHandler { + fn enter(&mut self, + _evqh: &mut EventQueueHandle, + _proxy: &wl_pointer::WlPointer, + _serial: u32, + surface: &wl_surface::WlSurface, + surface_x: f64, + surface_y: f64) + { + self.mouse_location = (surface_x as i32, surface_y as i32); + for window in &self.windows { + if window.equals(surface) { + self.mouse_focus = Some(window.clone()); + let (w, h) = self.mouse_location; + let mut guard = self.callback.lock().unwrap(); + guard.send_event(Event::MouseEntered, make_wid(window)); + guard.send_event(Event::MouseMoved(w, h), make_wid(window)); + break; + } + } + } + + fn leave(&mut self, + _evqh: &mut EventQueueHandle, + _proxy: &wl_pointer::WlPointer, + _serial: u32, + surface: &wl_surface::WlSurface) + { + self.mouse_focus = None; + for window in &self.windows { + if window.equals(surface) { + self.callback.lock().unwrap().send_event(Event::MouseLeft, make_wid(window)); + } + } + } + + fn motion(&mut self, + _evqh: &mut EventQueueHandle, + _proxy: &wl_pointer::WlPointer, + _time: u32, + surface_x: f64, + surface_y: f64) + { + self.mouse_location = (surface_x as i32, surface_y as i32); + if let Some(ref window) = self.mouse_focus { + let (w,h) = self.mouse_location; + self.callback.lock().unwrap().send_event(Event::MouseMoved(w, h), make_wid(window)); + } + } + + fn button(&mut self, + _evqh: &mut EventQueueHandle, + _proxy: &wl_pointer::WlPointer, + _serial: u32, + _time: u32, + button: u32, + state: wl_pointer::ButtonState) + { + if let Some(ref window) = self.mouse_focus { + let state = match state { + wl_pointer::ButtonState::Pressed => ElementState::Pressed, + wl_pointer::ButtonState::Released => ElementState::Released + }; + let button = match button { + 0x110 => MouseButton::Left, + 0x111 => MouseButton::Right, + 0x112 => MouseButton::Middle, + // TODO figure out the translation ? + _ => return + }; + self.callback.lock().unwrap().send_event(Event::MouseInput(state, button), make_wid(window)); + } + } + + fn axis(&mut self, + _evqh: &mut EventQueueHandle, + _proxy: &wl_pointer::WlPointer, + _time: u32, + axis: wl_pointer::Axis, + value: f64) + { + let (mut x, mut y) = self.axis_buffer.unwrap_or((0.0, 0.0)); + match axis { + wl_pointer::Axis::VerticalScroll => y += value as f32, + wl_pointer::Axis::HorizontalScroll => x += value as f32 + } + self.axis_buffer = Some((x,y)); + self.axis_state = match self.axis_state { + TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved, + _ => TouchPhase::Started + } + } + + fn frame(&mut self, + _evqh: &mut EventQueueHandle, + _proxy: &wl_pointer::WlPointer) + { + let axis_buffer = self.axis_buffer.take(); + let axis_discrete_buffer = self.axis_discrete_buffer.take(); + if let Some(ref window) = self.mouse_focus { + if let Some((x, y)) = axis_discrete_buffer { + self.callback.lock().unwrap().send_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 { + self.callback.lock().unwrap().send_event( + Event::MouseWheel( + MouseScrollDelta::PixelDelta(x as f32, y as f32), + self.axis_state + ), + make_wid(window) + ); + } + } + } + + fn axis_source(&mut self, + _evqh: &mut EventQueueHandle, + _proxy: &wl_pointer::WlPointer, + _axis_source: wl_pointer::AxisSource) + { + } + + fn axis_stop(&mut self, + _evqh: &mut EventQueueHandle, + _proxy: &wl_pointer::WlPointer, + _time: u32, + _axis: wl_pointer::Axis) + { + self.axis_state = TouchPhase::Ended; + } + + fn axis_discrete(&mut self, + _evqh: &mut EventQueueHandle, + _proxy: &wl_pointer::WlPointer, + axis: wl_pointer::Axis, + discrete: i32) + { + let (mut x, mut y) = self.axis_discrete_buffer.unwrap_or((0,0)); + match axis { + wl_pointer::Axis::VerticalScroll => y += discrete, + wl_pointer::Axis::HorizontalScroll => x += discrete + } + self.axis_discrete_buffer = Some((x,y)); + self.axis_state = match self.axis_state { + TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved, + _ => TouchPhase::Started + } + } +} + +declare_handler!(InputHandler, wl_pointer::Handler, wl_pointer::WlPointer); + +/* + * Keyboard Handling + */ + +impl wl_keyboard::Handler for InputHandler { + // mostly pass-through + fn keymap(&mut self, + evqh: &mut EventQueueHandle, + proxy: &wl_keyboard::WlKeyboard, + format: wl_keyboard::KeymapFormat, + fd: ::std::os::unix::io::RawFd, + size: u32) + { + match self.kbd_handler { + KbdType::Mapped(ref mut h) => h.keymap(evqh, proxy, format, fd, size), + _ => () + } + } + + fn enter(&mut self, + evqh: &mut EventQueueHandle, + proxy: &wl_keyboard::WlKeyboard, + serial: u32, + surface: &wl_surface::WlSurface, + keys: Vec) + { + for window in &self.windows { + if window.equals(surface) { + self.callback.lock().unwrap().send_event(Event::Focused(true), make_wid(window)); + match self.kbd_handler { + KbdType::Mapped(ref mut h) => { + h.handler().target = Some(make_wid(window)); + h.enter(evqh, proxy, serial, surface, keys); + }, + KbdType::Plain(ref mut target) => { + *target = Some(make_wid(window)) + } + } + break; + } + } + } + + fn leave(&mut self, + evqh: &mut EventQueueHandle, + proxy: &wl_keyboard::WlKeyboard, + serial: u32, + surface: &wl_surface::WlSurface) + { + for window in &self.windows { + if window.equals(surface) { + self.callback.lock().unwrap().send_event(Event::Focused(false), make_wid(window)); + match self.kbd_handler { + KbdType::Mapped(ref mut h) => { + h.handler().target = None; + h.leave(evqh, proxy, serial, surface); + }, + KbdType::Plain(ref mut target) => { + *target = None + } + } + break; + } + } + } + + fn key(&mut self, + evqh: &mut EventQueueHandle, + proxy: &wl_keyboard::WlKeyboard, + serial: u32, + time: u32, + key: u32, + state: wl_keyboard::KeyState) + { + match self.kbd_handler { + KbdType::Mapped(ref mut h) => h.key(evqh, proxy, serial, time, key, state), + KbdType::Plain(Some(wid)) => { + let state = match state { + wl_keyboard::KeyState::Pressed => ElementState::Pressed, + wl_keyboard::KeyState::Released => ElementState::Released, + }; + // This is fallback impl if libxkbcommon was not available + // This case should probably never happen, as most wayland + // compositors _need_ libxkbcommon anyway... + // + // 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) + self.callback.lock().unwrap().send_event( + Event::KeyboardInput( + state, + key as u8, + None, + ModifiersState::default() + ), + wid + ); + }, + KbdType::Plain(None) => () + } + } + + fn modifiers(&mut self, + evqh: &mut EventQueueHandle, + proxy: &wl_keyboard::WlKeyboard, + serial: u32, + mods_depressed: u32, + mods_latched: u32, + mods_locked: u32, + group: u32) + { + match self.kbd_handler { + KbdType::Mapped(ref mut h) => h.modifiers(evqh, proxy, serial, mods_depressed, + mods_latched, mods_locked, group), + _ => () + } + } + + fn repeat_info(&mut self, + evqh: &mut EventQueueHandle, + proxy: &wl_keyboard::WlKeyboard, + rate: i32, + delay: i32) + { + match self.kbd_handler { + KbdType::Mapped(ref mut h) => h.repeat_info(evqh, proxy, rate, delay), + _ => () + } + } +} + +declare_handler!(InputHandler, wl_keyboard::Handler, wl_keyboard::WlKeyboard); diff --git a/src/platform/linux/wayland/keyboard.rs b/src/platform/linux/wayland/keyboard.rs index 98b8e1bd..95e70b03 100644 --- a/src/platform/linux/wayland/keyboard.rs +++ b/src/platform/linux/wayland/keyboard.rs @@ -1,21 +1,21 @@ -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, EventsLoopSink, WindowId}; use wayland_client::EventQueueHandle; use wayland_client::protocol::wl_keyboard; pub struct KbdHandler { - pub target: Option>>> + sink: Arc>, + pub target: Option } impl KbdHandler { - pub fn new() -> KbdHandler { - KbdHandler { target: None } + pub fn new(sink: Arc>) -> KbdHandler { + KbdHandler { sink: sink, target: None } } } @@ -31,14 +31,14 @@ impl wayland_kbd::Handler for KbdHandler { state: wl_keyboard::KeyState, utf8: Option) { - if let Some(ref eviter) = self.target { + if let Some(wid) = 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 = self.sink.lock().unwrap(); + guard.send_event( Event::KeyboardInput( state, rawkey as u8, @@ -49,13 +49,14 @@ impl wayland_kbd::Handler for KbdHandler { alt: mods.alt, logo: mods.logo } - ) + ), + wid ); // 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.send_event(Event::ReceivedCharacter(chr), wid); } } } diff --git a/src/platform/linux/wayland/mod.rs b/src/platform/linux/wayland/mod.rs index 9cf6751c..f2ae3477 100644 --- a/src/platform/linux/wayland/mod.rs +++ b/src/platform/linux/wayland/mod.rs @@ -1,123 +1,17 @@ #![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::window::{Window, 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 platform::PlatformSpecificWindowBuilderAttributes; -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 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 _); - } - } - } -} diff --git a/src/platform/linux/wayland/window.rs b/src/platform/linux/wayland/window.rs index f4977451..6486c710 100644 --- a/src/platform/linux/wayland/window.rs +++ b/src/platform/linux/wayland/window.rs @@ -1,184 +1,98 @@ -use std::collections::VecDeque; use std::sync::{Arc, Mutex}; +use std::sync::atomic::AtomicBool; -use wayland_client::{EventQueue, EventQueueHandle, Init}; +use wayland_client::{EventQueue, EventQueueHandle, 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; -#[derive(Clone)] -pub struct WindowProxy { - ctxt: Arc, - eviter: Arc>>, -} - -impl WindowProxy { - #[inline] - pub fn wakeup_event_loop(&self) { - // Send a sync event, so that any waiting "dispatch" will return - self.ctxt.display.sync(); - self.eviter.lock().unwrap().push_back(Event::Awakened); - } -} - pub struct Window { + // the global wayland context ctxt: Arc, - evq: Mutex, - eviter: Arc>>, + // the EventQueue of our EventsLoop + evq: Arc>, + // signal to advertize the EventsLoop when we are destroyed + cleanup_signal: Arc, + // our wayland surface surface: Arc, + // our current inner dimensions size: Mutex<(u32, u32)>, - handler_id: usize, + // the id of our DecoratedHandler in the EventQueue 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) - } -} - -pub struct WaitEventsIterator<'a> { - window: &'a Window, -} - -impl<'a> Iterator for WaitEventsIterator<'a> { - type Item = Event; - - fn next(&mut self) -> Option { - self.window.next_event(true) - } +#[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::(); // 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, 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); + { + // initialize the DecoratedHandler + 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); + // set fullscreen if necessary + 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, + cleanup_signal: cleanup_signal, surface: surface, size: Mutex::new((width, height)), - handler_id: handler_id, decorated_id: decorated_id - }) + }; + + // register ourselves to the EventsLoop + evlp.register_window(me.decorated_id, me.surface.clone()); + + Ok(me) } - fn process_resize(&self) { - use std::cmp::max; - let mut evq_guard = self.evq.lock().unwrap(); - let mut state = evq_guard.state(); - let newsize = { - let decorated = state.get_mut_handler::>(self.decorated_id); - let newsize = decorated.handler().as_mut().and_then(|h| h.take_newsize()); - if let Some((w, h)) = newsize { - decorated.resize(w as i32, h as i32); - *self.size.lock().unwrap() = (w, h); - } - newsize - }; - // callback_resize if any - if let Some((w, h)) = newsize { - let mut handler = state.get_mut_handler::(self.handler_id); - if let Some(ref callback) = handler.resize_callback { - callback(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(); - } - - // try a pending dispatch - { - self.ctxt.dispatch_pending(); - self.evq.lock().unwrap().dispatch_pending(); - // some events were dispatched, need to process a potential resising - self.process_resize(); - } - - let mut 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(); - // 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 + #[inline] + pub fn id(&self) -> WindowId { + make_wid(&self.surface) } pub fn set_title(&self, title: &str) { let mut guard = self.evq.lock().unwrap(); let mut state = guard.state(); - let mut decorated = state.get_mut_handler::>(self.decorated_id); + let decorated = state.get_mut_handler::>(self.decorated_id); decorated.set_title(title.into()) } @@ -223,36 +137,6 @@ impl Window { decorated.resize(x as i32, y as i32); } - #[inline] - pub fn create_window_proxy(&self) -> WindowProxy { - WindowProxy { - ctxt: self.ctxt.clone(), - eviter: self.eviter.clone() - } - } - - #[inline] - pub fn poll_events(&self) -> PollEventsIterator { - PollEventsIterator { - window: self - } - } - - #[inline] - pub fn wait_events(&self) -> WaitEventsIterator { - WaitEventsIterator { - window: self - } - } - - #[inline] - pub fn set_window_resize_callback(&mut self, callback: Option) { - let mut guard = self.evq.lock().unwrap(); - let mut state = guard.state(); - let mut handler = state.get_mut_handler::(self.handler_id); - handler.resize_callback = callback; - } - #[inline] pub fn set_cursor(&self, _cursor: MouseCursor) { // TODO @@ -293,17 +177,18 @@ impl Window { impl Drop for Window { fn drop(&mut self) { self.surface.destroy(); - self.ctxt.prune_dead_windows(); + self.cleanup_signal.store(true, ::std::sync::atomic::Ordering::Relaxed); } } -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() } } @@ -318,23 +203,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, - resize_callback: Option, -} - -impl WindowHandler { - fn new() -> WindowHandler { - WindowHandler { - my_id: 0, - resize_callback: None - } - } -} - -impl Init for WindowHandler { - fn init(&mut self, evqh: &mut EventQueueHandle, index: usize) { - self.my_id = index; - } -} diff --git a/src/platform/linux/x11/mod.rs b/src/platform/linux/x11/mod.rs index a4f59c8a..43721b7b 100644 --- a/src/platform/linux/x11/mod.rs +++ b/src/platform/linux/x11/mod.rs @@ -44,7 +44,7 @@ impl EventsLoop { pub fn poll_events(&self, mut callback: F) where F: FnMut(::Event) { - let mut windows = self.windows.lock().unwrap(); + let windows = self.windows.lock().unwrap(); for window in windows.iter() { for event in window.poll_events() { callback(::Event::WindowEvent { @@ -63,7 +63,7 @@ impl EventsLoop { // Yeah that's a very bad implementation. loop { self.poll_events(|e| callback(e)); - ::std::thread::sleep_ms(5); + ::std::thread::sleep(::std::time::Duration::from_millis(5)); if self.interrupted.load(::std::sync::atomic::Ordering::Relaxed) { break; } diff --git a/src/platform/linux/x11/window.rs b/src/platform/linux/x11/window.rs index 59732f58..deca3d2c 100644 --- a/src/platform/linux/x11/window.rs +++ b/src/platform/linux/x11/window.rs @@ -836,7 +836,7 @@ impl Window { // differs on the desktop environments or themes. // // Try the better looking (or more suiting) names first. - let mut xcursor = match cursor { + let xcursor = match cursor { MouseCursor::Alias => load("link"), MouseCursor::Arrow => load("arrow"), MouseCursor::Cell => load("plus"), diff --git a/src/platform/linux/x11/xdisplay.rs b/src/platform/linux/x11/xdisplay.rs index 14e058f8..05a29f40 100644 --- a/src/platform/linux/x11/xdisplay.rs +++ b/src/platform/linux/x11/xdisplay.rs @@ -1,7 +1,6 @@ use std::ptr; use std::fmt; use std::error::Error; -use std::ffi::CString; use std::sync::Mutex; use libc;