From 555ffca915985466938a6c4a666c37c7241eb413 Mon Sep 17 00:00:00 2001 From: atagen Date: Sat, 5 Jul 2025 15:26:56 +1000 Subject: [PATCH] refactor: allow multiple actions for do_action --- daemon/manager.rs | 195 +++++++++++++++++++++++----------------------- 1 file changed, 98 insertions(+), 97 deletions(-) diff --git a/daemon/manager.rs b/daemon/manager.rs index 7332485..108f0ab 100644 --- a/daemon/manager.rs +++ b/daemon/manager.rs @@ -135,7 +135,7 @@ impl NiriTag { } } - async fn do_action(&mut self, action: TagAction) -> Result<()> { + async fn do_actions(&mut self, actions: &[TagAction]) -> Result<()> { use TagAction::*; let (active, inactive): (HashMap<_, _>, HashMap<_, _>) = self .state @@ -144,102 +144,103 @@ impl NiriTag { .clone() .into_iter() .partition(|(_, ws)| ws.is_active); - match action { - Window(wid) => { - let current_tag = *self.windows.entry(wid).or_insert(0); - let tag_visible = self.tags.entry(current_tag).or_default().enabled; - let win = self - .state - .windows - .windows - .get(&wid) - .ok_or(anyhow!("Failed to retrieve window {} from niri state", wid))?; - let wsid: u64 = win - .workspace_id - .ok_or(anyhow!("Retrieving workspace id of a changed window"))?; - let win_visible = active.contains_key(&wsid); - match (win_visible, tag_visible) { - (true, false) => { - let inactive_same_output = self.same_output(wsid, &inactive)?; - tell( - &mut self.socket, - Request::Action(Action::MoveWindowToWorkspace { - window_id: Some(wid), - reference: WorkspaceReferenceArg::Id(inactive_same_output.id), - focus: false, - }), - ) - .await + for action in actions { + match action { + Window(wid) => { + let current_tag = *self.windows.entry(*wid).or_insert(0); + let tag_visible = self.tags.entry(current_tag).or_default().enabled; + let win = self + .state + .windows + .windows + .get(wid) + .ok_or(anyhow!("Failed to retrieve window {} from niri state", wid))?; + let wsid: u64 = win + .workspace_id + .ok_or(anyhow!("Retrieving workspace id of a changed window"))?; + let win_visible = active.contains_key(&wsid); + match (win_visible, tag_visible) { + (true, false) => { + let inactive_same_output = self.same_output(wsid, &inactive)?; + tell( + &mut self.socket, + Request::Action(Action::MoveWindowToWorkspace { + window_id: Some(*wid), + reference: WorkspaceReferenceArg::Id(inactive_same_output.id), + focus: false, + }), + ) + .await? + } + (false, true) => { + let active_same_output = self.same_output(wsid, &active)?; + tell( + &mut self.socket, + Request::Action(Action::MoveWindowToWorkspace { + window_id: Some(*wid), + reference: WorkspaceReferenceArg::Id(active_same_output.id), + focus: true, + }), + ) + .await? + } + _ => (), } - (false, true) => { - let active_same_output = self.same_output(wsid, &active)?; - tell( - &mut self.socket, - Request::Action(Action::MoveWindowToWorkspace { - window_id: Some(wid), - reference: WorkspaceReferenceArg::Id(active_same_output.id), - focus: true, - }), - ) - .await - } - _ => Ok(()), } - } - Tag(tag) => { - tracing::debug!("Changing tag {}", tag); - let tag_visible = self.tags.entry(tag).or_default().enabled; - let affected_windows: Vec = self - .windows - .iter() - .filter(|(_, t)| tag == **t) - .map(|(wid, _)| *wid) - .collect(); - tracing::debug!( - "{} affected windows of tag {}: {:?}", - affected_windows.len(), - tag, - affected_windows - ); - let focus = affected_windows.last().cloned(); - self.move_windows( - if tag_visible { &active } else { &inactive }, - affected_windows, - ) - .await; - if let Some(focus) = focus { - if tag_visible { + Tag(tag) => { + tracing::debug!("Changing tag {}", tag); + let tag_visible = self.tags.entry(*tag).or_default().enabled; + let affected_windows: Vec = self + .windows + .iter() + .filter(|(_, t)| *tag == **t) + .map(|(wid, _)| *wid) + .collect(); + tracing::debug!( + "{} affected windows of tag {}: {:?}", + affected_windows.len(), + tag, + affected_windows + ); + let focus = affected_windows.last().cloned(); + self.move_windows( + if tag_visible { &active } else { &inactive }, + affected_windows, + ) + .await; + if let Some(focus) = focus { + if tag_visible { + tell( + &mut self.socket, + Request::Action(Action::FocusWindow { id: focus }), + ) + .await?; + } + } + } + TagExclusive(t) => { + tracing::debug!("Changing all tags"); + let (active_wid, inactive_wid): (HashMap, HashMap) = self + .windows + .iter() + .filter(|(_, it)| **it != 0) + .partition(|(_, it)| **it == *t); + let focus = active_wid.keys().last(); + self.move_windows(&inactive, inactive_wid.keys().cloned().collect()) + .await; + self.move_windows(&active, active_wid.keys().cloned().collect()) + .await; + if let Some(f) = focus { tell( &mut self.socket, - Request::Action(Action::FocusWindow { id: focus }), + Request::Action(Action::FocusWindow { id: *f }), ) .await?; } } - Ok(()) - } - TagExclusive(t) => { - tracing::debug!("Changing all tags"); - let (active_wid, inactive_wid): (HashMap, HashMap) = self - .windows - .iter() - .filter(|(_, it)| **it != 0) - .partition(|(_, it)| **it == t); - let focus = active_wid.keys().last(); - self.move_windows(&inactive, inactive_wid.keys().cloned().collect()) - .await; - self.move_windows(&active, active_wid.keys().cloned().collect()) - .await; - if let Some(f) = focus { - tell( - &mut self.socket, - Request::Action(Action::FocusWindow { id: *f }), - ) - .await?; - } - Ok(()) } } + Ok(()) } async fn get_focused_window(&mut self) -> Result { @@ -275,7 +276,7 @@ impl NiriTag { async fn handle_recvd(&mut self, recvd: Receivable) -> Result<()> { use TagAction::*; // first do any local mutations - let action: TagAction = match recvd { + let actions: &[TagAction] = match recvd { Receivable::Event(ev) => { let _ = self.state.apply(ev.clone()); return self.handle_event(ev).await; @@ -294,12 +295,12 @@ impl NiriTag { TagCmd::AddTagToWin(t) => { let wid = self.get_focused_window().await?.id; self.change_window_tag(wid, Some(t)).await?; - Window(wid) + &[Window(wid)] } TagCmd::RemoveTagFromWin(_) => { let wid = self.get_focused_window().await?.id; self.change_window_tag(wid, None).await?; - Window(wid) + &[Window(wid)] } TagCmd::ToggleTagOnWin(t) => { let wid = self.get_focused_window().await?.id; @@ -310,7 +311,7 @@ impl NiriTag { }; self.change_window_tag(wid, Some(new_tag)).await?; tracing::debug!("toggling {} to tag {}", wid, new_tag); - Window(wid) + &[Window(wid)] } TagCmd::EnableTag(t) => { @@ -319,7 +320,7 @@ impl NiriTag { .and_modify(|ts| ts.enabled = true) .or_default(); self.fire_event(TagEvent::TagEnabled(t)).await; - Tag(t) + &[Tag(t)] } TagCmd::DisableTag(t) => { self.tags @@ -327,7 +328,7 @@ impl NiriTag { .and_modify(|ts| ts.enabled = false) .or_default(); self.fire_event(TagEvent::TagDisabled(t)).await; - Tag(t) + &[Tag(t)] } TagCmd::ToggleTag(t) => { let new_state = self @@ -342,7 +343,7 @@ impl NiriTag { TagEvent::TagDisabled(t) }) .await; - Tag(t) + &[Tag(t)] } TagCmd::ExclusiveTag(t) => { self.tags @@ -354,12 +355,12 @@ impl NiriTag { .filter(|(it, _)| **it != 0) .for_each(|(it, ts)| ts.enabled = *it == t); self.fire_event(TagEvent::TagExclusive(t)).await; - TagExclusive(t) + &[TagExclusive(t)] } }, }; // then arrange corresponding state in the compositor - self.do_action(action).await?; + self.do_actions(actions).await?; tell( &mut self.socket, Request::Action(Action::CenterVisibleColumns {}), @@ -431,7 +432,7 @@ impl NiriTag { WindowsChanged { windows } => { for w in windows { self.change_window_tag(w.id, None).await?; - let action = self.do_action(TagAction::Window(w.id)).await; + let action = self.do_actions(&[TagAction::Window(w.id)]).await; if let Err(e) = action { tracing::warn!("Failed to ChangeWindow on {}: {}", w.id, e); }