First 'working' version

This commit is contained in:
Skia 2020-12-26 04:28:06 +01:00
parent 2a7a77b0ab
commit 992800800b
3 changed files with 209 additions and 8 deletions

80
Cargo.lock generated
View file

@ -6,9 +6,89 @@ version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
[[package]]
name = "itoa"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
[[package]]
name = "proc-macro2"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "serde"
version = "1.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]] [[package]]
name = "swaysome" name = "swaysome"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"serde",
"serde_json",
] ]
[[package]]
name = "syn"
version = "1.0.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a571a711dddd09019ccc628e1b17fe87c59b09d513c06c026877aa708334f37a"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"

View file

@ -8,3 +8,5 @@ edition = "2018"
[dependencies] [dependencies]
byteorder = "1" byteorder = "1"
serde = { version = "1", features = ["derive"] }
serde_json = "1"

View file

@ -1,5 +1,7 @@
// client.rs // client.rs
extern crate byteorder; extern crate byteorder;
extern crate serde;
extern crate serde_json;
use std::env; use std::env;
use std::path::Path; use std::path::Path;
@ -9,8 +11,55 @@ use std::os::unix::net::UnixStream;
use std::mem; use std::mem;
use std::io::Cursor; use std::io::Cursor;
use serde::{Deserialize, Serialize};
use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian}; use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian};
const RUN_COMMAND: u32 = 0;
const GET_WORKSPACES: u32 = 1;
const SUBSCRIBE: u32 = 2;
const GET_OUTPUTS: u32 = 3;
#[derive(Serialize, Deserialize)]
struct WorkspaceRect {
x: usize,
y: usize,
}
#[derive(Serialize, Deserialize)]
struct Workspace {
num: usize,
name: String,
visible: bool,
focused: bool,
rect: WorkspaceRect,
output: String,
}
#[derive(Serialize, Deserialize)]
struct OutputMode {
width: usize,
height: usize,
refresh: usize,
}
#[derive(Serialize, Deserialize)]
struct Output {
name: String,
make: String,
model: String,
serial: String,
active: bool,
primary: bool,
focused: bool,
scale: f32,
subpixel_hinting: String,
transform: String,
current_workspace: String,
modes: Vec<OutputMode>,
current_mode: OutputMode,
}
fn get_stream() -> UnixStream { fn get_stream() -> UnixStream {
let socket_path = match env::var("I3SOCK") { let socket_path = match env::var("I3SOCK") {
@ -37,20 +86,23 @@ fn send_msg(mut stream: &UnixStream, msg_type: u32, payload: &str) {
// let magic = b"i3-ipc"; // let magic = b"i3-ipc";
// let mut msg = b"i3-ipc".to_vec(); // let mut msg = b"i3-ipc".to_vec();
let mut msg: [u8; 6 * mem::size_of::<u8>() + 2 * mem::size_of::<u32>()] = *b"i3-ipc00000000"; let mut msg_prefix: [u8; 6 * mem::size_of::<u8>() + 2 * mem::size_of::<u32>()] = *b"i3-ipc00000000";
msg[6..].as_mut() msg_prefix[6..].as_mut()
.write_u32::<LittleEndian>(payload_length) .write_u32::<LittleEndian>(payload_length)
.expect("Unable to write"); .expect("Unable to write");
msg[10..].as_mut() msg_prefix[10..].as_mut()
.write_u32::<LittleEndian>(msg_type) .write_u32::<LittleEndian>(msg_type)
.expect("Unable to write"); .expect("Unable to write");
// let msg = format!("{}{}{}{}", magic, pl_t, pl_l, payload); // let msg_prefix = format!("{}{}{}{}", magic, pl_t, pl_l, payload);
println!("msg: {:x?}", msg); println!("msg_prefix: {:x?}", msg_prefix);
match stream.write_all(&msg) { let mut msg: Vec<u8> = msg_prefix[..].to_vec();
msg.extend(payload.as_bytes());
match stream.write_all(&msg[..]) {
Err(_) => panic!("couldn't send message"), Err(_) => panic!("couldn't send message"),
Ok(_) => {} Ok(_) => {}
} }
@ -83,6 +135,64 @@ fn read_msg(mut stream: &UnixStream) -> Result<String, &str> {
} }
} }
fn get_current_output_name(stream: &UnixStream) -> String {
send_msg(&stream, GET_OUTPUTS, "");
let o = match read_msg(&stream) {
Ok(msg) => msg,
Err(_) => panic!("Unable to get current workspace"),
};
let outputs: Vec<Output> = serde_json::from_str(&o).unwrap();
let focused_output_index = match outputs.iter().position(|x| x.focused) {
Some(i) => i,
None => panic!("WTF! No focused output???"),
};
// outputs[focused_output_index].name.clone()
format!("{}", focused_output_index)
}
fn get_current_workspace_name(stream: &UnixStream) -> String {
send_msg(&stream, GET_WORKSPACES, "");
let ws = match read_msg(&stream) {
Ok(msg) => msg,
Err(_) => panic!("Unable to get current workspace"),
};
let workspaces: Vec<Workspace> = serde_json::from_str(&ws).unwrap();
let focused_workspace_index = match workspaces.iter().position(|x| x.focused) {
Some(i) => i,
None => panic!("WTF! No focused workspace???"),
};
workspaces[focused_workspace_index].name.clone()
}
fn move_container_to_workspace(stream: &UnixStream, workspace_name: &String) {
let mut cmd: String = "move container to workspace ".to_string();
let output = get_current_output_name(stream);
cmd.push_str(&output);
cmd.push_str(&workspace_name);
println!("Sending command: '{}'", &cmd);
send_msg(&stream, RUN_COMMAND, &cmd);
match read_msg(&stream) {
Ok(msg) => println!("msg: {}", msg),
Err(_) => panic!("Unable to get current workspace"),
};
}
fn focus_to_workspace(stream: &UnixStream, workspace_name: &String) {
let mut cmd: String = "workspace ".to_string();
let output = get_current_output_name(stream);
cmd.push_str(&output);
cmd.push_str(&workspace_name);
println!("Sending command: '{}'", &cmd);
send_msg(&stream, RUN_COMMAND, &cmd);
match read_msg(&stream) {
Ok(msg) => println!("msg: {}", msg),
Err(_) => panic!("Unable to get current workspace"),
};
}
fn main() { fn main() {
// `args` returns the arguments passed to the program // `args` returns the arguments passed to the program
@ -91,8 +201,17 @@ fn main() {
let mut stream = get_stream(); let mut stream = get_stream();
send_msg(&stream, 1, ""); println!("Current workspace name: {}", get_current_workspace_name(&mut stream));
read_msg(&stream); send_msg(&stream, 3, "");
match read_msg(&stream) {
Ok(msg) => println!("outputs: {}", msg),
Err(_) => panic!("Unable to get current workspace"),
};
match args[1].as_str() {
"move" => move_container_to_workspace(&stream, &args[2]),
"focus" => focus_to_workspace(&stream, &args[2]),
_ => {},
}
} }