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 super::{LayoutElement, Options};
|
||||||
use crate::animation::Animation;
|
use crate::animation::Animation;
|
||||||
use crate::render_helpers::renderer::NiriRenderer;
|
use crate::render_helpers::renderer::NiriRenderer;
|
||||||
|
use crate::rubber_band::RubberBand;
|
||||||
use crate::swipe_tracker::SwipeTracker;
|
use crate::swipe_tracker::SwipeTracker;
|
||||||
use crate::utils::output_size;
|
use crate::utils::output_size;
|
||||||
|
|
||||||
/// Amount of touchpad movement to scroll the height of one workspace.
|
/// Amount of touchpad movement to scroll the height of one workspace.
|
||||||
const WORKSPACE_GESTURE_MOVEMENT: f64 = 300.;
|
const WORKSPACE_GESTURE_MOVEMENT: f64 = 300.;
|
||||||
|
|
||||||
|
const WORKSPACE_GESTURE_RUBBER_BAND: RubberBand = RubberBand {
|
||||||
|
stiffness: 0.5,
|
||||||
|
limit: 0.05,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Monitor<W: LayoutElement> {
|
pub struct Monitor<W: LayoutElement> {
|
||||||
/// Output for this monitor.
|
/// Output for this monitor.
|
||||||
@ -762,7 +768,8 @@ impl<W: LayoutElement> Monitor<W> {
|
|||||||
|
|
||||||
let min = gesture.center_idx.saturating_sub(1) as f64;
|
let min = gesture.center_idx.saturating_sub(1) as f64;
|
||||||
let max = (gesture.center_idx + 1).min(self.workspaces.len() - 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 {
|
if gesture.current_idx == new_idx {
|
||||||
return Some(false);
|
return Some(false);
|
||||||
@ -783,14 +790,23 @@ impl<W: LayoutElement> Monitor<W> {
|
|||||||
return true;
|
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 pos = gesture.tracker.projected_end_pos() / WORKSPACE_GESTURE_MOVEMENT;
|
||||||
|
|
||||||
let min = gesture.center_idx.saturating_sub(1) as f64;
|
let min = gesture.center_idx.saturating_sub(1) as f64;
|
||||||
let max = (gesture.center_idx + 1).min(self.workspaces.len() - 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;
|
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.active_workspace_idx = new_idx;
|
||||||
self.workspace_switch = Some(WorkspaceSwitch::Animation(Animation::new(
|
self.workspace_switch = Some(WorkspaceSwitch::Animation(Animation::new(
|
||||||
gesture.current_idx,
|
gesture.current_idx,
|
||||||
|
@ -15,6 +15,7 @@ pub mod layout;
|
|||||||
pub mod niri;
|
pub mod niri;
|
||||||
pub mod protocols;
|
pub mod protocols;
|
||||||
pub mod render_helpers;
|
pub mod render_helpers;
|
||||||
|
pub mod rubber_band;
|
||||||
pub mod swipe_tracker;
|
pub mod swipe_tracker;
|
||||||
pub mod ui;
|
pub mod ui;
|
||||||
pub mod utils;
|
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