use std::collections::HashMap;
use futures::Stream;
use niri_ipc::{Action, Event, Output, Reply, Request, Workspace, socket::Socket};
pub use state::{Snapshot, Window};
pub use window_stream::WindowStream;
use crate::error::Error;
mod reply;
mod state;
mod window_stream;
#[derive(Debug, Clone, Copy)]
pub struct Niri {}
impl Niri {
pub fn new() -> Self {
Self {}
}
#[tracing::instrument(level = "TRACE", err)]
pub fn activate_window(&self, id: u64) -> Result<(), Error> {
let reply = request(Request::Action(Action::FocusWindow { id }))?;
reply::typed!(Handled, reply)
}
pub fn outputs(&self) -> Result<HashMap<String, Output>, Error> {
let reply = request(Request::Outputs)?;
reply::typed!(Outputs, reply)
}
pub fn window_stream(&self) -> WindowStream {
WindowStream::new()
}
pub fn workspace_stream(&self) -> Result<impl Stream<Item = Vec<Workspace>> + use<>, Error> {
let mut socket = socket()?;
let reply = socket.send(Request::EventStream).map_err(Error::NiriIpc)?;
reply::typed!(Handled, reply)?;
let mut next = socket.read_events();
Ok(async_stream::stream! {
loop {
match next() {
Ok(Event::WorkspacesChanged { workspaces }) => {
yield workspaces;
}
Ok(_) => (),
Err(e) => {
tracing::error!(%e, "Niri IPC error reading from event stream");
}
}
}
})
}
}
#[tracing::instrument(level = "TRACE", err)]
fn request(request: Request) -> Result<Reply, Error> {
socket()?.send(request).map_err(Error::NiriIpc)
}
#[tracing::instrument(level = "TRACE", err)]
fn socket() -> Result<Socket, Error> {
Socket::connect().map_err(Error::NiriIpc)
}