New commands: next-window & prev-window

timeout_old
Tassilo Horn 4 years ago
parent 8b7bc263dd
commit cdba9b1186
  1. 31
      README.md
  2. 61
      src/client.rs
  3. 25
      src/con.rs

@ -5,8 +5,12 @@ window/workspace creations, deletions, and focus changes using sway's JSON IPC
interface. The client `swayr` offers subcommands, see `swayr --help`.
Right now, there are these subcommands:
* `switch-window` displays all windows in the order urgent first, then LRU,
focused last and focuses the selected.
* `next-window` focuses the next window in depth-first iteration order of the
tree.
* `prev-window` focuses the previous window in depth-first iteration order of
the tree.
* `switch-window` displays all windows in the order urgent first, then
last-recently-used, focused last and focuses the selected.
* `quit-window` displays all windows and quits the selected one.
* `switch-to-urgent-or-lru-window` switches to the next window with urgency
hint (if any) or to the last recently used window.
@ -43,14 +47,29 @@ Next to starting the demon, you want to bind swayr commands to some keys like
so:
```
bindsym $mod+Delete exec env RUST_BACKTRACE=1 swayr quit-window > /tmp/swayr.log 2>&1
bindsym $mod+Space exec env RUST_BACKTRACE=1 swayr switch-window >> /tmp/swayr.log 2>&1
bindsym $mod+Space exec env RUST_BACKTRACE=1 \
swayr switch-window >> /tmp/swayr.log 2>&1
bindsym $mod+Delete exec env RUST_BACKTRACE=1 \
swayr quit-window > /tmp/swayr.log 2>&1
bindsym $mod+Tab exec env RUST_BACKTRACE=1 \
swayr switch-to-urgent-or-lru-window >> /tmp/swayr.log 2>&1
bindsym $mod+Next exec env RUST_BACKTRACE=1 \
swayr next-window >> /tmp/swayr.log 2>&2
bindsym $mod+Prior exec env RUST_BACKTRACE=1 \
swayr prev-window >> /tmp/swayr.log 2>&2
bindsym $mod+Shift+Space exec env RUST_BACKTRACE=1 \
swayr switch-workspace-or-window >> /tmp/swayr.log 2>&1
bindsym $mod+c exec env RUST_BACKTRACE=1 swayr execute-swaymsg-command >> /tmp/swayr.log 2>&1
bindsym $mod+Shift+c exec env RUST_BACKTRACE=1 swayr execute-swayr-command >> /tmp/swa
bindsym $mod+c exec env RUST_BACKTRACE=1 \
swayr execute-swaymsg-command >> /tmp/swayr.log 2>&1
bindsym $mod+Shift+c exec env RUST_BACKTRACE=1 \
swayr execute-swayr-command >> /tmp/swa
```
Of course, configure the keys to your liking. Again, enabling rust backtraces

