123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- use std::io::prelude::*;
- use std::os::unix::net::UnixStream;
- use std::cell::RefCell;
- use std::convert::AsMut;
- use serde::Deserialize;
- fn into_array<A, T>(slice: &[T]) -> A
- where A: Sized + Default + AsMut<[T]>,
- T: Clone
- {
- let mut a = Default::default();
- <A as AsMut<[T]>>::as_mut(&mut a).clone_from_slice(slice);
- a
- }
- #[repr(u32)]
- #[allow(unused)]
- #[derive(Clone, Copy, Debug)]
- enum PacketType {
- RunCommand = 0,
- GetWorkspaces,
- Subscribe,
- GetOutputs,
- GetTree,
- GetMarks,
- GetBarConfig,
- GetVersion,
- GetBindingModes,
- GetConfig,
- SendTick,
- SyncMsg,
- GetBindingState,
- GetInputs = 100,
- GetSeats
- }
- const HEADER_MAGIC: [u8;6] = ['i' as u8, '3' as u8, '-' as u8, 'i' as u8, 'p' as u8, 'c' as u8];
- #[repr(packed)]
- #[derive(Clone, Copy, Debug)]
- struct PacketHeader {
- _magic: [u8;6],
- len: u32,
- _ptype: PacketType,
- }
- const PACKET_HEADER_LEN : usize = 14;
- impl PacketHeader {
- fn buffer_with_data(self, data: &str) -> Vec<u8> {
- let mut ret = Vec::new();
- let self_data = &self as *const _ as *const u8;
- ret.extend_from_slice(unsafe {
- std::slice::from_raw_parts(self_data, core::mem::size_of::<Self>())
- });
- ret.extend_from_slice(data.as_bytes());
- ret
- }
- fn parse(data: [u8; 14]) -> Self {
- Self { _magic: into_array(&data[0..6]), len: unsafe { std::mem::transmute::<[u8;4], u32>(into_array(&data[6..10])) }, _ptype: unsafe { std::mem::transmute::<[u8;4], PacketType>(into_array(&data[10..14])) } }
- }
- }
- pub struct SwayInterface {
- sock: RefCell<UnixStream>
- }
- impl SwayInterface {
- pub fn new() -> Self {
- let path = std::env::var("SWAYSOCK").expect("SWAYSOCK to be set");
- let sock = UnixStream::connect(path).expect("Can connect to sway socket");
- SwayInterface { sock: RefCell::new(sock) }
- }
- fn send_packet(&self, ptype: PacketType, data: &str) -> Result<(), std::io::Error> {
- let phdr = PacketHeader { _magic: HEADER_MAGIC, len: data.len() as u32, _ptype: ptype };
- self.sock.borrow_mut().write(&phdr.buffer_with_data(data))?;
- Ok(())
- }
- fn read_packet(&self) -> Result<serde_json::Value, std::io::Error> {
- let mut header_data = [0u8; PACKET_HEADER_LEN];
- self.sock.borrow_mut().read_exact(&mut header_data)?;
- let header = PacketHeader::parse(header_data);
- let mut body : Vec<u8> = Vec::new();
- body.resize(header.len as usize, 0);
- self.sock.borrow_mut().read_exact(&mut body)?;
- let body = std::str::from_utf8(body.as_slice()).expect("Valid unicode");
- let v: serde_json::Value = serde_json::from_str(body).expect("to get good JSON back from sway");
- Ok(v)
- }
- pub fn switch_to_workspace(&self, name: &str) -> Result<(), std::io::Error> {
- self.send_packet(PacketType::RunCommand, format!("workspace {}", name).as_str())?;
- self.read_packet()?;
- Ok(())
- }
- pub fn move_to_workspace(&self, name: &str) -> Result<(), std::io::Error> {
- self.send_packet(PacketType::RunCommand, format!("move container to workspace {}", name).as_str())?;
- self.read_packet()?;
- Ok(())
- }
- pub fn get_workspaces(&self) -> Result<Vec<Workspace>, std::io::Error> {
- self.send_packet(PacketType::GetWorkspaces, "")?;
- let response = self.read_packet()?;
- let ws : Vec<Workspace> = serde_json::from_value(response).expect("valid schema");
- Ok(ws)
- }
- pub fn get_current_workspace(&self) -> Result<String, std::io::Error> {
- let ws = self.get_workspaces()?;
- for w in ws {
- if w.focused { return Ok(w.name) }
- }
- unreachable!("At least one workspace will be focused");
- }
- }
- #[derive(Deserialize)]
- pub struct Workspace {
- id: u32,
- pub name: String,
- focused: bool
- }
|