diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-10-20 09:13:00 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-10-27 23:07:39 -0700 |
| commit | da3e5c44248fdb12b700e3a99c3e777c57942dc7 (patch) | |
| tree | ed2f9b1dd8040a16735ad3949f01aef72d5e86ba /src | |
| parent | 26ab4dfb87550b2f8ceed5d11be614a239703fd7 (diff) | |
| download | niri-da3e5c44248fdb12b700e3a99c3e777c57942dc7.tar.gz niri-da3e5c44248fdb12b700e3a99c3e777c57942dc7.tar.bz2 niri-da3e5c44248fdb12b700e3a99c3e777c57942dc7.zip | |
Implement touch interactive resize
Diffstat (limited to 'src')
| -rw-r--r-- | src/handlers/xdg_shell.rs | 60 | ||||
| -rw-r--r-- | src/input/mod.rs | 1 | ||||
| -rw-r--r-- | src/input/touch_resize_grab.rs | 119 | ||||
| -rw-r--r-- | src/layout/workspace.rs | 4 |
4 files changed, 168 insertions, 16 deletions
diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs index 856a0453..8cccfd9e 100644 --- a/src/handlers/xdg_shell.rs +++ b/src/handlers/xdg_shell.rs @@ -39,6 +39,7 @@ use tracing::field::Empty; use crate::input::move_grab::MoveGrab; use crate::input::resize_grab::ResizeGrab; use crate::input::touch_move_grab::TouchMoveGrab; +use crate::input::touch_resize_grab::TouchResizeGrab; use crate::input::{PointerOrTouchStartData, DOUBLE_CLICK_TIME}; use crate::layout::workspace::ColumnWidth; use crate::niri::{PopupGrabState, State}; @@ -149,24 +150,39 @@ impl XdgShellHandler for State { serial: Serial, edges: xdg_toplevel::ResizeEdge, ) { + let wl_surface = surface.wl_surface(); + + let mut grab_start_data = None; + + // See if this comes from a pointer grab. let pointer = self.niri.seat.get_pointer().unwrap(); - if !pointer.has_grab(serial) { - return; + if pointer.has_grab(serial) { + if let Some(start_data) = pointer.grab_start_data() { + if let Some((focus, _)) = &start_data.focus { + if focus.id().same_client_as(&wl_surface.id()) { + grab_start_data = Some(PointerOrTouchStartData::Pointer(start_data)); + } + } + } } - let Some(start_data) = pointer.grab_start_data() else { - return; - }; + // See if this comes from a touch grab. + if let Some(touch) = self.niri.seat.get_touch() { + if touch.has_grab(serial) { + if let Some(start_data) = touch.grab_start_data() { + if let Some((focus, _)) = &start_data.focus { + if focus.id().same_client_as(&wl_surface.id()) { + grab_start_data = Some(PointerOrTouchStartData::Touch(start_data)); + } + } + } + } + } - let Some((focus, _)) = &start_data.focus else { + let Some(start_data) = grab_start_data else { return; }; - let wl_surface = surface.wl_surface(); - if !focus.id().same_client_as(&wl_surface.id()) { - return; - } - let Some((mapped, _)) = self.niri.layout.find_window_and_output(wl_surface) else { return; }; @@ -201,14 +217,26 @@ impl XdgShellHandler for State { } } - let grab = ResizeGrab::new(start_data, window.clone()); - - if !self.niri.layout.interactive_resize_begin(window, edges) { + if !self + .niri + .layout + .interactive_resize_begin(window.clone(), edges) + { return; } - pointer.set_grab(self, grab, serial, Focus::Clear); - self.niri.pointer_grab_ongoing = true; + match start_data { + PointerOrTouchStartData::Pointer(start_data) => { + let grab = ResizeGrab::new(start_data, window); + pointer.set_grab(self, grab, serial, Focus::Clear); + self.niri.pointer_grab_ongoing = true; + } + PointerOrTouchStartData::Touch(start_data) => { + let touch = self.niri.seat.get_touch().unwrap(); + let grab = TouchResizeGrab::new(start_data, window); + touch.set_grab(self, grab, serial); + } + } } fn reposition_request( diff --git a/src/input/mod.rs b/src/input/mod.rs index 11612f2f..07c77e8c 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -46,6 +46,7 @@ pub mod scroll_tracker; pub mod spatial_movement_grab; pub mod swipe_tracker; pub mod touch_move_grab; +pub mod touch_resize_grab; pub const DOUBLE_CLICK_TIME: Duration = Duration::from_millis(400); diff --git a/src/input/touch_resize_grab.rs b/src/input/touch_resize_grab.rs new file mode 100644 index 00000000..91156411 --- /dev/null +++ b/src/input/touch_resize_grab.rs @@ -0,0 +1,119 @@ +use smithay::desktop::Window; +use smithay::input::touch::{ + DownEvent, GrabStartData as TouchGrabStartData, MotionEvent, OrientationEvent, ShapeEvent, + TouchGrab, TouchInnerHandle, UpEvent, +}; +use smithay::input::SeatHandler; +use smithay::utils::{IsAlive, Logical, Point, Serial}; + +use crate::niri::State; + +pub struct TouchResizeGrab { + start_data: TouchGrabStartData<State>, + window: Window, +} + +impl TouchResizeGrab { + pub fn new(start_data: TouchGrabStartData<State>, window: Window) -> Self { + Self { start_data, window } + } + + fn on_ungrab(&mut self, state: &mut State) { + state.niri.layout.interactive_resize_end(&self.window); + } +} + +impl TouchGrab<State> for TouchResizeGrab { + fn down( + &mut self, + data: &mut State, + handle: &mut TouchInnerHandle<'_, State>, + _focus: Option<(<State as SeatHandler>::TouchFocus, Point<f64, Logical>)>, + event: &DownEvent, + seq: Serial, + ) { + handle.down(data, None, event, seq); + } + + fn up( + &mut self, + data: &mut State, + handle: &mut TouchInnerHandle<'_, State>, + event: &UpEvent, + seq: Serial, + ) { + handle.up(data, event, seq); + + if event.slot != self.start_data.slot { + return; + } + + handle.unset_grab(self, data); + } + + fn motion( + &mut self, + data: &mut State, + handle: &mut TouchInnerHandle<'_, State>, + _focus: Option<(<State as SeatHandler>::TouchFocus, Point<f64, Logical>)>, + event: &MotionEvent, + seq: Serial, + ) { + handle.motion(data, None, event, seq); + + if event.slot != self.start_data.slot { + return; + } + + if self.window.alive() { + let delta = event.location - self.start_data.location; + let ongoing = data + .niri + .layout + .interactive_resize_update(&self.window, delta); + if ongoing { + return; + } + } + + // The resize is no longer ongoing. + handle.unset_grab(self, data); + } + + fn frame(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, seq: Serial) { + handle.frame(data, seq); + } + + fn cancel(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, seq: Serial) { + handle.cancel(data, seq); + handle.unset_grab(self, data); + } + + fn shape( + &mut self, + data: &mut State, + handle: &mut TouchInnerHandle<'_, State>, + event: &ShapeEvent, + seq: Serial, + ) { + handle.shape(data, event, seq); + } + + fn orientation( + &mut self, + data: &mut State, + handle: &mut TouchInnerHandle<'_, State>, + event: &OrientationEvent, + seq: Serial, + ) { + handle.orientation(data, event, seq); + } + + fn start_data(&self) -> &TouchGrabStartData<State> { + &self.start_data + } + + fn unset(&mut self, data: &mut State) { + self.on_ungrab(data); + } +} diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs index 84920bde..0f378abc 100644 --- a/src/layout/workspace.rs +++ b/src/layout/workspace.rs @@ -2978,6 +2978,10 @@ impl<W: LayoutElement> Workspace<W> { } pub fn interactive_resize_begin(&mut self, window: W::Id, edges: ResizeEdge) -> bool { + if self.interactive_resize.is_some() { + return false; + } + let col = self .columns .iter_mut() |
