From a17271a9186959acf36719ad243c15fbe4b1ebd8 Mon Sep 17 00:00:00 2001 From: Tassilo Horn Date: Sat, 23 Jan 2021 22:44:25 +0100 Subject: [PATCH] New subcommand switch-workspace-or-window --- .gitignore | 1 + src/bin/swayr.rs | 5 ++++ src/client.rs | 22 ++++++++++++++++++ src/con.rs | 59 ++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 78 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index ea8c4bf..96ef6c0 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +Cargo.lock diff --git a/src/bin/swayr.rs b/src/bin/swayr.rs index 1e040c9..41df1d7 100644 --- a/src/bin/swayr.rs +++ b/src/bin/swayr.rs @@ -24,6 +24,8 @@ enum SwayrCommand { QuitWindow, /// Switch workspace with LRU display order SwitchWorkspace, + /// Switch workspace or window with LRU display order + SwitchWorkspaceOrWindow, /// Select and execute a swaymsg command ExecuteSwaymsgCommand, } @@ -34,6 +36,9 @@ fn main() { SwayrCommand::SwitchWindow => client::switch_window(), SwayrCommand::QuitWindow => client::quit_window(), SwayrCommand::SwitchWorkspace => client::switch_workspace(), + SwayrCommand::SwitchWorkspaceOrWindow => { + client::switch_workspace_or_window() + } SwayrCommand::ExecuteSwaymsgCommand => client::exec_swaymsg_command(), } } diff --git a/src/client.rs b/src/client.rs index 9bc34df..1c1cb6c 100644 --- a/src/client.rs +++ b/src/client.rs @@ -26,6 +26,28 @@ pub fn switch_workspace() { } } +pub fn switch_workspace_or_window() { + let root = con::get_tree(); + let workspaces = con::get_workspaces(&root, false); + let ws_or_wins = con::WsOrWin::from_workspaces(&workspaces); + if let Some(ws_or_win) = con::select_workspace_or_window( + "Select workspace or window", + &ws_or_wins, + ) { + match ws_or_win { + con::WsOrWin::Ws { ws } => { + util::swaymsg(&["workspace", "number", ws.get_name()]); + } + con::WsOrWin::Win { win } => { + util::swaymsg(&[ + format!("[con_id={}]", win.get_id()).as_str(), + "focus", + ]); + } + } + } +} + pub fn quit_window() { let root = con::get_tree(); let mut windows = con::get_windows(&root); diff --git a/src/con.rs b/src/con.rs index 60995ec..37ecd8f 100644 --- a/src/con.rs +++ b/src/con.rs @@ -140,18 +140,20 @@ fn build_workspaces( ) -> Vec { let mut v = vec![]; for workspace in root.workspaces() { + let mut wins: Vec = workspace + .windows() + .iter() + .map(|w| Window { + node: &w, + con_props: con_props.remove(&w.id), + workspace: &workspace, + }) + .collect(); + wins.sort(); v.push(Workspace { node: &workspace, con_props: con_props.remove(&workspace.id), - windows: workspace - .windows() - .iter() - .map(|w| Window { - node: &w, - con_props: con_props.remove(&w.id), - workspace: &workspace, - }) - .collect(), + windows: wins, }) } v @@ -246,6 +248,45 @@ pub fn select_workspace<'a>( util::wofi_select(prompt, workspaces) } +pub enum WsOrWin<'a> { + Ws { ws: &'a Workspace<'a> }, + Win { win: &'a Window<'a> }, +} + +impl<'a> fmt::Display for WsOrWin<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + match self { + WsOrWin::Ws { ws } => ws.fmt(f), + WsOrWin::Win { win } => match f.write_str("\t") { + Ok(()) => win.fmt(f), + Err(e) => Err(e), + }, + } + } +} + +impl WsOrWin<'_> { + pub fn from_workspaces<'a>( + workspaces: &'a [Workspace], + ) -> Vec> { + let mut v = vec![]; + for ws in workspaces { + v.push(WsOrWin::Ws { ws }); + for win in &ws.windows { + v.push(WsOrWin::Win { win: &win }); + } + } + v + } +} + +pub fn select_workspace_or_window<'a>( + prompt: &'a str, + ws_or_wins: &'a [WsOrWin<'a>], +) -> Option<&'a WsOrWin<'a>> { + util::wofi_select(prompt, ws_or_wins) +} + pub struct Workspace<'a> { node: &'a ipc::Node, con_props: Option,