use std::path::PathBuf;
use tokio::io::{AsyncReadExt, AsyncWriteExt, BufReader};
use tokio::net::UnixStream;
use crate::error::{Result, StutterError};
#[derive(Debug, serde::Deserialize)]
pub struct ActiveWindow {
pub pid: u32,
}
fn socket_path(name: &str) -> Result<PathBuf> {
let runtime_dir = std::env::var("XDG_RUNTIME_DIR").map_err(|_| StutterError::NoRuntimeDir)?;
let sig = std::env::var("HYPRLAND_INSTANCE_SIGNATURE")
.map_err(|_| StutterError::NoInstanceSignature)?;
Ok(PathBuf::from(runtime_dir).join("hypr").join(sig).join(name))
}
pub async fn connect_events() -> Result<BufReader<UnixStream>> {
let path = socket_path(".socket2.sock")?;
let stream = UnixStream::connect(path).await?;
Ok(BufReader::new(stream))
}
pub async fn get_active_window_pid() -> Result<u32> {
let path = socket_path(".socket.sock")?;
let mut stream = UnixStream::connect(path).await?;
stream.write_all(b"j/activewindow").await?;
stream.shutdown().await?;
let mut buf = String::new();
stream.read_to_string(&mut buf).await?;
let buf = buf.trim();
crate::log!("[stutter] debug: raw response: '{buf}'");
if buf.is_empty() || buf == "{}" || buf == "unknown request" {
return Err(StutterError::NoActiveWindow);
}
let window: ActiveWindow = serde_json::from_str(buf)?;
if window.pid == 0 {
return Err(StutterError::NoActiveWindow);
}
Ok(window.pid)
}