From a607da7f4479d857a45503b84ae4920698fe27b0 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 13 Oct 2025 14:11:48 -0700 Subject: [PATCH] Use libcosmic `DiscreteScrollState` helper --- Cargo.lock | 122 ++++++++++++++++++++++++++++++++++++---------------- src/main.rs | 101 ++++++++----------------------------------- 2 files changed, 102 insertions(+), 121 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5acf6f3..645fb22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -690,6 +690,15 @@ dependencies = [ "serde", ] +[[package]] +name = "btoi" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b5ab9db53bcda568284df0fd39f6eac24ad6f7ba7ff1168b9e76eba6576b976" +dependencies = [ + "num-traits", +] + [[package]] name = "bumpalo" version = "3.19.0" @@ -1109,7 +1118,7 @@ dependencies = [ [[package]] name = "cosmic-config" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#d6b3720e1f161f064a586f4317422e78cbb60214" +source = "git+https://github.com/pop-os/libcosmic#2f0b3334914e4ab1b0f3df821eeadd7ad700566f" dependencies = [ "atomicwrites", "cosmic-config-derive", @@ -1130,7 +1139,7 @@ dependencies = [ [[package]] name = "cosmic-config-derive" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#d6b3720e1f161f064a586f4317422e78cbb60214" +source = "git+https://github.com/pop-os/libcosmic#2f0b3334914e4ab1b0f3df821eeadd7ad700566f" dependencies = [ "quote", "syn 2.0.110", @@ -1139,10 +1148,11 @@ dependencies = [ [[package]] name = "cosmic-freedesktop-icons" version = "0.4.0" -source = "git+https://github.com/pop-os/freedesktop-icons#689c60d428f46dc59316eafa22297e196afa4b15" +source = "git+https://github.com/pop-os/freedesktop-icons#7a61a704f6d1ec41f71cbe766e3cc484858523fa" dependencies = [ - "dirs", - "ini_core", + "bstr", + "btoi", + "memchr", "memmap2 0.9.9", "thiserror 2.0.17", "tracing", @@ -1180,7 +1190,7 @@ dependencies = [ [[package]] name = "cosmic-settings-config" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-settings-daemon#fbd4adede269681c07cd273f417f9296feabc26e" +source = "git+https://github.com/pop-os/cosmic-settings-daemon#d67de203ced04c5b8ec3486d93e0e61876a8ee91" dependencies = [ "cosmic-config", "ron", @@ -1201,7 +1211,7 @@ dependencies = [ [[package]] name = "cosmic-text" version = "0.15.0" -source = "git+https://github.com/pop-os/cosmic-text.git#9339446cfa9b7f0110094a97764dccc09cfa98a2" +source = "git+https://github.com/pop-os/cosmic-text.git#a07a6190548c8e40a55f6b7761387047ff1bf6ff" dependencies = [ "bitflags 2.10.0", "fontdb 0.23.0", @@ -1224,7 +1234,7 @@ dependencies = [ [[package]] name = "cosmic-theme" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#d6b3720e1f161f064a586f4317422e78cbb60214" +source = "git+https://github.com/pop-os/libcosmic#2f0b3334914e4ab1b0f3df821eeadd7ad700566f" dependencies = [ "almost", "cosmic-config", @@ -1324,7 +1334,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fda6aace1fbef3aa217b27f4c8d7d071ef2a70a5ca51050b1f17d40299d3f16" dependencies = [ - "phf", + "phf 0.11.3", "serde", ] @@ -1581,7 +1591,7 @@ checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] name = "dpi" version = "0.1.1" -source = "git+https://github.com/pop-os/winit.git?tag=iced-xdg-surface-0.13-rc#8dfaba290f9a00d3e13be71f1e6f438889cf5546" +source = "git+https://github.com/pop-os/winit.git?tag=iced-xdg-surface-0.13-rc#12a5f17d1811cdebbcbd310a3d92965e9142fa12" [[package]] name = "drm" @@ -2538,7 +2548,7 @@ dependencies = [ [[package]] name = "iced" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#d6b3720e1f161f064a586f4317422e78cbb60214" +source = "git+https://github.com/pop-os/libcosmic#2f0b3334914e4ab1b0f3df821eeadd7ad700566f" dependencies = [ "dnd", "iced_accessibility", @@ -2556,7 +2566,7 @@ dependencies = [ [[package]] name = "iced_accessibility" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#d6b3720e1f161f064a586f4317422e78cbb60214" +source = "git+https://github.com/pop-os/libcosmic#2f0b3334914e4ab1b0f3df821eeadd7ad700566f" dependencies = [ "accesskit", "accesskit_winit", @@ -2565,7 +2575,7 @@ dependencies = [ [[package]] name = "iced_core" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#d6b3720e1f161f064a586f4317422e78cbb60214" +source = "git+https://github.com/pop-os/libcosmic#2f0b3334914e4ab1b0f3df821eeadd7ad700566f" dependencies = [ "bitflags 2.10.0", "bytes", @@ -2589,7 +2599,7 @@ dependencies = [ [[package]] name = "iced_futures" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#d6b3720e1f161f064a586f4317422e78cbb60214" +source = "git+https://github.com/pop-os/libcosmic#2f0b3334914e4ab1b0f3df821eeadd7ad700566f" dependencies = [ "futures", "iced_core", @@ -2615,7 +2625,7 @@ dependencies = [ [[package]] name = "iced_graphics" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#d6b3720e1f161f064a586f4317422e78cbb60214" +source = "git+https://github.com/pop-os/libcosmic#2f0b3334914e4ab1b0f3df821eeadd7ad700566f" dependencies = [ "bitflags 2.10.0", "bytemuck", @@ -2637,7 +2647,7 @@ dependencies = [ [[package]] name = "iced_renderer" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#d6b3720e1f161f064a586f4317422e78cbb60214" +source = "git+https://github.com/pop-os/libcosmic#2f0b3334914e4ab1b0f3df821eeadd7ad700566f" dependencies = [ "iced_graphics", "iced_tiny_skia", @@ -2649,7 +2659,7 @@ dependencies = [ [[package]] name = "iced_runtime" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#d6b3720e1f161f064a586f4317422e78cbb60214" +source = "git+https://github.com/pop-os/libcosmic#2f0b3334914e4ab1b0f3df821eeadd7ad700566f" dependencies = [ "bytes", "cosmic-client-toolkit", @@ -2664,7 +2674,7 @@ dependencies = [ [[package]] name = "iced_tiny_skia" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#d6b3720e1f161f064a586f4317422e78cbb60214" +source = "git+https://github.com/pop-os/libcosmic#2f0b3334914e4ab1b0f3df821eeadd7ad700566f" dependencies = [ "bytemuck", "cosmic-text", @@ -2680,7 +2690,7 @@ dependencies = [ [[package]] name = "iced_wgpu" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#d6b3720e1f161f064a586f4317422e78cbb60214" +source = "git+https://github.com/pop-os/libcosmic#2f0b3334914e4ab1b0f3df821eeadd7ad700566f" dependencies = [ "as-raw-xcb-connection", "bitflags 2.10.0", @@ -2711,7 +2721,7 @@ dependencies = [ [[package]] name = "iced_widget" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#d6b3720e1f161f064a586f4317422e78cbb60214" +source = "git+https://github.com/pop-os/libcosmic#2f0b3334914e4ab1b0f3df821eeadd7ad700566f" dependencies = [ "cosmic-client-toolkit", "dnd", @@ -2730,7 +2740,7 @@ dependencies = [ [[package]] name = "iced_winit" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#d6b3720e1f161f064a586f4317422e78cbb60214" +source = "git+https://github.com/pop-os/libcosmic#2f0b3334914e4ab1b0f3df821eeadd7ad700566f" dependencies = [ "cosmic-client-toolkit", "dnd", @@ -2917,15 +2927,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "ini_core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a467a31a9f439b5262fa99c17084537bff57f24703d5a09a2b5c9657ec73a61" -dependencies = [ - "cfg-if", -] - [[package]] name = "inotify" version = "0.11.0" @@ -3188,7 +3189,7 @@ checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libcosmic" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#d6b3720e1f161f064a586f4317422e78cbb60214" +source = "git+https://github.com/pop-os/libcosmic#2f0b3334914e4ab1b0f3df821eeadd7ad700566f" dependencies = [ "apply", "ashpd 0.12.0", @@ -3217,8 +3218,10 @@ dependencies = [ "iced_winit", "image", "libc", + "log", "mime 0.3.17", "palette", + "phf 0.13.1", "raw-window-handle", "rfd", "ron", @@ -4030,7 +4033,7 @@ dependencies = [ "approx", "fast-srgb8", "palette_derive", - "phf", + "phf 0.11.3", "serde", ] @@ -4118,8 +4121,19 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ - "phf_macros", - "phf_shared", + "phf_macros 0.11.3", + "phf_shared 0.11.3", +] + +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_macros 0.13.1", + "phf_shared 0.13.1", + "serde", ] [[package]] @@ -4128,18 +4142,41 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ - "phf_shared", + "phf_shared 0.11.3", "rand 0.8.5", ] +[[package]] +name = "phf_generator" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +dependencies = [ + "fastrand 2.3.0", + "phf_shared 0.13.1", +] + [[package]] name = "phf_macros" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "phf_macros" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +dependencies = [ + "phf_generator 0.13.1", + "phf_shared 0.13.1", "proc-macro2", "quote", "syn 2.0.110", @@ -4154,6 +4191,15 @@ dependencies = [ "siphasher", ] +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", +] + [[package]] name = "pico-args" version = "0.5.0" @@ -6647,7 +6693,7 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winit" version = "0.30.5" -source = "git+https://github.com/pop-os/winit.git?tag=iced-xdg-surface-0.13-rc#8dfaba290f9a00d3e13be71f1e6f438889cf5546" +source = "git+https://github.com/pop-os/winit.git?tag=iced-xdg-surface-0.13-rc#12a5f17d1811cdebbcbd310a3d92965e9142fa12" dependencies = [ "ahash", "android-activity", diff --git a/src/main.rs b/src/main.rs index 17b7edc..65fd6db 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,6 +28,7 @@ use cosmic::{ iced_winit::platform_specific::wayland::commands::layer_surface::{ destroy_layer_surface, get_layer_surface, }, + scroll::DiscreteScrollState, }; use cosmic_comp_config::CosmicCompConfig; use cosmic_config::{CosmicConfigEntry, cosmic_config_derive::CosmicConfigEntry}; @@ -38,7 +39,7 @@ use std::{ mem, path::PathBuf, str, - time::{Duration, Instant}, + time::Duration, }; mod dbus; @@ -53,8 +54,7 @@ mod utils; mod widgets; use dnd::{DragSurface, DragToplevel, DragWorkspace, DropTarget}; -// Number of scroll pixels before changing workspace -const SCROLL_PIXELS: f32 = 24.0; +const SCROLL_RATE_LIMIT: Duration = Duration::from_millis(200); #[derive(Clone, Debug, Default, PartialEq, CosmicConfigEntry)] struct CosmicWorkspacesConfig { @@ -86,11 +86,6 @@ impl CosmicFlags for Args { } } -enum ScrollDirection { - Next, - Prev, -} - #[derive(Clone, Debug)] enum Msg { WaylandEvent(WaylandEvent), @@ -200,7 +195,7 @@ struct App { conf: Conf, core: cosmic::app::Core, drop_target: Option, - scroll: Option<(f32, Instant)>, + scroll: DiscreteScrollState, dbus_interface: Option, panel_configs: HashMap>, } @@ -415,6 +410,7 @@ impl Application for App { ( Self { core, + scroll: DiscreteScrollState::default().rate_limit(Some(SCROLL_RATE_LIMIT)), ..Default::default() }, Task::none(), @@ -672,81 +668,20 @@ impl Application for App { } } Msg::OnScroll(output, delta) => { - // Accumulate delta with a timer - // TODO: Should x scroll be handled too? - // Best time/pixel count? - - let previous_scroll = if let Some((scroll, last_scroll_time)) = self.scroll { - if last_scroll_time.elapsed() > Duration::from_millis(100) { - 0. - } else { - scroll + let discrete_delta = self.scroll.update(delta); + if discrete_delta.y != 0 { + // 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()) { + // Add delta_num, to index wrapping around + let new_workspace_idx = (workspace_idx as isize - discrete_delta.y) + .rem_euclid(workspaces.len() as isize) + as usize; + let workspace = workspaces[new_workspace_idx]; + self.send_wayland_cmd(backend::Cmd::ActivateWorkspace( + workspace.handle().clone(), + )); } - } else { - 0. - }; - - let direction = match delta { - ScrollDelta::Pixels { x: _, mut y } => { - y = -y; - - let scroll = previous_scroll + y; - if scroll <= -SCROLL_PIXELS { - self.scroll = None; - ScrollDirection::Prev - } else if scroll >= SCROLL_PIXELS { - 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: _, mut y } => { - y = -y; - - let scroll = previous_scroll + y; - if scroll <= -1. { - self.scroll = None; - ScrollDirection::Prev - } else if scroll >= 1. { - self.scroll = None; - ScrollDirection::Next - } else { - self.scroll = if y != 0. { - Some((scroll, Instant::now())) - } else { - None - }; - 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 new_workspace_idx = match direction { - // Next workspace on output, wrapping to start - ScrollDirection::Next => (workspace_idx + 1) % workspaces.len(), - // Previous workspace on output, wrapping to end - ScrollDirection::Prev => { - if workspace_idx == 0 { - workspaces.len() - 1 - } else { - workspace_idx - 1 - } - } - }; - let workspace = workspaces[new_workspace_idx]; - self.send_wayland_cmd(backend::Cmd::ActivateWorkspace( - workspace.handle().clone(), - )); } } Msg::DndWorkspaceDrag => {}