From 90a0bd7cb9445e9afe0932cb77cab375b46cf36c Mon Sep 17 00:00:00 2001 From: Tassilo Horn Date: Fri, 18 Mar 2022 09:04:18 +0100 Subject: [PATCH] New command `switch-to-mark-or-urgent-or-lru-window` (#18) Fixes: ~tsdh/swayr/18 --- NEWS.md | 11 +++++++++++ README.md | 10 +++++++++- src/cmds.rs | 49 +++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/NEWS.md b/NEWS.md index ea2d129..074a5bd 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,14 @@ +swayr v0.16.0 +============= + +- There's the new command `switch-to-mark-or-urgent-or-lru-window` which + switches to a specific window matched by mark (`con_mark`) unless it's + already focused. In that case, it acts just like + `switch-to-urgent-or-lru-window`. For example, you can assign a "browser" + mark to your browser window (using a standard sway `for_window` rule). Then + you can provide "browser" as argument to this command to have a convenient + browser <-> last-recently-used window toggle. + swayr v0.15.0 ============= diff --git a/README.md b/README.md index 2695878..593112f 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,15 @@ Right now, there are these subcommands: hint (if any) or to the last recently used window. * `switch-to-app-or-urgent-or-lru-window` switches to a specific window matched by application ID or window class unless it's already focused. In that case, - it acts just like `switch-to-urgent-or-lru-window`. + it acts just like `switch-to-urgent-or-lru-window`. For example, you can + provide "firefox" as argument to this command to have a convenient firefox + <-> last-recently-used window toggle. +* `switch-to-mark-or-urgent-or-lru-window` switches to a specific window + matched by mark (`con_mark`) unless it's already focused. In that case, it + acts just like `switch-to-urgent-or-lru-window`. For example, you can assign + a "browser" mark to your browser window (using a standard sway `for_window` + rule). Then you can provide "browser" as argument to this command to have a + convenient browser <-> last-recently-used window toggle. * `switch-window` displays all windows in the order urgent first, then last-recently-used, focused last and focuses the selected. * `switch-workspace` displays all workspaces in LRU order and switches to the diff --git a/src/cmds.rs b/src/cmds.rs index 52096f6..62166eb 100644 --- a/src/cmds.rs +++ b/src/cmds.rs @@ -68,9 +68,21 @@ pub enum SwayrCommand { /// Switch to next urgent window (if any) or to last recently used window. SwitchToUrgentOrLRUWindow, /// Switch to the given app (given by app_id or window class) if that's not - /// currently focused. If it is, switch to the next urgent window (if any) + /// focused already. If it is, switch to the next urgent window (if any) /// or to last recently used window. + /// + /// For example, you can provide "firefox" as argument to this command to + /// have a convenient firefox <-> last-recently-used window toggle. SwitchToAppOrUrgentOrLRUWindow { name: String }, + /// Switch to the window with the given mark if that's not focused already. + /// If it is, switch to the next urgent window (if any) or to last recently + /// used window. + /// + /// For example, you can assign a "browser" mark to your browser window + /// (using a standard sway `for_window` rule). Then you can provide + /// "browser" as argument to this command to have a convenient browser <-> + /// last-recently-used window toggle. + SwitchToMarkOrUrgentOrLRUWindow { con_mark: String }, /// Focus the selected window. SwitchWindow, /// Switch to the selected workspace. @@ -259,6 +271,12 @@ pub fn exec_swayr_cmd(args: ExecSwayrCmdArgs) { &*props.read().unwrap(), ) } + SwayrCommand::SwitchToMarkOrUrgentOrLRUWindow { con_mark } => { + switch_to_mark_or_urgent_or_lru_window( + Some(con_mark), + &*props.read().unwrap(), + ) + } SwayrCommand::SwitchWindow => switch_window(&*props.read().unwrap()), SwayrCommand::SwitchWorkspace => { switch_workspace(&*props.read().unwrap()) @@ -499,12 +517,31 @@ pub fn switch_to_app_or_urgent_or_lru_window( let wins = tree.get_windows(); let app_win = name.and_then(|n| wins.iter().find(|w| w.node.get_app_name() == n)); - match app_win { - Some(app_win) if !app_win.node.is_current() => { - focus_window_by_id(app_win.node.id) - } + focus_win_if_not_focused(app_win, wins.get(0)) +} + +pub fn switch_to_mark_or_urgent_or_lru_window( + con_mark: Option<&str>, + extra_props: &HashMap, +) { + let root = get_tree(false); + let tree = t::get_tree(&root, extra_props); + let wins = tree.get_windows(); + let marked_win = con_mark.and_then(|mark| { + wins.iter() + .find(|w| w.node.marks.contains(&mark.to_owned())) + }); + focus_win_if_not_focused(marked_win, wins.get(0)) +} + +pub fn focus_win_if_not_focused( + win: Option<&t::DisplayNode>, + other: Option<&t::DisplayNode>, +) { + match win { + Some(win) if !win.node.is_current() => focus_window_by_id(win.node.id), _ => { - if let Some(win) = wins.get(0) { + if let Some(win) = other { focus_window_by_id(win.node.id) } else { log::debug!("No window to switch to.")