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.
This commit is contained in:
Ian Douglas Scott 2025-02-06 13:30:34 -08:00 • committed by Ian Douglas Scott
parent 3d7d3823c4
commit 5842829c59

View file

@ -35,6 +35,7 @@ use std::{
mem, mem,
path::PathBuf, path::PathBuf,
str, str,
time::{Duration, Instant},
}; };
mod desktop_info; mod desktop_info;
@ -78,6 +79,11 @@ impl CosmicFlags for Args {
} }
} }
enum ScrollDirection {
Next,
Prev,
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
enum Msg { enum Msg {
WaylandEvent(WaylandEvent), WaylandEvent(WaylandEvent),
@ -156,6 +162,7 @@ struct App {
conf: Conf, conf: Conf,
core: cosmic::app::Core, core: cosmic::app::Core,
drop_target: Option<DropTarget>, drop_target: Option<DropTarget>,
scroll: Option<(f32, Instant)>,
} }
impl App { impl App {
@ -540,26 +547,66 @@ impl Application for App {
} }
} }
Msg::OnScroll(output, delta) => { Msg::OnScroll(output, delta) => {
// TODO assumes only one active workspace per output // Accumulate delta with a timer
let mut workspaces = self.workspaces_for_output(&output).collect::<Vec<_>>(); // TODO: Should x scroll be handled too?
if let Some(workspace_idx) = workspaces.iter().position(|i| i.is_active) { // Best time/pixel count?
if let ScrollDelta::Pixels { x: _, y } = delta { let direction = match delta {
// XXX accumulate delta, with timer? ScrollDelta::Pixels { x: _, y } => {
let workspace = if y <= -4. { let previous_scroll = if let Some((scroll, last_scroll_time)) = self.scroll
// Next workspace on output {
workspaces[workspace_idx + 1..].iter().next() if last_scroll_time.elapsed() > Duration::from_millis(100) {
} else if y >= 4. { 0.
// Previous workspace on output } else {
workspaces[..workspace_idx].iter().last() scroll
}
} else { } else {
None 0.
}; };
if let Some(workspace) = workspace {
self.send_wayland_cmd(backend::Cmd::ActivateWorkspace( //let scroll = previous_scroll + y;
dbg!(workspace).handle.clone(), 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::<Vec<_>>();
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 => {} Msg::Ignore => {}