shell: Add DelayGrab for client initiated move requests
This commit is contained in:
parent
25904ca189
commit
123add9dee
3 changed files with 664 additions and 3 deletions
285
src/shell/grabs/delay.rs
Normal file
285
src/shell/grabs/delay.rs
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
use smithay::{
|
||||
input::{
|
||||
Seat, SeatHandler,
|
||||
pointer::{
|
||||
AxisFrame, ButtonEvent, Focus, GestureHoldBeginEvent, GestureHoldEndEvent,
|
||||
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
|
||||
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
|
||||
GrabStartData as PointerGrabStartData, MotionEvent as PointerMotionEvent, PointerGrab,
|
||||
PointerInnerHandle, RelativeMotionEvent,
|
||||
},
|
||||
touch::{
|
||||
DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent,
|
||||
OrientationEvent, ShapeEvent, TouchGrab, TouchInnerHandle, UpEvent,
|
||||
},
|
||||
},
|
||||
utils::{Logical, Point, SERIAL_COUNTER, Serial},
|
||||
};
|
||||
|
||||
use crate::state::State;
|
||||
|
||||
use super::GrabStartData;
|
||||
|
||||
pub struct DelayGrab<G> {
|
||||
grab_factory: Option<Box<dyn FnOnce(&mut State) -> Option<(G, Focus)>>>,
|
||||
seat: Seat<State>,
|
||||
serial: Option<Serial>,
|
||||
start_data: GrabStartData,
|
||||
}
|
||||
|
||||
unsafe impl<G> Send for DelayGrab<G> {}
|
||||
|
||||
impl<G> DelayGrab<G> {
|
||||
pub fn new(
|
||||
factory: impl FnOnce(&mut State) -> Option<(G, Focus)> + 'static,
|
||||
seat: Seat<State>,
|
||||
serial: Option<Serial>,
|
||||
start_data: GrabStartData,
|
||||
) -> Self {
|
||||
DelayGrab {
|
||||
grab_factory: Some(Box::new(factory)),
|
||||
seat,
|
||||
serial,
|
||||
start_data,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_touch_grab(&self) -> bool {
|
||||
match self.start_data {
|
||||
GrabStartData::Touch(_) => true,
|
||||
GrabStartData::Pointer(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: PointerGrab<State>> PointerGrab<State> for DelayGrab<G> {
|
||||
fn motion(
|
||||
&mut self,
|
||||
data: &mut State,
|
||||
handle: &mut PointerInnerHandle<'_, State>,
|
||||
focus: Option<(<State as SeatHandler>::PointerFocus, Point<f64, Logical>)>,
|
||||
event: &PointerMotionEvent,
|
||||
) {
|
||||
handle.motion(data, focus, event);
|
||||
|
||||
let distance = self.start_data.distance(event.location);
|
||||
if distance >= 1. {
|
||||
if let Some(factory) = self.grab_factory.take() {
|
||||
let serial = self.serial.unwrap_or(event.serial);
|
||||
let seat = self.seat.clone();
|
||||
data.common.event_loop_handle.insert_idle(move |data| {
|
||||
if let Some((grab, focus)) = factory(data) {
|
||||
seat.get_pointer()
|
||||
.unwrap()
|
||||
.set_grab(data, grab, serial, focus);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn relative_motion(
|
||||
&mut self,
|
||||
data: &mut State,
|
||||
handle: &mut PointerInnerHandle<'_, State>,
|
||||
focus: Option<(<State as SeatHandler>::PointerFocus, Point<f64, Logical>)>,
|
||||
event: &RelativeMotionEvent,
|
||||
) {
|
||||
handle.relative_motion(data, focus, event);
|
||||
}
|
||||
|
||||
fn button(
|
||||
&mut self,
|
||||
data: &mut State,
|
||||
handle: &mut PointerInnerHandle<'_, State>,
|
||||
event: &ButtonEvent,
|
||||
) {
|
||||
handle.button(data, event);
|
||||
if handle.current_pressed().is_empty() {
|
||||
handle.unset_grab(self, data, event.serial, event.time, true);
|
||||
}
|
||||
}
|
||||
|
||||
fn axis(
|
||||
&mut self,
|
||||
data: &mut State,
|
||||
handle: &mut PointerInnerHandle<'_, State>,
|
||||
details: AxisFrame,
|
||||
) {
|
||||
handle.axis(data, details);
|
||||
}
|
||||
|
||||
fn frame(&mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>) {
|
||||
handle.frame(data);
|
||||
}
|
||||
|
||||
fn gesture_swipe_begin(
|
||||
&mut self,
|
||||
data: &mut State,
|
||||
handle: &mut PointerInnerHandle<'_, State>,
|
||||
event: &GestureSwipeBeginEvent,
|
||||
) {
|
||||
handle.gesture_swipe_begin(data, event);
|
||||
}
|
||||
|
||||
fn gesture_swipe_update(
|
||||
&mut self,
|
||||
data: &mut State,
|
||||
handle: &mut PointerInnerHandle<'_, State>,
|
||||
event: &GestureSwipeUpdateEvent,
|
||||
) {
|
||||
handle.gesture_swipe_update(data, event);
|
||||
}
|
||||
|
||||
fn gesture_swipe_end(
|
||||
&mut self,
|
||||
data: &mut State,
|
||||
handle: &mut PointerInnerHandle<'_, State>,
|
||||
event: &GestureSwipeEndEvent,
|
||||
) {
|
||||
handle.gesture_swipe_end(data, event);
|
||||
}
|
||||
|
||||
fn gesture_pinch_begin(
|
||||
&mut self,
|
||||
data: &mut State,
|
||||
handle: &mut PointerInnerHandle<'_, State>,
|
||||
event: &GesturePinchBeginEvent,
|
||||
) {
|
||||
handle.gesture_pinch_begin(data, event);
|
||||
}
|
||||
|
||||
fn gesture_pinch_update(
|
||||
&mut self,
|
||||
data: &mut State,
|
||||
handle: &mut PointerInnerHandle<'_, State>,
|
||||
event: &GesturePinchUpdateEvent,
|
||||
) {
|
||||
handle.gesture_pinch_update(data, event);
|
||||
}
|
||||
|
||||
fn gesture_pinch_end(
|
||||
&mut self,
|
||||
data: &mut State,
|
||||
handle: &mut PointerInnerHandle<'_, State>,
|
||||
event: &GesturePinchEndEvent,
|
||||
) {
|
||||
handle.gesture_pinch_end(data, event);
|
||||
}
|
||||
|
||||
fn gesture_hold_begin(
|
||||
&mut self,
|
||||
data: &mut State,
|
||||
handle: &mut PointerInnerHandle<'_, State>,
|
||||
event: &GestureHoldBeginEvent,
|
||||
) {
|
||||
handle.gesture_hold_begin(data, event);
|
||||
}
|
||||
|
||||
fn gesture_hold_end(
|
||||
&mut self,
|
||||
data: &mut State,
|
||||
handle: &mut PointerInnerHandle<'_, State>,
|
||||
event: &GestureHoldEndEvent,
|
||||
) {
|
||||
handle.gesture_hold_end(data, event);
|
||||
}
|
||||
|
||||
fn start_data(&self) -> &PointerGrabStartData<State> {
|
||||
match &self.start_data {
|
||||
GrabStartData::Pointer(start_data) => start_data,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn unset(&mut self, _data: &mut State) {}
|
||||
}
|
||||
|
||||
impl<G: TouchGrab<State>> TouchGrab<State> for DelayGrab<G> {
|
||||
fn down(
|
||||
&mut self,
|
||||
data: &mut State,
|
||||
handle: &mut TouchInnerHandle<'_, State>,
|
||||
focus: Option<(<State as SeatHandler>::TouchFocus, Point<f64, Logical>)>,
|
||||
event: &DownEvent,
|
||||
seq: Serial,
|
||||
) {
|
||||
handle.down(data, focus, event, seq);
|
||||
}
|
||||
|
||||
fn up(
|
||||
&mut self,
|
||||
data: &mut State,
|
||||
handle: &mut TouchInnerHandle<'_, State>,
|
||||
event: &UpEvent,
|
||||
seq: Serial,
|
||||
) {
|
||||
handle.up(data, event, seq);
|
||||
|
||||
if event.slot == TouchGrab::start_data(self).slot {
|
||||
handle.unset_grab(self, data);
|
||||
}
|
||||
}
|
||||
|
||||
fn motion(
|
||||
&mut self,
|
||||
data: &mut State,
|
||||
handle: &mut TouchInnerHandle<'_, State>,
|
||||
focus: Option<(<State as SeatHandler>::TouchFocus, Point<f64, Logical>)>,
|
||||
event: &TouchMotionEvent,
|
||||
seq: Serial,
|
||||
) {
|
||||
handle.motion(data, focus, event, seq);
|
||||
|
||||
let distance = self.start_data.distance(event.location);
|
||||
if distance >= 1. {
|
||||
if let Some(factory) = self.grab_factory.take() {
|
||||
let seat = self.seat.clone();
|
||||
let serial = self.serial.unwrap_or_else(|| SERIAL_COUNTER.next_serial());
|
||||
data.common.event_loop_handle.insert_idle(move |data| {
|
||||
if let Some((grab, _)) = factory(data) {
|
||||
seat.get_touch().unwrap().set_grab(data, grab, serial);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn frame(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, seq: Serial) {
|
||||
handle.frame(data, seq)
|
||||
}
|
||||
|
||||
fn cancel(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, seq: Serial) {
|
||||
handle.cancel(data, seq);
|
||||
handle.unset_grab(self, data);
|
||||
}
|
||||
|
||||
fn shape(
|
||||
&mut self,
|
||||
data: &mut State,
|
||||
handle: &mut TouchInnerHandle<'_, State>,
|
||||
event: &ShapeEvent,
|
||||
seq: Serial,
|
||||
) {
|
||||
handle.shape(data, event, seq)
|
||||
}
|
||||
|
||||
fn orientation(
|
||||
&mut self,
|
||||
data: &mut State,
|
||||
handle: &mut TouchInnerHandle<'_, State>,
|
||||
event: &OrientationEvent,
|
||||
seq: Serial,
|
||||
) {
|
||||
handle.orientation(data, event, seq);
|
||||
}
|
||||
|
||||
fn start_data(&self) -> &TouchGrabStartData<State> {
|
||||
match &self.start_data {
|
||||
GrabStartData::Touch(start_data) => start_data,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn unset(&mut self, _data: &mut State) {}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue