From 6467f79025e2ffc32ed7df659c597beb4baa08b2 Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Tue, 11 Aug 2026 18:18:02 +0200 Subject: [PATCH] shell: Add tablet grabs --- src/input/mod.rs | 70 ++--- src/shell/element/stack.rs | 198 +++++++++++--- src/shell/element/window.rs | 153 +++++++++-- src/shell/focus/target.rs | 132 ++++++++- src/shell/grabs/delay.rs | 161 +++++++++-- src/shell/grabs/menu/default.rs | 216 +++++++++------ src/shell/grabs/menu/mod.rs | 304 +++++++++++++++++++-- src/shell/grabs/mod.rs | 315 ++++++++++++++++++++-- src/shell/grabs/moving.rs | 152 +++++++++-- src/shell/layout/floating/grabs/resize.rs | 150 +++++++++-- src/shell/layout/tiling/grabs/resize.rs | 284 ++++++++++++++++--- src/shell/layout/tiling/mod.rs | 20 +- src/shell/mod.rs | 12 +- src/shell/zoom.rs | 217 +++++++++++++-- src/utils/iced/mod.rs | 166 +++++++++++- src/wayland/handlers/tablet_manager.rs | 6 +- src/wayland/handlers/xdg_shell/mod.rs | 39 ++- src/xwayland.rs | 58 ++-- 18 files changed, 2262 insertions(+), 391 deletions(-) diff --git a/src/input/mod.rs b/src/input/mod.rs index 0228d3cb..cbf99cae 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -52,10 +52,11 @@ use smithay::{ keyboard::KeyboardHandle, keyboard::{FilterResult, KeyboardSource, KeysymHandle, ModifiersState}, pointer::{ - AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, - PointerGrab, PointerHandle, RelativeMotionEvent, + AxisFrame, ButtonEvent as PointerButtonEvent, GestureHoldBeginEvent, + GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchEndEvent, + GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, + GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, PointerGrab, PointerHandle, + RelativeMotionEvent, }, tablet::{TabletDescriptor, TabletSeatTrait, tool}, touch::{DownEvent, MotionEvent as TouchMotionEvent, UpEvent}, @@ -326,7 +327,7 @@ impl State { } InputEvent::PointerMotion { event, .. } => { - use smithay::backend::input::PointerMotionEvent; + use smithay::backend::input::PointerMotionEvent as _; let shell = self.common.shell.write(); if let Some(seat) = shell @@ -639,7 +640,7 @@ impl State { ptr.motion( self, under, - &MotionEvent { + &PointerMotionEvent { location: position.as_logical(), serial, time: event.time(), @@ -754,7 +755,7 @@ impl State { ptr.motion( self, under, - &MotionEvent { + &PointerMotionEvent { location: position.as_logical(), serial, time: event.time(), @@ -781,9 +782,8 @@ impl State { } } InputEvent::PointerButton { event, .. } => { - use smithay::backend::input::{ButtonState, PointerButtonEvent}; + use smithay::backend::input::{ButtonState, PointerButtonEvent as _}; - // let Some(seat) = self .common .shell @@ -857,7 +857,7 @@ impl State { && !shortcuts_inhibited { let seat_clone = seat.clone(); - let mouse_button = PointerButtonEvent::button(&event); + let mouse_button = event.button(); let mut supress_button = || { // If the logo is held then the pointer event is @@ -1017,7 +1017,7 @@ impl State { if pass_event { ptr.button( self, - &ButtonEvent { + &PointerButtonEvent { button, state: event.state(), serial, @@ -1597,7 +1597,7 @@ impl State { pointer.motion( self, under.clone(), - &MotionEvent { + &PointerMotionEvent { location: position.as_logical(), serial: SERIAL_COUNTER.next_serial(), time: InputTime::now(), @@ -1626,8 +1626,7 @@ impl State { tool.motion( self, - under - .and_then(|(f, loc)| f.wl_surface().map(|s| (s.into_owned(), loc))), + under, &tool::MotionEvent { location: position.as_logical(), serial: SERIAL_COUNTER.next_serial(), @@ -1666,7 +1665,7 @@ impl State { pointer.motion( self, under.clone(), - &MotionEvent { + &PointerMotionEvent { location: position.as_logical(), serial: SERIAL_COUNTER.next_serial(), time: InputTime::now(), @@ -1698,22 +1697,17 @@ impl State { }; match event.state() { - ProximityState::In => { - let under = under.and_then(|(f, loc)| { - f.wl_surface().map(|s| (s.into_owned(), loc)) - }); - tool.proximity_in( - self, - under, - tablet, - &tool::ProximityInEvent { - location: position.as_logical(), - axis: Some(frame), - serial: SERIAL_COUNTER.next_serial(), - time: event.time(), - }, - ) - } + ProximityState::In => tool.proximity_in( + self, + under, + tablet, + &tool::ProximityInEvent { + location: position.as_logical(), + axis: Some(frame), + serial: SERIAL_COUNTER.next_serial(), + time: event.time(), + }, + ), ProximityState::Out => tool.proximity_out( self, &tool::ProximityOutEvent { @@ -1728,6 +1722,18 @@ impl State { } } InputEvent::TabletToolTip { event, .. } => { + { + let mut shell = self.common.shell.write(); + if let Some(Trigger::Tool(desc, trigger)) = + shell.overview_mode().0.active_trigger() + && event.tool() == *desc + && matches!(*trigger, tool::GrabTrigger::Tip) + && event.tip_state() == TabletToolTipState::Up + { + shell.set_overview_mode(None, self.common.event_loop_handle.clone()); + } + } + let maybe_seat = self .common .shell @@ -2968,7 +2974,7 @@ impl State { pointer.motion( self, under, - &MotionEvent { + &PointerMotionEvent { location: point.as_logical(), serial, time, diff --git a/src/shell/element/stack.rs b/src/shell/element/stack.rs index 2fed0977..34e6f876 100644 --- a/src/shell/element/stack.rs +++ b/src/shell/element/stack.rs @@ -11,7 +11,7 @@ use crate::{ shell::{ element::{CosmicMappedKey, CosmicMappedKeyInner}, focus::target::PointerFocusTarget, - grabs::{ReleaseMode, ResizeEdge}, + grabs::{GrabType, ReleaseMode, ResizeEdge}, layout::tiling::NodeDesc, }, state::State, @@ -38,7 +38,7 @@ use shortcuts::action::{Direction, FocusDirection}; use smithay::{ backend::{ drm::DrmNode, - input::{InputTime, KeyState}, + input::{InputTime, KeyState, TabletToolDescriptor}, renderer::{ ImportAll, ImportMem, Renderer, element::{Element, Id as RendererId, Kind, RenderElement, UnderlyingStorage}, @@ -52,14 +52,23 @@ use smithay::{ Seat, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ - AxisFrame, ButtonEvent, CursorImageStatus, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, + AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorImageStatus, + GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, PointerTarget, RelativeMotionEvent, }, + tablet::{ + Tablet, TabletSeatTrait, + tool::{ + AxisFrame as ToolAxisFrame, ButtonEvent as ToolButtonEvent, + DownEvent as ToolDownEvent, MotionEvent as ToolMotionEvent, TabletToolTarget, + UpEvent as ToolUpEvent, + }, + }, touch::{ - DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, - TouchTarget, UpEvent, + DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, + OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, }, }, output::Output, @@ -909,12 +918,19 @@ impl CosmicStack { false, ); if let Some((grab, focus)) = res { - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - seat.get_pointer() + 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); + .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), } } }); @@ -1089,12 +1105,19 @@ impl Program for CosmicStackInternal { false, ); if let Some((grab, focus)) = res { - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - seat.get_pointer() + 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); + .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), } } }); @@ -1597,7 +1620,7 @@ impl KeyboardTarget for CosmicStack { } impl PointerTarget for CosmicStack { - fn enter(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { + fn enter(&self, seat: &Seat, data: &mut State, event: &PointerMotionEvent) { let mut event = event.clone(); self.0.with_program(|p| { let active_window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; @@ -1625,7 +1648,7 @@ impl PointerTarget for CosmicStack { PointerTarget::enter(&self.0, seat, data, &event) } - fn motion(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { + fn motion(&self, seat: &Seat, data: &mut State, event: &PointerMotionEvent) { let mut event = event.clone(); self.0.with_program(|p| { let active = p.active.load(Ordering::SeqCst); @@ -1668,7 +1691,7 @@ impl PointerTarget for CosmicStack { ) { } - fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { + fn button(&self, seat: &Seat, data: &mut State, event: &PointerButtonEvent) { match self.0.with_program(|p| p.current_focus()) { Some(Focus::Header) => PointerTarget::button(&self.0, seat, data, event), Some(x) => { @@ -1700,12 +1723,19 @@ impl PointerTarget for CosmicStack { false, ); if let Some((grab, focus)) = res { - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - seat.get_pointer() + 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); + .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), } } }); @@ -1714,7 +1744,7 @@ impl PointerTarget for CosmicStack { } } - fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { + fn axis(&self, seat: &Seat, data: &mut State, frame: PointerAxisFrame) { if let Some(Focus::Header) = self.0.with_program(|p| p.current_focus()) { PointerTarget::axis(&self.0, seat, data, frame) } @@ -1763,12 +1793,19 @@ impl PointerTarget for CosmicStack { false, ); if let Some((grab, focus)) = res { - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - seat.get_pointer() + 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); + .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), } } }); @@ -1842,7 +1879,7 @@ impl PointerTarget for CosmicStack { } impl TouchTarget for CosmicStack { - fn down(&self, seat: &Seat, data: &mut State, event: &DownEvent) { + fn down(&self, seat: &Seat, data: &mut State, event: &TouchDownEvent) { let mut event = event.clone(); let active_window_geo = self.0.with_program(|p| { p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].geometry() @@ -1853,7 +1890,7 @@ impl TouchTarget for CosmicStack { TouchTarget::down(&self.0, seat, data, &event) } - fn up(&self, seat: &Seat, data: &mut State, event: &UpEvent) { + fn up(&self, seat: &Seat, data: &mut State, event: &TouchUpEvent) { TouchTarget::up(&self.0, seat, data, event) } @@ -1901,6 +1938,101 @@ impl TouchTarget for CosmicStack { } } +impl TabletToolTarget for CosmicStack { + fn proximity_in( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + tablet: &Tablet, + serial: Serial, + ) { + TabletToolTarget::proximity_in(&self.0, seat, data, tool_descriptor, tablet, serial) + } + + fn proximity_out( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + ) { + TabletToolTarget::proximity_out(&self.0, seat, data, tool_descriptor) + } + + fn down( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolDownEvent, + ) { + TabletToolTarget::down(&self.0, seat, data, tool_descriptor, event) + } + + fn up( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolUpEvent, + ) { + TabletToolTarget::up(&self.0, seat, data, tool_descriptor, event) + } + + fn motion( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolMotionEvent, + ) { + let mut event = event.clone(); + let active_window_geo = self.0.with_program(|p| { + p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].geometry() + }); + event.location -= active_window_geo.loc.to_f64(); + TabletToolTarget::motion(&self.0, seat, data, tool_descriptor, &event); + + if event.location.y < 0.0 + || event.location.y > TAB_HEIGHT as f64 + || event.location.x < 64.0 + || event.location.x > (active_window_geo.size.w as f64 - 64.0) + { + self.start_drag(data, seat, event.serial); + } + } + + fn axis( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + frame: ToolAxisFrame, + ) { + TabletToolTarget::axis(&self.0, seat, data, tool_descriptor, frame) + } + + fn button( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolButtonEvent, + ) { + TabletToolTarget::button(&self.0, seat, data, tool_descriptor, event) + } + + fn frame( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + time: InputTime, + ) { + TabletToolTarget::frame(&self.0, seat, data, tool_descriptor, time) + } +} + pub enum CosmicStackRenderElement { Header(IcedRenderElement), Shadow(PixelShaderElement), diff --git a/src/shell/element/window.rs b/src/shell/element/window.rs index 53b2caee..846d9da4 100644 --- a/src/shell/element/window.rs +++ b/src/shell/element/window.rs @@ -7,7 +7,7 @@ use crate::{ shell::{ element::{CosmicMappedKey, CosmicMappedKeyInner}, focus::target::PointerFocusTarget, - grabs::{ReleaseMode, ResizeEdge}, + grabs::{GrabType, ReleaseMode, ResizeEdge}, }, state::State, utils::{ @@ -21,7 +21,7 @@ use cosmic_comp_config::AppearanceConfig; use smithay::{ backend::{ drm::DrmNode, - input::{InputTime, KeyState}, + input::{InputTime, KeyState, TabletToolDescriptor}, renderer::{ ImportAll, ImportMem, Renderer, element::{Element, Id as RendererId, Kind, RenderElement, UnderlyingStorage}, @@ -35,14 +35,23 @@ use smithay::{ Seat, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ - AxisFrame, ButtonEvent, CursorIcon, CursorImageStatus, GestureHoldBeginEvent, - GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchEndEvent, - GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, - GestureSwipeUpdateEvent, MotionEvent, PointerTarget, RelativeMotionEvent, + AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorIcon, + CursorImageStatus, GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, + PointerTarget, RelativeMotionEvent, + }, + tablet::{ + Tablet, TabletSeatTrait, + tool::{ + AxisFrame as ToolAxisFrame, ButtonEvent as ToolButtonEvent, + DownEvent as ToolDownEvent, MotionEvent as ToolMotionEvent, TabletToolTarget, + UpEvent as ToolUpEvent, + }, }, touch::{ - DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, - TouchTarget, UpEvent, + DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, + OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, }, }, output::Output, @@ -746,12 +755,19 @@ impl Program for CosmicWindowInternal { false, ); if let Some((grab, focus)) = res { - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - seat.get_pointer() + 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); + .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), } } }); @@ -1003,7 +1019,7 @@ impl KeyboardTarget for CosmicWindow { } impl PointerTarget for CosmicWindow { - fn enter(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { + fn enter(&self, seat: &Seat, data: &mut State, event: &PointerMotionEvent) { let mut event = event.clone(); self.0.with_program(|p| { let has_ssd = p.has_ssd(false); @@ -1029,7 +1045,7 @@ impl PointerTarget for CosmicWindow { PointerTarget::enter(&self.0, seat, data, &event) } - fn motion(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { + fn motion(&self, seat: &Seat, data: &mut State, event: &PointerMotionEvent) { let mut event = event.clone(); self.0.with_program(|p| { let has_ssd = p.has_ssd(false); @@ -1061,7 +1077,7 @@ impl PointerTarget for CosmicWindow { ) { } - fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { + fn button(&self, seat: &Seat, data: &mut State, event: &PointerButtonEvent) { match self.0.with_program(|p| p.current_focus()) { Some(Focus::Header) => PointerTarget::button(&self.0, seat, data, event), Some(x) => { @@ -1098,12 +1114,19 @@ impl PointerTarget for CosmicWindow { ); if let Some((grab, focus)) = res { - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - seat.get_pointer() + 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); + .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), } } }); @@ -1112,7 +1135,7 @@ impl PointerTarget for CosmicWindow { } } - fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { + fn axis(&self, seat: &Seat, data: &mut State, frame: PointerAxisFrame) { if let Some(Focus::Header) = self.0.with_program(|p| p.current_focus()) { PointerTarget::axis(&self.0, seat, data, frame) } @@ -1199,7 +1222,7 @@ impl PointerTarget for CosmicWindow { } impl TouchTarget for CosmicWindow { - fn down(&self, seat: &Seat, data: &mut State, event: &DownEvent) { + fn down(&self, seat: &Seat, data: &mut State, event: &TouchDownEvent) { let mut event = event.clone(); self.0.with_program(|p| { event.location -= p.window.geometry().loc.to_f64(); @@ -1207,7 +1230,7 @@ impl TouchTarget for CosmicWindow { TouchTarget::down(&self.0, seat, data, &event) } - fn up(&self, seat: &Seat, data: &mut State, event: &UpEvent) { + fn up(&self, seat: &Seat, data: &mut State, event: &TouchUpEvent) { TouchTarget::up(&self.0, seat, data, event) } @@ -1238,6 +1261,88 @@ impl TouchTarget for CosmicWindow { } } +impl TabletToolTarget for CosmicWindow { + fn proximity_in( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + tablet: &Tablet, + serial: Serial, + ) { + TabletToolTarget::proximity_in(&self.0, seat, data, tool_descriptor, tablet, serial) + } + + fn proximity_out( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + ) { + TabletToolTarget::proximity_out(&self.0, seat, data, tool_descriptor) + } + + fn down( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolDownEvent, + ) { + TabletToolTarget::down(&self.0, seat, data, tool_descriptor, event) + } + + fn up( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolUpEvent, + ) { + TabletToolTarget::up(&self.0, seat, data, tool_descriptor, event) + } + + fn motion( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolMotionEvent, + ) { + TabletToolTarget::motion(&self.0, seat, data, tool_descriptor, event) + } + + fn axis( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + frame: ToolAxisFrame, + ) { + TabletToolTarget::axis(&self.0, seat, data, tool_descriptor, frame) + } + + fn button( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolButtonEvent, + ) { + TabletToolTarget::button(&self.0, seat, data, tool_descriptor, event) + } + + fn frame( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + time: InputTime, + ) { + TabletToolTarget::frame(&self.0, seat, data, tool_descriptor, time) + } +} + impl WaylandFocus for CosmicWindow { fn wl_surface(&self) -> Option> { self.0.with_program(|p| { diff --git a/src/shell/focus/target.rs b/src/shell/focus/target.rs index 56af0ccc..6ca13279 100644 --- a/src/shell/focus/target.rs +++ b/src/shell/focus/target.rs @@ -16,21 +16,30 @@ use crate::{ }; use id_tree::NodeId; use smithay::{ - backend::input::{InputTime, KeyState}, + backend::input::{InputTime, KeyState, TabletToolDescriptor}, desktop::{LayerSurface, PopupKind, WindowSurface, WindowSurfaceType, space::SpaceElement}, input::{ Seat, dnd::{DndFocus, OfferData, Source}, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ - AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, - MotionEvent as PointerMotionEvent, PointerTarget, RelativeMotionEvent, + AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, + GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, + PointerTarget, RelativeMotionEvent, + }, + tablet::{ + Tablet, + tool::{ + AxisFrame as ToolAxisFrame, ButtonEvent as ToolButtonEvent, + DownEvent as ToolDownEvent, MotionEvent as ToolMotionEvent, TabletToolTarget, + UpEvent as ToolUpEvent, + }, }, touch::{ - DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, - TouchTarget, UpEvent, + DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, + OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, }, }, reexports::wayland_server::{ @@ -164,6 +173,17 @@ impl PointerFocusTarget { } } + fn inner_tablet_tool_target(&self) -> &dyn TabletToolTarget { + match self { + PointerFocusTarget::WlSurface { surface, .. } => surface, + PointerFocusTarget::X11Surface { surface, .. } => surface, + PointerFocusTarget::StackUI(u) => u, + PointerFocusTarget::WindowUI(u) => u, + PointerFocusTarget::ResizeFork(f) => f, + PointerFocusTarget::ZoomUI(e) => e, + } + } + pub fn under_surface>>( surface: &CosmicSurface, point: P, @@ -409,10 +429,10 @@ impl PointerTarget for PointerFocusTarget { self.inner_pointer_target() .relative_motion(seat, data, event); } - fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { + fn button(&self, seat: &Seat, data: &mut State, event: &PointerButtonEvent) { self.inner_pointer_target().button(seat, data, event); } - fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { + fn axis(&self, seat: &Seat, data: &mut State, frame: PointerAxisFrame) { self.inner_pointer_target().axis(seat, data, frame); } fn frame(&self, seat: &Seat, data: &mut State) { @@ -498,12 +518,102 @@ impl PointerTarget for PointerFocusTarget { } } +impl TabletToolTarget for PointerFocusTarget { + fn proximity_in( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + tablet: &Tablet, + serial: Serial, + ) { + self.inner_tablet_tool_target() + .proximity_in(seat, data, tool_descriptor, tablet, serial); + } + + fn proximity_out( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + ) { + self.inner_tablet_tool_target() + .proximity_out(seat, data, tool_descriptor); + } + + fn down( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolDownEvent, + ) { + self.inner_tablet_tool_target() + .down(seat, data, tool_descriptor, event); + } + + fn up( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolUpEvent, + ) { + self.inner_tablet_tool_target() + .up(seat, data, tool_descriptor, event); + } + + fn motion( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolMotionEvent, + ) { + self.inner_tablet_tool_target() + .motion(seat, data, tool_descriptor, event); + } + + fn axis( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + frame: ToolAxisFrame, + ) { + self.inner_tablet_tool_target() + .axis(seat, data, tool_descriptor, frame); + } + + fn button( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolButtonEvent, + ) { + self.inner_tablet_tool_target() + .button(seat, data, tool_descriptor, event); + } + + fn frame( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + time: InputTime, + ) { + self.inner_tablet_tool_target() + .frame(seat, data, tool_descriptor, time); + } +} + impl TouchTarget for PointerFocusTarget { - fn down(&self, seat: &Seat, data: &mut State, event: &DownEvent) { + fn down(&self, seat: &Seat, data: &mut State, event: &TouchDownEvent) { self.inner_touch_target().down(seat, data, event); } - fn up(&self, seat: &Seat, data: &mut State, event: &UpEvent) { + fn up(&self, seat: &Seat, data: &mut State, event: &TouchUpEvent) { self.inner_touch_target().up(seat, data, event); } diff --git a/src/shell/grabs/delay.rs b/src/shell/grabs/delay.rs index 96d33dc6..ca19e4cb 100644 --- a/src/shell/grabs/delay.rs +++ b/src/shell/grabs/delay.rs @@ -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 DelayGrab { } } - 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> PointerGrab for DelayGrab { &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> PointerGrab for DelayGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - details: AxisFrame, + details: PointerAxisFrame, ) { handle.axis(data, details); } @@ -201,12 +218,17 @@ impl> TouchGrab for DelayGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, focus: Option<(::TouchFocus, Point)>, - 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> TouchGrab for DelayGrab { fn unset(&mut self, _data: &mut State) {} } + +impl> TabletToolGrab for DelayGrab { + fn start_data(&self) -> &TabletGrabStartData { + 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<(::ToolFocus, Point)>, + 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<(::ToolFocus, Point)>, + event: &ProximityInEvent, + ) { + handle.proximity_in(data, focus, event); + } +} diff --git a/src/shell/grabs/menu/default.rs b/src/shell/grabs/menu/default.rs index 81673efd..26cca2f5 100644 --- a/src/shell/grabs/menu/default.rs +++ b/src/shell/grabs/menu/default.rs @@ -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), } } } diff --git a/src/shell/grabs/menu/mod.rs b/src/shell/grabs/menu/mod.rs index 72ea065b..dafbd6cc 100644 --- a/src/shell/grabs/menu/mod.rs +++ b/src/shell/grabs/menu/mod.rs @@ -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, pointer_entered: bool, touch_entered: Option, + tablet_entered: Option, } pub struct MenuGrab { @@ -516,6 +529,7 @@ pub struct MenuGrab { seat: Seat, screen_space_relative: Option, scale: Arc>, + last_tablet_idx: Option, } impl PointerGrab for MenuGrab { @@ -598,7 +612,7 @@ impl PointerGrab 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 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 for MenuGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &DownEvent, + event: &TouchDownEvent, ) { { let mut guard = self.elements.lock().unwrap(); @@ -757,7 +771,7 @@ impl TouchGrab 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 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 for MenuGrab { fn unset(&mut self, _data: &mut State) {} } +impl TabletToolGrab for MenuGrab { + fn start_data(&self) -> &TabletGrabStartData { + match &self.start_data { + GrabStartData::TabletTool { data, .. } => data, + _ => unreachable!(), + } + } + + fn proximity_in( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + _focus: Option<(::ToolFocus, Point)>, + 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<(::ToolFocus, Point)>, + 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 } } } diff --git a/src/shell/grabs/mod.rs b/src/shell/grabs/mod.rs index 515916fd..9524f425 100644 --- a/src/shell/grabs/mod.rs +++ b/src/shell/grabs/mod.rs @@ -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), Pointer(PointerGrabStartData), + TabletTool { + tool: TabletToolDescriptor, + data: TabletGrabStartData, + }, +} + +#[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 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 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 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 for ResizeGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, focus: Option<(PointerFocusTarget, Point)>, - event: &DownEvent, + event: &TouchDownEvent, ) { match self { ResizeGrab::Floating(grab) => TouchGrab::down(grab, data, handle, focus, event), @@ -394,7 +432,12 @@ impl TouchGrab 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 for ResizeGrab { } } +impl TabletToolGrab 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)>, + 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 { + 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), @@ -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 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 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 for MoveGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, focus: Option<(PointerFocusTarget, Point)>, - event: &DownEvent, + event: &TouchDownEvent, ) { match self { MoveGrab::Move(grab) => TouchGrab::down(grab, data, handle, focus, event), @@ -726,7 +877,12 @@ impl TouchGrab 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 for MoveGrab { } } } + +impl TabletToolGrab 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)>, + 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 { + 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), + } + } +} diff --git a/src/shell/grabs/moving.rs b/src/shell/grabs/moving.rs index 05923bc7..15225212 100644 --- a/src/shell/grabs/moving.rs +++ b/src/shell/grabs/moving.rs @@ -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 for MoveGrab { state: &mut State, handle: &mut PointerInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &MotionEvent, + event: &PointerMotionEvent, ) { self.update_location(state, event.location); @@ -529,7 +544,7 @@ impl PointerGrab 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 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 for MoveGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &touch::DownEvent, + event: &TouchDownEvent, ) { handle.down(data, None, event) } @@ -656,7 +671,7 @@ impl TouchGrab for MoveGrab { &mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, - event: &touch::UpEvent, + event: &TouchUpEvent, ) { if event.slot == >::start_data(self).slot { handle.unset_grab(self, data); @@ -670,7 +685,7 @@ impl TouchGrab for MoveGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &touch::MotionEvent, + event: &TouchMotionEvent, ) { if event.slot == >::start_data(self).slot { self.update_location(data, event.location); @@ -691,7 +706,7 @@ impl TouchGrab 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 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 for MoveGrab { fn unset(&mut self, _data: &mut State) {} } +impl TabletToolGrab for MoveGrab { + fn start_data(&self) -> &TabletGrabStartData { + 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<(::ToolFocus, Point)>, + 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<(::ToolFocus, Point)>, + 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(), diff --git a/src/shell/layout/floating/grabs/resize.rs b/src/shell/layout/floating/grabs/resize.rs index f9e5cbfd..9d767671 100644 --- a/src/shell/layout/floating/grabs/resize.rs +++ b/src/shell/layout/floating/grabs/resize.rs @@ -7,25 +7,36 @@ use crate::{ shell::{ element::CosmicMapped, focus::target::PointerFocusTarget, - grabs::{GrabStartData, ReleaseMode, ResizeEdge}, + grabs::{GrabStartData, GrabType, ReleaseMode, ResizeEdge}, }, utils::prelude::*, }; use smithay::{ - backend::input::ButtonState, + backend::input::{ButtonState, InputTime, TabletToolDescriptor}, desktop::{WindowSurface, space::SpaceElement}, 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, }, + 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, 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, @@ -170,10 +181,19 @@ impl ResizeSurfaceGrab { false } - pub fn is_touch_grab(&self) -> bool { + pub fn grab_type(&self) -> GrabType { match self.start_data { - GrabStartData::Touch(_) => true, - GrabStartData::Pointer(_) => false, + GrabStartData::Pointer(_) => GrabType::Pointer, + GrabStartData::Touch(_) => GrabType::Touch, + GrabStartData::TabletTool { .. } => GrabType::TabletTool, + } + } + + pub fn tool(&self) -> Option<&TabletToolDescriptor> { + if let GrabStartData::TabletTool { tool, .. } = &self.start_data { + Some(tool) + } else { + None } } } @@ -184,7 +204,7 @@ impl PointerGrab for ResizeSurfaceGrab { data: &mut State, handle: &mut PointerInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &MotionEvent, + event: &PointerMotionEvent, ) { // While the grab is active, no client has pointer focus handle.motion(data, None, event); @@ -209,7 +229,7 @@ impl PointerGrab for ResizeSurfaceGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - event: &ButtonEvent, + event: &PointerButtonEvent, ) { handle.button(data, event); match self.release { @@ -230,7 +250,7 @@ impl PointerGrab for ResizeSurfaceGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - details: AxisFrame, + details: PointerAxisFrame, ) { handle.axis(data, details) } @@ -329,12 +349,17 @@ impl TouchGrab for ResizeSurfaceGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &DownEvent, + event: &TouchDownEvent, ) { 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, + ) { if event.slot == >::start_data(self).slot { handle.unset_grab(self, data); } @@ -396,6 +421,99 @@ impl TouchGrab for ResizeSurfaceGrab { } } +impl TabletToolGrab for ResizeSurfaceGrab { + fn start_data(&self) -> &TabletGrabStartData { + match &self.start_data { + GrabStartData::TabletTool { data, .. } => data, + _ => unreachable!(), + } + } + + fn proximity_out( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &ProximityOutEvent, + ) { + handle.unset_grab(self, data, event.serial, event.time, true); + handle.proximity_out(data, event); + } + + fn motion( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + _focus: Option<(::ToolFocus, Point)>, + event: &TabletMotionEvent, + ) { + if self.update_location(event.location.as_global()) { + handle.unset_grab(self, data, event.serial, event.time, true); + } + + handle.motion(data, None, event); + } + + 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.unset_grab(self, data, event.serial, event.time, true); + 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) { + self.ungrab() + } + + fn proximity_in( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + _focus: Option<(::ToolFocus, Point)>, + event: &ProximityInEvent, + ) { + handle.proximity_in(data, None, event); + } +} + pub struct ResizeGrabMarker(AtomicBool); impl ResizeGrabMarker { diff --git a/src/shell/layout/tiling/grabs/resize.rs b/src/shell/layout/tiling/grabs/resize.rs index 91873793..b6452168 100644 --- a/src/shell/layout/tiling/grabs/resize.rs +++ b/src/shell/layout/tiling/grabs/resize.rs @@ -1,34 +1,47 @@ // SPDX-License-Identifier: GPL-3.0-only +use std::cell::Cell; + use crate::{ backend::render::cursor::CursorState, shell::{ focus::target::PointerFocusTarget, - grabs::{GrabStartData, ReleaseMode}, + grabs::{GrabStartData, GrabType, ReleaseMode}, layout::Orientation, }, utils::prelude::*, }; use id_tree::{NodeId, Tree}; use smithay::{ - backend::input::{ButtonState, InputTime}, + backend::input::{ButtonState, InputTime, TabletToolDescriptor}, input::{ Seat, pointer::{ - AxisFrame, ButtonEvent, CursorIcon, Focus, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, - GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle, - PointerTarget, RelativeMotionEvent, + AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorIcon, Focus, + GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, + MotionEvent as PointerMotionEvent, PointerGrab, PointerInnerHandle, PointerTarget, + RelativeMotionEvent, + }, + tablet::{ + Tablet, TabletSeatHandler, TabletSeatTrait, + tool::{ + AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent, + DownEvent as TabletDownEvent, GrabStartData as TabletToolGrabStartData, + GrabTrigger as TabletToolGrabTrigger, MotionEvent as TabletMotionEvent, + ProximityInEvent, ProximityOutEvent, TabletToolGrab, TabletToolInnerHandle, + TabletToolTarget, UpEvent as TabletUpEvent, + }, }, touch::{ - DownEvent, FrameMarker, GrabStartData as TouchGrabStartData, + DownEvent as TouchDownEvent, FrameMarker, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab, - TouchInnerHandle, TouchTarget, UpEvent, + TouchInnerHandle, TouchTarget, UpEvent as TouchUpEvent, }, }, output::WeakOutput, - utils::{IsAlive, Logical, Point}, + utils::{IsAlive, Logical, Point, Serial}, }; use super::super::{Data, TilingLayout}; @@ -39,6 +52,7 @@ pub struct ResizeForkTarget { pub output: WeakOutput, pub left_up_idx: usize, pub orientation: Orientation, + pub last_tablet_location: Cell>>, } impl IsAlive for ResizeForkTarget { @@ -48,7 +62,7 @@ impl IsAlive for ResizeForkTarget { } impl PointerTarget for ResizeForkTarget { - fn enter(&self, seat: &Seat, _data: &mut State, _event: &MotionEvent) { + fn enter(&self, seat: &Seat, _data: &mut State, _event: &PointerMotionEvent) { let user_data = seat.user_data(); let cursor_state = user_data.get::().unwrap(); cursor_state @@ -60,19 +74,13 @@ impl PointerTarget for ResizeForkTarget { }); } - fn leave( - &self, - seat: &Seat, - _data: &mut State, - _serial: smithay::utils::Serial, - _time: InputTime, - ) { + fn leave(&self, seat: &Seat, _data: &mut State, _serial: Serial, _time: InputTime) { let user_data = seat.user_data(); let cursor_state = user_data.get::().unwrap(); cursor_state.lock().unwrap().unset_shape(); } - fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { + fn button(&self, seat: &Seat, data: &mut State, event: &PointerButtonEvent) { if event.button == 0x110 && event.state == ButtonState::Pressed { let seat = seat.clone(); let node = self.node.clone(); @@ -106,7 +114,7 @@ impl PointerTarget for ResizeForkTarget { } } - fn motion(&self, _seat: &Seat, _data: &mut State, _event: &MotionEvent) {} + fn motion(&self, _seat: &Seat, _data: &mut State, _event: &PointerMotionEvent) {} fn relative_motion( &self, _seat: &Seat, @@ -114,7 +122,7 @@ impl PointerTarget for ResizeForkTarget { _event: &RelativeMotionEvent, ) { } - fn axis(&self, _seat: &Seat, _data: &mut State, _frame: AxisFrame) {} + fn axis(&self, _seat: &Seat, _data: &mut State, _frame: PointerAxisFrame) {} fn frame(&self, _seat: &Seat, _data: &mut State) {} fn gesture_swipe_begin(&self, _: &Seat, _: &mut State, _: &GestureSwipeBeginEvent) {} fn gesture_swipe_update(&self, _: &Seat, _: &mut State, _: &GestureSwipeUpdateEvent) {} @@ -127,7 +135,7 @@ impl PointerTarget for ResizeForkTarget { } impl TouchTarget for ResizeForkTarget { - fn down(&self, seat: &Seat, data: &mut State, event: &DownEvent) { + fn down(&self, seat: &Seat, data: &mut State, event: &TouchDownEvent) { let seat = seat.clone(); let node = self.node.clone(); let output = self.output.clone(); @@ -158,7 +166,7 @@ impl TouchTarget for ResizeForkTarget { }); } - fn up(&self, _seat: &Seat, _data: &mut State, _event: &UpEvent) {} + fn up(&self, _seat: &Seat, _data: &mut State, _event: &TouchUpEvent) {} fn motion(&self, _seat: &Seat, _data: &mut State, _event: &TouchMotionEvent) {} fn frame(&self, _seat: &Seat, _data: &mut State, _frame: FrameMarker) {} fn cancel(&self, _seat: &Seat, _data: &mut State, _frame: FrameMarker) {} @@ -169,6 +177,113 @@ impl TouchTarget for ResizeForkTarget { } } +impl TabletToolTarget for ResizeForkTarget { + fn down( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &TabletDownEvent, + ) { + let seat = seat.clone(); + let node = self.node.clone(); + let output = self.output.clone(); + let left_up_idx = self.left_up_idx; + let orientation = self.orientation; + let serial = event.serial; + let time = event.time; + let tool = tool_descriptor.clone(); + let Some(location) = self.last_tablet_location.take() else { + return; + }; + data.common.event_loop_handle.insert_idle(move |state| { + let tablet = seat.tablet_seat().get_tool(&tool).unwrap(); + tablet.set_grab( + state, + ResizeForkGrab::new( + GrabStartData::TabletTool { + tool, + data: TabletToolGrabStartData { + focus: None, + location: location.as_logical(), + trigger: TabletToolGrabTrigger::Tip, + }, + }, + location, + node, + left_up_idx, + orientation, + output, + ReleaseMode::NoMouseButtons, + ), + time, + serial, + Focus::Keep, + ) + }); + } + fn motion( + &self, + _seat: &Seat, + _data: &mut State, + _tool_descriptor: &TabletToolDescriptor, + event: &TabletMotionEvent, + ) { + self.last_tablet_location + .set(Some(event.location.as_global())) + } + fn proximity_out( + &self, + _seat: &Seat, + _data: &mut State, + _tool_descriptor: &TabletToolDescriptor, + ) { + self.last_tablet_location.set(None); + } + + fn proximity_in( + &self, + _seat: &Seat, + _data: &mut State, + _tool_descriptor: &TabletToolDescriptor, + _tablet: &Tablet, + _serial: Serial, + ) { + } + fn up( + &self, + _seat: &Seat, + _data: &mut State, + _tool_descriptor: &TabletToolDescriptor, + _event: &TabletUpEvent, + ) { + } + fn axis( + &self, + _seat: &Seat, + _data: &mut State, + _tool_descriptor: &TabletToolDescriptor, + _frame: TabletAxisFrame, + ) { + } + fn button( + &self, + _seat: &Seat, + _data: &mut State, + _tool_descriptor: &TabletToolDescriptor, + _event: &TabletButtonEvent, + ) { + } + fn frame( + &self, + _seat: &Seat, + _data: &mut State, + _tool_descriptor: &TabletToolDescriptor, + _time: InputTime, + ) { + } +} + pub struct ResizeForkGrab { start_data: GrabStartData, last_loc: Point, @@ -338,10 +453,19 @@ impl ResizeForkGrab { false } - pub fn is_touch_grab(&self) -> bool { + pub fn grab_type(&self) -> GrabType { match self.start_data { - GrabStartData::Touch(_) => true, - GrabStartData::Pointer(_) => false, + GrabStartData::Pointer(_) => GrabType::Pointer, + GrabStartData::Touch(_) => GrabType::Touch, + GrabStartData::TabletTool { .. } => GrabType::TabletTool, + } + } + + pub fn tool(&self) -> Option<&TabletToolDescriptor> { + if let GrabStartData::TabletTool { tool, .. } = &self.start_data { + Some(tool) + } else { + None } } } @@ -352,7 +476,7 @@ impl PointerGrab for ResizeForkGrab { data: &mut State, handle: &mut PointerInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &MotionEvent, + event: &PointerMotionEvent, ) { // While the grab is active, no client has pointer focus handle.motion(data, None, event); @@ -377,7 +501,7 @@ impl PointerGrab for ResizeForkGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - event: &ButtonEvent, + event: &PointerButtonEvent, ) { handle.button(data, event); match self.release { @@ -398,7 +522,7 @@ impl PointerGrab for ResizeForkGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - details: AxisFrame, + details: PointerAxisFrame, ) { handle.axis(data, details) } @@ -497,12 +621,17 @@ impl TouchGrab for ResizeForkGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &DownEvent, + event: &TouchDownEvent, ) { 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, + ) { if event.slot == >::start_data(self).slot { handle.unset_grab(self, data); } @@ -563,3 +692,96 @@ impl TouchGrab for ResizeForkGrab { self.update_location(data, self.last_loc.as_logical(), true); } } + +impl TabletToolGrab for ResizeForkGrab { + fn start_data(&self) -> &TabletToolGrabStartData { + 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); + handle.unset_grab(self, data, event.serial, event.time, true); + } + + fn motion( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + _focus: Option<(::ToolFocus, Point)>, + event: &TabletMotionEvent, + ) { + handle.motion(data, None, event); + + if self.update_location(data, event.location, false) { + 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, + ) { + handle.up(data, event); + handle.unset_grab(self, data, event.serial, event.time, true); + } + + 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) { + self.update_location(data, self.last_loc.as_logical(), true); + } + + fn proximity_in( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + focus: Option<(::ToolFocus, Point)>, + event: &ProximityInEvent, + ) { + handle.proximity_in(data, focus, event); + } +} diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index 2d95cd27..2f694acd 100644 --- a/src/shell/layout/tiling/mod.rs +++ b/src/shell/layout/tiling/mod.rs @@ -67,6 +67,7 @@ use smithay::{ wayland::{compositor::add_blocker, seat::WaylandFocus}, }; use std::{ + cell::Cell, collections::{HashMap, VecDeque}, sync::{Arc, Weak}, time::{Duration, Instant}, @@ -3348,6 +3349,7 @@ impl TilingLayout { output: self.output.downgrade(), left_up_idx: idx, orientation, + last_tablet_location: Cell::new(None), } .into(), (last_geometry.loc @@ -3381,7 +3383,7 @@ impl TilingLayout { let Some(root) = tree.root_node_id() else { if matches!( overview.active_trigger(), - Some(Trigger::Pointer(_) | Trigger::Touch(_)) + Some(Trigger::Pointer(_) | Trigger::Touch(_) | Trigger::Tool(_, _)) ) && location_f64.is_some() { let mut tree = tree.copy_clone(); @@ -3414,7 +3416,7 @@ impl TilingLayout { if matches!( overview.active_trigger(), - Some(Trigger::Pointer(_) | Trigger::Touch(_)) + Some(Trigger::Pointer(_) | Trigger::Touch(_) | Trigger::Tool(_, _)) ) { let non_exclusive_zone = layer_map_for_output(&self.output) .non_exclusive_zone() @@ -4062,8 +4064,11 @@ impl TilingLayout { let draw_groups = overview.0.alpha(); let is_overview = !matches!(overview.0, OverviewMode::None); - let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_)))) - .then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone)); + let is_mouse_tiling = (matches!( + overview.0.trigger(), + Some(Trigger::Pointer(_) | Trigger::Tool(_, _)) + )) + .then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone)); let swap_desc = if let Some(Trigger::KeyboardSwap(_, desc)) = overview.0.trigger() { Some(desc.clone()) } else { @@ -4216,8 +4221,11 @@ impl TilingLayout { }; let draw_groups = overview.0.alpha(); - let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_)))) - .then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone)); + let is_mouse_tiling = (matches!( + overview.0.trigger(), + Some(Trigger::Pointer(_) | Trigger::Tool(_, _)) + )) + .then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone)); let swap_desc = if let Some(Trigger::KeyboardSwap(_, desc)) = overview.0.trigger() { Some(desc.clone()) } else { diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 3fa863d3..b10d9d63 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -32,7 +32,10 @@ use cosmic_settings_config::shortcuts::action::{Direction, FocusDirection, Resiz use cosmic_settings_config::{shortcuts, window_rules::ApplicationException}; use keyframe::{ease, functions::EaseInOutCubic}; use smithay::{ - backend::{input::TouchSlot, renderer::element::RenderElementStates}, + backend::{ + input::{TabletToolDescriptor, TouchSlot}, + renderer::element::RenderElementStates, + }, desktop::{ LayerSurface, PopupKind, WindowSurface, WindowSurfaceType, layer_map_for_output, space::SpaceElement, @@ -46,6 +49,7 @@ use smithay::{ pointer::{ CursorImageStatus, CursorImageSurfaceData, Focus, GrabStartData as PointerGrabStartData, }, + tablet::tool::GrabTrigger as TabletGrabTrigger, }, output::{Output, WeakOutput}, reexports::{ @@ -130,6 +134,7 @@ pub enum Trigger { KeyboardMove(shortcuts::Modifiers), Pointer(u32), Touch(TouchSlot), + Tool(TabletToolDescriptor, TabletGrabTrigger), } #[derive(Debug, Clone)] @@ -1755,7 +1760,7 @@ impl Shell { if let Some(set) = self.workspaces.sets.get_mut(output) { if matches!( self.overview_mode.active_trigger(), - Some(Trigger::Pointer(_) | Trigger::Touch(_)) + Some(Trigger::Pointer(_) | Trigger::Touch(_) | Trigger::Tool(_, _)) ) { set.workspaces[set.active].tiling_layer.cleanup_drag(); } @@ -1806,7 +1811,7 @@ impl Shell { if let Some(set) = self.workspaces.sets.get_mut(output) { if matches!( self.overview_mode.active_trigger(), - Some(Trigger::Pointer(_) | Trigger::Touch(_)) + Some(Trigger::Pointer(_) | Trigger::Touch(_) | Trigger::Tool(_, _)) ) { set.workspaces[set.active].tiling_layer.cleanup_drag(); } @@ -3840,6 +3845,7 @@ impl Shell { let trigger = match &start_data { GrabStartData::Pointer(start_data) => Trigger::Pointer(start_data.button), GrabStartData::Touch(start_data) => Trigger::Touch(start_data.slot), + GrabStartData::TabletTool { tool, data } => Trigger::Tool(tool.clone(), data.trigger), }; let active_hint = if config.cosmic_conf.active_hint { self.theme.cosmic().active_hint as u8 diff --git a/src/shell/zoom.rs b/src/shell/zoom.rs index cfe84f06..b3a795e7 100644 --- a/src/shell/zoom.rs +++ b/src/shell/zoom.rs @@ -11,19 +11,31 @@ use cosmic_comp_config::{ZoomConfig, ZoomMovement}; use cosmic_config::ConfigSet; use keyframe::{ease, functions::Linear}; use smithay::{ - backend::{input::InputTime, renderer::ImportMem}, + backend::{ + input::{InputTime, TabletToolDescriptor}, + renderer::ImportMem, + }, desktop::space::SpaceElement, input::{ Seat, pointer::{ - AxisFrame, ButtonEvent, Focus, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, - MotionEvent as PointerMotionEvent, PointerTarget, RelativeMotionEvent, + AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, Focus, + GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, + PointerTarget, RelativeMotionEvent, + }, + tablet::{ + Tablet, TabletSeatTrait, + tool::{ + AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent, + DownEvent as TabletDownEvent, MotionEvent as TabletMotionEvent, TabletToolTarget, + UpEvent as TabletUpEvent, + }, }, touch::{ - DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, - TouchTarget, UpEvent, + DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, + OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, }, }, output::Output, @@ -33,6 +45,7 @@ use tracing::error; use crate::{ backend::render::element::AsGlowRenderer, + shell::grabs::GrabType, state::State, utils::{ iced::{IcedElement, IcedRenderElement, Program}, @@ -698,15 +711,27 @@ impl Program for ZoomProgram { ); std::mem::drop(shell); - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - seat.get_pointer().unwrap().set_grab( + 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::Clear, - ); + ), + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab( + state, + grab, + InputTime::now(), + serial, + Focus::Clear, + ), } } } @@ -785,15 +810,27 @@ impl Program for ZoomProgram { ); std::mem::drop(shell); - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - seat.get_pointer().unwrap().set_grab( + 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::Clear, - ); + ), + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab( + state, + grab, + InputTime::now(), + serial, + Focus::Clear, + ), } } } @@ -883,14 +920,14 @@ impl PointerTarget for ZoomFocusTarget { } } - fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { + fn button(&self, seat: &Seat, data: &mut State, event: &PointerButtonEvent) { match self { ZoomFocusTarget::Main(elem) => PointerTarget::button(elem, seat, data, event), ZoomFocusTarget::Menu(elem) => PointerTarget::button(elem, seat, data, event), } } - fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { + fn axis(&self, seat: &Seat, data: &mut State, frame: PointerAxisFrame) { match self { ZoomFocusTarget::Main(elem) => PointerTarget::axis(elem, seat, data, frame), ZoomFocusTarget::Menu(elem) => PointerTarget::axis(elem, seat, data, frame), @@ -1032,14 +1069,14 @@ impl PointerTarget for ZoomFocusTarget { } impl TouchTarget for ZoomFocusTarget { - fn down(&self, seat: &Seat, data: &mut State, event: &DownEvent) { + fn down(&self, seat: &Seat, data: &mut State, event: &TouchDownEvent) { match self { ZoomFocusTarget::Main(elem) => TouchTarget::down(elem, seat, data, event), ZoomFocusTarget::Menu(elem) => TouchTarget::down(elem, seat, data, event), } } - fn up(&self, seat: &Seat, data: &mut State, event: &UpEvent) { + fn up(&self, seat: &Seat, data: &mut State, event: &TouchUpEvent) { match self { ZoomFocusTarget::Main(elem) => TouchTarget::up(elem, seat, data, event), ZoomFocusTarget::Menu(elem) => TouchTarget::up(elem, seat, data, event), @@ -1089,6 +1126,144 @@ impl TouchTarget for ZoomFocusTarget { } } +impl TabletToolTarget for ZoomFocusTarget { + fn proximity_in( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + tablet: &Tablet, + serial: Serial, + ) { + match self { + ZoomFocusTarget::Main(elem) => { + TabletToolTarget::proximity_in(elem, seat, data, tool_descriptor, tablet, serial) + } + ZoomFocusTarget::Menu(elem) => { + TabletToolTarget::proximity_in(elem, seat, data, tool_descriptor, tablet, serial) + } + } + } + + fn proximity_out( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + ) { + match self { + ZoomFocusTarget::Main(elem) => { + TabletToolTarget::proximity_out(elem, seat, data, tool_descriptor) + } + ZoomFocusTarget::Menu(elem) => { + TabletToolTarget::proximity_out(elem, seat, data, tool_descriptor) + } + } + } + + fn down( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &TabletDownEvent, + ) { + match self { + ZoomFocusTarget::Main(elem) => { + TabletToolTarget::down(elem, seat, data, tool_descriptor, event) + } + ZoomFocusTarget::Menu(elem) => { + TabletToolTarget::down(elem, seat, data, tool_descriptor, event) + } + } + } + + fn up( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &TabletUpEvent, + ) { + match self { + ZoomFocusTarget::Main(elem) => { + TabletToolTarget::up(elem, seat, data, tool_descriptor, event) + } + ZoomFocusTarget::Menu(elem) => { + TabletToolTarget::up(elem, seat, data, tool_descriptor, event) + } + } + } + + fn motion( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &TabletMotionEvent, + ) { + match self { + ZoomFocusTarget::Main(elem) => { + TabletToolTarget::motion(elem, seat, data, tool_descriptor, event) + } + ZoomFocusTarget::Menu(elem) => { + TabletToolTarget::motion(elem, seat, data, tool_descriptor, event) + } + } + } + + fn axis( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + frame: TabletAxisFrame, + ) { + match self { + ZoomFocusTarget::Main(elem) => { + TabletToolTarget::axis(elem, seat, data, tool_descriptor, frame) + } + ZoomFocusTarget::Menu(elem) => { + TabletToolTarget::axis(elem, seat, data, tool_descriptor, frame) + } + } + } + + fn button( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &TabletButtonEvent, + ) { + match self { + ZoomFocusTarget::Main(elem) => { + TabletToolTarget::button(elem, seat, data, tool_descriptor, event) + } + ZoomFocusTarget::Menu(elem) => { + TabletToolTarget::button(elem, seat, data, tool_descriptor, event) + } + } + } + + fn frame( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + time: InputTime, + ) { + match self { + ZoomFocusTarget::Main(elem) => { + TabletToolTarget::frame(elem, seat, data, tool_descriptor, time) + } + ZoomFocusTarget::Menu(elem) => { + TabletToolTarget::frame(elem, seat, data, tool_descriptor, time) + } + } + } +} + impl IsAlive for ZoomFocusTarget { fn alive(&self) -> bool { match self { diff --git a/src/utils/iced/mod.rs b/src/utils/iced/mod.rs index 94b27ea7..8680bed3 100644 --- a/src/utils/iced/mod.rs +++ b/src/utils/iced/mod.rs @@ -31,7 +31,7 @@ use ordered_float::OrderedFloat; use smithay::{ backend::{ allocator::Fourcc, - input::{ButtonState, InputTime, KeyState}, + input::{ButtonState, InputTime, KeyState, TabletToolDescriptor}, renderer::{ ImportMem, element::{ @@ -45,14 +45,23 @@ use smithay::{ Seat, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ - AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, + AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, + GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, PointerTarget, RelativeMotionEvent, }, + tablet::{ + Tablet, + tool::{ + AxisFrame as ToolAxisFrame, ButtonEvent as ToolButtonEvent, + DownEvent as ToolDownEvent, MotionEvent as ToolMotionEvent, TabletToolTarget, + UpEvent as ToolUpEvent, + }, + }, touch::{ - DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, - TouchTarget, UpEvent, + DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, + OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, }, }, output::Output, @@ -189,6 +198,7 @@ pub(crate) struct IcedElementInternal { touch_map: HashMap, last_touch_frame: Option, last_touch_serial: Option, + last_tablet_serial: Option, // iced theme: Theme, @@ -240,6 +250,7 @@ impl Clone for IcedElementInternal

{ touch_map: self.touch_map.clone(), last_touch_frame: None, last_touch_serial: None, + last_tablet_serial: None, theme: self.theme.clone(), renderer, state, @@ -267,6 +278,7 @@ impl fmt::Debug for IcedElementInternal

{ .field("touch_map", &self.touch_map) .field("last_touch_frame", &self.last_touch_frame) .field("last_touch_serial", &self.last_touch_serial) + .field("last_tablet_serial", &self.last_tablet_serial) .field("theme", &"...") .field("renderer", &"...") .field("state", &"...") @@ -326,6 +338,7 @@ impl IcedElement

{ touch_map: HashMap::new(), last_touch_frame: None, last_touch_serial: None, + last_tablet_serial: None, theme, renderer, state, @@ -481,12 +494,141 @@ impl IcedElementInternal

{ } } +impl TabletToolTarget for IcedElement

{ + fn proximity_in( + &self, + _seat: &Seat, + _data: &mut crate::state::State, + _tool_descriptor: &TabletToolDescriptor, + _tablet: &Tablet, + _serial: Serial, + ) { + let mut internal = self.0.lock().unwrap(); + internal + .state + .queue_event(Event::Mouse(MouseEvent::CursorEntered)); + internal.update(false); + } + + fn proximity_out( + &self, + _seat: &Seat, + _data: &mut crate::state::State, + _tool_descriptor: &TabletToolDescriptor, + ) { + let mut internal = self.0.lock().unwrap(); + internal + .state + .queue_event(Event::Mouse(MouseEvent::CursorLeft)); + internal.update(false); + } + + fn down( + &self, + seat: &Seat, + _data: &mut crate::state::State, + _tool_descriptor: &TabletToolDescriptor, + event: &ToolDownEvent, + ) { + let mut internal = self.0.lock().unwrap(); + let id = Finger(0); + let Some(event_location) = internal.cursor_pos else { + return; + }; + let position = IcedPoint::new(event_location.x as f32, event_location.y as f32); + internal + .state + .queue_event(Event::Touch(TouchEvent::FingerPressed { id, position })); + internal.last_tablet_serial = Some(event.serial); + *internal.last_seat.lock().unwrap() = Some((seat.clone(), event.serial)); + internal.update(false); + } + + fn up( + &self, + seat: &Seat, + _data: &mut crate::state::State, + _tool_descriptor: &TabletToolDescriptor, + _event: &ToolUpEvent, + ) { + let mut internal = self.0.lock().unwrap(); + let id = Finger(0); + if let Some(event_location) = internal.cursor_pos { + *internal.last_seat.lock().unwrap() = + Some((seat.clone(), internal.last_tablet_serial.unwrap())); + let position = IcedPoint::new(event_location.x as f32, event_location.y as f32); + internal + .state + .queue_event(Event::Touch(TouchEvent::FingerLifted { id, position })); + internal.update(false); + } + } + + fn motion( + &self, + seat: &Seat, + _data: &mut crate::state::State, + _tool_descriptor: &TabletToolDescriptor, + event: &ToolMotionEvent, + ) { + let mut internal = self.0.lock().unwrap(); + let event_location = event.location.downscale(internal.additional_scale); + let position = IcedPoint::new(event_location.x as f32, event_location.y as f32); + internal + .state + .queue_event(Event::Mouse(MouseEvent::CursorMoved { position })); + internal.cursor_pos = Some(event_location); + *internal.last_seat.lock().unwrap() = Some((seat.clone(), event.serial)); + internal.update(false); + } + + fn axis( + &self, + _seat: &Seat, + _data: &mut crate::state::State, + _tool_descriptor: &TabletToolDescriptor, + _frame: ToolAxisFrame, + ) { + } + + fn button( + &self, + seat: &Seat, + _data: &mut crate::state::State, + _tool_descriptor: &TabletToolDescriptor, + event: &ToolButtonEvent, + ) { + let mut internal = self.0.lock().unwrap(); + let button = match event.button { + 0x110 => MouseButton::Left, + 0x111 => MouseButton::Right, + 0x112 => MouseButton::Middle, + x => MouseButton::Other(x as u16), + }; + internal.state.queue_event(Event::Mouse(match event.state { + ButtonState::Pressed => MouseEvent::ButtonPressed(button), + ButtonState::Released => MouseEvent::ButtonReleased(button), + })); + *internal.last_seat.lock().unwrap() = Some((seat.clone(), event.serial)); + internal.update(false); + } + + fn frame( + &self, + _seat: &Seat, + _data: &mut crate::state::State, + _tool_descriptor: &TabletToolDescriptor, + _time: InputTime, + ) { + } +} + impl PointerTarget for IcedElement

{ fn enter( &self, seat: &Seat, _data: &mut crate::state::State, - event: &MotionEvent, + event: &PointerMotionEvent, ) { let mut internal = self.0.lock().unwrap(); internal @@ -507,7 +649,7 @@ impl PointerTarget for IcedEle &self, seat: &Seat, _data: &mut crate::state::State, - event: &MotionEvent, + event: &PointerMotionEvent, ) { let mut internal = self.0.lock().unwrap(); let event_location = event.location.downscale(internal.additional_scale); @@ -532,7 +674,7 @@ impl PointerTarget for IcedEle &self, seat: &Seat, _data: &mut crate::state::State, - event: &ButtonEvent, + event: &PointerButtonEvent, ) { let mut internal = self.0.lock().unwrap(); let button = match event.button { @@ -553,7 +695,7 @@ impl PointerTarget for IcedEle &self, _seat: &Seat, _data: &mut crate::state::State, - frame: AxisFrame, + frame: PointerAxisFrame, ) { let mut internal = self.0.lock().unwrap(); internal @@ -653,7 +795,7 @@ impl TouchTarget for IcedEleme &self, seat: &Seat, _data: &mut crate::state::State, - event: &DownEvent, + event: &TouchDownEvent, ) { let mut internal = self.0.lock().unwrap(); let id = Finger(i32::from(event.slot) as u64); @@ -673,7 +815,7 @@ impl TouchTarget for IcedEleme &self, seat: &Seat, _data: &mut crate::state::State, - event: &UpEvent, + event: &TouchUpEvent, ) { let mut internal = self.0.lock().unwrap(); let id = Finger(i32::from(event.slot) as u64); diff --git a/src/wayland/handlers/tablet_manager.rs b/src/wayland/handlers/tablet_manager.rs index e4b84434..7cf2b8cb 100644 --- a/src/wayland/handlers/tablet_manager.rs +++ b/src/wayland/handlers/tablet_manager.rs @@ -1,13 +1,13 @@ // SPDX-License-Identifier: GPL-3.0-only -use crate::state::State; +use crate::{shell::focus::target::PointerFocusTarget, state::State}; use smithay::{ backend::input::TabletToolDescriptor, input::pointer::CursorImageStatus, - input::tablet::TabletSeatHandler, reexports::wayland_server::protocol::wl_surface, + input::tablet::TabletSeatHandler, }; impl TabletSeatHandler for State { - type ToolFocus = wl_surface::WlSurface; + type ToolFocus = PointerFocusTarget; fn tablet_tool_image(&mut self, _tool: &TabletToolDescriptor, _image: CursorImageStatus) { // TODO display cursor for each tablet tool diff --git a/src/wayland/handlers/xdg_shell/mod.rs b/src/wayland/handlers/xdg_shell/mod.rs index c9fb926f..be7084dd 100644 --- a/src/wayland/handlers/xdg_shell/mod.rs +++ b/src/wayland/handlers/xdg_shell/mod.rs @@ -1,11 +1,15 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::{ - shell::{CosmicSurface, PendingWindow, focus::target::KeyboardFocusTarget, grabs::ReleaseMode}, + shell::{ + CosmicSurface, PendingWindow, + focus::target::KeyboardFocusTarget, + grabs::{GrabType, ReleaseMode}, + }, utils::prelude::*, }; -use smithay::desktop::layer_map_for_output; use smithay::{ + backend::input::InputTime, desktop::{ PopupGrab, PopupKeyboardGrab, PopupKind, PopupPointerGrab, PopupUngrabStrategy, WindowSurfaceType, find_popup_root_surface, @@ -26,6 +30,7 @@ use smithay::{ }, }, }; +use smithay::{desktop::layer_map_for_output, input::tablet::TabletSeatTrait}; use std::cell::Cell; use tracing::warn; @@ -190,12 +195,17 @@ impl XdgShellHandler for State { true, ) { std::mem::drop(shell); - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(self, grab, serial); - } else { - seat.get_pointer() + match grab.grab_type() { + GrabType::Touch => seat.get_touch().unwrap().set_grab(self, grab, serial), + GrabType::Pointer => seat + .get_pointer() .unwrap() - .set_grab(self, grab, serial, focus) + .set_grab(self, grab, serial, focus), + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab(self, grab, InputTime::now(), serial, focus), } } } @@ -218,12 +228,17 @@ impl XdgShellHandler for State { true, ) { std::mem::drop(shell); - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(self, grab, serial) - } else { - seat.get_pointer() + match grab.grab_type() { + GrabType::Touch => seat.get_touch().unwrap().set_grab(self, grab, serial), + GrabType::Pointer => seat + .get_pointer() .unwrap() - .set_grab(self, grab, serial, focus) + .set_grab(self, grab, serial, focus), + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab(self, grab, InputTime::now(), serial, focus), } } } diff --git a/src/xwayland.rs b/src/xwayland.rs index 78193d13..cc6be3b4 100644 --- a/src/xwayland.rs +++ b/src/xwayland.rs @@ -9,7 +9,9 @@ use std::{ use crate::{ backend::render::cursor::{Cursor, load_cursor_env, load_cursor_theme}, shell::{ - CosmicSurface, PendingWindow, Shell, focus::target::KeyboardFocusTarget, grabs::ReleaseMode, + CosmicSurface, PendingWindow, Shell, + focus::target::KeyboardFocusTarget, + grabs::{GrabType, ReleaseMode}, }, state::State, utils::prelude::*, @@ -32,7 +34,7 @@ use smithay::{ }, }, desktop::space::SpaceElement, - input::{keyboard::ModifiersState, pointer::CursorIcon}, + input::{keyboard::ModifiersState, pointer::CursorIcon, tablet::TabletSeatTrait}, reexports::{wayland_server::Client, x11rb::protocol::xproto::Window as X11Window}, utils::{ Buffer as BufferCoords, Logical, Point, Rectangle, SERIAL_COUNTER, Serial, Size, Transform, @@ -1045,17 +1047,29 @@ impl XwmHandler for State { true, ) { std::mem::drop(shell); - if grab.is_touch_grab() { - seat.get_touch() - .unwrap() - .set_grab(self, grab, SERIAL_COUNTER.next_serial()) - } else { - seat.get_pointer().unwrap().set_grab( + match grab.grab_type() { + GrabType::Touch => { + seat.get_touch() + .unwrap() + .set_grab(self, grab, SERIAL_COUNTER.next_serial()) + } + GrabType::Pointer => seat.get_pointer().unwrap().set_grab( self, grab, SERIAL_COUNTER.next_serial(), focus, - ) + ), + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab( + self, + grab, + InputTime::now(), + SERIAL_COUNTER.next_serial(), + focus, + ), } } } @@ -1076,17 +1090,29 @@ impl XwmHandler for State { true, ) { std::mem::drop(shell); - if grab.is_touch_grab() { - seat.get_touch() - .unwrap() - .set_grab(self, grab, SERIAL_COUNTER.next_serial()) - } else { - seat.get_pointer().unwrap().set_grab( + match grab.grab_type() { + GrabType::Touch => { + seat.get_touch() + .unwrap() + .set_grab(self, grab, SERIAL_COUNTER.next_serial()) + } + GrabType::Pointer => seat.get_pointer().unwrap().set_grab( self, grab, SERIAL_COUNTER.next_serial(), focus, - ) + ), + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab( + self, + grab, + InputTime::now(), + SERIAL_COUNTER.next_serial(), + focus, + ), } } }