diff --git a/src/shell/element/stack.rs b/src/shell/element/stack.rs index 0c322638..6411a1c6 100644 --- a/src/shell/element/stack.rs +++ b/src/shell/element/stack.rs @@ -42,6 +42,10 @@ use smithay::{ GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, PointerTarget, RelativeMotionEvent, }, + touch::{ + DownEvent, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchTarget, + UpEvent, + }, Seat, }, output::Output, @@ -1428,6 +1432,51 @@ impl PointerTarget for CosmicStack { } } +impl TouchTarget for CosmicStack { + fn down(&self, seat: &Seat, data: &mut State, event: &DownEvent, seq: Serial) { + 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(); + TouchTarget::down(&self.0, seat, data, &event, seq) + } + + fn up(&self, seat: &Seat, data: &mut State, event: &UpEvent, seq: Serial) { + TouchTarget::up(&self.0, seat, data, &event, seq) + } + + fn motion(&self, seat: &Seat, data: &mut State, event: &TouchMotionEvent, seq: Serial) { + 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(); + TouchTarget::motion(&self.0, seat, data, &event, seq) + } + + fn frame(&self, seat: &Seat, data: &mut State, seq: Serial) { + TouchTarget::frame(&self.0, seat, data, seq) + } + + fn cancel(&self, seat: &Seat, data: &mut State, seq: Serial) { + TouchTarget::cancel(&self.0, seat, data, seq) + } + + fn shape(&self, seat: &Seat, data: &mut State, event: &ShapeEvent, seq: Serial) { + TouchTarget::shape(&self.0, seat, data, event, seq) + } + + fn orientation( + &self, + _seat: &Seat, + _data: &mut State, + _event: &OrientationEvent, + _seq: Serial, + ) { + } +} + render_elements! { pub CosmicStackRenderElement where R: ImportAll + ImportMem; Header = MemoryRenderBufferRenderElement, diff --git a/src/shell/element/window.rs b/src/shell/element/window.rs index 0e7875ea..3e749eac 100644 --- a/src/shell/element/window.rs +++ b/src/shell/element/window.rs @@ -33,6 +33,10 @@ use smithay::{ GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, PointerTarget, RelativeMotionEvent, }, + touch::{ + DownEvent, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchTarget, + UpEvent, + }, Seat, }, output::Output, @@ -832,6 +836,45 @@ impl PointerTarget for CosmicWindow { } } +impl TouchTarget for CosmicWindow { + fn down(&self, seat: &Seat, data: &mut State, event: &DownEvent, seq: Serial) { + let mut event = event.clone(); + event.location -= self.0.with_program(|p| p.window.geometry().loc.to_f64()); + TouchTarget::down(&self.0, seat, data, &event, seq) + } + + fn up(&self, seat: &Seat, data: &mut State, event: &UpEvent, seq: Serial) { + TouchTarget::up(&self.0, seat, data, &event, seq) + } + + fn motion(&self, seat: &Seat, data: &mut State, event: &TouchMotionEvent, seq: Serial) { + let mut event = event.clone(); + event.location -= self.0.with_program(|p| p.window.geometry().loc.to_f64()); + TouchTarget::motion(&self.0, seat, data, &event, seq) + } + + fn frame(&self, seat: &Seat, data: &mut State, seq: Serial) { + TouchTarget::frame(&self.0, seat, data, seq) + } + + fn cancel(&self, seat: &Seat, data: &mut State, seq: Serial) { + TouchTarget::cancel(&self.0, seat, data, seq) + } + + fn shape(&self, seat: &Seat, data: &mut State, event: &ShapeEvent, seq: Serial) { + TouchTarget::shape(&self.0, seat, data, event, seq) + } + + fn orientation( + &self, + _seat: &Seat, + _data: &mut State, + _event: &OrientationEvent, + _seq: Serial, + ) { + } +} + impl WaylandFocus for CosmicWindow { fn wl_surface(&self) -> Option { self.0.with_program(|p| p.window.wl_surface()) diff --git a/src/shell/focus/target.rs b/src/shell/focus/target.rs index 9a4e14bc..0e4581c3 100644 --- a/src/shell/focus/target.rs +++ b/src/shell/focus/target.rs @@ -493,9 +493,11 @@ impl TouchTarget for PointerFocusTarget { PointerFocusTarget::WlSurface { surface, .. } => { TouchTarget::down(surface, seat, data, event, seq) } - // TODO: implement TouchTarget for iced/CosmicWindow/CosmicStack/ResizeFork/Grabs - PointerFocusTarget::WindowUI(_window) => {} - PointerFocusTarget::StackUI(_stack) => {} + PointerFocusTarget::WindowUI(window) => { + TouchTarget::down(window, seat, data, event, seq) + } + PointerFocusTarget::StackUI(stack) => TouchTarget::down(stack, seat, data, event, seq), + // TODO: implement TouchTarget for ResizeFork/Grabs PointerFocusTarget::ResizeFork(_fork) => {} } } @@ -505,8 +507,8 @@ impl TouchTarget for PointerFocusTarget { PointerFocusTarget::WlSurface { surface, .. } => { TouchTarget::up(surface, seat, data, event, seq) } - PointerFocusTarget::WindowUI(_window) => {} - PointerFocusTarget::StackUI(_stack) => {} + PointerFocusTarget::WindowUI(window) => TouchTarget::up(window, seat, data, event, seq), + PointerFocusTarget::StackUI(stack) => TouchTarget::up(stack, seat, data, event, seq), PointerFocusTarget::ResizeFork(_fork) => {} } } @@ -516,8 +518,12 @@ impl TouchTarget for PointerFocusTarget { PointerFocusTarget::WlSurface { surface, .. } => { TouchTarget::motion(surface, seat, data, event, seq) } - PointerFocusTarget::WindowUI(_window) => {} - PointerFocusTarget::StackUI(_stack) => {} + PointerFocusTarget::WindowUI(window) => { + TouchTarget::motion(window, seat, data, event, seq) + } + PointerFocusTarget::StackUI(stack) => { + TouchTarget::motion(stack, seat, data, event, seq) + } PointerFocusTarget::ResizeFork(_fork) => {} } } @@ -527,8 +533,8 @@ impl TouchTarget for PointerFocusTarget { PointerFocusTarget::WlSurface { surface, .. } => { TouchTarget::frame(surface, seat, data, seq) } - PointerFocusTarget::WindowUI(_window) => {} - PointerFocusTarget::StackUI(_stack) => {} + PointerFocusTarget::WindowUI(window) => TouchTarget::frame(window, seat, data, seq), + PointerFocusTarget::StackUI(stack) => TouchTarget::frame(stack, seat, data, seq), PointerFocusTarget::ResizeFork(_fork) => {} } } @@ -538,8 +544,8 @@ impl TouchTarget for PointerFocusTarget { PointerFocusTarget::WlSurface { surface, .. } => { TouchTarget::cancel(surface, seat, data, seq) } - PointerFocusTarget::WindowUI(_window) => {} - PointerFocusTarget::StackUI(_stack) => {} + PointerFocusTarget::WindowUI(window) => TouchTarget::cancel(window, seat, data, seq), + PointerFocusTarget::StackUI(stack) => TouchTarget::cancel(stack, seat, data, seq), PointerFocusTarget::ResizeFork(_fork) => {} } } @@ -549,8 +555,10 @@ impl TouchTarget for PointerFocusTarget { PointerFocusTarget::WlSurface { surface, .. } => { TouchTarget::shape(surface, seat, data, event, seq) } - PointerFocusTarget::WindowUI(_window) => {} - PointerFocusTarget::StackUI(_stack) => {} + PointerFocusTarget::WindowUI(window) => { + TouchTarget::shape(window, seat, data, event, seq) + } + PointerFocusTarget::StackUI(stack) => TouchTarget::shape(stack, seat, data, event, seq), PointerFocusTarget::ResizeFork(_fork) => {} } } @@ -566,8 +574,12 @@ impl TouchTarget for PointerFocusTarget { PointerFocusTarget::WlSurface { surface, .. } => { TouchTarget::orientation(surface, seat, data, event, seq) } - PointerFocusTarget::WindowUI(_window) => {} - PointerFocusTarget::StackUI(_stack) => {} + PointerFocusTarget::WindowUI(window) => { + TouchTarget::orientation(window, seat, data, event, seq) + } + PointerFocusTarget::StackUI(stack) => { + TouchTarget::orientation(stack, seat, data, event, seq) + } PointerFocusTarget::ResizeFork(_fork) => {} } } diff --git a/src/utils/iced.rs b/src/utils/iced.rs index 71e66e51..75e49941 100644 --- a/src/utils/iced.rs +++ b/src/utils/iced.rs @@ -12,6 +12,7 @@ use cosmic::{ event::Event, keyboard::{Event as KeyboardEvent, Modifiers as IcedModifiers}, mouse::{Button as MouseButton, Cursor, Event as MouseEvent, ScrollDelta}, + touch::{Event as TouchEvent, Finger}, window::{Event as WindowEvent, Id}, Command, Limits, Point as IcedPoint, Rectangle as IcedRectangle, Size as IcedSize, }, @@ -51,6 +52,10 @@ use smithay::{ GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, PointerTarget, RelativeMotionEvent, }, + touch::{ + DownEvent, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchTarget, + UpEvent, + }, Seat, }, output::Output, @@ -143,6 +148,7 @@ struct IcedElementInternal { // state size: Size, cursor_pos: Option>, + touch_map: HashMap, // iced theme: Theme, @@ -191,6 +197,7 @@ impl Clone for IcedElementInternal

{ pending_update: self.pending_update.clone(), size: self.size.clone(), cursor_pos: self.cursor_pos.clone(), + touch_map: self.touch_map.clone(), theme: self.theme.clone(), renderer, state, @@ -265,6 +272,7 @@ impl IcedElement

{ pending_update: None, size, cursor_pos: None, + touch_map: HashMap::new(), theme, renderer, state, @@ -422,6 +430,7 @@ impl PointerTarget for IcedEle internal .state .queue_event(Event::Mouse(MouseEvent::CursorMoved { position })); + // TODO: Update iced widgets to handle touch using event position, not cursor_pos internal.cursor_pos = Some(event.location); let _ = internal.update(true); } @@ -568,6 +577,102 @@ impl PointerTarget for IcedEle } } +impl TouchTarget for IcedElement

{ + fn down( + &self, + _seat: &Seat, + _data: &mut crate::state::State, + event: &DownEvent, + _seq: Serial, + ) { + let mut internal = self.0.lock().unwrap(); + let id = Finger(i32::from(event.slot) as u64); + 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.touch_map.insert(id, position); + internal.cursor_pos = Some(event.location); + let _ = internal.update(true); + } + + fn up( + &self, + _seat: &Seat, + _data: &mut crate::state::State, + event: &UpEvent, + _seq: Serial, + ) { + let mut internal = self.0.lock().unwrap(); + let id = Finger(i32::from(event.slot) as u64); + if let Some(position) = internal.touch_map.remove(&id) { + internal + .state + .queue_event(Event::Touch(TouchEvent::FingerLifted { id, position })); + let _ = internal.update(true); + } + } + + fn motion( + &self, + _seat: &Seat, + _data: &mut crate::state::State, + event: &TouchMotionEvent, + _seq: Serial, + ) { + let mut internal = self.0.lock().unwrap(); + let id = Finger(i32::from(event.slot) as u64); + let position = IcedPoint::new(event.location.x as f32, event.location.y as f32); + internal + .state + .queue_event(Event::Touch(TouchEvent::FingerMoved { id, position })); + internal.touch_map.insert(id, position); + internal.cursor_pos = Some(event.location); + let _ = internal.update(true); + } + + fn frame( + &self, + _seat: &Seat, + _data: &mut crate::state::State, + _seq: Serial, + ) { + } + + fn cancel( + &self, + _seat: &Seat, + _data: &mut crate::state::State, + _seq: Serial, + ) { + let mut internal = self.0.lock().unwrap(); + for (id, position) in std::mem::take(&mut internal.touch_map) { + internal + .state + .queue_event(Event::Touch(TouchEvent::FingerLost { id, position })); + } + let _ = internal.update(true); + } + + fn shape( + &self, + _seat: &Seat, + _data: &mut crate::state::State, + _event: &ShapeEvent, + _seq: Serial, + ) { + } + + fn orientation( + &self, + _seat: &Seat, + _data: &mut crate::state::State, + _event: &OrientationEvent, + _seq: Serial, + ) { + } +} + impl KeyboardTarget for IcedElement

{ fn enter( &self,