mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-22 02:01:55 +07:00
Implement touch interactive resize
This commit is contained in:
+46
-18
@@ -39,6 +39,7 @@ use tracing::field::Empty;
|
|||||||
use crate::input::move_grab::MoveGrab;
|
use crate::input::move_grab::MoveGrab;
|
||||||
use crate::input::resize_grab::ResizeGrab;
|
use crate::input::resize_grab::ResizeGrab;
|
||||||
use crate::input::touch_move_grab::TouchMoveGrab;
|
use crate::input::touch_move_grab::TouchMoveGrab;
|
||||||
|
use crate::input::touch_resize_grab::TouchResizeGrab;
|
||||||
use crate::input::{PointerOrTouchStartData, DOUBLE_CLICK_TIME};
|
use crate::input::{PointerOrTouchStartData, DOUBLE_CLICK_TIME};
|
||||||
use crate::layout::workspace::ColumnWidth;
|
use crate::layout::workspace::ColumnWidth;
|
||||||
use crate::niri::{PopupGrabState, State};
|
use crate::niri::{PopupGrabState, State};
|
||||||
@@ -149,23 +150,38 @@ impl XdgShellHandler for State {
|
|||||||
serial: Serial,
|
serial: Serial,
|
||||||
edges: xdg_toplevel::ResizeEdge,
|
edges: xdg_toplevel::ResizeEdge,
|
||||||
) {
|
) {
|
||||||
let pointer = self.niri.seat.get_pointer().unwrap();
|
|
||||||
if !pointer.has_grab(serial) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(start_data) = pointer.grab_start_data() else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some((focus, _)) = &start_data.focus else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let wl_surface = surface.wl_surface();
|
let wl_surface = surface.wl_surface();
|
||||||
if !focus.id().same_client_as(&wl_surface.id()) {
|
|
||||||
return;
|
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) {
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(start_data) = grab_start_data else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
let Some((mapped, _)) = self.niri.layout.find_window_and_output(wl_surface) else {
|
let Some((mapped, _)) = self.niri.layout.find_window_and_output(wl_surface) else {
|
||||||
return;
|
return;
|
||||||
@@ -201,15 +217,27 @@ impl XdgShellHandler for State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let grab = ResizeGrab::new(start_data, window.clone());
|
if !self
|
||||||
|
.niri
|
||||||
if !self.niri.layout.interactive_resize_begin(window, edges) {
|
.layout
|
||||||
|
.interactive_resize_begin(window.clone(), edges)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match start_data {
|
||||||
|
PointerOrTouchStartData::Pointer(start_data) => {
|
||||||
|
let grab = ResizeGrab::new(start_data, window);
|
||||||
pointer.set_grab(self, grab, serial, Focus::Clear);
|
pointer.set_grab(self, grab, serial, Focus::Clear);
|
||||||
self.niri.pointer_grab_ongoing = true;
|
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(
|
fn reposition_request(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ pub mod scroll_tracker;
|
|||||||
pub mod spatial_movement_grab;
|
pub mod spatial_movement_grab;
|
||||||
pub mod swipe_tracker;
|
pub mod swipe_tracker;
|
||||||
pub mod touch_move_grab;
|
pub mod touch_move_grab;
|
||||||
|
pub mod touch_resize_grab;
|
||||||
|
|
||||||
pub const DOUBLE_CLICK_TIME: Duration = Duration::from_millis(400);
|
pub const DOUBLE_CLICK_TIME: Duration = Duration::from_millis(400);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2978,6 +2978,10 @@ impl<W: LayoutElement> Workspace<W> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn interactive_resize_begin(&mut self, window: W::Id, edges: ResizeEdge) -> bool {
|
pub fn interactive_resize_begin(&mut self, window: W::Id, edges: ResizeEdge) -> bool {
|
||||||
|
if self.interactive_resize.is_some() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
let col = self
|
let col = self
|
||||||
.columns
|
.columns
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
|
|||||||
Reference in New Issue
Block a user