mirror of
https://github.com/YaLTeR/niri.git
synced 2025-08-04 17:07:59 +00:00
Freeze view when pointer or touch is grabbed
This commit is contained in:
parent
6ecbf2db8a
commit
012340c5f4
4 changed files with 67 additions and 4 deletions
|
@ -1735,6 +1735,8 @@ impl State {
|
|||
},
|
||||
);
|
||||
pointer.frame(self);
|
||||
|
||||
self.niri.refresh_layout_is_grabbed();
|
||||
}
|
||||
|
||||
fn on_pointer_axis<I: InputBackend>(&mut self, event: I::PointerAxisEvent) {
|
||||
|
@ -2370,6 +2372,8 @@ impl State {
|
|||
|
||||
// We're using touch, hide the pointer.
|
||||
self.niri.pointer_hidden = true;
|
||||
|
||||
self.niri.refresh_layout_is_grabbed();
|
||||
}
|
||||
fn on_touch_up<I: InputBackend>(&mut self, evt: I::TouchUpEvent) {
|
||||
let Some(handle) = self.niri.seat.get_touch() else {
|
||||
|
|
|
@ -1928,6 +1928,12 @@ impl<W: LayoutElement> Layout<W> {
|
|||
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)]
|
||||
fn verify_invariants(&self) {
|
||||
use std::collections::HashSet;
|
||||
|
@ -2912,6 +2918,13 @@ impl<W: LayoutElement> Layout<W> {
|
|||
.unwrap();
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,6 +114,11 @@ pub struct Workspace<W: LayoutElement> {
|
|||
/// Buffer for the insert hint.
|
||||
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.
|
||||
pub(super) base_options: Rc<Options>,
|
||||
|
||||
|
@ -441,6 +446,7 @@ impl<W: LayoutElement> Workspace<W> {
|
|||
closing_windows: vec![],
|
||||
insert_hint: None,
|
||||
insert_hint_buffer: SolidColorBuffer::new((0., 0.), [0., 0., 0., 1.]),
|
||||
is_pointer_grabbed: false,
|
||||
base_options,
|
||||
options,
|
||||
name: config.map(|c| c.name.0),
|
||||
|
@ -481,6 +487,7 @@ impl<W: LayoutElement> Workspace<W> {
|
|||
closing_windows: vec![],
|
||||
insert_hint: None,
|
||||
insert_hint_buffer: SolidColorBuffer::new((0., 0.), [0., 0., 0., 1.]),
|
||||
is_pointer_grabbed: false,
|
||||
base_options,
|
||||
options,
|
||||
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) {
|
||||
if let Some(ViewOffsetAdjustment::Animation(anim)) = &mut self.view_offset_adj {
|
||||
anim.set_current_time(current_time);
|
||||
self.view_offset = anim.value();
|
||||
if anim.is_done() {
|
||||
self.view_offset_adj = None;
|
||||
if !self.is_pointer_grabbed {
|
||||
anim.set_current_time(current_time);
|
||||
self.view_offset = anim.value();
|
||||
if anim.is_done() {
|
||||
self.view_offset_adj = None;
|
||||
}
|
||||
}
|
||||
} else if let Some(ViewOffsetAdjustment::Gesture(gesture)) = &self.view_offset_adj {
|
||||
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)]
|
||||
pub fn verify_invariants(&self, move_win_id: Option<&W::Id>) {
|
||||
use approx::assert_abs_diff_eq;
|
||||
|
|
10
src/niri.rs
10
src/niri.rs
|
@ -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) {
|
||||
self.refresh_layout_is_grabbed();
|
||||
|
||||
let layout_is_active = match &self.keyboard_focus {
|
||||
KeyboardFocus::Layout { .. } => true,
|
||||
KeyboardFocus::LayerShell { .. } => false,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue