From 3f090e290ccfbec1d17663278d40cc79c1f81331 Mon Sep 17 00:00:00 2001 From: Tassilo Horn Date: Thu, 7 Oct 2021 22:08:37 +0200 Subject: [PATCH] New commands: {Next,Prev}{Tiled,TabbedOrStacked}Window --- Cargo.lock | 12 ++++++------ src/cmds.rs | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++--- src/con.rs | 16 ++++++++++++++++ 3 files changed, 72 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 46fa8a0..01acb82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -150,9 +150,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.102" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103" +checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" [[package]] name = "memchr" @@ -207,9 +207,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" dependencies = [ "proc-macro2", ] @@ -372,9 +372,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.77" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5239bc68e0fef57495900cfea4e8dc75596d9a319d7e16b1e0a440d24e6fe0a0" +checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194" dependencies = [ "proc-macro2", "quote", diff --git a/src/cmds.rs b/src/cmds.rs index 152ddff..15c99f7 100644 --- a/src/cmds.rs +++ b/src/cmds.rs @@ -48,6 +48,14 @@ pub enum SwayrCommand { NextWindow, /// Focus the previous window. PrevWindow, + /// Focus the next window of a tiled container. + NextTiledWindow, + /// Focus the previous window of a tiled container. + PrevTiledWindow, + /// Focus the next window of a tabbed or stacked container. + NextTabbedOrStackedWindow, + /// Focus the previous window of a tabbed or stacked container. + PrevTabbedOrStackedWindow, /// Quit the selected window. QuitWindow, /// Switch to the selected workspace. @@ -98,6 +106,10 @@ impl DisplayFormat for SwayrCommand { } } +fn always_true(_x: &con::Window) -> bool { + true +} + pub fn exec_swayr_cmd(args: ExecSwayrCmdArgs) { let props = args.extra_props; match args.cmd { @@ -110,11 +122,41 @@ pub fn exec_swayr_cmd(args: ExecSwayrCmdArgs) { SwayrCommand::NextWindow => focus_next_window_in_direction( Direction::Forward, Some(&*props.read().unwrap()), + Box::new(always_true), ), SwayrCommand::PrevWindow => focus_next_window_in_direction( Direction::Backward, Some(&*props.read().unwrap()), + Box::new(always_true), + ), + SwayrCommand::NextTiledWindow => focus_next_window_in_direction( + Direction::Forward, + Some(&*props.read().unwrap()), + Box::new(|w: &con::Window| w.is_child_of_tiled_container()), + ), + SwayrCommand::PrevTiledWindow => focus_next_window_in_direction( + Direction::Backward, + Some(&*props.read().unwrap()), + Box::new(|w: &con::Window| w.is_child_of_tiled_container()), ), + SwayrCommand::NextTabbedOrStackedWindow => { + focus_next_window_in_direction( + Direction::Forward, + Some(&*props.read().unwrap()), + Box::new(|w: &con::Window| { + w.is_child_of_tabbed_or_stacked_container() + }), + ) + } + SwayrCommand::PrevTabbedOrStackedWindow => { + focus_next_window_in_direction( + Direction::Backward, + Some(&*props.read().unwrap()), + Box::new(|w: &con::Window| { + w.is_child_of_tabbed_or_stacked_container() + }), + ) + } SwayrCommand::QuitWindow => quit_window(Some(&*props.read().unwrap())), SwayrCommand::SwitchWorkspace => { switch_workspace(Some(&*props.read().unwrap())) @@ -181,6 +223,8 @@ pub fn exec_swayr_cmd(args: ExecSwayrCmdArgs) { }, SwayrCommand::NextWindow, SwayrCommand::PrevWindow, + SwayrCommand::NextTiledWindow, + SwayrCommand::PrevTiledWindow, ], ) { exec_swayr_cmd(ExecSwayrCmdArgs { @@ -238,9 +282,12 @@ pub enum Direction { Forward, } +// TODO: Maybe we should have a bool parameter telling if it should act on all +// windows or just the ones on the current workspace. pub fn focus_next_window_in_direction( dir: Direction, extra_props: Option<&HashMap>, + pred: Box bool>, ) { let root = get_tree(); let windows = con::get_windows(&root, false, None); @@ -249,7 +296,7 @@ pub fn focus_next_window_in_direction( return; } - let pred: Box bool> = + let is_focused_window: Box bool> = if !windows.iter().any(|w| w.is_focused()) { let last_focused_win_id = con::get_windows(&root, false, extra_props) @@ -268,8 +315,8 @@ pub fn focus_next_window_in_direction( loop { let win = iter.next().unwrap(); - if pred(win) { - let win = iter.next().unwrap(); + if is_focused_window(win) { + let win = iter.filter(|w| pred(w)).next().unwrap(); focus_window_by_id(win.get_id()); return; } diff --git a/src/con.rs b/src/con.rs index 0f4561a..c8c702f 100644 --- a/src/con.rs +++ b/src/con.rs @@ -157,6 +157,22 @@ impl Window<'_> { pub fn is_floating(&self) -> bool { self.node.node_type == s::NodeType::FloatingCon } + + pub fn get_parent(&self) -> &s::Node { + NodeIter::new(self.workspace) + .find(|n| n.nodes.contains(self.node)) + .expect("No parent node of a window!") + } + + pub fn is_child_of_tiled_container(&self) -> bool { + let layout = &self.get_parent().layout; + layout == &s::NodeLayout::SplitH || layout == &s::NodeLayout::SplitV + } + + pub fn is_child_of_tabbed_or_stacked_container(&self) -> bool { + let layout = &self.get_parent().layout; + layout == &s::NodeLayout::Tabbed || layout == &s::NodeLayout::Stacked + } } impl PartialEq for Window<'_> {