From 3555de114a05c3f5079f8315602cb8bf8b0cb7b3 Mon Sep 17 00:00:00 2001 From: Cherser-s Date: Tue, 25 Jun 2019 12:00:41 +0300 Subject: [PATCH] Wayland: Add relative pointer movement (#973) * Add relative pointer movement for Wayland * Format changed code with rustfmt * Wayland: merge window and device event queues into one * Replace map_or_else call for simplification --- src/platform_impl/linux/wayland/event_loop.rs | 101 ++++++++++++------ src/platform_impl/linux/wayland/pointer.rs | 48 +++++++-- src/platform_impl/linux/wayland/touch.rs | 12 +-- 3 files changed, 113 insertions(+), 48 deletions(-) diff --git a/src/platform_impl/linux/wayland/event_loop.rs b/src/platform_impl/linux/wayland/event_loop.rs index 8fa7c994..7c3b21a0 100644 --- a/src/platform_impl/linux/wayland/event_loop.rs +++ b/src/platform_impl/linux/wayland/event_loop.rs @@ -7,6 +7,11 @@ use std::{ time::Instant, }; +use smithay_client_toolkit::reexports::protocols::unstable::relative_pointer::v1::client::{ + zwp_relative_pointer_manager_v1::ZwpRelativePointerManagerV1, + zwp_relative_pointer_v1::ZwpRelativePointerV1, +}; + use crate::{ dpi::{PhysicalPosition, PhysicalSize}, event::ModifiersState, @@ -15,7 +20,7 @@ use crate::{ platform_impl::platform::sticky_exit_callback, }; -use super::{window::WindowStore, WindowId}; +use super::{window::WindowStore, DeviceId, WindowId}; use smithay_client_toolkit::{ output::OutputMgr, @@ -26,33 +31,37 @@ use smithay_client_toolkit::{ Environment, }; -pub struct WindowEventsSink { - buffer: VecDeque<(crate::event::WindowEvent, crate::window::WindowId)>, +pub struct WindowEventsSink { + buffer: VecDeque>, } -impl WindowEventsSink { - pub fn new() -> WindowEventsSink { +impl WindowEventsSink { + pub fn new() -> WindowEventsSink { WindowEventsSink { buffer: VecDeque::new(), } } - pub fn send_event(&mut self, evt: crate::event::WindowEvent, wid: WindowId) { - self.buffer.push_back(( - evt, - crate::window::WindowId(crate::platform_impl::WindowId::Wayland(wid)), - )); + pub fn send_window_event(&mut self, evt: crate::event::WindowEvent, wid: WindowId) { + self.buffer.push_back(crate::event::Event::WindowEvent { + event: evt, + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Wayland(wid)), + }); } - fn empty_with(&mut self, mut callback: F) + pub fn send_device_event(&mut self, evt: crate::event::DeviceEvent, dev_id: DeviceId) { + self.buffer.push_back(crate::event::Event::DeviceEvent { + event: evt, + device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(dev_id)), + }); + } + + fn empty_with(&mut self, mut callback: F) where F: FnMut(crate::event::Event), { - for (evt, wid) in self.buffer.drain(..) { - callback(crate::event::Event::WindowEvent { - event: evt, - window_id: wid, - }) + for evt in self.buffer.drain(..) { + callback(evt) } } } @@ -65,7 +74,7 @@ pub struct EventLoop { // the output manager pub outputs: OutputMgr, // our sink, shared with some handlers, buffering the events - sink: Arc>, + sink: Arc>>, pending_user_events: Rc>>, _user_source: ::calloop::Source<::calloop::channel::Channel>, user_sender: ::calloop::channel::Sender, @@ -122,13 +131,14 @@ impl EventLoop { .handle() .insert_source(kbd_channel, move |evt, &mut ()| { if let ::calloop::channel::Event::Msg((evt, wid)) = evt { - kbd_sink.lock().unwrap().send_event(evt, wid); + kbd_sink.lock().unwrap().send_window_event(evt, wid); } }) .unwrap(); let mut seat_manager = SeatManager { sink: sink.clone(), + relative_pointer_manager_proxy: None, store: store.clone(), seats: seats.clone(), kbd_sender, @@ -143,6 +153,15 @@ impl EventLoop { ref interface, version, } => { + if interface == "zwp_relative_pointer_manager_v1" { + seat_manager.relative_pointer_manager_proxy = Some( + registry + .bind(version, id, move |pointer_manager| { + pointer_manager.implement_closure(|_, _| (), ()) + }) + .unwrap(), + ) + } if interface == "wl_seat" { seat_manager.add_seat(id, version, registry) } @@ -388,7 +407,7 @@ impl EventLoop { let pruned = window_target.store.lock().unwrap().cleanup(); *cleanup_needed = false; for wid in pruned { - sink.send_event(crate::event::WindowEvent::Destroyed, wid); + sink.send_window_event(crate::event::WindowEvent::Destroyed, wid); } } } @@ -400,7 +419,10 @@ impl EventLoop { frame.resize(w, h); frame.refresh(); let logical_size = crate::dpi::LogicalSize::new(w as f64, h as f64); - sink.send_event(crate::event::WindowEvent::Resized(logical_size), wid); + sink.send_window_event( + crate::event::WindowEvent::Resized(logical_size), + wid, + ); *size = (w, h); } else if frame_refresh { frame.refresh(); @@ -410,16 +432,16 @@ impl EventLoop { } } if let Some(dpi) = new_dpi { - sink.send_event( + sink.send_window_event( crate::event::WindowEvent::HiDpiFactorChanged(dpi as f64), wid, ); } if refresh { - sink.send_event(crate::event::WindowEvent::RedrawRequested, wid); + sink.send_window_event(crate::event::WindowEvent::RedrawRequested, wid); } if closed { - sink.send_event(crate::event::WindowEvent::CloseRequested, wid); + sink.send_window_event(crate::event::WindowEvent::CloseRequested, wid); } }, ) @@ -430,14 +452,15 @@ impl EventLoop { * Wayland protocol implementations */ -struct SeatManager { - sink: Arc>, +struct SeatManager { + sink: Arc>>, store: Arc>, seats: Arc>>, kbd_sender: ::calloop::channel::Sender<(crate::event::WindowEvent, super::WindowId)>, + relative_pointer_manager_proxy: Option, } -impl SeatManager { +impl SeatManager { fn add_seat(&mut self, id: u32, version: u32, registry: wl_registry::WlRegistry) { use std::cmp::min; @@ -445,6 +468,8 @@ impl SeatManager { sink: self.sink.clone(), store: self.store.clone(), pointer: None, + relative_pointer: None, + relative_pointer_manager_proxy: self.relative_pointer_manager_proxy.as_ref().cloned(), keyboard: None, touch: None, kbd_sender: self.kbd_sender.clone(), @@ -470,17 +495,19 @@ impl SeatManager { } } -struct SeatData { - sink: Arc>, +struct SeatData { + sink: Arc>>, store: Arc>, kbd_sender: ::calloop::channel::Sender<(crate::event::WindowEvent, super::WindowId)>, pointer: Option, + relative_pointer: Option, + relative_pointer_manager_proxy: Option, keyboard: Option, touch: Option, modifiers_tracker: Arc>, } -impl SeatData { +impl SeatData { fn receive(&mut self, evt: wl_seat::Event, seat: wl_seat::WlSeat) { match evt { wl_seat::Event::Name { .. } => (), @@ -492,7 +519,19 @@ impl SeatData { self.sink.clone(), self.store.clone(), self.modifiers_tracker.clone(), - )) + )); + + self.relative_pointer = + self.relative_pointer_manager_proxy + .as_ref() + .and_then(|manager| { + super::pointer::implement_relative_pointer( + self.sink.clone(), + self.pointer.as_ref().unwrap(), + manager, + ) + .ok() + }) } // destroy pointer if applicable if !capabilities.contains(wl_seat::Capability::Pointer) { @@ -540,7 +579,7 @@ impl SeatData { } } -impl Drop for SeatData { +impl Drop for SeatData { fn drop(&mut self) { if let Some(pointer) = self.pointer.take() { if pointer.as_ref().version() >= 3 { diff --git a/src/platform_impl/linux/wayland/pointer.rs b/src/platform_impl/linux/wayland/pointer.rs index b2f00d89..b5ec7e3c 100644 --- a/src/platform_impl/linux/wayland/pointer.rs +++ b/src/platform_impl/linux/wayland/pointer.rs @@ -1,7 +1,8 @@ use std::sync::{Arc, Mutex}; use crate::event::{ - ElementState, ModifiersState, MouseButton, MouseScrollDelta, TouchPhase, WindowEvent, + DeviceEvent, ElementState, ModifiersState, MouseButton, MouseScrollDelta, TouchPhase, + WindowEvent, }; use super::{event_loop::WindowEventsSink, window::WindowStore, DeviceId}; @@ -11,9 +12,14 @@ use smithay_client_toolkit::reexports::client::protocol::{ wl_seat, }; -pub fn implement_pointer( +use smithay_client_toolkit::reexports::protocols::unstable::relative_pointer::v1::client::{ + zwp_relative_pointer_manager_v1::ZwpRelativePointerManagerV1, zwp_relative_pointer_v1::Event, + zwp_relative_pointer_v1::ZwpRelativePointerV1, +}; + +pub fn implement_pointer( seat: &wl_seat::WlSeat, - sink: Arc>, + sink: Arc>>, store: Arc>, modifiers_tracker: Arc>, ) -> WlPointer { @@ -37,7 +43,7 @@ pub fn implement_pointer( let wid = store.find_wid(&surface); if let Some(wid) = wid { mouse_focus = Some(wid); - sink.send_event( + sink.send_window_event( WindowEvent::CursorEntered { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Wayland(DeviceId), @@ -45,7 +51,7 @@ pub fn implement_pointer( }, wid, ); - sink.send_event( + sink.send_window_event( WindowEvent::CursorMoved { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Wayland(DeviceId), @@ -61,7 +67,7 @@ pub fn implement_pointer( mouse_focus = None; let wid = store.find_wid(&surface); if let Some(wid) = wid { - sink.send_event( + sink.send_window_event( WindowEvent::CursorLeft { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Wayland(DeviceId), @@ -77,7 +83,7 @@ pub fn implement_pointer( .. } => { if let Some(wid) = mouse_focus { - sink.send_event( + sink.send_window_event( WindowEvent::CursorMoved { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Wayland(DeviceId), @@ -103,7 +109,7 @@ pub fn implement_pointer( // TODO figure out the translation ? _ => return, }; - sink.send_event( + sink.send_window_event( WindowEvent::MouseInput { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Wayland(DeviceId), @@ -127,7 +133,7 @@ pub fn implement_pointer( wl_pointer::Axis::HorizontalScroll => x += value as f32, _ => unreachable!(), } - sink.send_event( + sink.send_window_event( WindowEvent::MouseWheel { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Wayland(DeviceId), @@ -161,7 +167,7 @@ pub fn implement_pointer( let axis_discrete_buffer = axis_discrete_buffer.take(); if let Some(wid) = mouse_focus { if let Some((x, y)) = axis_discrete_buffer { - sink.send_event( + sink.send_window_event( WindowEvent::MouseWheel { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Wayland(DeviceId), @@ -173,7 +179,7 @@ pub fn implement_pointer( wid, ); } else if let Some((x, y)) = axis_buffer { - sink.send_event( + sink.send_window_event( WindowEvent::MouseWheel { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Wayland(DeviceId), @@ -215,3 +221,23 @@ pub fn implement_pointer( }) .unwrap() } + +pub fn implement_relative_pointer( + sink: Arc>>, + pointer: &WlPointer, + manager: &ZwpRelativePointerManagerV1, +) -> Result { + manager.get_relative_pointer(pointer, |rel_pointer| { + rel_pointer.implement_closure( + move |evt, _rel_pointer| { + let mut sink = sink.lock().unwrap(); + match evt { + Event::RelativeMotion { dx, dy, .. } => sink + .send_device_event(DeviceEvent::MouseMotion { delta: (dx, dy) }, DeviceId), + _ => unreachable!(), + } + }, + (), + ) + }) +} diff --git a/src/platform_impl/linux/wayland/touch.rs b/src/platform_impl/linux/wayland/touch.rs index 916c4536..b72be7b8 100644 --- a/src/platform_impl/linux/wayland/touch.rs +++ b/src/platform_impl/linux/wayland/touch.rs @@ -15,9 +15,9 @@ struct TouchPoint { id: i32, } -pub(crate) fn implement_touch( +pub(crate) fn implement_touch( seat: &wl_seat::WlSeat, - sink: Arc>, + sink: Arc>>, store: Arc>, ) -> WlTouch { let mut pending_ids = Vec::new(); @@ -32,7 +32,7 @@ pub(crate) fn implement_touch( } => { let wid = store.find_wid(&surface); if let Some(wid) = wid { - sink.send_event( + sink.send_window_event( WindowEvent::Touch(crate::event::Touch { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Wayland(DeviceId), @@ -54,7 +54,7 @@ pub(crate) fn implement_touch( let idx = pending_ids.iter().position(|p| p.id == id); if let Some(idx) = idx { let pt = pending_ids.remove(idx); - sink.send_event( + sink.send_window_event( WindowEvent::Touch(crate::event::Touch { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Wayland(DeviceId), @@ -71,7 +71,7 @@ pub(crate) fn implement_touch( let pt = pending_ids.iter_mut().find(|p| p.id == id); if let Some(pt) = pt { pt.location = (x, y); - sink.send_event( + sink.send_window_event( WindowEvent::Touch(crate::event::Touch { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Wayland(DeviceId), @@ -87,7 +87,7 @@ pub(crate) fn implement_touch( TouchEvent::Frame => (), TouchEvent::Cancel => { for pt in pending_ids.drain(..) { - sink.send_event( + sink.send_window_event( WindowEvent::Touch(crate::event::Touch { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Wayland(DeviceId),