use crate::wayland::{self, WorkspaceEvent, WorkspaceList}; use calloop::channel::SyncSender; use futures::{channel::mpsc, StreamExt}; use std::hash::Hash; #[derive(Debug, Clone)] pub enum WorkspacesUpdate { Workspaces(WorkspaceList), Started(SyncSender), Errored, } pub fn workspaces( id: I, ) -> cosmic::iced::Subscription<(I, WorkspacesUpdate)> { use cosmic::iced::subscription; subscription::unfold(id, State::Ready, move |state| _workspaces(id, state)) } async fn _workspaces(id: I, mut state: State) -> ((I, WorkspacesUpdate), State) { loop { let (update, new_state) = match state { State::Ready => { if let Ok(watcher) = WorkspacesWatcher::new() { ( Some((id, WorkspacesUpdate::Started(watcher.get_sender()))), State::Waiting(watcher), ) } else { (Some((id, WorkspacesUpdate::Errored)), State::Error) } } State::Waiting(mut t) => { if let Some(w) = t.workspaces().await { ( Some((id, WorkspacesUpdate::Workspaces(w))), State::Waiting(t), ) } else { (Some((id, WorkspacesUpdate::Errored)), State::Error) } } State::Error => cosmic::iced::futures::future::pending().await, }; state = new_state; if let Some(update) = update { return (update, state); } } } pub enum State { Ready, Waiting(WorkspacesWatcher), Error, } pub struct WorkspacesWatcher { rx: mpsc::Receiver, tx: SyncSender, } impl WorkspacesWatcher { pub fn new() -> anyhow::Result { let (tx, rx) = mpsc::channel(20); let tx = wayland::spawn_workspaces(tx); Ok(Self { tx, rx }) } pub fn get_sender(&self) -> SyncSender { self.tx.clone() } pub async fn workspaces(&mut self) -> Option { self.rx.next().await } }