diff options
author | Victor Berger <victor.berger@m4x.org> | 2015-12-13 13:13:20 +0100 |
---|---|---|
committer | Victor Berger <victor.berger@m4x.org> | 2015-12-22 14:36:41 +0100 |
commit | 0792557f4bc05125f0181729a6adbaf1aa52ec27 (patch) | |
tree | 5ec91790f77500f72e78886f1d71cbd5ea8218e4 | |
parent | 6294d3c7ddc303913c83fd74d14c7a801d496c9e (diff) | |
download | glutin-0792557f4bc05125f0181729a6adbaf1aa52ec27.tar.gz glutin-0792557f4bc05125f0181729a6adbaf1aa52ec27.zip |
api/wayland: pointer events support.
-rw-r--r-- | src/api/wayland/context.rs | 33 | ||||
-rw-r--r-- | src/api/wayland/events.rs | 91 | ||||
-rw-r--r-- | src/api/wayland/window.rs | 4 |
3 files changed, 119 insertions, 9 deletions
diff --git a/src/api/wayland/context.rs b/src/api/wayland/context.rs index 8e1196d..4b39d85 100644 --- a/src/api/wayland/context.rs +++ b/src/api/wayland/context.rs @@ -1,6 +1,6 @@ use Event as GlutinEvent; -use std::collections::{HashMap, VecDeque}; +use std::collections::{HashMap, VecDeque, HashSet}; use std::sync::{Arc, Mutex}; use libc::c_void; @@ -9,7 +9,7 @@ use wayland_client::{EventIterator, Proxy, ProxyId}; use wayland_client::wayland::get_display; use wayland_client::wayland::compositor::{WlCompositor, WlSurface}; use wayland_client::wayland::output::WlOutput; -use wayland_client::wayland::seat::WlSeat; +use wayland_client::wayland::seat::{WlSeat, WlPointer}; use wayland_client::wayland::shell::WlShell; use wayland_client::wayland::shm::WlShm; use wayland_client::wayland::subcompositor::WlSubcompositor; @@ -30,11 +30,20 @@ wayland_env!(InnerEnv, subcompositor: WlSubcompositor ); +pub struct WaylandFocuses { + pub pointer: Option<WlPointer>, + pub pointer_on: Option<ProxyId>, + pub pointer_at: Option<(f64, f64)>, + pub keyboard_on: Option<ProxyId> +} + pub struct WaylandContext { inner: InnerEnv, iterator: Mutex<EventIterator>, monitors: Vec<WlOutput>, - queues: Mutex<HashMap<ProxyId, Arc<Mutex<VecDeque<GlutinEvent>>>>> + queues: Mutex<HashMap<ProxyId, Arc<Mutex<VecDeque<GlutinEvent>>>>>, + known_surfaces: Mutex<HashSet<ProxyId>>, + focuses: Mutex<WaylandFocuses> } impl WaylandContext { @@ -57,7 +66,14 @@ impl WaylandContext { inner: inner_env, iterator: Mutex::new(iterator), monitors: monitors, - queues: Mutex::new(HashMap::new()) + queues: Mutex::new(HashMap::new()), + known_surfaces: Mutex::new(HashSet::new()), + focuses: Mutex::new(WaylandFocuses { + pointer: None, + pointer_on: None, + pointer_at: None, + keyboard_on: None + }) }) } @@ -71,12 +87,14 @@ impl WaylandContext { Arc::new(Mutex::new(q)) }; self.queues.lock().unwrap().insert(id, queue.clone()); + self.known_surfaces.lock().unwrap().insert(id); (s, queue) }) } pub fn dropped_surface(&self, id: ProxyId) { self.queues.lock().unwrap().remove(&id); + self.known_surfaces.lock().unwrap().remove(&id); } pub fn decorated_from(&self, surface: &WlSurface, width: i32, height: i32) -> Option<DecoratedSurface> { @@ -100,9 +118,14 @@ impl WaylandContext { pub fn dispatch_events(&self) { self.inner.display.dispatch_pending().unwrap(); let mut iterator = self.iterator.lock().unwrap(); + let mut focuses = self.focuses.lock().unwrap(); + let known_ids = self.known_surfaces.lock().unwrap(); let queues = self.queues.lock().unwrap(); for evt in &mut *iterator { - if let Some((evt, id)) = super::events::translate_event(evt) { + if let Some((evt, id)) = super::events::translate_event( + evt, &mut *focuses, &known_ids, + self.inner.seat.as_ref().map(|s| &s.0)) + { if let Some(q) = queues.get(&id) { q.lock().unwrap().push_back(evt); } diff --git a/src/api/wayland/events.rs b/src/api/wayland/events.rs index 86f0575..6a7a2e7 100644 --- a/src/api/wayland/events.rs +++ b/src/api/wayland/events.rs @@ -1,10 +1,97 @@ +use std::collections::HashSet; + use Event as GlutinEvent; +use ElementState; +use MouseButton; +use MouseScrollDelta; use wayland_client::Event as WaylandEvent; use wayland_client::ProxyId; +use wayland_client::wayland::WaylandProtocolEvent as WPE; +use wayland_client::wayland::seat::{WlSeat, WlSeatEvent, WlPointerEvent, + WlPointerButtonState, + WlPointerAxis, WlSeatCapability}; + +use super::context::WaylandFocuses; -pub fn translate_event(evt: WaylandEvent) -> Option<(GlutinEvent, ProxyId)> { - match evt { +pub fn translate_event( + evt: WaylandEvent, + focuses: &mut WaylandFocuses, + known_surfaces: &HashSet<ProxyId>, + seat: Option<&WlSeat>, +) -> Option<(GlutinEvent, ProxyId)> { + let WaylandEvent::Wayland(wayland_evt) = evt; + match wayland_evt { + WPE::WlSeat(_, seat_evt) => match seat_evt { + WlSeatEvent::Capabilities(cap) => { + if cap.contains(WlSeatCapability::Pointer) && focuses.pointer.is_none() { + if let Some(seat) = seat { + focuses.pointer = Some(seat.get_pointer()); + } + } + None + }, + _ => None + }, + WPE::WlPointer(_, pointer_evt) => match pointer_evt { + WlPointerEvent::Enter(_, surface, x, y) => { + if known_surfaces.contains(&surface) { + focuses.pointer_on = Some(surface); + focuses.pointer_at = Some((x, y)); + Some((GlutinEvent::MouseMoved((x as i32, y as i32)), surface)) + } else { + None + } + } + WlPointerEvent::Leave(_, _) => { + focuses.pointer_on = None; + focuses.pointer_at = None; + None + } + WlPointerEvent::Motion(_, x, y) => { + if let Some(surface) = focuses.pointer_on { + focuses.pointer_at = Some((x, y)); + Some((GlutinEvent::MouseMoved((x as i32, y as i32)), surface)) + } else { + None + } + } + WlPointerEvent::Button(_, _, button, state) => { + if let Some(surface) = focuses.pointer_on { + Some((GlutinEvent::MouseInput( + match state { + WlPointerButtonState::Pressed => ElementState::Pressed, + WlPointerButtonState::Released => ElementState::Released + }, + match button { + 0x110 => MouseButton::Left, + 0x111 => MouseButton::Right, + 0x112 => MouseButton::Middle, + // TODO figure out the translation ? + _ => return None + } + ), surface)) + } else { + None + } + } + WlPointerEvent::Axis(_, axis, amplitude) => { + if let Some(surface) = focuses.pointer_on { + Some((GlutinEvent::MouseWheel( + match axis { + WlPointerAxis::VerticalScroll => { + MouseScrollDelta::PixelDelta(amplitude as f32, 0.0) + } + WlPointerAxis::HorizontalScroll => { + MouseScrollDelta::PixelDelta(0.0, amplitude as f32) + } + } + ), surface)) + } else { + None + } + } + }, _ => None } }
\ No newline at end of file diff --git a/src/api/wayland/window.rs b/src/api/wayland/window.rs index 7532443..faf772e 100644 --- a/src/api/wayland/window.rs +++ b/src/api/wayland/window.rs @@ -225,12 +225,12 @@ impl Window { } #[inline] - pub fn set_cursor(&self, cursor: MouseCursor) { + pub fn set_cursor(&self, _cursor: MouseCursor) { // TODO } #[inline] - pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> { + pub fn set_cursor_state(&self, _state: CursorState) -> Result<(), String> { // TODO Ok(()) } |