From 3b4f15b935ed9d949e346f613005d712cc04b64f Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Mon, 20 Jun 2022 14:42:12 -0400 Subject: [PATCH] feat: scrolling --- Cargo.lock | 2 +- applets/cosmic-applet-workspaces/src/main.rs | 4 +- applets/cosmic-applet-workspaces/src/utils.rs | 6 +++ .../cosmic-applet-workspaces/src/wayland.rs | 50 +++++++++++++++---- .../src/workspace_button/mod.rs | 4 +- .../src/workspace_list/imp.rs | 2 +- .../src/workspace_list/mod.rs | 20 ++++++++ 7 files changed, 73 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a3f3bc9f..b462569a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -428,7 +428,7 @@ dependencies = [ [[package]] name = "cosmic-panel-config" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-panel#231dc1ec0656840458d9f0d3468d9c7ea5c2a98c" +source = "git+https://github.com/pop-os/cosmic-panel/#231dc1ec0656840458d9f0d3468d9c7ea5c2a98c" dependencies = [ "anyhow", "gtk4", diff --git a/applets/cosmic-applet-workspaces/src/main.rs b/applets/cosmic-applet-workspaces/src/main.rs index 520673a2..78304a4a 100644 --- a/applets/cosmic-applet-workspaces/src/main.rs +++ b/applets/cosmic-applet-workspaces/src/main.rs @@ -11,7 +11,7 @@ use once_cell::sync::OnceCell; use wayland::State; use std::sync::{Arc, Mutex}; use tokio::sync::mpsc; -use utils::{Activate}; +use utils::{Activate, WorkspaceEvent}; use window::CosmicWorkspacesWindow; mod localize; @@ -24,7 +24,7 @@ mod workspace_list; mod workspace_object; const ID: &str = "com.system76.CosmicAppletWorkspaces"; -static TX: OnceCell> = OnceCell::new(); +static TX: OnceCell> = OnceCell::new(); pub fn localize() { let localizer = crate::localize::localizer(); diff --git a/applets/cosmic-applet-workspaces/src/utils.rs b/applets/cosmic-applet-workspaces/src/utils.rs index 733302c1..1e99418e 100644 --- a/applets/cosmic-applet-workspaces/src/utils.rs +++ b/applets/cosmic-applet-workspaces/src/utils.rs @@ -7,6 +7,12 @@ use std::future::Future; pub type Activate = String; +#[derive(Debug, Clone)] +pub enum WorkspaceEvent { + Activate(String), + Scroll(f64), +} + pub fn data_path() -> PathBuf { let mut path = glib::user_data_dir(); path.push(crate::ID); diff --git a/applets/cosmic-applet-workspaces/src/wayland.rs b/applets/cosmic-applet-workspaces/src/wayland.rs index 2fede4a8..a3419561 100644 --- a/applets/cosmic-applet-workspaces/src/wayland.rs +++ b/applets/cosmic-applet-workspaces/src/wayland.rs @@ -1,4 +1,4 @@ -use crate::{utils::{Activate}, wayland::generated::client::zext_workspace_manager_v1::ZextWorkspaceManagerV1, wayland_source::WaylandSource}; +use crate::{utils::{Activate, WorkspaceEvent}, wayland::generated::client::zext_workspace_manager_v1::ZextWorkspaceManagerV1, wayland_source::WaylandSource}; use std::{env, os::unix::net::UnixStream, path::PathBuf, sync::Arc, mem, time::Duration}; use gtk4::glib; use tokio::sync::mpsc; @@ -38,7 +38,7 @@ use self::generated::client::{ zext_workspace_handle_v1::{self, ZextWorkspaceHandleV1}, }; -pub fn spawn_workspaces(tx: glib::Sender) -> mpsc::Sender { +pub fn spawn_workspaces(tx: glib::Sender) -> mpsc::Sender { let (workspaces_tx, mut workspaces_rx) = mpsc::channel(100); if let Ok(Ok(conn)) = std::env::var("HOST_WAYLAND_DISPLAY") .map_err(anyhow::Error::msg) @@ -75,14 +75,46 @@ pub fn spawn_workspaces(tx: glib::Sender) -> mpsc::Sender { while state.running { let mut changed = false; while let Ok(request) = workspaces_rx.try_recv() { - if let Some(w) = state.workspace_groups.iter().find_map(|g| { - g.workspaces - .iter() - .find(|w| w.name == request) - }) { - w.workspace_handle.activate(); + match request { + WorkspaceEvent::Activate(id) => { + if let Some(w) = state.workspace_groups.iter().find_map(|g| { + g.workspaces + .iter() + .find(|w| w.name == id) + }) { + w.workspace_handle.activate(); + changed = true; + } + } + WorkspaceEvent::Scroll(v) => { + dbg!(v); + if let Some((w_g, w_i)) = state.workspace_groups.iter().enumerate().find_map(|(g_i, g)| { + g.workspaces + .iter() + .position(|w| w.state == 0) + .map(|w_i| (g, w_i)) + }) { + let max_w = w_g.workspaces.len().wrapping_sub(1); + let d_i = if v > 0.0 { + if w_i == max_w { + 0 + } else { + w_i.wrapping_add(1) + } + } else { + if w_i == 0 { + max_w + } else { + w_i.wrapping_sub(1) + } }; + if let Some(w) = w_g.workspaces.get(d_i) { + w.workspace_handle.activate(); + changed = true; + } + } + } } - changed = true; + } if changed { state.workspace_manager.as_ref().unwrap().commit(); diff --git a/applets/cosmic-applet-workspaces/src/workspace_button/mod.rs b/applets/cosmic-applet-workspaces/src/workspace_button/mod.rs index d609c96e..9d466d27 100644 --- a/applets/cosmic-applet-workspaces/src/workspace_button/mod.rs +++ b/applets/cosmic-applet-workspaces/src/workspace_button/mod.rs @@ -1,6 +1,6 @@ mod imp; -use crate::{workspace_object::WorkspaceObject, Activate, TX}; +use crate::{workspace_object::WorkspaceObject, Activate, TX, utils::WorkspaceEvent}; use glib::Object; use gtk4::{glib, prelude::*, subclass::prelude::*, ToggleButton}; @@ -44,7 +44,7 @@ impl WorkspaceButton { let id_clone = id.clone(); if !is_active { glib::MainContext::default().spawn_local(async move { - TX.get().unwrap().send(id_clone).await.unwrap(); + TX.get().unwrap().send(WorkspaceEvent::Activate(id_clone)).await.unwrap(); }); } }); diff --git a/applets/cosmic-applet-workspaces/src/workspace_list/imp.rs b/applets/cosmic-applet-workspaces/src/workspace_list/imp.rs index 634c1714..94f4da3e 100644 --- a/applets/cosmic-applet-workspaces/src/workspace_list/imp.rs +++ b/applets/cosmic-applet-workspaces/src/workspace_list/imp.rs @@ -2,7 +2,7 @@ use cosmic_panel_config::config::CosmicPanelConfig; use gtk4::subclass::prelude::*; -use gtk4::{gio, glib}; +use gtk4::{gio, glib, EventControllerScroll}; use gtk4::{Box, ListView}; use once_cell::sync::OnceCell; use tokio::sync::mpsc; diff --git a/applets/cosmic-applet-workspaces/src/workspace_list/mod.rs b/applets/cosmic-applet-workspaces/src/workspace_list/mod.rs index baaa415a..8416352b 100644 --- a/applets/cosmic-applet-workspaces/src/workspace_list/mod.rs +++ b/applets/cosmic-applet-workspaces/src/workspace_list/mod.rs @@ -1,14 +1,19 @@ // SPDX-License-Identifier: MPL-2.0-only +use crate::TX; use crate::utils::Activate; +use crate::utils::WorkspaceEvent; use crate::wayland::State; use crate::workspace_button::WorkspaceButton; use crate::workspace_object::WorkspaceObject; use cascade::cascade; use cosmic_panel_config::config::{CosmicPanelConfig}; +use gtk4::EventControllerScrollFlags; +use gtk4::Inhibit; use gtk4::ListView; use gtk4::Orientation; use gtk4::SignalListItemFactory; +use gtk4::builders::EventControllerScrollBuilder; use gtk4::{gio, glib, prelude::*, subclass::prelude::*}; use tokio::sync::mpsc::Sender; @@ -48,6 +53,21 @@ impl WorkspaceList { ..add_css_class("transparent"); }; self.append(&list_view); + + let flags = EventControllerScrollFlags::BOTH_AXES; + + let scroll_controller = EventControllerScrollBuilder::new() + .flags(flags.union(EventControllerScrollFlags::DISCRETE)) + .build(); + + scroll_controller.connect_scroll( |_, dx, dy| { + glib::MainContext::default().spawn_local(async move { + TX.get().unwrap().send(WorkspaceEvent::Scroll(dx + dy)).await.unwrap(); + }); + Inhibit::default() + }); + + list_view.add_controller(&scroll_controller); imp.list_view.set(list_view).unwrap(); }