From 0792557f4bc05125f0181729a6adbaf1aa52ec27 Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Sun, 13 Dec 2015 13:13:20 +0100 Subject: api/wayland: pointer events support. --- src/api/wayland/context.rs | 33 ++++++++++++++--- src/api/wayland/events.rs | 91 +++++++++++++++++++++++++++++++++++++++++++++- src/api/wayland/window.rs | 4 +- 3 files changed, 119 insertions(+), 9 deletions(-) (limited to 'src') 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, + pub pointer_on: Option, + pub pointer_at: Option<(f64, f64)>, + pub keyboard_on: Option +} + pub struct WaylandContext { inner: InnerEnv, iterator: Mutex, monitors: Vec, - queues: Mutex>>>> + queues: Mutex>>>>, + known_surfaces: Mutex>, + focuses: Mutex } 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 { @@ -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, + 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(()) } -- cgit v1.2.3