shell: Add tablet grabs

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

View file

@ -52,10 +52,11 @@ use smithay::{
keyboard::KeyboardHandle, keyboard::KeyboardHandle,
keyboard::{FilterResult, KeyboardSource, KeysymHandle, ModifiersState}, keyboard::{FilterResult, KeyboardSource, KeysymHandle, ModifiersState},
pointer::{ pointer::{
AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, AxisFrame, ButtonEvent as PointerButtonEvent, GestureHoldBeginEvent,
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchEndEvent,
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent,
PointerGrab, PointerHandle, RelativeMotionEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, PointerGrab, PointerHandle,
RelativeMotionEvent,
}, },
tablet::{TabletDescriptor, TabletSeatTrait, tool}, tablet::{TabletDescriptor, TabletSeatTrait, tool},
touch::{DownEvent, MotionEvent as TouchMotionEvent, UpEvent}, touch::{DownEvent, MotionEvent as TouchMotionEvent, UpEvent},
@ -326,7 +327,7 @@ impl State {
} }
InputEvent::PointerMotion { event, .. } => { InputEvent::PointerMotion { event, .. } => {
use smithay::backend::input::PointerMotionEvent; use smithay::backend::input::PointerMotionEvent as _;
let shell = self.common.shell.write(); let shell = self.common.shell.write();
if let Some(seat) = shell if let Some(seat) = shell
@ -639,7 +640,7 @@ impl State {
ptr.motion( ptr.motion(
self, self,
under, under,
&MotionEvent { &PointerMotionEvent {
location: position.as_logical(), location: position.as_logical(),
serial, serial,
time: event.time(), time: event.time(),
@ -754,7 +755,7 @@ impl State {
ptr.motion( ptr.motion(
self, self,
under, under,
&MotionEvent { &PointerMotionEvent {
location: position.as_logical(), location: position.as_logical(),
serial, serial,
time: event.time(), time: event.time(),
@ -781,9 +782,8 @@ impl State {
} }
} }
InputEvent::PointerButton { event, .. } => { InputEvent::PointerButton { event, .. } => {
use smithay::backend::input::{ButtonState, PointerButtonEvent}; use smithay::backend::input::{ButtonState, PointerButtonEvent as _};
//
let Some(seat) = self let Some(seat) = self
.common .common
.shell .shell
@ -857,7 +857,7 @@ impl State {
&& !shortcuts_inhibited && !shortcuts_inhibited
{ {
let seat_clone = seat.clone(); let seat_clone = seat.clone();
let mouse_button = PointerButtonEvent::button(&event); let mouse_button = event.button();
let mut supress_button = || { let mut supress_button = || {
// If the logo is held then the pointer event is // If the logo is held then the pointer event is
@ -1017,7 +1017,7 @@ impl State {
if pass_event { if pass_event {
ptr.button( ptr.button(
self, self,
&ButtonEvent { &PointerButtonEvent {
button, button,
state: event.state(), state: event.state(),
serial, serial,
@ -1597,7 +1597,7 @@ impl State {
pointer.motion( pointer.motion(
self, self,
under.clone(), under.clone(),
&MotionEvent { &PointerMotionEvent {
location: position.as_logical(), location: position.as_logical(),
serial: SERIAL_COUNTER.next_serial(), serial: SERIAL_COUNTER.next_serial(),
time: InputTime::now(), time: InputTime::now(),
@ -1626,8 +1626,7 @@ impl State {
tool.motion( tool.motion(
self, self,
under under,
.and_then(|(f, loc)| f.wl_surface().map(|s| (s.into_owned(), loc))),
&tool::MotionEvent { &tool::MotionEvent {
location: position.as_logical(), location: position.as_logical(),
serial: SERIAL_COUNTER.next_serial(), serial: SERIAL_COUNTER.next_serial(),
@ -1666,7 +1665,7 @@ impl State {
pointer.motion( pointer.motion(
self, self,
under.clone(), under.clone(),
&MotionEvent { &PointerMotionEvent {
location: position.as_logical(), location: position.as_logical(),
serial: SERIAL_COUNTER.next_serial(), serial: SERIAL_COUNTER.next_serial(),
time: InputTime::now(), time: InputTime::now(),
@ -1698,22 +1697,17 @@ impl State {
}; };
match event.state() { match event.state() {
ProximityState::In => { ProximityState::In => tool.proximity_in(
let under = under.and_then(|(f, loc)| { self,
f.wl_surface().map(|s| (s.into_owned(), loc)) under,
}); tablet,
tool.proximity_in( &tool::ProximityInEvent {
self, location: position.as_logical(),
under, axis: Some(frame),
tablet, serial: SERIAL_COUNTER.next_serial(),
&tool::ProximityInEvent { time: event.time(),
location: position.as_logical(), },
axis: Some(frame), ),
serial: SERIAL_COUNTER.next_serial(),
time: event.time(),
},
)
}
ProximityState::Out => tool.proximity_out( ProximityState::Out => tool.proximity_out(
self, self,
&tool::ProximityOutEvent { &tool::ProximityOutEvent {
@ -1728,6 +1722,18 @@ impl State {
} }
} }
InputEvent::TabletToolTip { event, .. } => { 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 let maybe_seat = self
.common .common
.shell .shell
@ -2968,7 +2974,7 @@ impl State {
pointer.motion( pointer.motion(
self, self,
under, under,
&MotionEvent { &PointerMotionEvent {
location: point.as_logical(), location: point.as_logical(),
serial, serial,
time, time,

View file

@ -11,7 +11,7 @@ use crate::{
shell::{ shell::{
element::{CosmicMappedKey, CosmicMappedKeyInner}, element::{CosmicMappedKey, CosmicMappedKeyInner},
focus::target::PointerFocusTarget, focus::target::PointerFocusTarget,
grabs::{ReleaseMode, ResizeEdge}, grabs::{GrabType, ReleaseMode, ResizeEdge},
layout::tiling::NodeDesc, layout::tiling::NodeDesc,
}, },
state::State, state::State,
@ -38,7 +38,7 @@ use shortcuts::action::{Direction, FocusDirection};
use smithay::{ use smithay::{
backend::{ backend::{
drm::DrmNode, drm::DrmNode,
input::{InputTime, KeyState}, input::{InputTime, KeyState, TabletToolDescriptor},
renderer::{ renderer::{
ImportAll, ImportMem, Renderer, ImportAll, ImportMem, Renderer,
element::{Element, Id as RendererId, Kind, RenderElement, UnderlyingStorage}, element::{Element, Id as RendererId, Kind, RenderElement, UnderlyingStorage},
@ -52,14 +52,23 @@ use smithay::{
Seat, Seat,
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
pointer::{ pointer::{
AxisFrame, ButtonEvent, CursorImageStatus, GestureHoldBeginEvent, GestureHoldEndEvent, AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorImageStatus,
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent,
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent,
PointerTarget, RelativeMotionEvent, PointerTarget, RelativeMotionEvent,
}, },
tablet::{
Tablet, TabletSeatTrait,
tool::{
AxisFrame as ToolAxisFrame, ButtonEvent as ToolButtonEvent,
DownEvent as ToolDownEvent, MotionEvent as ToolMotionEvent, TabletToolTarget,
UpEvent as ToolUpEvent,
},
},
touch::{ touch::{
DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent,
TouchTarget, UpEvent, OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent,
}, },
}, },
output::Output, output::Output,
@ -909,12 +918,19 @@ impl CosmicStack {
false, false,
); );
if let Some((grab, focus)) = res { if let Some((grab, focus)) = res {
if grab.is_touch_grab() { match grab.grab_type() {
seat.get_touch().unwrap().set_grab(state, grab, serial); GrabType::Touch => {
} else { seat.get_touch().unwrap().set_grab(state, grab, serial)
seat.get_pointer() }
GrabType::Pointer => seat
.get_pointer()
.unwrap() .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, false,
); );
if let Some((grab, focus)) = res { if let Some((grab, focus)) = res {
if grab.is_touch_grab() { match grab.grab_type() {
seat.get_touch().unwrap().set_grab(state, grab, serial); GrabType::Touch => {
} else { seat.get_touch().unwrap().set_grab(state, grab, serial)
seat.get_pointer() }
GrabType::Pointer => seat
.get_pointer()
.unwrap() .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<State> for CosmicStack {
} }
impl PointerTarget<State> for CosmicStack { impl PointerTarget<State> for CosmicStack {
fn enter(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) { fn enter(&self, seat: &Seat<State>, data: &mut State, event: &PointerMotionEvent) {
let mut event = event.clone(); let mut event = event.clone();
self.0.with_program(|p| { self.0.with_program(|p| {
let active_window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; let active_window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)];
@ -1625,7 +1648,7 @@ impl PointerTarget<State> for CosmicStack {
PointerTarget::enter(&self.0, seat, data, &event) PointerTarget::enter(&self.0, seat, data, &event)
} }
fn motion(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) { fn motion(&self, seat: &Seat<State>, data: &mut State, event: &PointerMotionEvent) {
let mut event = event.clone(); let mut event = event.clone();
self.0.with_program(|p| { self.0.with_program(|p| {
let active = p.active.load(Ordering::SeqCst); let active = p.active.load(Ordering::SeqCst);
@ -1668,7 +1691,7 @@ impl PointerTarget<State> for CosmicStack {
) { ) {
} }
fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) { fn button(&self, seat: &Seat<State>, data: &mut State, event: &PointerButtonEvent) {
match self.0.with_program(|p| p.current_focus()) { match self.0.with_program(|p| p.current_focus()) {
Some(Focus::Header) => PointerTarget::button(&self.0, seat, data, event), Some(Focus::Header) => PointerTarget::button(&self.0, seat, data, event),
Some(x) => { Some(x) => {
@ -1700,12 +1723,19 @@ impl PointerTarget<State> for CosmicStack {
false, false,
); );
if let Some((grab, focus)) = res { if let Some((grab, focus)) = res {
if grab.is_touch_grab() { match grab.grab_type() {
seat.get_touch().unwrap().set_grab(state, grab, serial); GrabType::Touch => {
} else { seat.get_touch().unwrap().set_grab(state, grab, serial)
seat.get_pointer() }
GrabType::Pointer => seat
.get_pointer()
.unwrap() .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<State> for CosmicStack {
} }
} }
fn axis(&self, seat: &Seat<State>, data: &mut State, frame: AxisFrame) { fn axis(&self, seat: &Seat<State>, data: &mut State, frame: PointerAxisFrame) {
if let Some(Focus::Header) = self.0.with_program(|p| p.current_focus()) { if let Some(Focus::Header) = self.0.with_program(|p| p.current_focus()) {
PointerTarget::axis(&self.0, seat, data, frame) PointerTarget::axis(&self.0, seat, data, frame)
} }
@ -1763,12 +1793,19 @@ impl PointerTarget<State> for CosmicStack {
false, false,
); );
if let Some((grab, focus)) = res { if let Some((grab, focus)) = res {
if grab.is_touch_grab() { match grab.grab_type() {
seat.get_touch().unwrap().set_grab(state, grab, serial); GrabType::Touch => {
} else { seat.get_touch().unwrap().set_grab(state, grab, serial)
seat.get_pointer() }
GrabType::Pointer => seat
.get_pointer()
.unwrap() .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<State> for CosmicStack {
} }
impl TouchTarget<State> for CosmicStack { impl TouchTarget<State> for CosmicStack {
fn down(&self, seat: &Seat<State>, data: &mut State, event: &DownEvent) { fn down(&self, seat: &Seat<State>, data: &mut State, event: &TouchDownEvent) {
let mut event = event.clone(); let mut event = event.clone();
let active_window_geo = self.0.with_program(|p| { let active_window_geo = self.0.with_program(|p| {
p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].geometry() p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].geometry()
@ -1853,7 +1890,7 @@ impl TouchTarget<State> for CosmicStack {
TouchTarget::down(&self.0, seat, data, &event) TouchTarget::down(&self.0, seat, data, &event)
} }
fn up(&self, seat: &Seat<State>, data: &mut State, event: &UpEvent) { fn up(&self, seat: &Seat<State>, data: &mut State, event: &TouchUpEvent) {
TouchTarget::up(&self.0, seat, data, event) TouchTarget::up(&self.0, seat, data, event)
} }
@ -1901,6 +1938,101 @@ impl TouchTarget<State> for CosmicStack {
} }
} }
impl TabletToolTarget<State> for CosmicStack {
fn proximity_in(
&self,
seat: &Seat<State>,
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<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
) {
TabletToolTarget::proximity_out(&self.0, seat, data, tool_descriptor)
}
fn down(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolDownEvent,
) {
TabletToolTarget::down(&self.0, seat, data, tool_descriptor, event)
}
fn up(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolUpEvent,
) {
TabletToolTarget::up(&self.0, seat, data, tool_descriptor, event)
}
fn motion(
&self,
seat: &Seat<State>,
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<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
frame: ToolAxisFrame,
) {
TabletToolTarget::axis(&self.0, seat, data, tool_descriptor, frame)
}
fn button(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolButtonEvent,
) {
TabletToolTarget::button(&self.0, seat, data, tool_descriptor, event)
}
fn frame(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
time: InputTime,
) {
TabletToolTarget::frame(&self.0, seat, data, tool_descriptor, time)
}
}
pub enum CosmicStackRenderElement<R: Renderer + ImportAll + ImportMem> { pub enum CosmicStackRenderElement<R: Renderer + ImportAll + ImportMem> {
Header(IcedRenderElement<R>), Header(IcedRenderElement<R>),
Shadow(PixelShaderElement), Shadow(PixelShaderElement),

View file

@ -7,7 +7,7 @@ use crate::{
shell::{ shell::{
element::{CosmicMappedKey, CosmicMappedKeyInner}, element::{CosmicMappedKey, CosmicMappedKeyInner},
focus::target::PointerFocusTarget, focus::target::PointerFocusTarget,
grabs::{ReleaseMode, ResizeEdge}, grabs::{GrabType, ReleaseMode, ResizeEdge},
}, },
state::State, state::State,
utils::{ utils::{
@ -21,7 +21,7 @@ use cosmic_comp_config::AppearanceConfig;
use smithay::{ use smithay::{
backend::{ backend::{
drm::DrmNode, drm::DrmNode,
input::{InputTime, KeyState}, input::{InputTime, KeyState, TabletToolDescriptor},
renderer::{ renderer::{
ImportAll, ImportMem, Renderer, ImportAll, ImportMem, Renderer,
element::{Element, Id as RendererId, Kind, RenderElement, UnderlyingStorage}, element::{Element, Id as RendererId, Kind, RenderElement, UnderlyingStorage},
@ -35,14 +35,23 @@ use smithay::{
Seat, Seat,
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
pointer::{ pointer::{
AxisFrame, ButtonEvent, CursorIcon, CursorImageStatus, GestureHoldBeginEvent, AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorIcon,
GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchEndEvent, CursorImageStatus, GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent,
GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent,
GestureSwipeUpdateEvent, MotionEvent, PointerTarget, RelativeMotionEvent, 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::{ touch::{
DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent,
TouchTarget, UpEvent, OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent,
}, },
}, },
output::Output, output::Output,
@ -746,12 +755,19 @@ impl Program for CosmicWindowInternal {
false, false,
); );
if let Some((grab, focus)) = res { if let Some((grab, focus)) = res {
if grab.is_touch_grab() { match grab.grab_type() {
seat.get_touch().unwrap().set_grab(state, grab, serial); GrabType::Touch => {
} else { seat.get_touch().unwrap().set_grab(state, grab, serial)
seat.get_pointer() }
GrabType::Pointer => seat
.get_pointer()
.unwrap() .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<State> for CosmicWindow {
} }
impl PointerTarget<State> for CosmicWindow { impl PointerTarget<State> for CosmicWindow {
fn enter(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) { fn enter(&self, seat: &Seat<State>, data: &mut State, event: &PointerMotionEvent) {
let mut event = event.clone(); let mut event = event.clone();
self.0.with_program(|p| { self.0.with_program(|p| {
let has_ssd = p.has_ssd(false); let has_ssd = p.has_ssd(false);
@ -1029,7 +1045,7 @@ impl PointerTarget<State> for CosmicWindow {
PointerTarget::enter(&self.0, seat, data, &event) PointerTarget::enter(&self.0, seat, data, &event)
} }
fn motion(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) { fn motion(&self, seat: &Seat<State>, data: &mut State, event: &PointerMotionEvent) {
let mut event = event.clone(); let mut event = event.clone();
self.0.with_program(|p| { self.0.with_program(|p| {
let has_ssd = p.has_ssd(false); let has_ssd = p.has_ssd(false);
@ -1061,7 +1077,7 @@ impl PointerTarget<State> for CosmicWindow {
) { ) {
} }
fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) { fn button(&self, seat: &Seat<State>, data: &mut State, event: &PointerButtonEvent) {
match self.0.with_program(|p| p.current_focus()) { match self.0.with_program(|p| p.current_focus()) {
Some(Focus::Header) => PointerTarget::button(&self.0, seat, data, event), Some(Focus::Header) => PointerTarget::button(&self.0, seat, data, event),
Some(x) => { Some(x) => {
@ -1098,12 +1114,19 @@ impl PointerTarget<State> for CosmicWindow {
); );
if let Some((grab, focus)) = res { if let Some((grab, focus)) = res {
if grab.is_touch_grab() { match grab.grab_type() {
seat.get_touch().unwrap().set_grab(state, grab, serial); GrabType::Touch => {
} else { seat.get_touch().unwrap().set_grab(state, grab, serial)
seat.get_pointer() }
GrabType::Pointer => seat
.get_pointer()
.unwrap() .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<State> for CosmicWindow {
} }
} }
fn axis(&self, seat: &Seat<State>, data: &mut State, frame: AxisFrame) { fn axis(&self, seat: &Seat<State>, data: &mut State, frame: PointerAxisFrame) {
if let Some(Focus::Header) = self.0.with_program(|p| p.current_focus()) { if let Some(Focus::Header) = self.0.with_program(|p| p.current_focus()) {
PointerTarget::axis(&self.0, seat, data, frame) PointerTarget::axis(&self.0, seat, data, frame)
} }
@ -1199,7 +1222,7 @@ impl PointerTarget<State> for CosmicWindow {
} }
impl TouchTarget<State> for CosmicWindow { impl TouchTarget<State> for CosmicWindow {
fn down(&self, seat: &Seat<State>, data: &mut State, event: &DownEvent) { fn down(&self, seat: &Seat<State>, data: &mut State, event: &TouchDownEvent) {
let mut event = event.clone(); let mut event = event.clone();
self.0.with_program(|p| { self.0.with_program(|p| {
event.location -= p.window.geometry().loc.to_f64(); event.location -= p.window.geometry().loc.to_f64();
@ -1207,7 +1230,7 @@ impl TouchTarget<State> for CosmicWindow {
TouchTarget::down(&self.0, seat, data, &event) TouchTarget::down(&self.0, seat, data, &event)
} }
fn up(&self, seat: &Seat<State>, data: &mut State, event: &UpEvent) { fn up(&self, seat: &Seat<State>, data: &mut State, event: &TouchUpEvent) {
TouchTarget::up(&self.0, seat, data, event) TouchTarget::up(&self.0, seat, data, event)
} }
@ -1238,6 +1261,88 @@ impl TouchTarget<State> for CosmicWindow {
} }
} }
impl TabletToolTarget<State> for CosmicWindow {
fn proximity_in(
&self,
seat: &Seat<State>,
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<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
) {
TabletToolTarget::proximity_out(&self.0, seat, data, tool_descriptor)
}
fn down(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolDownEvent,
) {
TabletToolTarget::down(&self.0, seat, data, tool_descriptor, event)
}
fn up(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolUpEvent,
) {
TabletToolTarget::up(&self.0, seat, data, tool_descriptor, event)
}
fn motion(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolMotionEvent,
) {
TabletToolTarget::motion(&self.0, seat, data, tool_descriptor, event)
}
fn axis(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
frame: ToolAxisFrame,
) {
TabletToolTarget::axis(&self.0, seat, data, tool_descriptor, frame)
}
fn button(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolButtonEvent,
) {
TabletToolTarget::button(&self.0, seat, data, tool_descriptor, event)
}
fn frame(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
time: InputTime,
) {
TabletToolTarget::frame(&self.0, seat, data, tool_descriptor, time)
}
}
impl WaylandFocus for CosmicWindow { impl WaylandFocus for CosmicWindow {
fn wl_surface(&self) -> Option<Cow<'_, WlSurface>> { fn wl_surface(&self) -> Option<Cow<'_, WlSurface>> {
self.0.with_program(|p| { self.0.with_program(|p| {

View file

@ -16,21 +16,30 @@ use crate::{
}; };
use id_tree::NodeId; use id_tree::NodeId;
use smithay::{ use smithay::{
backend::input::{InputTime, KeyState}, backend::input::{InputTime, KeyState, TabletToolDescriptor},
desktop::{LayerSurface, PopupKind, WindowSurface, WindowSurfaceType, space::SpaceElement}, desktop::{LayerSurface, PopupKind, WindowSurface, WindowSurfaceType, space::SpaceElement},
input::{ input::{
Seat, Seat,
dnd::{DndFocus, OfferData, Source}, dnd::{DndFocus, OfferData, Source},
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
pointer::{ pointer::{
AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent,
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent,
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent,
MotionEvent as PointerMotionEvent, PointerTarget, RelativeMotionEvent, 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::{ touch::{
DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent,
TouchTarget, UpEvent, OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent,
}, },
}, },
reexports::wayland_server::{ reexports::wayland_server::{
@ -164,6 +173,17 @@ impl PointerFocusTarget {
} }
} }
fn inner_tablet_tool_target(&self) -> &dyn TabletToolTarget<State> {
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<P: Into<Point<f64, Logical>>>( pub fn under_surface<P: Into<Point<f64, Logical>>>(
surface: &CosmicSurface, surface: &CosmicSurface,
point: P, point: P,
@ -409,10 +429,10 @@ impl PointerTarget<State> for PointerFocusTarget {
self.inner_pointer_target() self.inner_pointer_target()
.relative_motion(seat, data, event); .relative_motion(seat, data, event);
} }
fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) { fn button(&self, seat: &Seat<State>, data: &mut State, event: &PointerButtonEvent) {
self.inner_pointer_target().button(seat, data, event); self.inner_pointer_target().button(seat, data, event);
} }
fn axis(&self, seat: &Seat<State>, data: &mut State, frame: AxisFrame) { fn axis(&self, seat: &Seat<State>, data: &mut State, frame: PointerAxisFrame) {
self.inner_pointer_target().axis(seat, data, frame); self.inner_pointer_target().axis(seat, data, frame);
} }
fn frame(&self, seat: &Seat<State>, data: &mut State) { fn frame(&self, seat: &Seat<State>, data: &mut State) {
@ -498,12 +518,102 @@ impl PointerTarget<State> for PointerFocusTarget {
} }
} }
impl TabletToolTarget<State> for PointerFocusTarget {
fn proximity_in(
&self,
seat: &Seat<State>,
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<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
) {
self.inner_tablet_tool_target()
.proximity_out(seat, data, tool_descriptor);
}
fn down(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolDownEvent,
) {
self.inner_tablet_tool_target()
.down(seat, data, tool_descriptor, event);
}
fn up(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolUpEvent,
) {
self.inner_tablet_tool_target()
.up(seat, data, tool_descriptor, event);
}
fn motion(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolMotionEvent,
) {
self.inner_tablet_tool_target()
.motion(seat, data, tool_descriptor, event);
}
fn axis(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
frame: ToolAxisFrame,
) {
self.inner_tablet_tool_target()
.axis(seat, data, tool_descriptor, frame);
}
fn button(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolButtonEvent,
) {
self.inner_tablet_tool_target()
.button(seat, data, tool_descriptor, event);
}
fn frame(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
time: InputTime,
) {
self.inner_tablet_tool_target()
.frame(seat, data, tool_descriptor, time);
}
}
impl TouchTarget<State> for PointerFocusTarget { impl TouchTarget<State> for PointerFocusTarget {
fn down(&self, seat: &Seat<State>, data: &mut State, event: &DownEvent) { fn down(&self, seat: &Seat<State>, data: &mut State, event: &TouchDownEvent) {
self.inner_touch_target().down(seat, data, event); self.inner_touch_target().down(seat, data, event);
} }
fn up(&self, seat: &Seat<State>, data: &mut State, event: &UpEvent) { fn up(&self, seat: &Seat<State>, data: &mut State, event: &TouchUpEvent) {
self.inner_touch_target().up(seat, data, event); self.inner_touch_target().up(seat, data, event);
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -7,25 +7,36 @@ use crate::{
shell::{ shell::{
element::CosmicMapped, element::CosmicMapped,
focus::target::PointerFocusTarget, focus::target::PointerFocusTarget,
grabs::{GrabStartData, ReleaseMode, ResizeEdge}, grabs::{GrabStartData, GrabType, ReleaseMode, ResizeEdge},
}, },
utils::prelude::*, utils::prelude::*,
}; };
use smithay::{ use smithay::{
backend::input::ButtonState, backend::input::{ButtonState, InputTime, TabletToolDescriptor},
desktop::{WindowSurface, space::SpaceElement}, desktop::{WindowSurface, space::SpaceElement},
input::{ input::{
Seat, Seat,
pointer::{ pointer::{
AxisFrame, ButtonEvent, CursorIcon, GestureHoldBeginEvent, GestureHoldEndEvent, AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorIcon,
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent,
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent,
GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle, GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData,
MotionEvent as PointerMotionEvent, PointerGrab, PointerInnerHandle,
RelativeMotionEvent, 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::{ touch::{
DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent, DownEvent as TouchDownEvent, GrabStartData as TouchGrabStartData,
OrientationEvent, ShapeEvent, TouchGrab, TouchInnerHandle, UpEvent, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab,
TouchInnerHandle, UpEvent as TouchUpEvent,
}, },
}, },
output::Output, output::Output,
@ -170,10 +181,19 @@ impl ResizeSurfaceGrab {
false false
} }
pub fn is_touch_grab(&self) -> bool { pub fn grab_type(&self) -> GrabType {
match self.start_data { match self.start_data {
GrabStartData::Touch(_) => true, GrabStartData::Pointer(_) => GrabType::Pointer,
GrabStartData::Pointer(_) => false, 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<State> for ResizeSurfaceGrab {
data: &mut State, data: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
_focus: Option<(PointerFocusTarget, Point<f64, Logical>)>, _focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &MotionEvent, event: &PointerMotionEvent,
) { ) {
// While the grab is active, no client has pointer focus // While the grab is active, no client has pointer focus
handle.motion(data, None, event); handle.motion(data, None, event);
@ -209,7 +229,7 @@ impl PointerGrab<State> for ResizeSurfaceGrab {
&mut self, &mut self,
data: &mut State, data: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
event: &ButtonEvent, event: &PointerButtonEvent,
) { ) {
handle.button(data, event); handle.button(data, event);
match self.release { match self.release {
@ -230,7 +250,7 @@ impl PointerGrab<State> for ResizeSurfaceGrab {
&mut self, &mut self,
data: &mut State, data: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
details: AxisFrame, details: PointerAxisFrame,
) { ) {
handle.axis(data, details) handle.axis(data, details)
} }
@ -329,12 +349,17 @@ impl TouchGrab<State> for ResizeSurfaceGrab {
data: &mut State, data: &mut State,
handle: &mut TouchInnerHandle<'_, State>, handle: &mut TouchInnerHandle<'_, State>,
_focus: Option<(PointerFocusTarget, Point<f64, Logical>)>, _focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &DownEvent, event: &TouchDownEvent,
) { ) {
handle.down(data, None, event) 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 == <Self as TouchGrab<State>>::start_data(self).slot { if event.slot == <Self as TouchGrab<State>>::start_data(self).slot {
handle.unset_grab(self, data); handle.unset_grab(self, data);
} }
@ -396,6 +421,99 @@ impl TouchGrab<State> for ResizeSurfaceGrab {
} }
} }
impl TabletToolGrab<State> for ResizeSurfaceGrab {
fn start_data(&self) -> &TabletGrabStartData<State> {
match &self.start_data {
GrabStartData::TabletTool { data, .. } => data,
_ => unreachable!(),
}
}
fn proximity_out(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &ProximityOutEvent,
) {
handle.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<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
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<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &ProximityInEvent,
) {
handle.proximity_in(data, None, event);
}
}
pub struct ResizeGrabMarker(AtomicBool); pub struct ResizeGrabMarker(AtomicBool);
impl ResizeGrabMarker { impl ResizeGrabMarker {

View file

@ -1,34 +1,47 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use std::cell::Cell;
use crate::{ use crate::{
backend::render::cursor::CursorState, backend::render::cursor::CursorState,
shell::{ shell::{
focus::target::PointerFocusTarget, focus::target::PointerFocusTarget,
grabs::{GrabStartData, ReleaseMode}, grabs::{GrabStartData, GrabType, ReleaseMode},
layout::Orientation, layout::Orientation,
}, },
utils::prelude::*, utils::prelude::*,
}; };
use id_tree::{NodeId, Tree}; use id_tree::{NodeId, Tree};
use smithay::{ use smithay::{
backend::input::{ButtonState, InputTime}, backend::input::{ButtonState, InputTime, TabletToolDescriptor},
input::{ input::{
Seat, Seat,
pointer::{ pointer::{
AxisFrame, ButtonEvent, CursorIcon, Focus, GestureHoldBeginEvent, GestureHoldEndEvent, AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorIcon, Focus,
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent,
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent,
GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle, GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData,
PointerTarget, RelativeMotionEvent, 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::{ touch::{
DownEvent, FrameMarker, GrabStartData as TouchGrabStartData, DownEvent as TouchDownEvent, FrameMarker, GrabStartData as TouchGrabStartData,
MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab,
TouchInnerHandle, TouchTarget, UpEvent, TouchInnerHandle, TouchTarget, UpEvent as TouchUpEvent,
}, },
}, },
output::WeakOutput, output::WeakOutput,
utils::{IsAlive, Logical, Point}, utils::{IsAlive, Logical, Point, Serial},
}; };
use super::super::{Data, TilingLayout}; use super::super::{Data, TilingLayout};
@ -39,6 +52,7 @@ pub struct ResizeForkTarget {
pub output: WeakOutput, pub output: WeakOutput,
pub left_up_idx: usize, pub left_up_idx: usize,
pub orientation: Orientation, pub orientation: Orientation,
pub last_tablet_location: Cell<Option<Point<f64, Global>>>,
} }
impl IsAlive for ResizeForkTarget { impl IsAlive for ResizeForkTarget {
@ -48,7 +62,7 @@ impl IsAlive for ResizeForkTarget {
} }
impl PointerTarget<State> for ResizeForkTarget { impl PointerTarget<State> for ResizeForkTarget {
fn enter(&self, seat: &Seat<State>, _data: &mut State, _event: &MotionEvent) { fn enter(&self, seat: &Seat<State>, _data: &mut State, _event: &PointerMotionEvent) {
let user_data = seat.user_data(); let user_data = seat.user_data();
let cursor_state = user_data.get::<CursorState>().unwrap(); let cursor_state = user_data.get::<CursorState>().unwrap();
cursor_state cursor_state
@ -60,19 +74,13 @@ impl PointerTarget<State> for ResizeForkTarget {
}); });
} }
fn leave( fn leave(&self, seat: &Seat<State>, _data: &mut State, _serial: Serial, _time: InputTime) {
&self,
seat: &Seat<State>,
_data: &mut State,
_serial: smithay::utils::Serial,
_time: InputTime,
) {
let user_data = seat.user_data(); let user_data = seat.user_data();
let cursor_state = user_data.get::<CursorState>().unwrap(); let cursor_state = user_data.get::<CursorState>().unwrap();
cursor_state.lock().unwrap().unset_shape(); cursor_state.lock().unwrap().unset_shape();
} }
fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) { fn button(&self, seat: &Seat<State>, data: &mut State, event: &PointerButtonEvent) {
if event.button == 0x110 && event.state == ButtonState::Pressed { if event.button == 0x110 && event.state == ButtonState::Pressed {
let seat = seat.clone(); let seat = seat.clone();
let node = self.node.clone(); let node = self.node.clone();
@ -106,7 +114,7 @@ impl PointerTarget<State> for ResizeForkTarget {
} }
} }
fn motion(&self, _seat: &Seat<State>, _data: &mut State, _event: &MotionEvent) {} fn motion(&self, _seat: &Seat<State>, _data: &mut State, _event: &PointerMotionEvent) {}
fn relative_motion( fn relative_motion(
&self, &self,
_seat: &Seat<State>, _seat: &Seat<State>,
@ -114,7 +122,7 @@ impl PointerTarget<State> for ResizeForkTarget {
_event: &RelativeMotionEvent, _event: &RelativeMotionEvent,
) { ) {
} }
fn axis(&self, _seat: &Seat<State>, _data: &mut State, _frame: AxisFrame) {} fn axis(&self, _seat: &Seat<State>, _data: &mut State, _frame: PointerAxisFrame) {}
fn frame(&self, _seat: &Seat<State>, _data: &mut State) {} fn frame(&self, _seat: &Seat<State>, _data: &mut State) {}
fn gesture_swipe_begin(&self, _: &Seat<State>, _: &mut State, _: &GestureSwipeBeginEvent) {} fn gesture_swipe_begin(&self, _: &Seat<State>, _: &mut State, _: &GestureSwipeBeginEvent) {}
fn gesture_swipe_update(&self, _: &Seat<State>, _: &mut State, _: &GestureSwipeUpdateEvent) {} fn gesture_swipe_update(&self, _: &Seat<State>, _: &mut State, _: &GestureSwipeUpdateEvent) {}
@ -127,7 +135,7 @@ impl PointerTarget<State> for ResizeForkTarget {
} }
impl TouchTarget<State> for ResizeForkTarget { impl TouchTarget<State> for ResizeForkTarget {
fn down(&self, seat: &Seat<State>, data: &mut State, event: &DownEvent) { fn down(&self, seat: &Seat<State>, data: &mut State, event: &TouchDownEvent) {
let seat = seat.clone(); let seat = seat.clone();
let node = self.node.clone(); let node = self.node.clone();
let output = self.output.clone(); let output = self.output.clone();
@ -158,7 +166,7 @@ impl TouchTarget<State> for ResizeForkTarget {
}); });
} }
fn up(&self, _seat: &Seat<State>, _data: &mut State, _event: &UpEvent) {} fn up(&self, _seat: &Seat<State>, _data: &mut State, _event: &TouchUpEvent) {}
fn motion(&self, _seat: &Seat<State>, _data: &mut State, _event: &TouchMotionEvent) {} fn motion(&self, _seat: &Seat<State>, _data: &mut State, _event: &TouchMotionEvent) {}
fn frame(&self, _seat: &Seat<State>, _data: &mut State, _frame: FrameMarker) {} fn frame(&self, _seat: &Seat<State>, _data: &mut State, _frame: FrameMarker) {}
fn cancel(&self, _seat: &Seat<State>, _data: &mut State, _frame: FrameMarker) {} fn cancel(&self, _seat: &Seat<State>, _data: &mut State, _frame: FrameMarker) {}
@ -169,6 +177,113 @@ impl TouchTarget<State> for ResizeForkTarget {
} }
} }
impl TabletToolTarget<State> for ResizeForkTarget {
fn down(
&self,
seat: &Seat<State>,
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<State>,
_data: &mut State,
_tool_descriptor: &TabletToolDescriptor,
event: &TabletMotionEvent,
) {
self.last_tablet_location
.set(Some(event.location.as_global()))
}
fn proximity_out(
&self,
_seat: &Seat<State>,
_data: &mut State,
_tool_descriptor: &TabletToolDescriptor,
) {
self.last_tablet_location.set(None);
}
fn proximity_in(
&self,
_seat: &Seat<State>,
_data: &mut State,
_tool_descriptor: &TabletToolDescriptor,
_tablet: &Tablet,
_serial: Serial,
) {
}
fn up(
&self,
_seat: &Seat<State>,
_data: &mut State,
_tool_descriptor: &TabletToolDescriptor,
_event: &TabletUpEvent,
) {
}
fn axis(
&self,
_seat: &Seat<State>,
_data: &mut State,
_tool_descriptor: &TabletToolDescriptor,
_frame: TabletAxisFrame,
) {
}
fn button(
&self,
_seat: &Seat<State>,
_data: &mut State,
_tool_descriptor: &TabletToolDescriptor,
_event: &TabletButtonEvent,
) {
}
fn frame(
&self,
_seat: &Seat<State>,
_data: &mut State,
_tool_descriptor: &TabletToolDescriptor,
_time: InputTime,
) {
}
}
pub struct ResizeForkGrab { pub struct ResizeForkGrab {
start_data: GrabStartData, start_data: GrabStartData,
last_loc: Point<f64, Global>, last_loc: Point<f64, Global>,
@ -338,10 +453,19 @@ impl ResizeForkGrab {
false false
} }
pub fn is_touch_grab(&self) -> bool { pub fn grab_type(&self) -> GrabType {
match self.start_data { match self.start_data {
GrabStartData::Touch(_) => true, GrabStartData::Pointer(_) => GrabType::Pointer,
GrabStartData::Pointer(_) => false, 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<State> for ResizeForkGrab {
data: &mut State, data: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
_focus: Option<(PointerFocusTarget, Point<f64, Logical>)>, _focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &MotionEvent, event: &PointerMotionEvent,
) { ) {
// While the grab is active, no client has pointer focus // While the grab is active, no client has pointer focus
handle.motion(data, None, event); handle.motion(data, None, event);
@ -377,7 +501,7 @@ impl PointerGrab<State> for ResizeForkGrab {
&mut self, &mut self,
data: &mut State, data: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
event: &ButtonEvent, event: &PointerButtonEvent,
) { ) {
handle.button(data, event); handle.button(data, event);
match self.release { match self.release {
@ -398,7 +522,7 @@ impl PointerGrab<State> for ResizeForkGrab {
&mut self, &mut self,
data: &mut State, data: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
details: AxisFrame, details: PointerAxisFrame,
) { ) {
handle.axis(data, details) handle.axis(data, details)
} }
@ -497,12 +621,17 @@ impl TouchGrab<State> for ResizeForkGrab {
data: &mut State, data: &mut State,
handle: &mut TouchInnerHandle<'_, State>, handle: &mut TouchInnerHandle<'_, State>,
_focus: Option<(PointerFocusTarget, Point<f64, Logical>)>, _focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &DownEvent, event: &TouchDownEvent,
) { ) {
handle.down(data, None, event) 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 == <Self as TouchGrab<State>>::start_data(self).slot { if event.slot == <Self as TouchGrab<State>>::start_data(self).slot {
handle.unset_grab(self, data); handle.unset_grab(self, data);
} }
@ -563,3 +692,96 @@ impl TouchGrab<State> for ResizeForkGrab {
self.update_location(data, self.last_loc.as_logical(), true); self.update_location(data, self.last_loc.as_logical(), true);
} }
} }
impl TabletToolGrab<State> for ResizeForkGrab {
fn start_data(&self) -> &TabletToolGrabStartData<State> {
match &self.start_data {
GrabStartData::TabletTool { data, .. } => data,
_ => unreachable!(),
}
}
fn proximity_out(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &ProximityOutEvent,
) {
handle.proximity_out(data, event);
handle.unset_grab(self, data, event.serial, event.time, true);
}
fn motion(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
_focus: Option<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &TabletMotionEvent,
) {
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<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &ProximityInEvent,
) {
handle.proximity_in(data, focus, event);
}
}

View file

@ -67,6 +67,7 @@ use smithay::{
wayland::{compositor::add_blocker, seat::WaylandFocus}, wayland::{compositor::add_blocker, seat::WaylandFocus},
}; };
use std::{ use std::{
cell::Cell,
collections::{HashMap, VecDeque}, collections::{HashMap, VecDeque},
sync::{Arc, Weak}, sync::{Arc, Weak},
time::{Duration, Instant}, time::{Duration, Instant},
@ -3348,6 +3349,7 @@ impl TilingLayout {
output: self.output.downgrade(), output: self.output.downgrade(),
left_up_idx: idx, left_up_idx: idx,
orientation, orientation,
last_tablet_location: Cell::new(None),
} }
.into(), .into(),
(last_geometry.loc (last_geometry.loc
@ -3381,7 +3383,7 @@ impl TilingLayout {
let Some(root) = tree.root_node_id() else { let Some(root) = tree.root_node_id() else {
if matches!( if matches!(
overview.active_trigger(), overview.active_trigger(),
Some(Trigger::Pointer(_) | Trigger::Touch(_)) Some(Trigger::Pointer(_) | Trigger::Touch(_) | Trigger::Tool(_, _))
) && location_f64.is_some() ) && location_f64.is_some()
{ {
let mut tree = tree.copy_clone(); let mut tree = tree.copy_clone();
@ -3414,7 +3416,7 @@ impl TilingLayout {
if matches!( if matches!(
overview.active_trigger(), 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) let non_exclusive_zone = layer_map_for_output(&self.output)
.non_exclusive_zone() .non_exclusive_zone()
@ -4062,8 +4064,11 @@ impl TilingLayout {
let draw_groups = overview.0.alpha(); let draw_groups = overview.0.alpha();
let is_overview = !matches!(overview.0, OverviewMode::None); let is_overview = !matches!(overview.0, OverviewMode::None);
let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_)))) let is_mouse_tiling = (matches!(
.then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone)); 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() { let swap_desc = if let Some(Trigger::KeyboardSwap(_, desc)) = overview.0.trigger() {
Some(desc.clone()) Some(desc.clone())
} else { } else {
@ -4216,8 +4221,11 @@ impl TilingLayout {
}; };
let draw_groups = overview.0.alpha(); let draw_groups = overview.0.alpha();
let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_)))) let is_mouse_tiling = (matches!(
.then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone)); 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() { let swap_desc = if let Some(Trigger::KeyboardSwap(_, desc)) = overview.0.trigger() {
Some(desc.clone()) Some(desc.clone())
} else { } else {

View file

@ -32,7 +32,10 @@ use cosmic_settings_config::shortcuts::action::{Direction, FocusDirection, Resiz
use cosmic_settings_config::{shortcuts, window_rules::ApplicationException}; use cosmic_settings_config::{shortcuts, window_rules::ApplicationException};
use keyframe::{ease, functions::EaseInOutCubic}; use keyframe::{ease, functions::EaseInOutCubic};
use smithay::{ use smithay::{
backend::{input::TouchSlot, renderer::element::RenderElementStates}, backend::{
input::{TabletToolDescriptor, TouchSlot},
renderer::element::RenderElementStates,
},
desktop::{ desktop::{
LayerSurface, PopupKind, WindowSurface, WindowSurfaceType, layer_map_for_output, LayerSurface, PopupKind, WindowSurface, WindowSurfaceType, layer_map_for_output,
space::SpaceElement, space::SpaceElement,
@ -46,6 +49,7 @@ use smithay::{
pointer::{ pointer::{
CursorImageStatus, CursorImageSurfaceData, Focus, GrabStartData as PointerGrabStartData, CursorImageStatus, CursorImageSurfaceData, Focus, GrabStartData as PointerGrabStartData,
}, },
tablet::tool::GrabTrigger as TabletGrabTrigger,
}, },
output::{Output, WeakOutput}, output::{Output, WeakOutput},
reexports::{ reexports::{
@ -130,6 +134,7 @@ pub enum Trigger {
KeyboardMove(shortcuts::Modifiers), KeyboardMove(shortcuts::Modifiers),
Pointer(u32), Pointer(u32),
Touch(TouchSlot), Touch(TouchSlot),
Tool(TabletToolDescriptor, TabletGrabTrigger),
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -1755,7 +1760,7 @@ impl Shell {
if let Some(set) = self.workspaces.sets.get_mut(output) { if let Some(set) = self.workspaces.sets.get_mut(output) {
if matches!( if matches!(
self.overview_mode.active_trigger(), 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(); 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 let Some(set) = self.workspaces.sets.get_mut(output) {
if matches!( if matches!(
self.overview_mode.active_trigger(), 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(); set.workspaces[set.active].tiling_layer.cleanup_drag();
} }
@ -3840,6 +3845,7 @@ impl Shell {
let trigger = match &start_data { let trigger = match &start_data {
GrabStartData::Pointer(start_data) => Trigger::Pointer(start_data.button), GrabStartData::Pointer(start_data) => Trigger::Pointer(start_data.button),
GrabStartData::Touch(start_data) => Trigger::Touch(start_data.slot), 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 { let active_hint = if config.cosmic_conf.active_hint {
self.theme.cosmic().active_hint as u8 self.theme.cosmic().active_hint as u8

View file

@ -11,19 +11,31 @@ use cosmic_comp_config::{ZoomConfig, ZoomMovement};
use cosmic_config::ConfigSet; use cosmic_config::ConfigSet;
use keyframe::{ease, functions::Linear}; use keyframe::{ease, functions::Linear};
use smithay::{ use smithay::{
backend::{input::InputTime, renderer::ImportMem}, backend::{
input::{InputTime, TabletToolDescriptor},
renderer::ImportMem,
},
desktop::space::SpaceElement, desktop::space::SpaceElement,
input::{ input::{
Seat, Seat,
pointer::{ pointer::{
AxisFrame, ButtonEvent, Focus, GestureHoldBeginEvent, GestureHoldEndEvent, AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, Focus,
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent,
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent,
MotionEvent as PointerMotionEvent, PointerTarget, RelativeMotionEvent, 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::{ touch::{
DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent,
TouchTarget, UpEvent, OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent,
}, },
}, },
output::Output, output::Output,
@ -33,6 +45,7 @@ use tracing::error;
use crate::{ use crate::{
backend::render::element::AsGlowRenderer, backend::render::element::AsGlowRenderer,
shell::grabs::GrabType,
state::State, state::State,
utils::{ utils::{
iced::{IcedElement, IcedRenderElement, Program}, iced::{IcedElement, IcedRenderElement, Program},
@ -698,15 +711,27 @@ impl Program for ZoomProgram {
); );
std::mem::drop(shell); std::mem::drop(shell);
if grab.is_touch_grab() { match grab.grab_type() {
seat.get_touch().unwrap().set_grab(state, grab, serial); GrabType::Touch => {
} else { seat.get_touch().unwrap().set_grab(state, grab, serial)
seat.get_pointer().unwrap().set_grab( }
GrabType::Pointer => seat.get_pointer().unwrap().set_grab(
state, state,
grab, grab,
serial, serial,
Focus::Clear, 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); std::mem::drop(shell);
if grab.is_touch_grab() { match grab.grab_type() {
seat.get_touch().unwrap().set_grab(state, grab, serial); GrabType::Touch => {
} else { seat.get_touch().unwrap().set_grab(state, grab, serial)
seat.get_pointer().unwrap().set_grab( }
GrabType::Pointer => seat.get_pointer().unwrap().set_grab(
state, state,
grab, grab,
serial, serial,
Focus::Clear, 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<State> for ZoomFocusTarget {
} }
} }
fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) { fn button(&self, seat: &Seat<State>, data: &mut State, event: &PointerButtonEvent) {
match self { match self {
ZoomFocusTarget::Main(elem) => PointerTarget::button(elem, seat, data, event), ZoomFocusTarget::Main(elem) => PointerTarget::button(elem, seat, data, event),
ZoomFocusTarget::Menu(elem) => PointerTarget::button(elem, seat, data, event), ZoomFocusTarget::Menu(elem) => PointerTarget::button(elem, seat, data, event),
} }
} }
fn axis(&self, seat: &Seat<State>, data: &mut State, frame: AxisFrame) { fn axis(&self, seat: &Seat<State>, data: &mut State, frame: PointerAxisFrame) {
match self { match self {
ZoomFocusTarget::Main(elem) => PointerTarget::axis(elem, seat, data, frame), ZoomFocusTarget::Main(elem) => PointerTarget::axis(elem, seat, data, frame),
ZoomFocusTarget::Menu(elem) => PointerTarget::axis(elem, seat, data, frame), ZoomFocusTarget::Menu(elem) => PointerTarget::axis(elem, seat, data, frame),
@ -1032,14 +1069,14 @@ impl PointerTarget<State> for ZoomFocusTarget {
} }
impl TouchTarget<State> for ZoomFocusTarget { impl TouchTarget<State> for ZoomFocusTarget {
fn down(&self, seat: &Seat<State>, data: &mut State, event: &DownEvent) { fn down(&self, seat: &Seat<State>, data: &mut State, event: &TouchDownEvent) {
match self { match self {
ZoomFocusTarget::Main(elem) => TouchTarget::down(elem, seat, data, event), ZoomFocusTarget::Main(elem) => TouchTarget::down(elem, seat, data, event),
ZoomFocusTarget::Menu(elem) => TouchTarget::down(elem, seat, data, event), ZoomFocusTarget::Menu(elem) => TouchTarget::down(elem, seat, data, event),
} }
} }
fn up(&self, seat: &Seat<State>, data: &mut State, event: &UpEvent) { fn up(&self, seat: &Seat<State>, data: &mut State, event: &TouchUpEvent) {
match self { match self {
ZoomFocusTarget::Main(elem) => TouchTarget::up(elem, seat, data, event), ZoomFocusTarget::Main(elem) => TouchTarget::up(elem, seat, data, event),
ZoomFocusTarget::Menu(elem) => TouchTarget::up(elem, seat, data, event), ZoomFocusTarget::Menu(elem) => TouchTarget::up(elem, seat, data, event),
@ -1089,6 +1126,144 @@ impl TouchTarget<State> for ZoomFocusTarget {
} }
} }
impl TabletToolTarget<State> for ZoomFocusTarget {
fn proximity_in(
&self,
seat: &Seat<State>,
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<State>,
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<State>,
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<State>,
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<State>,
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<State>,
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<State>,
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<State>,
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 { impl IsAlive for ZoomFocusTarget {
fn alive(&self) -> bool { fn alive(&self) -> bool {
match self { match self {

View file

@ -31,7 +31,7 @@ use ordered_float::OrderedFloat;
use smithay::{ use smithay::{
backend::{ backend::{
allocator::Fourcc, allocator::Fourcc,
input::{ButtonState, InputTime, KeyState}, input::{ButtonState, InputTime, KeyState, TabletToolDescriptor},
renderer::{ renderer::{
ImportMem, ImportMem,
element::{ element::{
@ -45,14 +45,23 @@ use smithay::{
Seat, Seat,
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
pointer::{ pointer::{
AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent,
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent,
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent,
PointerTarget, RelativeMotionEvent, PointerTarget, RelativeMotionEvent,
}, },
tablet::{
Tablet,
tool::{
AxisFrame as ToolAxisFrame, ButtonEvent as ToolButtonEvent,
DownEvent as ToolDownEvent, MotionEvent as ToolMotionEvent, TabletToolTarget,
UpEvent as ToolUpEvent,
},
},
touch::{ touch::{
DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent,
TouchTarget, UpEvent, OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent,
}, },
}, },
output::Output, output::Output,
@ -189,6 +198,7 @@ pub(crate) struct IcedElementInternal<P: Program + Send + 'static> {
touch_map: HashMap<Finger, IcedPoint>, touch_map: HashMap<Finger, IcedPoint>,
last_touch_frame: Option<FrameMarker>, last_touch_frame: Option<FrameMarker>,
last_touch_serial: Option<Serial>, last_touch_serial: Option<Serial>,
last_tablet_serial: Option<Serial>,
// iced // iced
theme: Theme, theme: Theme,
@ -240,6 +250,7 @@ impl<P: Program + Send + Clone + 'static> Clone for IcedElementInternal<P> {
touch_map: self.touch_map.clone(), touch_map: self.touch_map.clone(),
last_touch_frame: None, last_touch_frame: None,
last_touch_serial: None, last_touch_serial: None,
last_tablet_serial: None,
theme: self.theme.clone(), theme: self.theme.clone(),
renderer, renderer,
state, state,
@ -267,6 +278,7 @@ impl<P: Program + Send + 'static> fmt::Debug for IcedElementInternal<P> {
.field("touch_map", &self.touch_map) .field("touch_map", &self.touch_map)
.field("last_touch_frame", &self.last_touch_frame) .field("last_touch_frame", &self.last_touch_frame)
.field("last_touch_serial", &self.last_touch_serial) .field("last_touch_serial", &self.last_touch_serial)
.field("last_tablet_serial", &self.last_tablet_serial)
.field("theme", &"...") .field("theme", &"...")
.field("renderer", &"...") .field("renderer", &"...")
.field("state", &"...") .field("state", &"...")
@ -326,6 +338,7 @@ impl<P: Program + Send + 'static> IcedElement<P> {
touch_map: HashMap::new(), touch_map: HashMap::new(),
last_touch_frame: None, last_touch_frame: None,
last_touch_serial: None, last_touch_serial: None,
last_tablet_serial: None,
theme, theme,
renderer, renderer,
state, state,
@ -481,12 +494,141 @@ impl<P: Program + Send + 'static> IcedElementInternal<P> {
} }
} }
impl<P: Program + Send + 'static> TabletToolTarget<crate::state::State> for IcedElement<P> {
fn proximity_in(
&self,
_seat: &Seat<crate::state::State>,
_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<crate::state::State>,
_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<crate::state::State>,
_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<crate::state::State>,
_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<crate::state::State>,
_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<crate::state::State>,
_data: &mut crate::state::State,
_tool_descriptor: &TabletToolDescriptor,
_frame: ToolAxisFrame,
) {
}
fn button(
&self,
seat: &Seat<crate::state::State>,
_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<crate::state::State>,
_data: &mut crate::state::State,
_tool_descriptor: &TabletToolDescriptor,
_time: InputTime,
) {
}
}
impl<P: Program + Send + 'static> PointerTarget<crate::state::State> for IcedElement<P> { impl<P: Program + Send + 'static> PointerTarget<crate::state::State> for IcedElement<P> {
fn enter( fn enter(
&self, &self,
seat: &Seat<crate::state::State>, seat: &Seat<crate::state::State>,
_data: &mut crate::state::State, _data: &mut crate::state::State,
event: &MotionEvent, event: &PointerMotionEvent,
) { ) {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
internal internal
@ -507,7 +649,7 @@ impl<P: Program + Send + 'static> PointerTarget<crate::state::State> for IcedEle
&self, &self,
seat: &Seat<crate::state::State>, seat: &Seat<crate::state::State>,
_data: &mut crate::state::State, _data: &mut crate::state::State,
event: &MotionEvent, event: &PointerMotionEvent,
) { ) {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
let event_location = event.location.downscale(internal.additional_scale); let event_location = event.location.downscale(internal.additional_scale);
@ -532,7 +674,7 @@ impl<P: Program + Send + 'static> PointerTarget<crate::state::State> for IcedEle
&self, &self,
seat: &Seat<crate::state::State>, seat: &Seat<crate::state::State>,
_data: &mut crate::state::State, _data: &mut crate::state::State,
event: &ButtonEvent, event: &PointerButtonEvent,
) { ) {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
let button = match event.button { let button = match event.button {
@ -553,7 +695,7 @@ impl<P: Program + Send + 'static> PointerTarget<crate::state::State> for IcedEle
&self, &self,
_seat: &Seat<crate::state::State>, _seat: &Seat<crate::state::State>,
_data: &mut crate::state::State, _data: &mut crate::state::State,
frame: AxisFrame, frame: PointerAxisFrame,
) { ) {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
internal internal
@ -653,7 +795,7 @@ impl<P: Program + Send + 'static> TouchTarget<crate::state::State> for IcedEleme
&self, &self,
seat: &Seat<crate::state::State>, seat: &Seat<crate::state::State>,
_data: &mut crate::state::State, _data: &mut crate::state::State,
event: &DownEvent, event: &TouchDownEvent,
) { ) {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
let id = Finger(i32::from(event.slot) as u64); let id = Finger(i32::from(event.slot) as u64);
@ -673,7 +815,7 @@ impl<P: Program + Send + 'static> TouchTarget<crate::state::State> for IcedEleme
&self, &self,
seat: &Seat<crate::state::State>, seat: &Seat<crate::state::State>,
_data: &mut crate::state::State, _data: &mut crate::state::State,
event: &UpEvent, event: &TouchUpEvent,
) { ) {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
let id = Finger(i32::from(event.slot) as u64); let id = Finger(i32::from(event.slot) as u64);

View file

@ -1,13 +1,13 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use crate::state::State; use crate::{shell::focus::target::PointerFocusTarget, state::State};
use smithay::{ use smithay::{
backend::input::TabletToolDescriptor, input::pointer::CursorImageStatus, backend::input::TabletToolDescriptor, input::pointer::CursorImageStatus,
input::tablet::TabletSeatHandler, reexports::wayland_server::protocol::wl_surface, input::tablet::TabletSeatHandler,
}; };
impl TabletSeatHandler for State { impl TabletSeatHandler for State {
type ToolFocus = wl_surface::WlSurface; type ToolFocus = PointerFocusTarget;
fn tablet_tool_image(&mut self, _tool: &TabletToolDescriptor, _image: CursorImageStatus) { fn tablet_tool_image(&mut self, _tool: &TabletToolDescriptor, _image: CursorImageStatus) {
// TODO display cursor for each tablet tool // TODO display cursor for each tablet tool

View file

@ -1,11 +1,15 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use crate::{ use crate::{
shell::{CosmicSurface, PendingWindow, focus::target::KeyboardFocusTarget, grabs::ReleaseMode}, shell::{
CosmicSurface, PendingWindow,
focus::target::KeyboardFocusTarget,
grabs::{GrabType, ReleaseMode},
},
utils::prelude::*, utils::prelude::*,
}; };
use smithay::desktop::layer_map_for_output;
use smithay::{ use smithay::{
backend::input::InputTime,
desktop::{ desktop::{
PopupGrab, PopupKeyboardGrab, PopupKind, PopupPointerGrab, PopupUngrabStrategy, PopupGrab, PopupKeyboardGrab, PopupKind, PopupPointerGrab, PopupUngrabStrategy,
WindowSurfaceType, find_popup_root_surface, 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 std::cell::Cell;
use tracing::warn; use tracing::warn;
@ -190,12 +195,17 @@ impl XdgShellHandler for State {
true, true,
) { ) {
std::mem::drop(shell); std::mem::drop(shell);
if grab.is_touch_grab() { match grab.grab_type() {
seat.get_touch().unwrap().set_grab(self, grab, serial); GrabType::Touch => seat.get_touch().unwrap().set_grab(self, grab, serial),
} else { GrabType::Pointer => seat
seat.get_pointer() .get_pointer()
.unwrap() .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, true,
) { ) {
std::mem::drop(shell); std::mem::drop(shell);
if grab.is_touch_grab() { match grab.grab_type() {
seat.get_touch().unwrap().set_grab(self, grab, serial) GrabType::Touch => seat.get_touch().unwrap().set_grab(self, grab, serial),
} else { GrabType::Pointer => seat
seat.get_pointer() .get_pointer()
.unwrap() .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),
} }
} }
} }

View file

@ -9,7 +9,9 @@ use std::{
use crate::{ use crate::{
backend::render::cursor::{Cursor, load_cursor_env, load_cursor_theme}, backend::render::cursor::{Cursor, load_cursor_env, load_cursor_theme},
shell::{ shell::{
CosmicSurface, PendingWindow, Shell, focus::target::KeyboardFocusTarget, grabs::ReleaseMode, CosmicSurface, PendingWindow, Shell,
focus::target::KeyboardFocusTarget,
grabs::{GrabType, ReleaseMode},
}, },
state::State, state::State,
utils::prelude::*, utils::prelude::*,
@ -32,7 +34,7 @@ use smithay::{
}, },
}, },
desktop::space::SpaceElement, 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}, reexports::{wayland_server::Client, x11rb::protocol::xproto::Window as X11Window},
utils::{ utils::{
Buffer as BufferCoords, Logical, Point, Rectangle, SERIAL_COUNTER, Serial, Size, Transform, Buffer as BufferCoords, Logical, Point, Rectangle, SERIAL_COUNTER, Serial, Size, Transform,
@ -1045,17 +1047,29 @@ impl XwmHandler for State {
true, true,
) { ) {
std::mem::drop(shell); std::mem::drop(shell);
if grab.is_touch_grab() { match grab.grab_type() {
seat.get_touch() GrabType::Touch => {
.unwrap() seat.get_touch()
.set_grab(self, grab, SERIAL_COUNTER.next_serial()) .unwrap()
} else { .set_grab(self, grab, SERIAL_COUNTER.next_serial())
seat.get_pointer().unwrap().set_grab( }
GrabType::Pointer => seat.get_pointer().unwrap().set_grab(
self, self,
grab, grab,
SERIAL_COUNTER.next_serial(), SERIAL_COUNTER.next_serial(),
focus, 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, true,
) { ) {
std::mem::drop(shell); std::mem::drop(shell);
if grab.is_touch_grab() { match grab.grab_type() {
seat.get_touch() GrabType::Touch => {
.unwrap() seat.get_touch()
.set_grab(self, grab, SERIAL_COUNTER.next_serial()) .unwrap()
} else { .set_grab(self, grab, SERIAL_COUNTER.next_serial())
seat.get_pointer().unwrap().set_grab( }
GrabType::Pointer => seat.get_pointer().unwrap().set_grab(
self, self,
grab, grab,
SERIAL_COUNTER.next_serial(), SERIAL_COUNTER.next_serial(),
focus, focus,
) ),
GrabType::TabletTool => seat
.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(
self,
grab,
InputTime::now(),
SERIAL_COUNTER.next_serial(),
focus,
),
} }
} }
} }