From 03392bf7d19dce60ea6da8416c013d81bb7e2c89 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Sun, 2 Feb 2020 18:05:49 +0300 Subject: [PATCH] seat: add GrabStartData to PointerGrab Stores the data about the event that started the grab. Will be useful for things like move and resize requests. --- anvil/src/shell.rs | 20 +++++++---- src/wayland/data_device/dnd_grab.rs | 9 ++++- src/wayland/data_device/mod.rs | 20 ++++++++--- src/wayland/data_device/server_dnd_grab.rs | 9 ++++- src/wayland/seat/mod.rs | 3 +- src/wayland/seat/pointer.rs | 41 +++++++++++++++++++--- 6 files changed, 85 insertions(+), 17 deletions(-) diff --git a/anvil/src/shell.rs b/anvil/src/shell.rs index cfd4957..81b85b5 100644 --- a/anvil/src/shell.rs +++ b/anvil/src/shell.rs @@ -15,7 +15,7 @@ use smithay::{ wayland::{ compositor::{compositor_init, CompositorToken, RegionAttributes, SurfaceAttributes, SurfaceEvent}, data_device::DnDIconRole, - seat::{AxisFrame, CursorImageRole, PointerGrab, PointerInnerHandle, Seat}, + seat::{AxisFrame, CursorImageRole, GrabStartData, PointerGrab, PointerInnerHandle, Seat}, shell::{ legacy::{ wl_shell_init, ShellRequest, ShellState as WlShellState, ShellSurfaceKind, ShellSurfaceRole, @@ -47,9 +47,9 @@ pub type MyWindowMap = WindowMap< pub type MyCompositorToken = CompositorToken; struct MoveSurfaceGrab { + start_data: GrabStartData, window_map: Rc>, toplevel: SurfaceKind, - initial_pointer_location: (f64, f64), initial_window_location: (i32, i32), } @@ -62,8 +62,8 @@ impl PointerGrab for MoveSurfaceGrab { _serial: u32, _time: u32, ) { - let dx = location.0 - self.initial_pointer_location.0; - let dy = location.1 - self.initial_pointer_location.1; + let dx = location.0 - self.start_data.location.0; + let dy = location.1 - self.start_data.location.1; let new_window_x = (self.initial_window_location.0 as f64 + dx) as i32; let new_window_y = (self.initial_window_location.1 as f64 + dy) as i32; @@ -90,6 +90,10 @@ impl PointerGrab for MoveSurfaceGrab { fn axis(&mut self, handle: &mut PointerInnerHandle<'_>, details: AxisFrame) { handle.axis(details) } + + fn start_data(&self) -> &GrabStartData { + &self.start_data + } } pub fn init_shell( @@ -156,13 +160,15 @@ pub fn init_shell( // TODO: touch move. let pointer = seat.get_pointer().unwrap(); + let start_data = pointer.grab_start_data().unwrap(); + let toplevel = SurfaceKind::Xdg(surface); let initial_window_location = xdg_window_map.borrow().location(&toplevel).unwrap(); let grab = MoveSurfaceGrab { + start_data, window_map: xdg_window_map.clone(), toplevel, - initial_pointer_location: pointer.current_location(), initial_window_location, }; @@ -204,13 +210,15 @@ pub fn init_shell( // TODO: touch move. let pointer = seat.get_pointer().unwrap(); + let start_data = pointer.grab_start_data().unwrap(); + let toplevel = SurfaceKind::Wl(surface); let initial_window_location = shell_window_map.borrow().location(&toplevel).unwrap(); let grab = MoveSurfaceGrab { + start_data, window_map: shell_window_map.clone(), toplevel, - initial_pointer_location: pointer.current_location(), initial_window_location, }; diff --git a/src/wayland/data_device/dnd_grab.rs b/src/wayland/data_device/dnd_grab.rs index f97fd62..7b9c1cd 100644 --- a/src/wayland/data_device/dnd_grab.rs +++ b/src/wayland/data_device/dnd_grab.rs @@ -8,12 +8,13 @@ use wayland_server::{ use crate::wayland::{ compositor::{roles::Role, CompositorToken}, - seat::{AxisFrame, PointerGrab, PointerInnerHandle, Seat}, + seat::{AxisFrame, GrabStartData, PointerGrab, PointerInnerHandle, Seat}, }; use super::{with_source_metadata, DataDeviceData, DnDIconRole, SeatData}; pub(crate) struct DnDGrab { + start_data: GrabStartData, data_source: Option, current_focus: Option, pending_offers: Vec, @@ -27,6 +28,7 @@ pub(crate) struct DnDGrab { impl + 'static> DnDGrab { pub(crate) fn new( + start_data: GrabStartData, source: Option, origin: wl_surface::WlSurface, seat: Seat, @@ -35,6 +37,7 @@ impl + 'static> DnDGrab { callback: Rc>, ) -> DnDGrab { DnDGrab { + start_data, data_source: source, current_focus: None, pending_offers: Vec::with_capacity(1), @@ -222,6 +225,10 @@ impl + 'static> PointerGrab for DnDGrab { // we just forward the axis events as is handle.axis(details); } + + fn start_data(&self) -> &GrabStartData { + &self.start_data + } } struct OfferData { diff --git a/src/wayland/data_device/mod.rs b/src/wayland/data_device/mod.rs index 74ae600..96996b3 100644 --- a/src/wayland/data_device/mod.rs +++ b/src/wayland/data_device/mod.rs @@ -69,7 +69,7 @@ use wayland_server::{ use crate::wayland::{ compositor::{roles::Role, CompositorToken}, - seat::Seat, + seat::{GrabStartData, Seat}, }; mod data_source; @@ -354,8 +354,13 @@ pub fn set_data_device_selection(seat: &Seat, mime_types: Vec) { /// You'll receive events generated by the interaction of clients with your /// drag'n'drop in the provided callback. See [`ServerDndEvent`] for details about /// which events can be generated and what response is expected from you to them. -pub fn start_dnd(seat: &Seat, serial: u32, metadata: SourceMetadata, callback: C) -where +pub fn start_dnd( + seat: &Seat, + serial: u32, + start_data: GrabStartData, + metadata: SourceMetadata, + callback: C, +) where C: FnMut(ServerDndEvent) + 'static, { // TODO: same question as in set_data_device_focus @@ -366,7 +371,12 @@ where }); if let Some(pointer) = seat.get_pointer() { pointer.set_grab( - server_dnd_grab::ServerDnDGrab::new(metadata, seat.clone(), Rc::new(RefCell::new(callback))), + server_dnd_grab::ServerDnDGrab::new( + start_data, + metadata, + seat.clone(), + Rc::new(RefCell::new(callback)), + ), serial, ); return; @@ -466,8 +476,10 @@ where source: source.clone(), icon: icon.clone(), }); + let start_data = pointer.grab_start_data().unwrap(); pointer.set_grab( dnd_grab::DnDGrab::new( + start_data, source, origin, seat.clone(), diff --git a/src/wayland/data_device/server_dnd_grab.rs b/src/wayland/data_device/server_dnd_grab.rs index ab79fe4..a2ce916 100644 --- a/src/wayland/data_device/server_dnd_grab.rs +++ b/src/wayland/data_device/server_dnd_grab.rs @@ -7,7 +7,7 @@ use wayland_server::{ NewResource, }; -use crate::wayland::seat::{AxisFrame, PointerGrab, PointerInnerHandle, Seat}; +use crate::wayland::seat::{AxisFrame, GrabStartData, PointerGrab, PointerInnerHandle, Seat}; use super::{DataDeviceData, SeatData}; @@ -37,6 +37,7 @@ pub enum ServerDndEvent { } pub(crate) struct ServerDnDGrab { + start_data: GrabStartData, metadata: super::SourceMetadata, current_focus: Option, pending_offers: Vec, @@ -47,11 +48,13 @@ pub(crate) struct ServerDnDGrab { impl ServerDnDGrab { pub(crate) fn new( + start_data: GrabStartData, metadata: super::SourceMetadata, seat: Seat, callback: Rc>, ) -> ServerDnDGrab { ServerDnDGrab { + start_data, metadata, current_focus: None, pending_offers: Vec::with_capacity(1), @@ -212,6 +215,10 @@ where // we just forward the axis events as is handle.axis(details); } + + fn start_data(&self) -> &GrabStartData { + &self.start_data + } } struct OfferData { diff --git a/src/wayland/seat/mod.rs b/src/wayland/seat/mod.rs index fe58900..11f4b49 100644 --- a/src/wayland/seat/mod.rs +++ b/src/wayland/seat/mod.rs @@ -49,7 +49,8 @@ mod pointer; pub use self::{ keyboard::{keysyms, Error as KeyboardError, KeyboardHandle, Keysym, ModifiersState, XkbConfig}, pointer::{ - AxisFrame, CursorImageRole, CursorImageStatus, PointerGrab, PointerHandle, PointerInnerHandle, + AxisFrame, CursorImageRole, CursorImageStatus, GrabStartData, PointerGrab, PointerHandle, + PointerInnerHandle, }, }; diff --git a/src/wayland/seat/pointer.rs b/src/wayland/seat/pointer.rs index e674b4a..5d6a2b4 100644 --- a/src/wayland/seat/pointer.rs +++ b/src/wayland/seat/pointer.rs @@ -166,6 +166,15 @@ impl PointerHandle { } } + /// Returns the start data for the grab, if any. + pub fn grab_start_data(&self) -> Option { + let guard = self.inner.borrow(); + match &guard.grab { + GrabStatus::Active(_, g) => Some(g.start_data().clone()), + _ => None, + } + } + /// Notify that the pointer moved /// /// You provide the new location of the pointer, in the form of: @@ -226,6 +235,19 @@ impl PointerHandle { } } +/// Data about the event that started the grab. +#[derive(Clone)] +pub struct GrabStartData { + /// The focused surface and its location, if any, at the start of the grab. + /// + /// The location coordinates are in the global compositor space. + pub focus: Option<(WlSurface, (f64, f64))>, + /// The button that initiated the grab. + pub button: u32, + /// The location of the click that initiated the grab, in the global compositor space. + pub location: (f64, f64), +} + /// A trait to implement a pointer grab /// /// In some context, it is necessary to temporarily change the behavior of the pointer. This is @@ -262,6 +284,8 @@ pub trait PointerGrab { ); /// An axis scroll was reported fn axis(&mut self, handle: &mut PointerInnerHandle<'_>, details: AxisFrame); + /// The data about the event that started the grab. + fn start_data(&self) -> &GrabStartData; } /// This inner handle is accessed from inside a pointer grab logic, and directly @@ -631,11 +655,14 @@ impl PointerGrab for DefaultGrab { time: u32, ) { handle.button(button, state, serial, time); - let current_focus = handle.current_focus().cloned(); handle.set_grab( serial, ClickGrab { - current_focus, + start_data: GrabStartData { + focus: handle.current_focus().cloned(), + button, + location: handle.current_location(), + }, pending_focus: None, }, ); @@ -643,6 +670,9 @@ impl PointerGrab for DefaultGrab { fn axis(&mut self, handle: &mut PointerInnerHandle<'_>, details: AxisFrame) { handle.axis(details); } + fn start_data(&self) -> &GrabStartData { + unreachable!() + } } // A click grab, basic grab started when an user clicks a surface @@ -651,7 +681,7 @@ impl PointerGrab for DefaultGrab { // In case the user maintains several simultaneous clicks, release // the grab once all are released. struct ClickGrab { - current_focus: Option<(WlSurface, (f64, f64))>, + start_data: GrabStartData, pending_focus: Option<(WlSurface, (f64, f64))>, } @@ -666,7 +696,7 @@ impl PointerGrab for ClickGrab { ) { // buffer the future focus, but maintain the current one self.pending_focus = focus; - handle.motion(location, self.current_focus.clone(), serial, time); + handle.motion(location, self.start_data.focus.clone(), serial, time); } fn button( &mut self, @@ -685,4 +715,7 @@ impl PointerGrab for ClickGrab { fn axis(&mut self, handle: &mut PointerInnerHandle<'_>, details: AxisFrame) { handle.axis(details); } + fn start_data(&self) -> &GrabStartData { + &self.start_data + } }