latchshot 0.2.5

A lightweight yet intelligent window-aware screenshot tool
Documentation
use std::env;
use std::io::{BufReader, Read, Write};
use std::os::unix::net::UnixStream;

use anyhow::{Result, bail};
use serde::Deserialize;

const GET_TREE: u32 = 4;

pub(super) struct Socket {
    stream: BufReader<UnixStream>,
}

impl Socket {
    pub(super) fn connect() -> Result<Self> {
        let Some(path) = env::var_os("SWAYSOCK") else {
            bail!("SWAYSOCK is not set");
        };

        Ok(Self {
            stream: BufReader::new(UnixStream::connect(path)?),
        })
    }

    pub(super) fn tree(&mut self) -> Result<Node> {
        let mut request = Vec::with_capacity(14);
        request.extend_from_slice(b"i3-ipc");
        request.extend_from_slice(&0_u32.to_ne_bytes());
        request.extend_from_slice(&GET_TREE.to_ne_bytes());
        self.stream.get_mut().write_all(&request)?;

        let mut header = [0; 14];
        self.stream.read_exact(&mut header)?;
        assert_eq!(&header[..6], b"i3-ipc");
        assert_eq!(
            u32::from_ne_bytes(header[10..14].try_into().unwrap()),
            GET_TREE
        );
        let length = u32::from_ne_bytes(header[6..10].try_into().unwrap());
        let mut payload = vec![0; length as usize];
        self.stream.read_exact(&mut payload)?;

        Ok(serde_json::from_slice(&payload)?)
    }
}

#[derive(Deserialize)]
pub(super) struct Node {
    pub(super) rect: Geometry,
    pub(super) visible: Option<bool>,
    pub(super) nodes: Vec<Self>,
    pub(super) floating_nodes: Vec<Self>,
}

#[derive(Deserialize)]
pub(super) struct Geometry {
    pub(super) x: i32,
    pub(super) y: i32,
    pub(super) width: i32,
    pub(super) height: i32,
}