Compare commits

...

1 Commits

Author SHA1 Message Date
Ivan Molodetskikh 012340c5f4 Freeze view when pointer or touch is grabbed 2024-10-28 21:18:26 +03:00
4 changed files with 67 additions and 4 deletions
+4
View File
@@ -1735,6 +1735,8 @@ impl State {
}, },
); );
pointer.frame(self); pointer.frame(self);
self.niri.refresh_layout_is_grabbed();
} }
fn on_pointer_axis<I: InputBackend>(&mut self, event: I::PointerAxisEvent) { fn on_pointer_axis<I: InputBackend>(&mut self, event: I::PointerAxisEvent) {
@@ -2370,6 +2372,8 @@ impl State {
// We're using touch, hide the pointer. // We're using touch, hide the pointer.
self.niri.pointer_hidden = true; self.niri.pointer_hidden = true;
self.niri.refresh_layout_is_grabbed();
} }
fn on_touch_up<I: InputBackend>(&mut self, evt: I::TouchUpEvent) { fn on_touch_up<I: InputBackend>(&mut self, evt: I::TouchUpEvent) {
let Some(handle) = self.niri.seat.get_touch() else { let Some(handle) = self.niri.seat.get_touch() else {
+13
View File
@@ -1928,6 +1928,12 @@ impl<W: LayoutElement> Layout<W> {
mon.resize_edges_under(pos_within_output) mon.resize_edges_under(pos_within_output)
} }
pub fn set_pointer_grabbed(&mut self, is_grabbed: bool) {
for ws in self.workspaces_mut() {
ws.set_pointer_grabbed(is_grabbed);
}
}
#[cfg(test)] #[cfg(test)]
fn verify_invariants(&self) { fn verify_invariants(&self) {
use std::collections::HashSet; use std::collections::HashSet;
@@ -2912,6 +2918,13 @@ impl<W: LayoutElement> Layout<W> {
.unwrap(); .unwrap();
tile_pos = Some(ws_offset + tile_offset); tile_pos = Some(ws_offset + tile_offset);
// The view offset anim is paused because a grab is active. Since we
// just dragged a window out, cancel the animation, because when we put
// the window back, we will animate to it afresh.
let ws_id = ws.id();
let ws = self.workspaces_mut().find(|ws| ws.id() == ws_id).unwrap();
ws.cancel_view_offset_anim();
} }
} }
} }
+40 -4
View File
@@ -114,6 +114,11 @@ pub struct Workspace<W: LayoutElement> {
/// Buffer for the insert hint. /// Buffer for the insert hint.
insert_hint_buffer: SolidColorBuffer, insert_hint_buffer: SolidColorBuffer,
/// Whether a pointer grab is active.
///
/// This means that view offset animations should be temporarily frozen.
is_pointer_grabbed: bool,
/// Configurable properties of the layout as received from the parent monitor. /// Configurable properties of the layout as received from the parent monitor.
pub(super) base_options: Rc<Options>, pub(super) base_options: Rc<Options>,
@@ -441,6 +446,7 @@ impl<W: LayoutElement> Workspace<W> {
closing_windows: vec![], closing_windows: vec![],
insert_hint: None, insert_hint: None,
insert_hint_buffer: SolidColorBuffer::new((0., 0.), [0., 0., 0., 1.]), insert_hint_buffer: SolidColorBuffer::new((0., 0.), [0., 0., 0., 1.]),
is_pointer_grabbed: false,
base_options, base_options,
options, options,
name: config.map(|c| c.name.0), name: config.map(|c| c.name.0),
@@ -481,6 +487,7 @@ impl<W: LayoutElement> Workspace<W> {
closing_windows: vec![], closing_windows: vec![],
insert_hint: None, insert_hint: None,
insert_hint_buffer: SolidColorBuffer::new((0., 0.), [0., 0., 0., 1.]), insert_hint_buffer: SolidColorBuffer::new((0., 0.), [0., 0., 0., 1.]),
is_pointer_grabbed: false,
base_options, base_options,
options, options,
name: config.map(|c| c.name.0), name: config.map(|c| c.name.0),
@@ -515,10 +522,12 @@ impl<W: LayoutElement> Workspace<W> {
pub fn advance_animations(&mut self, current_time: Duration) { pub fn advance_animations(&mut self, current_time: Duration) {
if let Some(ViewOffsetAdjustment::Animation(anim)) = &mut self.view_offset_adj { if let Some(ViewOffsetAdjustment::Animation(anim)) = &mut self.view_offset_adj {
anim.set_current_time(current_time); if !self.is_pointer_grabbed {
self.view_offset = anim.value(); anim.set_current_time(current_time);
if anim.is_done() { self.view_offset = anim.value();
self.view_offset_adj = None; if anim.is_done() {
self.view_offset_adj = None;
}
} }
} else if let Some(ViewOffsetAdjustment::Gesture(gesture)) = &self.view_offset_adj { } else if let Some(ViewOffsetAdjustment::Gesture(gesture)) = &self.view_offset_adj {
self.view_offset = gesture.current_view_offset; self.view_offset = gesture.current_view_offset;
@@ -1699,6 +1708,33 @@ impl<W: LayoutElement> Workspace<W> {
} }
} }
pub fn set_pointer_grabbed(&mut self, is_grabbed: bool) {
if self.is_pointer_grabbed == is_grabbed {
return;
}
self.is_pointer_grabbed = is_grabbed;
// After ungrabbing, restart the view offset animation.
if !is_grabbed {
if let Some(ViewOffsetAdjustment::Animation(anim)) = &self.view_offset_adj {
// FIXME: preserve velocity.
let anim = anim.restarted(anim.value(), anim.to(), 0.);
self.view_offset_adj = Some(ViewOffsetAdjustment::Animation(anim));
}
}
}
/// Stops a view offset animation if one is in progress.
///
/// The view will stop in place. When calling this, make sure that you will move the view to
/// the active window when necessary.
pub fn cancel_view_offset_anim(&mut self) {
if let Some(ViewOffsetAdjustment::Animation(_)) = &self.view_offset_adj {
self.view_offset_adj = None;
}
}
#[cfg(test)] #[cfg(test)]
pub fn verify_invariants(&self, move_win_id: Option<&W::Id>) { pub fn verify_invariants(&self, move_win_id: Option<&W::Id>) {
use approx::assert_abs_diff_eq; use approx::assert_abs_diff_eq;
+10
View File
@@ -2840,7 +2840,17 @@ impl Niri {
} }
} }
pub fn refresh_layout_is_grabbed(&mut self) {
let pointer = self.seat.get_pointer().unwrap();
let touch = self.seat.get_touch();
let touch_is_grabbed = touch.map_or(false, |touch| touch.is_grabbed());
self.layout
.set_pointer_grabbed(pointer.is_grabbed() || touch_is_grabbed);
}
pub fn refresh_layout(&mut self) { pub fn refresh_layout(&mut self) {
self.refresh_layout_is_grabbed();
let layout_is_active = match &self.keyboard_focus { let layout_is_active = match &self.keyboard_focus {
KeyboardFocus::Layout { .. } => true, KeyboardFocus::Layout { .. } => true,
KeyboardFocus::LayerShell { .. } => false, KeyboardFocus::LayerShell { .. } => false,