shell: Add tablet grabs

This commit is contained in:
Victoria Brekenfeld 2026-08-11 18:18:02 +02:00 • committed by Victoria Brekenfeld
parent ca9dd27350
commit 6467f79025
18 changed files with 2262 additions and 391 deletions

View file

@ -1,22 +1,34 @@
use smithay::{
backend::input::{InputTime, TabletToolDescriptor},
input::{
Seat, SeatHandler,
pointer::{
AxisFrame, ButtonEvent, Focus, GestureHoldBeginEvent, GestureHoldEndEvent,
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
GrabStartData as PointerGrabStartData, MotionEvent as PointerMotionEvent, PointerGrab,
PointerInnerHandle, RelativeMotionEvent,
AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, Focus,
GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent,
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData,
MotionEvent as PointerMotionEvent, PointerGrab, PointerInnerHandle,
RelativeMotionEvent,
},
tablet::{
TabletSeatHandler, TabletSeatTrait,
tool::{
AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent,
DownEvent as TabletDownEvent, GrabStartData as TabletGrabStartData,
MotionEvent as TabletMotionEvent, ProximityInEvent, ProximityOutEvent,
TabletToolGrab, TabletToolInnerHandle, UpEvent as TabletUpEvent,
},
},
touch::{
DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent,
OrientationEvent, ShapeEvent, TouchGrab, TouchInnerHandle, UpEvent,
DownEvent as TouchDownEvent, GrabStartData as TouchGrabStartData,
MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab,
TouchInnerHandle, UpEvent as TouchUpEvent,
},
},
utils::{Logical, Point, SERIAL_COUNTER, Serial},
};
use crate::state::State;
use crate::{shell::grabs::GrabType, state::State};
use super::GrabStartData;
@ -44,10 +56,15 @@ impl<G> DelayGrab<G> {
}
}
pub fn is_touch_grab(&self) -> bool {
match self.start_data {
GrabStartData::Touch(_) => true,
GrabStartData::Pointer(_) => false,
pub fn grab_type(&self) -> GrabType {
self.start_data.type_()
}
pub fn tool(&self) -> Option<&TabletToolDescriptor> {
if let GrabStartData::TabletTool { tool, .. } = &self.start_data {
Some(tool)
} else {
None
}
}
}
@ -92,7 +109,7 @@ impl<G: PointerGrab<State>> PointerGrab<State> for DelayGrab<G> {
&mut self,
data: &mut State,
handle: &mut PointerInnerHandle<'_, State>,
event: &ButtonEvent,
event: &PointerButtonEvent,
) {
handle.button(data, event);
if handle.current_pressed().is_empty() {
@ -104,7 +121,7 @@ impl<G: PointerGrab<State>> PointerGrab<State> for DelayGrab<G> {
&mut self,
data: &mut State,
handle: &mut PointerInnerHandle<'_, State>,
details: AxisFrame,
details: PointerAxisFrame,
) {
handle.axis(data, details);
}
@ -201,12 +218,17 @@ impl<G: TouchGrab<State>> TouchGrab<State> for DelayGrab<G> {
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
focus: Option<(<State as SeatHandler>::TouchFocus, Point<f64, Logical>)>,
event: &DownEvent,
event: &TouchDownEvent,
) {
handle.down(data, focus, event);
}
fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) {
fn up(
&mut self,
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
event: &TouchUpEvent,
) {
handle.up(data, event);
if event.slot == TouchGrab::start_data(self).slot {
@ -273,3 +295,110 @@ impl<G: TouchGrab<State>> TouchGrab<State> for DelayGrab<G> {
fn unset(&mut self, _data: &mut State) {}
}
impl<G: TabletToolGrab<State>> TabletToolGrab<State> for DelayGrab<G> {
fn start_data(&self) -> &TabletGrabStartData<State> {
match &self.start_data {
GrabStartData::TabletTool { data, .. } => data,
_ => unreachable!(),
}
}
fn proximity_out(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &ProximityOutEvent,
) {
handle.proximity_out(data, event);
}
fn motion(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
focus: Option<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &TabletMotionEvent,
) {
handle.motion(data, focus, event);
let distance = self.start_data.distance(event.location);
if distance >= 1.
&& let Some(factory) = self.grab_factory.take()
{
let seat = self.seat.clone();
let serial = self.serial.unwrap_or_else(|| SERIAL_COUNTER.next_serial());
let time = InputTime::now();
let Some(tool) = self.tool().cloned() else {
handle.unset_grab(self, data, serial, time, true);
return;
};
data.common.event_loop_handle.insert_idle(move |data| {
if let Some((grab, focus)) = factory(data) {
seat.tablet_seat()
.get_tool(&tool)
.unwrap()
.set_grab(data, grab, time, serial, focus);
}
});
}
}
fn down(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletDownEvent,
) {
handle.down(data, event)
}
fn up(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletUpEvent,
) {
handle.up(data, event);
handle.unset_grab(self, data, event.serial, event.time, false);
}
fn button(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletButtonEvent,
) {
handle.button(data, event);
}
fn axis(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
frame: TabletAxisFrame,
) {
handle.axis(data, frame)
}
fn frame(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
time: InputTime,
) {
handle.frame(data, time)
}
fn unset(&mut self, _data: &mut State) {}
fn proximity_in(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
focus: Option<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &ProximityInEvent,
) {
handle.proximity_in(data, focus, event);
}
}

View file

@ -1,7 +1,9 @@
use cosmic_settings_config::shortcuts::Action;
use smithay::{
backend::input::InputTime, input::pointer::MotionEvent,
reexports::wayland_server::protocol::wl_surface::WlSurface, utils::SERIAL_COUNTER,
backend::input::InputTime,
input::{pointer::MotionEvent, tablet::TabletSeatTrait},
reexports::wayland_server::protocol::wl_surface::WlSurface,
utils::SERIAL_COUNTER,
wayland::seat::WaylandFocus,
};
@ -11,7 +13,7 @@ use crate::{
shell::{
CosmicSurface, PointGlobalExt, Shell,
element::{CosmicMapped, CosmicWindow},
grabs::ReleaseMode,
grabs::{GrabType, ReleaseMode},
},
state::State,
utils::{prelude::SeatExt, screenshot::screenshot_window},
@ -353,19 +355,20 @@ pub fn window_items(
std::mem::drop(shell);
if let Some((grab, focus)) = res {
if grab.is_touch_grab() {
seat.get_touch().unwrap().set_grab(
state,
grab,
SERIAL_COUNTER.next_serial(),
)
} else {
seat.get_pointer().unwrap().set_grab(
state,
grab,
SERIAL_COUNTER.next_serial(),
focus,
);
let serial = SERIAL_COUNTER.next_serial();
match grab.grab_type() {
GrabType::Touch => {
seat.get_touch().unwrap().set_grab(state, grab, serial)
}
GrabType::Pointer => seat
.get_pointer()
.unwrap()
.set_grab(state, grab, serial, focus),
GrabType::TabletTool => seat
.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus),
}
}
}
@ -389,21 +392,29 @@ pub fn window_items(
std::mem::drop(shell);
if let Some(((target, loc), (grab, focus))) = res {
let serial = SERIAL_COUNTER.next_serial();
if grab.is_touch_grab() {
seat.get_touch().unwrap().set_grab(state, grab, serial);
} else {
let pointer = seat.get_pointer().unwrap();
pointer.motion(
state,
target,
&MotionEvent {
location: loc.as_logical().to_f64(),
serial,
time: InputTime::now(),
},
);
pointer.frame(state);
pointer.set_grab(state, grab, serial, focus);
match grab.grab_type() {
GrabType::Touch => {
seat.get_touch().unwrap().set_grab(state, grab, serial)
}
GrabType::TabletTool => seat
.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus),
GrabType::Pointer => {
let pointer = seat.get_pointer().unwrap();
pointer.motion(
state,
target,
&MotionEvent {
location: loc.as_logical().to_f64(),
serial,
time: InputTime::now(),
},
);
pointer.frame(state);
pointer.set_grab(state, grab, serial, focus);
}
}
}
});
@ -424,21 +435,30 @@ pub fn window_items(
std::mem::drop(shell);
if let Some(((target, loc), (grab, focus))) = res {
let serial = SERIAL_COUNTER.next_serial();
if grab.is_touch_grab() {
seat.get_touch().unwrap().set_grab(state, grab, serial);
} else {
let pointer = seat.get_pointer().unwrap();
pointer.motion(
state,
target,
&MotionEvent {
location: loc.as_logical().to_f64(),
serial,
time: InputTime::now(),
},
);
pointer.frame(state);
pointer.set_grab(state, grab, serial, focus);
match grab.grab_type() {
GrabType::Touch => {
seat.get_touch().unwrap().set_grab(state, grab, serial)
}
GrabType::Pointer => {
let pointer = seat.get_pointer().unwrap();
pointer.motion(
state,
target,
&MotionEvent {
location: loc.as_logical().to_f64(),
serial,
time: InputTime::now(),
},
);
pointer.frame(state);
pointer.set_grab(state, grab, serial, focus);
}
GrabType::TabletTool => {
seat.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus);
}
}
}
});
@ -459,21 +479,30 @@ pub fn window_items(
std::mem::drop(shell);
if let Some(((target, loc), (grab, focus))) = res {
let serial = SERIAL_COUNTER.next_serial();
if grab.is_touch_grab() {
seat.get_touch().unwrap().set_grab(state, grab, serial);
} else {
let pointer = seat.get_pointer().unwrap();
pointer.motion(
state,
target,
&MotionEvent {
location: loc.as_logical().to_f64(),
serial,
time: InputTime::now(),
},
);
pointer.frame(state);
pointer.set_grab(state, grab, serial, focus);
match grab.grab_type() {
GrabType::Touch => {
seat.get_touch().unwrap().set_grab(state, grab, serial)
}
GrabType::Pointer => {
let pointer = seat.get_pointer().unwrap();
pointer.motion(
state,
target,
&MotionEvent {
location: loc.as_logical().to_f64(),
serial,
time: InputTime::now(),
},
);
pointer.frame(state);
pointer.set_grab(state, grab, serial, focus);
}
GrabType::TabletTool => {
seat.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus);
}
}
}
});
@ -494,21 +523,29 @@ pub fn window_items(
std::mem::drop(shell);
if let Some(((target, loc), (grab, focus))) = res {
let serial = SERIAL_COUNTER.next_serial();
if grab.is_touch_grab() {
seat.get_touch().unwrap().set_grab(state, grab, serial);
} else {
let pointer = seat.get_pointer().unwrap();
pointer.motion(
state,
target,
&MotionEvent {
location: loc.as_logical().to_f64(),
serial,
time: InputTime::now(),
},
);
pointer.frame(state);
pointer.set_grab(state, grab, serial, focus);
match grab.grab_type() {
GrabType::Touch => {
seat.get_touch().unwrap().set_grab(state, grab, serial)
}
GrabType::Pointer => {
let pointer = seat.get_pointer().unwrap();
pointer.motion(
state,
target,
&MotionEvent {
location: loc.as_logical().to_f64(),
serial,
time: InputTime::now(),
},
);
pointer.frame(state);
pointer.set_grab(state, grab, serial, focus);
}
GrabType::TabletTool => seat
.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus),
}
}
});
@ -628,19 +665,20 @@ pub fn fullscreen_items(window: &CosmicSurface, config: &Config) -> impl Iterato
std::mem::drop(shell);
if let Some((grab, focus)) = res {
if grab.is_touch_grab() {
seat.get_touch().unwrap().set_grab(
state,
grab,
SERIAL_COUNTER.next_serial(),
)
} else {
seat.get_pointer().unwrap().set_grab(
state,
grab,
SERIAL_COUNTER.next_serial(),
focus,
);
let serial = SERIAL_COUNTER.next_serial();
match grab.grab_type() {
GrabType::Touch => {
seat.get_touch().unwrap().set_grab(state, grab, serial)
}
GrabType::Pointer => seat
.get_pointer()
.unwrap()
.set_grab(state, grab, serial, focus),
GrabType::TabletTool => seat
.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus),
}
}
}

View file

@ -19,22 +19,33 @@ use cosmic::{
};
use smithay::{
backend::{
input::{ButtonState, TouchSlot},
input::{ButtonState, InputTime, TabletToolDescriptor, TouchSlot},
renderer::ImportMem,
},
desktop::space::SpaceElement,
input::{
Seat,
pointer::{
AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent,
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
GrabStartData as PointerGrabStartData, MotionEvent as PointerMotionEvent, PointerGrab,
PointerInnerHandle, PointerTarget, RelativeMotionEvent,
AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent,
GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent,
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData,
MotionEvent as PointerMotionEvent, PointerGrab, PointerInnerHandle, PointerTarget,
RelativeMotionEvent,
},
tablet::{
TabletSeatHandler,
tool::{
AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent,
DownEvent as TabletDownEvent, GrabStartData as TabletGrabStartData,
MotionEvent as TabletMotionEvent, ProximityInEvent, ProximityOutEvent,
TabletToolGrab, TabletToolInnerHandle, TabletToolTarget, UpEvent as TabletUpEvent,
},
},
touch::{
DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent,
TouchGrab, TouchInnerHandle, TouchTarget, UpEvent,
DownEvent as TouchDownEvent, GrabStartData as TouchGrabStartData,
MotionEvent as TouchMotionEvent, TouchGrab, TouchInnerHandle, TouchTarget,
UpEvent as TouchUpEvent,
},
},
output::Output,
@ -43,7 +54,7 @@ use smithay::{
use crate::{
backend::render::element::AsGlowRenderer,
shell::{SeatExt, focus::target::PointerFocusTarget},
shell::{SeatExt, focus::target::PointerFocusTarget, grabs::GrabType},
state::State,
utils::{
iced::{IcedElement, IcedRenderElement, Program},
@ -350,6 +361,7 @@ impl Program for ContextMenu {
position,
pointer_entered: false,
touch_entered: None,
tablet_entered: None,
})
}
});
@ -508,6 +520,7 @@ pub struct Element {
position: Point<i32, Global>,
pointer_entered: bool,
touch_entered: Option<TouchSlot>,
tablet_entered: Option<TabletToolDescriptor>,
}
pub struct MenuGrab {
@ -516,6 +529,7 @@ pub struct MenuGrab {
seat: Seat<State>,
screen_space_relative: Option<Output>,
scale: Arc<Mutex<f64>>,
last_tablet_idx: Option<usize>,
}
impl PointerGrab<State> for MenuGrab {
@ -598,7 +612,7 @@ impl PointerGrab<State> for MenuGrab {
&mut self,
state: &mut State,
handle: &mut PointerInnerHandle<'_, State>,
event: &ButtonEvent,
event: &PointerButtonEvent,
) {
let any_entered = self
.elements
@ -632,7 +646,7 @@ impl PointerGrab<State> for MenuGrab {
&mut self,
state: &mut State,
handle: &mut PointerInnerHandle<'_, State>,
details: AxisFrame,
details: PointerAxisFrame,
) {
handle.axis(state, details);
}
@ -729,7 +743,7 @@ impl TouchGrab<State> for MenuGrab {
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
_focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &DownEvent,
event: &TouchDownEvent,
) {
{
let mut guard = self.elements.lock().unwrap();
@ -757,7 +771,7 @@ impl TouchGrab<State> for MenuGrab {
}) {
let element = &mut elements[i];
let new_event = DownEvent {
let new_event = TouchDownEvent {
slot: event.slot,
location: event_location - element.position.as_logical().to_f64(),
serial: event.serial,
@ -772,7 +786,12 @@ impl TouchGrab<State> for MenuGrab {
handle.down(data, None, event);
}
fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) {
fn up(
&mut self,
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
event: &TouchUpEvent,
) {
{
let elements = self.elements.lock().unwrap();
for element in elements.iter().filter(|elem| {
@ -848,6 +867,248 @@ impl TouchGrab<State> for MenuGrab {
fn unset(&mut self, _data: &mut State) {}
}
impl TabletToolGrab<State> for MenuGrab {
fn start_data(&self) -> &TabletGrabStartData<State> {
match &self.start_data {
GrabStartData::TabletTool { data, .. } => data,
_ => unreachable!(),
}
}
fn proximity_in(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
_focus: Option<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &ProximityInEvent,
) {
{
let location = if let Some(output) = self.screen_space_relative.as_ref() {
if data.common.shell.read().zoom_state().is_some() {
event
.location
.as_global()
.to_zoomed(output)
.to_global(output)
.as_logical()
} else {
event.location
}
} else {
event.location
};
let mut elements = self.elements.lock().unwrap();
if let Some(i) = elements.iter().position(|elem| {
let mut bbox = elem.iced.bbox();
bbox.loc = elem.position.as_logical();
bbox.contains(location.to_i32_floor())
}) {
let element = &mut elements[i];
let new_event = TabletMotionEvent {
location: location - element.position.as_logical().to_f64(),
serial: event.serial,
time: event.time,
};
TabletToolTarget::proximity_in(
&element.iced,
&self.seat,
data,
handle.descriptor(),
&handle.current_tablet(),
event.serial,
);
element.tablet_entered = Some(handle.descriptor().clone());
TabletToolTarget::motion(
&element.iced,
&self.seat,
data,
handle.descriptor(),
&new_event,
);
self.last_tablet_idx = Some(i);
}
}
handle.proximity_in(data, None, event);
}
fn proximity_out(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &ProximityOutEvent,
) {
{
let mut elements = self.elements.lock().unwrap();
for element in elements.iter_mut().filter(|elem| {
elem.tablet_entered
.as_ref()
.is_some_and(|tool| tool == handle.descriptor())
}) {
TabletToolTarget::proximity_out(
&element.iced,
&self.seat,
data,
handle.descriptor(),
);
element.tablet_entered.take();
}
self.last_tablet_idx.take();
}
handle.unset_grab(self, data, event.serial, event.time, true);
}
fn motion(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
_focus: Option<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &TabletMotionEvent,
) {
{
let location = if let Some(output) = self.screen_space_relative.as_ref() {
if data.common.shell.read().zoom_state().is_some() {
event
.location
.as_global()
.to_zoomed(output)
.to_global(output)
.as_logical()
} else {
event.location
}
} else {
event.location
};
let mut elements = self.elements.lock().unwrap();
if let Some(i) = elements.iter().position(|elem| {
let mut bbox = elem.iced.bbox();
bbox.loc = elem.position.as_logical();
bbox.contains(location.to_i32_floor())
}) {
let element = &mut elements[i];
let new_event = TabletMotionEvent {
location: location - element.position.as_logical().to_f64(),
serial: event.serial,
time: event.time,
};
if element.tablet_entered.is_none() {
TabletToolTarget::proximity_in(
&element.iced,
&self.seat,
data,
handle.descriptor(),
&handle.current_tablet(),
event.serial,
);
element.tablet_entered = Some(handle.descriptor().clone());
}
TabletToolTarget::motion(
&element.iced,
&self.seat,
data,
handle.descriptor(),
&new_event,
);
self.last_tablet_idx = Some(i);
} else {
elements
.iter_mut()
.filter(|element| element.tablet_entered.is_some())
.skip(1)
.for_each(|element| {
TabletToolTarget::proximity_out(
&element.iced,
&self.seat,
data,
handle.descriptor(),
);
});
self.last_tablet_idx.take();
}
}
handle.motion(data, None, event);
}
fn down(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletDownEvent,
) {
let mut guard = self.elements.lock().unwrap();
let elements = &mut *guard;
if let Some(elem) = self.last_tablet_idx.and_then(|i| elements.get_mut(i))
&& elem
.tablet_entered
.as_ref()
.is_some_and(|desc| desc == handle.descriptor())
{
TabletToolTarget::down(&elem.iced, &self.seat, data, handle.descriptor(), event);
} else {
handle.down(data, event);
}
}
fn up(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletUpEvent,
) {
let mut guard = self.elements.lock().unwrap();
let elements = &mut *guard;
if let Some(elem) = self.last_tablet_idx.and_then(|i| elements.get_mut(i))
&& elem
.tablet_entered
.as_ref()
.is_some_and(|desc| desc == handle.descriptor())
{
TabletToolTarget::up(&elem.iced, &self.seat, data, handle.descriptor(), event);
} else {
handle.up(data, event);
}
}
fn button(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletButtonEvent,
) {
handle.button(data, event);
}
fn axis(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
frame: TabletAxisFrame,
) {
handle.axis(data, frame);
}
fn frame(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
time: InputTime,
) {
handle.frame(data, time);
}
fn unset(&mut self, _data: &mut State) {}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MenuAlignment {
pub x: AxisAlignment,
@ -1051,6 +1312,7 @@ impl MenuGrab {
position,
pointer_entered: false,
touch_entered: None,
tablet_entered: None,
}]));
let scale = Arc::new(Mutex::new(screen_space_relative.unwrap_or(1.)));
@ -1075,6 +1337,7 @@ impl MenuGrab {
seat: seat.clone(),
screen_space_relative,
scale,
last_tablet_idx: None,
}
}
@ -1085,10 +1348,15 @@ impl MenuGrab {
}
}
pub fn is_touch_grab(&self) -> bool {
match self.start_data {
GrabStartData::Touch(_) => true,
GrabStartData::Pointer(_) => false,
pub fn grab_type(&self) -> GrabType {
self.start_data.type_()
}
pub fn tool(&self) -> Option<&TabletToolDescriptor> {
if let GrabStartData::TabletTool { tool, .. } = &self.start_data {
Some(tool)
} else {
None
}
}
}

View file

@ -1,18 +1,26 @@
use calloop::LoopHandle;
use cosmic_settings_config::shortcuts;
use smithay::{
backend::input::{InputTime, TabletToolDescriptor},
input::{
Seat,
pointer::{
AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent,
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle,
RelativeMotionEvent,
AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent,
GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent,
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData,
MotionEvent, PointerGrab, PointerInnerHandle, RelativeMotionEvent,
},
tablet::tool::{
AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent,
DownEvent as TabletDownEvent, GrabStartData as TabletGrabStartData,
MotionEvent as TabletMotionEvent, ProximityOutEvent, TabletToolGrab,
TabletToolInnerHandle, UpEvent as TabletUpEvent,
},
touch::{
DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent,
OrientationEvent, ShapeEvent, TouchGrab, TouchInnerHandle, UpEvent,
DownEvent as TouchDownEvent, GrabStartData as TouchGrabStartData,
MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab,
TouchInnerHandle, UpEvent as TouchUpEvent,
},
},
output::Output,
@ -39,6 +47,17 @@ use super::{
pub enum GrabStartData {
Touch(TouchGrabStartData<State>),
Pointer(PointerGrabStartData<State>),
TabletTool {
tool: TabletToolDescriptor,
data: TabletGrabStartData<State>,
},
}
#[derive(Debug, Clone)]
pub enum GrabType {
Touch,
Pointer,
TabletTool,
}
impl GrabStartData {
@ -46,6 +65,7 @@ impl GrabStartData {
match self {
Self::Touch(touch) => touch.focus.as_ref(),
Self::Pointer(pointer) => pointer.focus.as_ref(),
Self::TabletTool { data, .. } => data.focus.as_ref(),
}
}
@ -53,6 +73,7 @@ impl GrabStartData {
match self {
Self::Touch(touch) => touch.focus = focus,
Self::Pointer(pointer) => pointer.focus = focus,
Self::TabletTool { data, .. } => data.focus = focus,
}
}
@ -60,6 +81,7 @@ impl GrabStartData {
match self {
Self::Touch(touch) => touch.location,
Self::Pointer(pointer) => pointer.location,
Self::TabletTool { data, .. } => data.location,
}
}
@ -67,6 +89,7 @@ impl GrabStartData {
match self {
Self::Touch(touch) => touch.location = location,
Self::Pointer(pointer) => pointer.location = location,
Self::TabletTool { data, .. } => data.location = location,
}
}
@ -76,6 +99,14 @@ impl GrabStartData {
((new.x - old.x).powi(2) + (new.y - old.y).powi(2)).sqrt()
}
pub fn type_(&self) -> GrabType {
match self {
Self::Pointer(_) => GrabType::Pointer,
Self::Touch(_) => GrabType::Touch,
Self::TabletTool { .. } => GrabType::TabletTool,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -203,10 +234,17 @@ impl From<ResizeForkGrab> for ResizeGrab {
}
impl ResizeGrab {
pub fn is_touch_grab(&self) -> bool {
pub fn grab_type(&self) -> GrabType {
match self {
ResizeGrab::Floating(grab) => grab.is_touch_grab(),
ResizeGrab::Tiling(grab) => grab.is_touch_grab(),
ResizeGrab::Floating(grab) => grab.grab_type(),
ResizeGrab::Tiling(grab) => grab.grab_type(),
}
}
pub fn tool(&self) -> Option<&TabletToolDescriptor> {
match self {
ResizeGrab::Floating(grab) => grab.tool(),
ResizeGrab::Tiling(grab) => grab.tool(),
}
}
}
@ -242,11 +280,11 @@ impl PointerGrab<State> for ResizeGrab {
&mut self,
data: &mut State,
handle: &mut PointerInnerHandle<'_, State>,
event: &ButtonEvent,
event: &PointerButtonEvent,
) {
match self {
ResizeGrab::Floating(grab) => grab.button(data, handle, event),
ResizeGrab::Tiling(grab) => grab.button(data, handle, event),
ResizeGrab::Floating(grab) => PointerGrab::button(grab, data, handle, event),
ResizeGrab::Tiling(grab) => PointerGrab::button(grab, data, handle, event),
}
}
@ -254,11 +292,11 @@ impl PointerGrab<State> for ResizeGrab {
&mut self,
data: &mut State,
handle: &mut PointerInnerHandle<'_, State>,
details: AxisFrame,
details: PointerAxisFrame,
) {
match self {
ResizeGrab::Floating(grab) => grab.axis(data, handle, details),
ResizeGrab::Tiling(grab) => grab.axis(data, handle, details),
ResizeGrab::Floating(grab) => PointerGrab::axis(grab, data, handle, details),
ResizeGrab::Tiling(grab) => PointerGrab::axis(grab, data, handle, details),
}
}
@ -386,7 +424,7 @@ impl TouchGrab<State> for ResizeGrab {
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &DownEvent,
event: &TouchDownEvent,
) {
match self {
ResizeGrab::Floating(grab) => TouchGrab::down(grab, data, handle, focus, event),
@ -394,7 +432,12 @@ impl TouchGrab<State> for ResizeGrab {
}
}
fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) {
fn up(
&mut self,
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
event: &TouchUpEvent,
) {
match self {
ResizeGrab::Floating(grab) => TouchGrab::up(grab, data, handle, event),
ResizeGrab::Tiling(grab) => TouchGrab::up(grab, data, handle, event),
@ -467,6 +510,107 @@ impl TouchGrab<State> for ResizeGrab {
}
}
impl TabletToolGrab<State> for ResizeGrab {
fn down(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletDownEvent,
) {
match self {
ResizeGrab::Floating(grab) => TabletToolGrab::down(grab, data, handle, event),
ResizeGrab::Tiling(grab) => TabletToolGrab::down(grab, data, handle, event),
}
}
fn up(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletUpEvent,
) {
match self {
ResizeGrab::Floating(grab) => TabletToolGrab::up(grab, data, handle, event),
ResizeGrab::Tiling(grab) => TabletToolGrab::up(grab, data, handle, event),
}
}
fn motion(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &TabletMotionEvent,
) {
match self {
ResizeGrab::Floating(grab) => TabletToolGrab::motion(grab, data, handle, focus, event),
ResizeGrab::Tiling(grab) => TabletToolGrab::motion(grab, data, handle, focus, event),
}
}
fn frame(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
serial: InputTime,
) {
match self {
ResizeGrab::Floating(grab) => TabletToolGrab::frame(grab, data, handle, serial),
ResizeGrab::Tiling(grab) => TabletToolGrab::frame(grab, data, handle, serial),
}
}
fn button(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletButtonEvent,
) {
match self {
ResizeGrab::Floating(grab) => TabletToolGrab::button(grab, data, handle, event),
ResizeGrab::Tiling(grab) => TabletToolGrab::button(grab, data, handle, event),
}
}
fn axis(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
details: TabletAxisFrame,
) {
match self {
ResizeGrab::Floating(grab) => TabletToolGrab::axis(grab, data, handle, details),
ResizeGrab::Tiling(grab) => TabletToolGrab::axis(grab, data, handle, details),
}
}
fn proximity_out(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &ProximityOutEvent,
) {
match self {
ResizeGrab::Floating(grab) => TabletToolGrab::proximity_out(grab, data, handle, event),
ResizeGrab::Tiling(grab) => TabletToolGrab::proximity_out(grab, data, handle, event),
}
}
fn start_data(&self) -> &TabletGrabStartData<State> {
match self {
ResizeGrab::Floating(grab) => TabletToolGrab::start_data(grab),
ResizeGrab::Tiling(grab) => TabletToolGrab::start_data(grab),
}
}
fn unset(&mut self, data: &mut State) {
match self {
ResizeGrab::Floating(grab) => TabletToolGrab::unset(grab, data),
ResizeGrab::Tiling(grab) => TabletToolGrab::unset(grab, data),
}
}
}
pub enum MoveGrab {
Move(moving::MoveGrab),
Delayed(delay::DelayGrab<MoveGrab>),
@ -536,10 +680,17 @@ impl MoveGrab {
}
}
pub fn is_touch_grab(&self) -> bool {
pub fn grab_type(&self) -> GrabType {
match self {
MoveGrab::Move(m) => m.is_touch_grab(),
MoveGrab::Delayed(d) => d.is_touch_grab(),
MoveGrab::Move(m) => m.grab_type(),
MoveGrab::Delayed(d) => d.grab_type(),
}
}
pub fn tool(&self) -> Option<&TabletToolDescriptor> {
match self {
MoveGrab::Move(m) => m.tool(),
MoveGrab::Delayed(d) => d.tool(),
}
}
}
@ -574,11 +725,11 @@ impl PointerGrab<State> for MoveGrab {
&mut self,
data: &mut State,
handle: &mut PointerInnerHandle<'_, State>,
event: &ButtonEvent,
event: &PointerButtonEvent,
) {
match self {
MoveGrab::Move(grab) => grab.button(data, handle, event),
MoveGrab::Delayed(grab) => grab.button(data, handle, event),
MoveGrab::Move(grab) => PointerGrab::button(grab, data, handle, event),
MoveGrab::Delayed(grab) => PointerGrab::button(grab, data, handle, event),
}
}
@ -586,11 +737,11 @@ impl PointerGrab<State> for MoveGrab {
&mut self,
data: &mut State,
handle: &mut PointerInnerHandle<'_, State>,
details: AxisFrame,
details: PointerAxisFrame,
) {
match self {
MoveGrab::Move(grab) => grab.axis(data, handle, details),
MoveGrab::Delayed(grab) => grab.axis(data, handle, details),
MoveGrab::Move(grab) => PointerGrab::axis(grab, data, handle, details),
MoveGrab::Delayed(grab) => PointerGrab::axis(grab, data, handle, details),
}
}
@ -718,7 +869,7 @@ impl TouchGrab<State> for MoveGrab {
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &DownEvent,
event: &TouchDownEvent,
) {
match self {
MoveGrab::Move(grab) => TouchGrab::down(grab, data, handle, focus, event),
@ -726,7 +877,12 @@ impl TouchGrab<State> for MoveGrab {
}
}
fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) {
fn up(
&mut self,
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
event: &TouchUpEvent,
) {
match self {
MoveGrab::Move(grab) => TouchGrab::up(grab, data, handle, event),
MoveGrab::Delayed(grab) => TouchGrab::up(grab, data, handle, event),
@ -798,3 +954,104 @@ impl TouchGrab<State> for MoveGrab {
}
}
}
impl TabletToolGrab<State> for MoveGrab {
fn down(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletDownEvent,
) {
match self {
MoveGrab::Move(grab) => TabletToolGrab::down(grab, data, handle, event),
MoveGrab::Delayed(grab) => TabletToolGrab::down(grab, data, handle, event),
}
}
fn up(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletUpEvent,
) {
match self {
MoveGrab::Move(grab) => TabletToolGrab::up(grab, data, handle, event),
MoveGrab::Delayed(grab) => TabletToolGrab::up(grab, data, handle, event),
}
}
fn motion(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &TabletMotionEvent,
) {
match self {
MoveGrab::Move(grab) => TabletToolGrab::motion(grab, data, handle, focus, event),
MoveGrab::Delayed(grab) => TabletToolGrab::motion(grab, data, handle, focus, event),
}
}
fn frame(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
serial: InputTime,
) {
match self {
MoveGrab::Move(grab) => TabletToolGrab::frame(grab, data, handle, serial),
MoveGrab::Delayed(grab) => TabletToolGrab::frame(grab, data, handle, serial),
}
}
fn button(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletButtonEvent,
) {
match self {
MoveGrab::Move(grab) => TabletToolGrab::button(grab, data, handle, event),
MoveGrab::Delayed(grab) => TabletToolGrab::button(grab, data, handle, event),
}
}
fn axis(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
details: TabletAxisFrame,
) {
match self {
MoveGrab::Move(grab) => TabletToolGrab::axis(grab, data, handle, details),
MoveGrab::Delayed(grab) => TabletToolGrab::axis(grab, data, handle, details),
}
}
fn proximity_out(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &ProximityOutEvent,
) {
match self {
MoveGrab::Move(grab) => TabletToolGrab::proximity_out(grab, data, handle, event),
MoveGrab::Delayed(grab) => TabletToolGrab::proximity_out(grab, data, handle, event),
}
}
fn start_data(&self) -> &TabletGrabStartData<State> {
match self {
MoveGrab::Move(grab) => TabletToolGrab::start_data(grab),
MoveGrab::Delayed(grab) => TabletToolGrab::start_data(grab),
}
}
fn unset(&mut self, data: &mut State) {
match self {
MoveGrab::Move(grab) => TabletToolGrab::unset(grab, data),
MoveGrab::Delayed(grab) => TabletToolGrab::unset(grab, data),
}
}
}

View file

@ -8,6 +8,7 @@ use crate::{
CosmicMapped, CosmicSurface, Direction, ManagedLayer,
element::{CosmicMappedRenderElement, stack_hover::StackHover},
focus::target::{KeyboardFocusTarget, PointerFocusTarget},
grabs::GrabType,
layout::floating::TiledCorners,
},
utils::prelude::*,
@ -20,7 +21,7 @@ use smallvec::SmallVec;
use smithay::{
backend::{
drm::DrmNode,
input::{ButtonState, InputTime},
input::{ButtonState, InputTime, TabletToolDescriptor},
renderer::{
ImportAll, ImportMem,
element::{RenderElement, utils::RescaleRenderElement},
@ -30,13 +31,27 @@ use smithay::{
input::{
Seat,
pointer::{
AxisFrame, ButtonEvent, CursorIcon, GestureHoldBeginEvent, GestureHoldEndEvent,
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle,
AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorIcon,
GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent,
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData,
MotionEvent as PointerMotionEvent, PointerGrab, PointerInnerHandle,
RelativeMotionEvent,
},
touch::{self, GrabStartData as TouchGrabStartData, TouchGrab, TouchInnerHandle},
tablet::{
TabletSeatHandler,
tool::{
AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent,
DownEvent as TabletDownEvent, GrabStartData as TabletGrabStartData,
MotionEvent as TabletMotionEvent, ProximityInEvent, ProximityOutEvent,
TabletToolGrab, TabletToolInnerHandle, UpEvent as TabletUpEvent,
},
},
touch::{
DownEvent as TouchDownEvent, GrabStartData as TouchGrabStartData,
MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab,
TouchInnerHandle, UpEvent as TouchUpEvent,
},
},
output::Output,
utils::{IsAlive, Logical, Point, Rectangle, SERIAL_COUNTER, Scale},
@ -503,7 +518,7 @@ impl PointerGrab<State> for MoveGrab {
state: &mut State,
handle: &mut PointerInnerHandle<'_, State>,
_focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &MotionEvent,
event: &PointerMotionEvent,
) {
self.update_location(state, event.location);
@ -529,7 +544,7 @@ impl PointerGrab<State> for MoveGrab {
&mut self,
state: &mut State,
handle: &mut PointerInnerHandle<'_, State>,
event: &ButtonEvent,
event: &PointerButtonEvent,
) {
handle.button(state, event);
match self.release {
@ -550,7 +565,7 @@ impl PointerGrab<State> for MoveGrab {
&mut self,
state: &mut State,
handle: &mut PointerInnerHandle<'_, State>,
details: AxisFrame,
details: PointerAxisFrame,
) {
handle.axis(state, details);
}
@ -647,7 +662,7 @@ impl TouchGrab<State> for MoveGrab {
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
_focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &touch::DownEvent,
event: &TouchDownEvent,
) {
handle.down(data, None, event)
}
@ -656,7 +671,7 @@ impl TouchGrab<State> for MoveGrab {
&mut self,
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
event: &touch::UpEvent,
event: &TouchUpEvent,
) {
if event.slot == <Self as TouchGrab<State>>::start_data(self).slot {
handle.unset_grab(self, data);
@ -670,7 +685,7 @@ impl TouchGrab<State> for MoveGrab {
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
_focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &touch::MotionEvent,
event: &TouchMotionEvent,
) {
if event.slot == <Self as TouchGrab<State>>::start_data(self).slot {
self.update_location(data, event.location);
@ -691,7 +706,7 @@ impl TouchGrab<State> for MoveGrab {
&mut self,
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
event: &touch::ShapeEvent,
event: &ShapeEvent,
) {
handle.shape(data, event)
}
@ -700,7 +715,7 @@ impl TouchGrab<State> for MoveGrab {
&mut self,
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
event: &touch::OrientationEvent,
event: &OrientationEvent,
) {
handle.orientation(data, event)
}
@ -715,6 +730,100 @@ impl TouchGrab<State> for MoveGrab {
fn unset(&mut self, _data: &mut State) {}
}
impl TabletToolGrab<State> for MoveGrab {
fn start_data(&self) -> &TabletGrabStartData<State> {
match &self.start_data {
GrabStartData::TabletTool { data, .. } => data,
_ => unreachable!(),
}
}
fn proximity_out(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &ProximityOutEvent,
) {
handle.proximity_out(data, event);
}
fn motion(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
_focus: Option<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &TabletMotionEvent,
) {
handle.motion(data, None, event);
self.update_location(data, event.location);
if !self.window.alive() {
handle.unset_grab(self, data, event.serial, event.time, true);
}
}
fn down(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletDownEvent,
) {
handle.down(data, event)
}
fn up(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletUpEvent,
) {
if self.tool().is_some_and(|tool| tool == handle.descriptor()) {
handle.unset_grab(self, data, event.serial, event.time, false);
}
handle.up(data, event);
}
fn button(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletButtonEvent,
) {
handle.button(data, event)
}
fn axis(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
frame: TabletAxisFrame,
) {
handle.axis(data, frame)
}
fn frame(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
time: InputTime,
) {
handle.frame(data, time)
}
fn proximity_in(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
focus: Option<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &ProximityInEvent,
) {
handle.proximity_in(data, focus, event);
}
fn unset(&mut self, _data: &mut State) {}
}
impl MoveGrab {
pub fn new(
start_data: GrabStartData,
@ -778,10 +887,15 @@ impl MoveGrab {
self.previous == ManagedLayer::Tiling
}
pub fn is_touch_grab(&self) -> bool {
match self.start_data {
GrabStartData::Touch(_) => true,
GrabStartData::Pointer(_) => false,
pub fn grab_type(&self) -> GrabType {
self.start_data.type_()
}
pub fn tool(&self) -> Option<&TabletToolDescriptor> {
if let GrabStartData::TabletTool { tool, .. } = &self.start_data {
Some(tool)
} else {
None
}
}
}
@ -953,7 +1067,7 @@ impl Drop for MoveGrab {
position.as_logical().to_f64() - window.geometry().loc.to_f64()
+ offset,
)),
&MotionEvent {
&PointerMotionEvent {
location: pointer.current_location(),
serial,
time: InputTime::now(),