105 lines
3.1 KiB
Rust
105 lines
3.1 KiB
Rust
use core::panic;
|
|
use std::{collections::HashMap, io::Write};
|
|
|
|
use niri_ipc::{
|
|
socket::Socket,
|
|
state::{EventStreamState, EventStreamStatePart},
|
|
Request, Response, Workspace,
|
|
};
|
|
use serde::Serialize;
|
|
|
|
// gruvbox colors
|
|
const COLORS: [[&str; 2]; 7] = [
|
|
["#458588", "#83a598"], // blue
|
|
["#b16286", "#d3869b"], // purple
|
|
["#689d6a", "#8ec07c"], // aqua
|
|
["#97971a", "#b8bb26"], // green
|
|
["#d79921", "#fabd2f"], // yellow
|
|
["#d65d0e", "#fe8019"], // orange
|
|
["#cc241d", "#fb4934"], // red
|
|
];
|
|
|
|
fn main() -> Result<(), std::io::Error> {
|
|
let mut state = EventStreamState::default();
|
|
let sock = Socket::connect()?;
|
|
let mut func = sock.send(Request::EventStream).and_then(|it| match it {
|
|
(Ok(Response::Handled), func) => Ok(func),
|
|
_ => unreachable!(),
|
|
})?;
|
|
|
|
while let Ok(ev) = (func)() {
|
|
// check only relevant later, only done here to avoid a clone
|
|
let ev_is_ws_related = matches!(
|
|
&ev,
|
|
niri_ipc::Event::WorkspacesChanged { .. }
|
|
| niri_ipc::Event::WorkspaceActivated { .. }
|
|
| niri_ipc::Event::WorkspaceActiveWindowChanged { .. }
|
|
);
|
|
|
|
// apply event to state
|
|
state.apply(ev);
|
|
|
|
if ev_is_ws_related {
|
|
let mut workspaces = state
|
|
.workspaces
|
|
.workspaces
|
|
.values()
|
|
.map(|it| it.clone())
|
|
.collect::<Vec<Workspace>>();
|
|
|
|
workspaces.sort_by(|a, b| a.idx.cmp(&b.idx));
|
|
workspaces.sort_by(|a, b| {
|
|
a.output
|
|
.clone()
|
|
.expect("unreachable")
|
|
.to_lowercase()
|
|
.cmp(&b.output.clone().expect("unreachable").to_lowercase())
|
|
});
|
|
|
|
let output_colors_lut = workspaces
|
|
.iter()
|
|
.map(|it| it.output.clone().expect("unreachable"))
|
|
.fold(Vec::new(), |mut acc, it| {
|
|
if !acc.contains(&it) {
|
|
acc.push(it);
|
|
}
|
|
acc
|
|
})
|
|
.into_iter()
|
|
.enumerate()
|
|
.map(|(idx, val)| (val, &COLORS[idx]))
|
|
.collect::<HashMap<String, &[&str; 2]>>();
|
|
|
|
let results = workspaces
|
|
.iter()
|
|
.map(
|
|
|Workspace {
|
|
idx,
|
|
output,
|
|
is_active,
|
|
is_focused,
|
|
..
|
|
}| WsData {
|
|
color: output_colors_lut[&output.clone().expect("unreachable")]
|
|
[if *is_active { 1 } else { 0 }],
|
|
idx: *idx,
|
|
focused: *is_focused,
|
|
active: *is_active,
|
|
},
|
|
)
|
|
.collect::<Vec<_>>();
|
|
|
|
println!("{}", serde_json::to_string(&results).unwrap());
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[derive(Debug, Serialize)]
|
|
struct WsData {
|
|
color: &'static str,
|
|
idx: u8,
|
|
focused: bool,
|
|
active: bool,
|
|
}
|