mirror of
https://github.com/YaLTeR/niri.git
synced 2024-10-26 11:48:09 +03:00
Implement rubber banding for the vertical gesture
This commit is contained in:
parent
ae89b2e514
commit
f9127616b0
@ -15,12 +15,18 @@ use super::workspace::{
|
||||
use super::{LayoutElement, Options};
|
||||
use crate::animation::Animation;
|
||||
use crate::render_helpers::renderer::NiriRenderer;
|
||||
use crate::rubber_band::RubberBand;
|
||||
use crate::swipe_tracker::SwipeTracker;
|
||||
use crate::utils::output_size;
|
||||
|
||||
/// Amount of touchpad movement to scroll the height of one workspace.
|
||||
const WORKSPACE_GESTURE_MOVEMENT: f64 = 300.;
|
||||
|
||||
const WORKSPACE_GESTURE_RUBBER_BAND: RubberBand = RubberBand {
|
||||
stiffness: 0.5,
|
||||
limit: 0.05,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Monitor<W: LayoutElement> {
|
||||
/// Output for this monitor.
|
||||
@ -762,7 +768,8 @@ impl<W: LayoutElement> Monitor<W> {
|
||||
|
||||
let min = gesture.center_idx.saturating_sub(1) as f64;
|
||||
let max = (gesture.center_idx + 1).min(self.workspaces.len() - 1) as f64;
|
||||
let new_idx = (gesture.center_idx as f64 + pos).clamp(min, max);
|
||||
let new_idx = gesture.center_idx as f64 + pos;
|
||||
let new_idx = WORKSPACE_GESTURE_RUBBER_BAND.clamp(min, max, new_idx);
|
||||
|
||||
if gesture.current_idx == new_idx {
|
||||
return Some(false);
|
||||
@ -783,14 +790,23 @@ impl<W: LayoutElement> Monitor<W> {
|
||||
return true;
|
||||
}
|
||||
|
||||
let velocity = gesture.tracker.velocity() / WORKSPACE_GESTURE_MOVEMENT;
|
||||
let mut velocity = gesture.tracker.velocity() / WORKSPACE_GESTURE_MOVEMENT;
|
||||
let current_pos = gesture.tracker.pos() / WORKSPACE_GESTURE_MOVEMENT;
|
||||
let pos = gesture.tracker.projected_end_pos() / WORKSPACE_GESTURE_MOVEMENT;
|
||||
|
||||
let min = gesture.center_idx.saturating_sub(1) as f64;
|
||||
let max = (gesture.center_idx + 1).min(self.workspaces.len() - 1) as f64;
|
||||
let new_idx = (gesture.center_idx as f64 + pos).clamp(min, max);
|
||||
let new_idx = gesture.center_idx as f64 + pos;
|
||||
|
||||
let new_idx = WORKSPACE_GESTURE_RUBBER_BAND.clamp(min, max, new_idx);
|
||||
let new_idx = new_idx.round() as usize;
|
||||
|
||||
velocity *= WORKSPACE_GESTURE_RUBBER_BAND.clamp_derivative(
|
||||
min,
|
||||
max,
|
||||
gesture.center_idx as f64 + current_pos,
|
||||
);
|
||||
|
||||
self.active_workspace_idx = new_idx;
|
||||
self.workspace_switch = Some(WorkspaceSwitch::Animation(Animation::new(
|
||||
gesture.current_idx,
|
||||
|
@ -15,6 +15,7 @@ pub mod layout;
|
||||
pub mod niri;
|
||||
pub mod protocols;
|
||||
pub mod render_helpers;
|
||||
pub mod rubber_band;
|
||||
pub mod swipe_tracker;
|
||||
pub mod ui;
|
||||
pub mod utils;
|
||||
|
39
src/rubber_band.rs
Normal file
39
src/rubber_band.rs
Normal file
@ -0,0 +1,39 @@
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct RubberBand {
|
||||
pub stiffness: f64,
|
||||
pub limit: f64,
|
||||
}
|
||||
|
||||
impl RubberBand {
|
||||
pub fn band(&self, x: f64) -> f64 {
|
||||
let c = self.stiffness;
|
||||
let d = self.limit;
|
||||
|
||||
(1. - (1. / (x * c / d + 1.))) * d
|
||||
}
|
||||
|
||||
pub fn derivative(&self, x: f64) -> f64 {
|
||||
let c = self.stiffness;
|
||||
let d = self.limit;
|
||||
|
||||
c * d * d / (c * x + d).powi(2)
|
||||
}
|
||||
|
||||
pub fn clamp(&self, min: f64, max: f64, x: f64) -> f64 {
|
||||
let clamped = x.clamp(min, max);
|
||||
let sign = if x < clamped { -1. } else { 1. };
|
||||
let diff = (x - clamped).abs();
|
||||
|
||||
clamped + sign * self.band(diff)
|
||||
}
|
||||
|
||||
pub fn clamp_derivative(&self, min: f64, max: f64, x: f64) -> f64 {
|
||||
if min <= x && x <= max {
|
||||
return 1.;
|
||||
}
|
||||
|
||||
let clamped = x.clamp(min, max);
|
||||
let diff = (x - clamped).abs();
|
||||
self.derivative(diff)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user