@ -12,6 +12,10 @@ pub enum SwayrCommand {
SwitchToUrgentOrLRUWindow,
/// Focus the selected window
SwitchWindow,
/// Focus the next window.
NextWindow,
/// Focus the previous window.
PrevWindow,
/// Quit the selected window
QuitWindow,
/// Switch to the selected workspace
@ -38,6 +42,12 @@ pub fn exec_swayr_cmd(cmd: &SwayrCommand) {
switch_to_urgent_or_lru_window()
}
SwayrCommand::SwitchWindow => switch_window(),
SwayrCommand::NextWindow => {
focus_next_window_in_direction(Direction::Forward)
}
SwayrCommand::PrevWindow => {
focus_next_window_in_direction(Direction::Backward)
}
SwayrCommand::QuitWindow => quit_window(),
SwayrCommand::SwitchWorkspace => switch_workspace(),
SwayrCommand::SwitchWorkspaceOrWindow => switch_workspace_or_window(),
@ -53,6 +63,9 @@ pub fn exec_swayr_cmd(cmd: &SwayrCommand) {
SwayrCommand::SwitchWindow,
SwayrCommand::SwitchWorkspace,
SwayrCommand::SwitchWorkspaceOrWindow,
SwayrCommand::SwitchToUrgentOrLRUWindow,
SwayrCommand::NextWindow,
SwayrCommand::PrevWindow,
],
) {
exec_swayr_cmd(c);
@ -71,12 +84,11 @@ fn quit_window_by_id(id: ipc::Id) {
pub fn switch_to_urgent_or_lru_window() {
let root = con::get_tree();
let windows = con::get_windows(&root);
let windows = con::get_windows(&root, true);
if let Some(win) = windows
.iter()
.filter(|w| w.is_urgent())
.next()
.or_else(|| windows.iter().next())
.find(|w| w.is_urgent())
.or_else(|| windows.get(0))
{
println!("Switching to {}", win);
focus_window_by_id(win.get_id())
@ -87,13 +99,50 @@ pub fn switch_to_urgent_or_lru_window() {
pub fn switch_window() {
let root = con::get_tree();
let windows = con::get_windows(&root);
let windows = con::get_windows(&root, true);
if let Some(window) = con::select_window("Switch to window", &windows) {
focus_window_by_id(window.get_id())
}
}
pub enum Direction {
Backward,
Forward,
}
pub fn focus_next_window_in_direction(dir: Direction) {
let root = con::get_tree();
let windows = con::get_windows(&root, false);
if windows.len() < 2 {
return;
}
let pred: Box<dyn Fn(&con::Window) -> bool> =
if windows.iter().find(|w| w.is_focused()).is_none() {
let last_focused_win_id =
con::get_windows(&root, true).get(0).unwrap().get_id();
Box::new(move |w| w.get_id() == last_focused_win_id)
} else {
Box::new(|w: &con::Window| w.is_focused())
};
let mut iter: Box<dyn Iterator<Item = &con::Window>> = match dir {
Direction::Forward => Box::new(windows.iter().rev().cycle()),
Direction::Backward => Box::new(windows.iter().cycle()),
};
loop {
let win = iter.next().unwrap();
if pred(win) {
let win = iter.next().unwrap();
focus_window_by_id(win.get_id());
return;
}
}
}
pub fn switch_workspace() {
let root = con::get_tree();
let workspaces = con::get_workspaces(&root, false);
@ -124,7 +173,7 @@ pub fn switch_workspace_or_window() {
pub fn quit_window() {
let root = con::get_tree();
let windows = con::get_windows(&root);
let windows = con::get_windows(&root, true);
if let Some(window) = con::select_window("Quit window", &windows) {
quit_window_by_id(window.get_id())

@ -144,7 +144,6 @@ fn build_windows(
})
}
}
v.sort();
v
}
@ -184,16 +183,24 @@ fn get_con_props() -> Result<HashMap<ipc::Id, ipc::ConProps>, serde_json::Error>
}
/// Gets all application windows of the tree.
pub fn get_windows(root: &ipc::Node) -> Vec<Window> {
let con_props = match get_con_props() {
Ok(con_props) => Some(con_props),
Err(e) => {
eprintln!("Got no con_props: {:?}", e);
None
pub fn get_windows(root: &ipc::Node, sort: bool) -> Vec<Window> {
let con_props = if sort {
match get_con_props() {
Ok(con_props) => Some(con_props),
Err(e) => {
eprintln!("Got no con_props: {:?}", e);
None
}
}
} else {
None
};
build_windows(root, con_props.unwrap_or_default())
let mut wins = build_windows(root, con_props.unwrap_or_default());
if sort {
wins.sort();
}
wins
}
/// Gets all application windows of the tree.
@ -225,7 +232,7 @@ pub fn get_workspaces(
#[test]
fn test_get_windows() {
let root = get_tree();
let cons = get_windows(&root);
let cons = get_windows(&root, true);
println!("There are {} cons.", cons.len());

Loading…
Cancel
Save