rewrite bar-ws-monitor for niri support

This commit is contained in:
Schrottkatze 2025-03-13 17:26:57 +01:00
parent b08b46f4a8
commit c7deaaa048
Signed by: schrottkatze
SSH key fingerprint: SHA256:FPOYVeBy3QP20FEM42uWF1Wa/Qhlk+L3S2+Wuau/Auo
4 changed files with 107 additions and 75 deletions

View file

@ -6,4 +6,4 @@ edition = "2021"
[dependencies]
serde = { version = "1.0.209", features = [ "derive" ] }
serde_json = "1.0.127"
swayipc = "3.0.2"
niri-ipc = "25.2.0"

View file

@ -1,28 +1,87 @@
use core::panic;
use std::{collections::HashMap, io::Write};
use niri_ipc::{
socket::Socket,
state::{EventStreamState, EventStreamStatePart},
Request, Response, Workspace,
};
use serde::Serialize;
use swayipc::{Connection, Event, EventType, Fallible, Workspace, WorkspaceChange};
fn main() -> Fallible<()> {
let mut con = Connection::new()?;
let mut workspaces: Vec<WsData> = con
.get_workspaces()?
.into_iter()
.map(|ws| ws.into())
.collect();
println!("{}", serde_json::ser::to_string(&workspaces).unwrap());
// 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
];
for ev in con.subscribe([EventType::Workspace])? {
// the lazy/ugly solution!
// we create a new connection and request workspaces again and again and again
// TODO: properly handle events one by one
let mut con = Connection::new()?;
workspaces = con
.get_workspaces()?
.into_iter()
.map(|ws| ws.into())
.collect();
println!("{}", serde_json::ser::to_string(&workspaces).unwrap());
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(|ws| WsData {
color: output_colors_lut[&ws.output.clone().expect("unreachable")]
[if ws.is_active { 1 } else { 0 }],
idx: ws.idx,
focused: ws.is_focused,
active: ws.is_active,
})
.collect::<Vec<_>>();
println!("{}", serde_json::to_string(&results).unwrap());
}
}
Ok(())
@ -30,24 +89,8 @@ fn main() -> Fallible<()> {
#[derive(Debug, Serialize)]
struct WsData {
name: String,
color: &'static str,
idx: u8,
focused: bool,
urgent: bool,
}
impl From<Workspace> for WsData {
fn from(
Workspace {
name,
focused,
urgent,
..
}: Workspace,
) -> Self {
WsData {
name,
focused,
urgent,
}
}
active: bool,
}