//! A command to rotate through scratch windows. extern crate "rustc-serialize" as serialize; extern crate i3; use serialize::json::Json; /// IPC includes. use i3::ipc::{I3Proto, get_socket_path, open_socket}; /// Includes for operations on the layout tree. use i3::tree::{iter_nodes, is_focused, is_scratch}; /// Finds a focused window inside a scratch container. fn focused_scratch(node: &Json) -> Option<&Json> { iter_nodes(node) // Filter focused nodes. `d` is the depth in the tree // so `d > 0` excludes the root node. .filter(|&(n, d)| d > 0 && is_focused(n)) // only return the node .map(|(n, _)| n) // return the first match .next() } /// Returns the focused scratch window. Or `None` if /// a different window is focused. fn get_focused_scratch(tree: &Json) -> Option<&Json> { // Iterate all the nodes in the tree. iter_nodes(tree) // Filter only scratch containers. .filter(|&(n, _)| is_scratch(n)) // Find a focused window inside the scratch container. .filter_map(|(n, _)| focused_scratch(n)) // return the first match .next() } fn main() { // Get the path to the i3 IPC socket and open it. let path = get_socket_path().unwrap(); let mut sock = open_socket(&path).unwrap(); let showit; // Get the tree as json objects. let tree = sock.request_tree().unwrap(); // If a scratch window is focused, move id back to scratchpad. if get_focused_scratch(&tree).is_some() { sock.request_command("move scratchpad").unwrap(); // Only show a window if there is not already another // scratch window below the moved one. let tree = sock.request_tree().unwrap(); showit = !get_focused_scratch(&tree).is_some() } else { showit = true; } if showit { // Show the next scratchpad window. sock.request_command("scratchpad show").unwrap(); } }