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,
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<DropTarget>,
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::<Vec<_>>();
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::<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 => {}