1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
use i3ipc::reply::{Node, NodeType, Workspace}; use i3ipc::I3Connection; fn find_active_workspace(workspaces: Vec<Workspace>) -> Workspace { for workspace in workspaces { if workspace.focused { return workspace; } } panic!("no focused workspace"); } fn find_active_workspace_in_tree(root: Node, active_ws: &Workspace) -> Option<Vec<Node>> { match root.nodetype { NodeType::Workspace => { let root_name = root.name.unwrap(); if root_name == active_ws.name { Some(root.nodes) } else { None } } _ => { for node in root.nodes { match find_active_workspace_in_tree(node, &active_ws) { Some(n) => { return Some(n); } None => {} } } None } } } #[derive(Debug)] struct NodePtr { id: i64, focused: bool, } fn collect_nodes(root: Node, coll: &mut Vec<NodePtr>) { if root.window.is_some() { coll.push(NodePtr { id: root.id, focused: root.focused, }); } for node in root.nodes { collect_nodes(node, coll); } } pub fn i3spin(distance: usize, forward: bool) { let mut i3 = I3Connection::connect().unwrap(); let workspaces = i3.get_workspaces().unwrap(); let workspace = find_active_workspace(workspaces.workspaces); let root = i3.get_tree().unwrap(); let ws_node = find_active_workspace_in_tree(root, &workspace).unwrap(); let mut ws_nodes = Vec::new(); for node in ws_node { collect_nodes(node, &mut ws_nodes); } let mut focused_i = None; for (i, node) in ws_nodes.iter().enumerate() { if node.focused { focused_i = Some(i); break; } } let focused_i = focused_i.unwrap(); let next_i = if forward { focused_i + (distance % ws_nodes.len()) } else { ws_nodes.len() + focused_i - (distance % ws_nodes.len()) } % ws_nodes.len(); i3.run_command(&format!("[con_id={}] focus", ws_nodes[next_i].id)) .unwrap(); }