aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-10-20 08:23:16 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2024-10-27 23:07:39 -0700
commit26ab4dfb87550b2f8ceed5d11be614a239703fd7 (patch)
treeb18cfb830f34e2c308cb11159b8459b31be5f9aa /src
parente887ee93a30390b641bf647d694a1424f7ce4592 (diff)
downloadniri-26ab4dfb87550b2f8ceed5d11be614a239703fd7.tar.gz
niri-26ab4dfb87550b2f8ceed5d11be614a239703fd7.tar.bz2
niri-26ab4dfb87550b2f8ceed5d11be614a239703fd7.zip
Implement touch interactive move
Diffstat (limited to 'src')
-rw-r--r--src/handlers/xdg_shell.rs60
-rw-r--r--src/input/mod.rs20
-rw-r--r--src/input/move_grab.rs2
-rw-r--r--src/input/touch_move_grab.rs136
4 files changed, 200 insertions, 18 deletions
diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs
index 2397f22a..856a0453 100644
--- a/src/handlers/xdg_shell.rs
+++ b/src/handlers/xdg_shell.rs
@@ -6,7 +6,7 @@ use smithay::desktop::{
PopupKeyboardGrab, PopupKind, PopupManager, PopupPointerGrab, PopupUngrabStrategy, Window,
WindowSurfaceType,
};
-use smithay::input::pointer::{Focus, PointerGrab};
+use smithay::input::pointer::Focus;
use smithay::output::Output;
use smithay::reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1;
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_positioner::ConstraintAdjustment;
@@ -38,7 +38,8 @@ use tracing::field::Empty;
use crate::input::move_grab::MoveGrab;
use crate::input::resize_grab::ResizeGrab;
-use crate::input::DOUBLE_CLICK_TIME;
+use crate::input::touch_move_grab::TouchMoveGrab;
+use crate::input::{PointerOrTouchStartData, DOUBLE_CLICK_TIME};
use crate::layout::workspace::ColumnWidth;
use crate::niri::{PopupGrabState, State};
use crate::utils::transaction::Transaction;
@@ -67,24 +68,39 @@ impl XdgShellHandler for State {
}
fn move_request(&mut self, surface: ToplevelSurface, _seat: WlSeat, serial: Serial) {
+ 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, output)) = self.niri.layout.find_window_and_output(wl_surface) else {
return;
};
@@ -100,7 +116,7 @@ impl XdgShellHandler for State {
.loc
.to_f64();
- let pos_within_output = start_data.location - output_pos;
+ let pos_within_output = start_data.location() - output_pos;
if !self
.niri
@@ -110,10 +126,20 @@ impl XdgShellHandler for State {
return;
}
- let grab = MoveGrab::new(start_data, window.clone());
+ match start_data {
+ PointerOrTouchStartData::Pointer(start_data) => {
+ let grab = MoveGrab::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 = TouchMoveGrab::new(start_data, window);
+ touch.set_grab(self, grab, serial);
+ }
+ }
- pointer.set_grab(self, grab, serial, Focus::Clear);
- self.niri.pointer_grab_ongoing = true;
+ self.niri.queue_redraw(&output);
}
fn resize_request(
diff --git a/src/input/mod.rs b/src/input/mod.rs
index b3e38892..11612f2f 100644
--- a/src/input/mod.rs
+++ b/src/input/mod.rs
@@ -24,7 +24,10 @@ use smithay::input::pointer::{
GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
GrabStartData as PointerGrabStartData, MotionEvent, RelativeMotionEvent,
};
-use smithay::input::touch::{DownEvent, MotionEvent as TouchMotionEvent, UpEvent};
+use smithay::input::touch::{
+ DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent, UpEvent,
+};
+use smithay::input::SeatHandler;
use smithay::utils::{Logical, Point, Rectangle, Transform, SERIAL_COUNTER};
use smithay::wayland::pointer_constraints::{with_pointer_constraint, PointerConstraint};
use smithay::wayland::tablet_manager::{TabletDescriptor, TabletSeatTrait};
@@ -42,6 +45,7 @@ pub mod resize_grab;
pub mod scroll_tracker;
pub mod spatial_movement_grab;
pub mod swipe_tracker;
+pub mod touch_move_grab;
pub const DOUBLE_CLICK_TIME: Duration = Duration::from_millis(400);
@@ -56,6 +60,20 @@ pub struct TabletData {
pub aspect_ratio: f64,
}
+pub enum PointerOrTouchStartData<D: SeatHandler> {
+ Pointer(PointerGrabStartData<D>),
+ Touch(TouchGrabStartData<D>),
+}
+
+impl<D: SeatHandler> PointerOrTouchStartData<D> {
+ pub fn location(&self) -> Point<f64, Logical> {
+ match self {
+ PointerOrTouchStartData::Pointer(x) => x.location,
+ PointerOrTouchStartData::Touch(x) => x.location,
+ }
+ }
+}
+
impl State {
pub fn process_input_event<I: InputBackend + 'static>(&mut self, event: InputEvent<I>)
where
diff --git a/src/input/move_grab.rs b/src/input/move_grab.rs
index 71d115d7..e62a74f8 100644
--- a/src/input/move_grab.rs
+++ b/src/input/move_grab.rs
@@ -73,6 +73,8 @@ impl PointerGrab<State> for MoveGrab {
false,
);
}
+ // FIXME: only redraw the previous and the new output.
+ data.niri.queue_redraw_all();
return;
}
} else {
diff --git a/src/input/touch_move_grab.rs b/src/input/touch_move_grab.rs
new file mode 100644
index 00000000..e69f4c6e
--- /dev/null
+++ b/src/input/touch_move_grab.rs
@@ -0,0 +1,136 @@
+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 TouchMoveGrab {
+ start_data: TouchGrabStartData<State>,
+ last_location: Point<f64, Logical>,
+ window: Window,
+}
+
+impl TouchMoveGrab {
+ pub fn new(start_data: TouchGrabStartData<State>, window: Window) -> Self {
+ Self {
+ last_location: start_data.location,
+ start_data,
+ window,
+ }
+ }
+
+ fn on_ungrab(&mut self, state: &mut State) {
+ state.niri.layout.interactive_move_end(&self.window);
+ // FIXME: only redraw the window output.
+ state.niri.queue_redraw_all();
+ }
+}
+
+impl TouchGrab<State> for TouchMoveGrab {
+ 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() {
+ if let Some((output, pos_within_output)) = data.niri.output_under(event.location) {
+ let output = output.clone();
+ let event_delta = event.location - self.last_location;
+ self.last_location = event.location;
+ let ongoing = data.niri.layout.interactive_move_update(
+ &self.window,
+ event_delta,
+ output,
+ pos_within_output,
+ );
+ if ongoing {
+ // FIXME: only redraw the previous and the new output.
+ data.niri.queue_redraw_all();
+ return;
+ }
+ } else {
+ return;
+ }
+ }
+
+ // The move 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);
+ }
+}