From 5842829c59b9346d0a0546a7444270c9f2970179 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Thu, 6 Feb 2025 13:30:34 -0800 Subject: [PATCH] Accumulate scroll events Not sure the perfect way to do this; the workspace applet is a little different. A helper of some kind should be added to libcosmic. --- src/main.rs | 79 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 16 deletions(-) diff --git a/src/main.rs b/src/main.rs index 4eaef5c..8f5422f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,6 +35,7 @@ use std::{ mem, path::PathBuf, str, + time::{Duration, Instant}, }; mod desktop_info; @@ -78,6 +79,11 @@ impl CosmicFlags for Args { } } +enum ScrollDirection { + Next, + Prev, +} + #[derive(Clone, Debug)] enum Msg { WaylandEvent(WaylandEvent), @@ -156,6 +162,7 @@ struct App { conf: Conf, core: cosmic::app::Core, drop_target: Option, + scroll: Option<(f32, Instant)>, } impl App { @@ -540,26 +547,66 @@ impl Application for App { } } Msg::OnScroll(output, delta) => { - // TODO assumes only one active workspace per output - let mut workspaces = self.workspaces_for_output(&output).collect::>(); - if let Some(workspace_idx) = workspaces.iter().position(|i| i.is_active) { - if let ScrollDelta::Pixels { x: _, y } = delta { - // XXX accumulate delta, with timer? - let workspace = if y <= -4. { - // Next workspace on output - workspaces[workspace_idx + 1..].iter().next() - } else if y >= 4. { - // Previous workspace on output - workspaces[..workspace_idx].iter().last() + // Accumulate delta with a timer + // TODO: Should x scroll be handled too? + // Best time/pixel count? + let direction = match delta { + ScrollDelta::Pixels { x: _, y } => { + let previous_scroll = if let Some((scroll, last_scroll_time)) = self.scroll + { + if last_scroll_time.elapsed() > Duration::from_millis(100) { + 0. + } else { + scroll + } } else { - None + 0. }; - if let Some(workspace) = workspace { - self.send_wayland_cmd(backend::Cmd::ActivateWorkspace( - dbg!(workspace).handle.clone(), - )); + + //let scroll = previous_scroll + y; + let scroll = y; + if scroll <= -4. { + self.scroll = None; + ScrollDirection::Prev + } else if scroll >= 4. { + self.scroll = None; + ScrollDirection::Next + } else { + // If scroll has y element, accumulate scroll + self.scroll = if y != 0. { + Some((scroll, Instant::now())) + } else { + None + }; + return Task::none(); } } + ScrollDelta::Lines { x: _, y } => { + self.scroll = None; + if y < 0. { + ScrollDirection::Prev + } else if y > 0. { + ScrollDirection::Next + } else { + return Task::none(); + } + } + }; + + // TODO assumes only one active workspace per output + let workspaces = self.workspaces_for_output(&output).collect::>(); + if let Some(workspace_idx) = workspaces.iter().position(|i| i.is_active) { + let workspace = match direction { + // Next workspace on output + ScrollDirection::Next => workspaces[workspace_idx + 1..].iter().next(), + // Previous workspace on output + ScrollDirection::Prev => workspaces[..workspace_idx].iter().last(), + }; + if let Some(workspace) = workspace { + self.send_wayland_cmd(backend::Cmd::ActivateWorkspace( + workspace.handle.clone(), + )); + } } } Msg::Ignore => {}