// extern crate assert_json_diff; use assert_json_diff::{assert_json_eq, assert_json_include}; use serde_json::json; use swaysome::SwaySome; mod utils; use utils::*; #[test] fn test_init_three_outputs() { let sway = Sway::start(); let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize"); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "1", "num": 1, "focused": true, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "2", "num": 2, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "3", "num": 3, "focused": false, "nodes": []}, ]}, ]})); eprintln!("Init 1"); swaysome.init_workspaces(1); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": true, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []}, ]}, ]})); } #[test] fn test_three_outputs_moving_around_same_workspace_group() { let sway = Sway::start(); let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize"); swaysome.init_workspaces(1); sway.spawn_some_apps(); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": false}, {"name": "TERM3", "focused": true}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []}, ]}, ]})); eprintln!("Move TERM3 to 2"); swaysome.move_container_to_workspace(2); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": true}, ]}, {"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []}, ]}, ]})); eprintln!("Focus to 2"); swaysome.focus_to_workspace(2); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": false}, ]}, {"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [ {"name": "TERM3", "focused": true}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []}, ]}, ]})); } #[test] fn test_three_outputs_moving_around_across_workspace_groups() { let sway = Sway::start(); let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize"); swaysome.init_workspaces(1); sway.spawn_some_apps(); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": false}, {"name": "TERM3", "focused": true}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []}, ]}, ]})); eprintln!("Move TERM3 to group 2"); swaysome.move_container_to_workspace_group(2); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": true}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []}, ]}, ]})); eprintln!("Focus to group 2"); swaysome.focus_to_group(2); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [ {"name": "TERM3", "focused": true}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []}, ]}, ]})); // HEADLESS-3 is still empty assert_json_eq!( swaysome.get_tree()["nodes"][3]["nodes"][0]["nodes"], json!([]) ); eprintln!("Focus to group 1"); swaysome.focus_to_group(1); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": true}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []}, ]}, ]})); // HEADLESS-3 is still empty assert_json_eq!( swaysome.get_tree()["nodes"][3]["nodes"][0]["nodes"], json!([]) ); eprintln!("Move TERM2 to group 2"); swaysome.move_container_to_workspace_group(3); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": true}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM2", "focused": false}, ]}, ]}, ]})); eprintln!("Focus all to 4"); swaysome.focus_all_outputs_to_workspace(4); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, ]}, {"type": "workspace", "name": "14", "num": 14, "focused": true, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, {"type": "workspace", "name": "24", "num": 24, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM2", "focused": false}, ]}, {"type": "workspace", "name": "34", "num": 34, "focused": false, "nodes": []}, ]}, ]})); eprintln!("Focus all back to 1"); swaysome.focus_all_outputs_to_workspace(1); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": true}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM2", "focused": false}, ]}, ]}, ]})); // shadow and re-init swaysome to get up-to-date internals (outputs, workspaces) // XXX this is more of a hack than anything else. Ideally, swaysome would never have out-of-date internals let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize"); eprintln!("Focus to prev group"); swaysome.focus_to_prev_group(); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "1", "num": 1, "focused": true, "nodes": []}, {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM2", "focused": false}, ]}, ]}, ]})); eprintln!("Focus to prev group again"); swaysome.focus_to_prev_group(); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "1", "num": 1, "focused": false, "nodes": []}, {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM2", "focused": true}, ]}, ]}, ]})); eprintln!("Focus to next group"); swaysome.focus_to_next_group(); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "1", "num": 1, "focused": true, "nodes": []}, {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM2", "focused": false}, ]}, ]}, ]})); eprintln!("Focus to next group again"); swaysome.focus_to_next_group(); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": true}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM2", "focused": false}, ]}, ]}, ]})); } #[test] fn test_three_outputs_moving_around_across_outputs() { let sway = Sway::start(); let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize"); swaysome.init_workspaces(1); sway.spawn_some_apps(); eprintln!("Move TERM3 to group 3"); swaysome.move_container_to_workspace_group(3); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": true}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, ]})); eprintln!("Move TERM2 to next output"); swaysome.move_container_to_next_output(); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [ {"name": "TERM2", "focused": true}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, ]})); eprintln!("Move TERM2 to prev output"); swaysome.move_container_to_prev_output(); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": true}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [ ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, ]})); eprintln!("Move TERM2 to prev output again"); swaysome.move_container_to_prev_output(); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [ ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, {"name": "TERM2", "focused": true}, ]}, ]}, ]})); } #[test] fn test_three_outputs_moving_around_across_outputs_without_init() { let sway = Sway::start(); let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize"); sway.spawn_some_apps(); eprintln!("Move TERM3 to group 3"); swaysome.move_container_to_workspace_group(3); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "1", "num": 1, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": true}, ]}, {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "2", "num": 2, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "3", "num": 3, "focused": false, "nodes": []}, ]}, ]})); } #[test] fn test_three_outputs_moving_around_absolute() { let sway = Sway::start(); let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize"); swaysome.init_workspaces(1); sway.spawn_some_apps(); // shadow and re-init swaysome to get up-to-date internals (outputs, workspaces) // XXX this is more of a hack than anything else. Ideally, swaysome would never have out-of-date internals let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize"); eprintln!("Moving TERM3 to 12"); swaysome.move_container_to_workspace(12); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": true}, ]}, {"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []}, ]}, ]})); eprintln!("Moving TERM2 to 42"); swaysome.move_container_to_workspace(42); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": true}, ]}, {"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, {"type": "workspace", "name": "42", "num": 42, "focused": false, "nodes": [ {"name": "TERM2", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []}, ]}, ]})); // shadow and re-init swaysome to get up-to-date internals (outputs, workspaces) // XXX this is more of a hack than anything else. Ideally, swaysome would never have out-of-date internals let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize"); eprintln!("Moving TERM1 to 42"); swaysome.move_container_to_workspace(42); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": true, "nodes": []}, {"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, {"type": "workspace", "name": "42", "num": 42, "focused": false, "nodes": [ {"name": "TERM2", "focused": false}, {"name": "TERM1", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []}, ]}, ]})); eprintln!("Spawn TERM4"); sway.send_command(["exec", "foot -T TERM4"].as_slice()); std::thread::sleep(std::time::Duration::from_millis(200)); eprintln!("Moving TERM4 to 22"); swaysome.move_container_to_workspace(22); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": true, "nodes": []}, {"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, {"type": "workspace", "name": "42", "num": 42, "focused": false, "nodes": [ {"name": "TERM2", "focused": false}, {"name": "TERM1", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, {"type": "workspace", "name": "22", "num": 22, "focused": false, "nodes": [ {"name": "TERM4", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []}, ]}, ]})); eprintln!("Focus on 42"); swaysome.focus_to_workspace(42); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, {"type": "workspace", "name": "42", "num": 42, "focused": false, "nodes": [ {"name": "TERM2", "focused": false}, {"name": "TERM1", "focused": true}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, {"type": "workspace", "name": "22", "num": 22, "focused": false, "nodes": [ {"name": "TERM4", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []}, ]}, ]})); eprintln!("Focus on 41"); swaysome.focus_to_workspace(41); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, {"type": "workspace", "name": "41", "num": 41, "focused": true, "nodes": []}, {"type": "workspace", "name": "42", "num": 42, "focused": false, "nodes": [ {"name": "TERM2", "focused": false}, {"name": "TERM1", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, {"type": "workspace", "name": "22", "num": 22, "focused": false, "nodes": [ {"name": "TERM4", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []}, ]}, ]})); eprintln!("Focus on 51"); swaysome.focus_to_workspace(51); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, {"type": "workspace", "name": "42", "num": 42, "focused": false, "nodes": [ {"name": "TERM2", "focused": false}, {"name": "TERM1", "focused": false}, ]}, {"type": "workspace", "name": "51", "num": 51, "focused": true, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, {"type": "workspace", "name": "22", "num": 22, "focused": false, "nodes": [ {"name": "TERM4", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []}, ]}, ]})); eprintln!("Focus on 32"); swaysome.focus_to_workspace(32); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, {"type": "workspace", "name": "42", "num": 42, "focused": false, "nodes": [ {"name": "TERM2", "focused": false}, {"name": "TERM1", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, {"type": "workspace", "name": "22", "num": 22, "focused": false, "nodes": [ {"name": "TERM4", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "32", "num": 32, "focused": true, "nodes": []}, ]}, ]})); } #[test] fn test_three_outputs_moving_groups_across_outputs() { let sway = Sway::start(); let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize"); swaysome.init_workspaces(1); sway.spawn_some_apps(); eprintln!("Move TERM3 to group 3"); swaysome.move_container_to_workspace_group(3); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": true}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, ]})); eprintln!("Move group 1 to prev output"); swaysome.move_workspace_group_to_prev_output(); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "1", "num": 1, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": true}, ]}, {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, ]})); eprintln!("Move group 1 to next output"); swaysome.move_workspace_group_to_next_output(); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": true}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, ]})); eprintln!("Move group 1 to next output again"); swaysome.move_workspace_group_to_next_output(); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "1", "num": 1, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": true}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, ]})); } #[test] fn test_three_outputs_plugging_unplugging_outputs() { let sway = Sway::start(); let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize"); swaysome.init_workspaces(1); sway.spawn_some_apps(); eprintln!("Move TERM3 to group 3"); swaysome.move_container_to_workspace_group(3); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": true}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, ]})); eprintln!("Disabling output 3"); sway.send_command(["output HEADLESS-3 disable"].as_slice()); std::thread::sleep(std::time::Duration::from_millis(200)); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": true}, ]}, {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, ]}, ]})); assert_eq!(swaysome.get_tree()["nodes"].as_array().unwrap().len(), 3); eprintln!("Enabling output 3"); sway.send_command(["output HEADLESS-3 enable"].as_slice()); std::thread::sleep(std::time::Duration::from_millis(200)); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": true}, ]}, {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, ]}, ]})); assert_eq!(swaysome.get_tree()["nodes"].as_array().unwrap().len(), 4); // shadow and re-init swaysome to get up-to-date internals (outputs, workspaces) // XXX this is more of a hack than anything else. Ideally, swaysome would never have out-of-date internals let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize"); swaysome.rearrange_workspaces(); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, {"name": "TERM2", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM3", "focused": true}, ]}, ]}, ]})); swaysome.focus_to_workspace(11); swaysome.move_container_to_workspace(21); eprintln!("Disabling output 2"); sway.send_command(["output HEADLESS-2 disable"].as_slice()); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": true}, ]}, {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [ {"name": "TERM2", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, ]})); eprintln!("Enabling output 2"); sway.send_command(["output HEADLESS-2 enable"].as_slice()); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": true}, ]}, {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [ {"name": "TERM2", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM3", "focused": false}, ]}, ]}, ]})); // shadow and re-init swaysome to get up-to-date internals (outputs, workspaces) // XXX this is more of a hack than anything else. Ideally, swaysome would never have out-of-date internals let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize"); swaysome.rearrange_workspaces(); assert_json_include!(actual: swaysome.get_tree(), expected: json!({ "nodes": [ {}, {"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [ {"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [ {"name": "TERM1", "focused": false}, ]}, ]}, {"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [ {"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [ {"name": "TERM3", "focused": true}, ]}, ]}, {"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [ {"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [ {"name": "TERM2", "focused": false}, ]}, ]}, ]})); }