New command switch-to-matching-or-urgent-or-lru-window

Implements: https://todo.sr.ht/~tsdh/swayr/21
main
Tassilo Horn 2 years ago
parent f0b0f71e38
commit 6aa7d05d07
  1. 62
      Cargo.lock
  2. 5
      README.md
  3. 9
      swayr/NEWS.md
  4. 68
      swayr/src/cmds.rs

62
Cargo.lock generated

@ -270,9 +270,9 @@ dependencies = [
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.1" version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
@ -288,9 +288,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.125" version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
[[package]] [[package]]
name = "log" name = "log"
@ -377,15 +377,15 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.10.0" version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
[[package]] [[package]]
name = "os_str_bytes" name = "os_str_bytes"
version = "6.0.0" version = "6.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa"
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
@ -419,11 +419,11 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.38" version = "1.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa" checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
dependencies = [ dependencies = [
"unicode-xid", "unicode-ident",
] ]
[[package]] [[package]]
@ -467,9 +467,9 @@ dependencies = [
[[package]] [[package]]
name = "rayon" name = "rayon"
version = "1.5.2" version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd249e82c21598a9a426a4e00dd7adc1d640b22445ec8545feef801d1a74c221" checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"crossbeam-deque", "crossbeam-deque",
@ -479,9 +479,9 @@ dependencies = [
[[package]] [[package]]
name = "rayon-core" name = "rayon-core"
version = "1.9.2" version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f51245e1e62e1f1629cbfec37b5793bbabcaeb90f30e94d2ba03564687353e4" checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
dependencies = [ dependencies = [
"crossbeam-channel", "crossbeam-channel",
"crossbeam-deque", "crossbeam-deque",
@ -511,9 +511,9 @@ dependencies = [
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.5.5" version = "1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@ -522,15 +522,15 @@ dependencies = [
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.6.25" version = "0.6.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
[[package]] [[package]]
name = "rt-format" name = "rt-format"
version = "0.3.0" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "953eff237fc52cbb1a78d9ef62de48422a42c49c4db65b7e7e9d3aa500b1bdae" checksum = "45087cee619d316fa4bd1675494acff4a5eaa0892fa53bc364bd246f13e452e2"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"regex", "regex",
@ -538,9 +538,9 @@ dependencies = [
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.9" version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
@ -658,20 +658,20 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.93" version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04066589568b72ec65f42d65a1a52436e954b168773148893c020269563decf2" checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"unicode-xid", "unicode-ident",
] ]
[[package]] [[package]]
name = "sysinfo" name = "sysinfo"
version = "0.23.12" version = "0.23.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56b1e20ee77901236c389ff74618a899ff5fd34719a7ff0fd1d64f0acca5179a" checksum = "3977ec2e0520829be45c8a2df70db2bf364714d8a748316a10c3c35d4d2b01c9"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"core-foundation-sys 0.8.3", "core-foundation-sys 0.8.3",
@ -743,10 +743,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-ident"
version = "0.2.3" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
[[package]] [[package]]
name = "uom" name = "uom"

@ -55,6 +55,11 @@ program.
a "browser" mark to your browser window (using a standard sway `for_window` 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 rule). Then you can provide "browser" as argument to this command to have a
convenient browser <-> last-recently-used window toggle. convenient browser <-> last-recently-used window toggle.
* `switch-to-matching-or-urgent-or-lru-window` switches to the (first) window
matching the given criterion (see section `CRITERIA` in `sway(5)`) if it
exists and is not already focused. Otherwise, switch to the next urgent
window (if any) or to the last recently used window.
#### Menu switchers #### Menu switchers

@ -1,3 +1,12 @@
swayr v0.19.0
=============
- There's a new command `switch-to-matching-or-urgent-or-lru-window` which
switches to the (first) window matching the given criteria (see section
`CRITERIA` in `sway(5)`) if it exists and is not already focused. Otherwise,
switch to the next urgent window (if any) or to the last recently used
window.
swayr v0.18.0 swayr v0.18.0
============= =============

@ -86,6 +86,11 @@ pub enum SwayrCommand {
/// "browser" as argument to this command to have a convenient browser <-> /// "browser" as argument to this command to have a convenient browser <->
/// last-recently-used window toggle. /// last-recently-used window toggle.
SwitchToMarkOrUrgentOrLRUWindow { con_mark: String }, SwitchToMarkOrUrgentOrLRUWindow { con_mark: String },
/// Switch to the (first) window matching the given criteria (see section
/// `CRITERIA` in `sway(5)`) if it exists and is not already focused.
/// Otherwise, switch to the next urgent window (if any) or to the last
/// recently used window.
SwitchToMatchingOrUrgentOrLRUWindow { criteria: String },
/// Focus the selected window. /// Focus the selected window.
SwitchWindow, SwitchWindow,
/// Switch to the selected workspace. /// Switch to the selected workspace.
@ -260,10 +265,13 @@ pub fn exec_swayr_cmd(args: ExecSwayrCmdArgs) {
switch_to_urgent_or_lru_window(fdata) switch_to_urgent_or_lru_window(fdata)
} }
SwayrCommand::SwitchToAppOrUrgentOrLRUWindow { name } => { SwayrCommand::SwitchToAppOrUrgentOrLRUWindow { name } => {
switch_to_app_or_urgent_or_lru_window(Some(name), fdata) switch_to_app_or_urgent_or_lru_window(name, fdata)
} }
SwayrCommand::SwitchToMarkOrUrgentOrLRUWindow { con_mark } => { SwayrCommand::SwitchToMarkOrUrgentOrLRUWindow { con_mark } => {
switch_to_mark_or_urgent_or_lru_window(Some(con_mark), fdata) switch_to_mark_or_urgent_or_lru_window(con_mark, fdata)
}
SwayrCommand::SwitchToMatchingOrUrgentOrLRUWindow { criteria } => {
switch_to_matching_or_urgent_or_lru_window(criteria, fdata)
} }
SwayrCommand::SwitchWindow => switch_window(fdata), SwayrCommand::SwitchWindow => switch_window(fdata),
SwayrCommand::SwitchWorkspace => switch_workspace(fdata), SwayrCommand::SwitchWorkspace => switch_workspace(fdata),
@ -470,35 +478,67 @@ pub fn get_outputs() -> Vec<s::Output> {
} }
pub fn switch_to_urgent_or_lru_window(fdata: &FocusData) { pub fn switch_to_urgent_or_lru_window(fdata: &FocusData) {
switch_to_app_or_urgent_or_lru_window(None, fdata) let root = ipc::get_root_node(false);
let tree = t::get_tree(&root);
let wins = tree.get_windows(fdata);
focus_win_if_not_focused(None, wins.get(0))
} }
pub fn switch_to_app_or_urgent_or_lru_window( pub fn switch_to_app_or_urgent_or_lru_window(name: &str, fdata: &FocusData) {
name: Option<&str>,
fdata: &FocusData,
) {
let root = ipc::get_root_node(false); let root = ipc::get_root_node(false);
let tree = t::get_tree(&root); let tree = t::get_tree(&root);
let wins = tree.get_windows(fdata); let wins = tree.get_windows(fdata);
let app_win = let app_win = wins.iter().find(|w| w.node.get_app_name() == name);
name.and_then(|n| wins.iter().find(|w| w.node.get_app_name() == n));
focus_win_if_not_focused(app_win, wins.get(0)) focus_win_if_not_focused(app_win, wins.get(0))
} }
pub fn switch_to_mark_or_urgent_or_lru_window( pub fn switch_to_mark_or_urgent_or_lru_window(
con_mark: Option<&str>, con_mark: &str,
fdata: &FocusData, fdata: &FocusData,
) { ) {
let root = ipc::get_root_node(false); let root = ipc::get_root_node(false);
let tree = t::get_tree(&root); let tree = t::get_tree(&root);
let wins = tree.get_windows(fdata); let wins = tree.get_windows(fdata);
let marked_win = con_mark.and_then(|mark| { let con_mark = &con_mark.to_owned();
wins.iter() let marked_win = wins.iter().find(|w| w.node.marks.contains(con_mark));
.find(|w| w.node.marks.contains(&mark.to_owned()))
});
focus_win_if_not_focused(marked_win, wins.get(0)) focus_win_if_not_focused(marked_win, wins.get(0))
} }
fn switch_to_matching_or_urgent_or_lru_window(
criteria: &str,
fdata: &FocusData,
) {
// TODO: It would be great if sway had some command which given a criteria
// query returns the matching windows. Unfortunately, it doesn't have it
// right now. So we call `CRITERION focus` and check if focus has moved.
// If not, we do the "urgent or LRU" thing.
let root = ipc::get_root_node(false);
let tree = t::get_tree(&root);
let wins = tree.get_windows(fdata);
let prev_win_id = wins
.iter()
.find(|w| w.node.focused)
.map(|w| w.node.id)
.unwrap_or(-1);
run_sway_command(&[criteria, "focus"]);
// Wait until the focus event had time to arrive.
std::thread::sleep(std::time::Duration::from_millis(50));
let root = ipc::get_root_node(false);
let tree = t::get_tree(&root);
let wins = tree.get_windows(fdata);
let cur_win_id = wins
.iter()
.find(|w| w.node.focused)
.map(|w| w.node.id)
.unwrap_or(-1);
if prev_win_id == cur_win_id {
focus_win_if_not_focused(None, wins.get(0))
}
}
pub fn focus_win_if_not_focused( pub fn focus_win_if_not_focused(
win: Option<&t::DisplayNode>, win: Option<&t::DisplayNode>,
other: Option<&t::DisplayNode>, other: Option<&t::DisplayNode>,

Loading…
Cancel
Save