feat: change socket nomenclature + implement events provider

This commit is contained in:
atagen 2025-06-21 17:20:01 +10:00
parent 389c4b3ee6
commit 05e12ea2f2
5 changed files with 212 additions and 65 deletions

View file

@ -4,9 +4,9 @@ use niri_ipc::{
Action, Event, Reply, Request, Response, Window, Workspace, WorkspaceReferenceArg,
state::{EventStreamState, EventStreamStatePart},
};
use niri_tag::TagCmd;
use niri_tag::{TagCmd, TagEvent};
use smol::{
channel::{self},
channel::{self, Sender},
future,
io::BufReader,
net::unix::UnixStream,
@ -18,6 +18,7 @@ pub struct NiriTag {
windows: HashMap<u64, u8>,
state: EventStreamState,
socket: BufReader<UnixStream>,
ev_tx: channel::Sender<TagEvent>,
}
enum TagAction {
@ -26,12 +27,13 @@ enum TagAction {
}
impl NiriTag {
pub async fn new() -> Result<Self> {
pub async fn new(ev_tx: channel::Sender<TagEvent>) -> Result<Self> {
Ok(Self {
tags: HashMap::new(),
windows: HashMap::new(),
state: EventStreamState::default(),
socket: create_niri_socket().await?,
ev_tx,
})
}
@ -196,6 +198,36 @@ impl NiriTag {
async fn handle_recvd(&mut self, recvd: Receivable) -> Result<()> {
use TagAction::*;
let send_event = async |tx: Sender<TagEvent>, ev| {
smol::spawn(async move {
tx.send(ev)
.await
.inspect_err(|e| tracing::error!("Failed to send event: {}", e))
})
.detach();
};
let add_tag = async |tx: Sender<TagEvent>, windows: &HashMap<u64, u8>, t| {
if windows
.iter()
.filter(|(_, tag)| **tag == t)
.collect::<HashMap<_, _>>()
.is_empty()
{
send_event(tx, TagEvent::TagOccupied(t)).await;
}
};
let rm_tag = async |tx: Sender<TagEvent>, windows: &HashMap<u64, u8>, wid, old_tag| {
if old_tag != 0
&& windows
.iter()
.filter(|(w, tag)| **tag == old_tag && **w != wid)
.collect::<Vec<(_, _)>>()
.is_empty()
{
send_event(tx, TagEvent::TagEmpty(old_tag)).await;
}
};
// first do any local mutations
let action: TagAction = match recvd {
Receivable::Event(ev) => {
@ -208,13 +240,17 @@ impl NiriTag {
let wid = win.id;
self.windows.insert(wid, t);
tracing::debug!("adding tag {} to {}", t, wid);
let tx = self.ev_tx.clone();
add_tag(tx, &self.windows, t).await;
ChangeWindow(wid)
}
TagCmd::RemoveTagFromWin(_) => {
let win = self.get_focused_window().await?;
let wid = win.id;
self.windows.insert(wid, 0);
let old_tag = self.windows.insert(wid, 0).unwrap_or(0);
tracing::debug!("resetting tag on {}", wid);
let tx = self.ev_tx.clone();
rm_tag(tx, &self.windows, wid, old_tag).await;
ChangeWindow(wid)
}
TagCmd::ToggleTagOnWin(t) => {
@ -223,6 +259,12 @@ impl NiriTag {
tracing::debug!("{} has tag {:?}", wid, self.windows.get(&wid));
let this_tag = *self.windows.entry(wid).or_insert(0);
let toggle = if this_tag == t { 0 } else { t };
let tx = self.ev_tx.clone();
if toggle == 0 {
rm_tag(tx, &self.windows, wid, this_tag).await;
} else {
add_tag(tx, &self.windows, t).await;
}
tracing::debug!("toggling {} to tag {}", wid, toggle);
self.windows.insert(wid, toggle);
ChangeWindow(wid)
@ -230,14 +272,21 @@ impl NiriTag {
TagCmd::EnableTag(t) => {
self.tags.insert(t, true);
send_event(self.ev_tx.clone(), TagEvent::TagEnabled(t)).await;
ChangeTag(t)
}
TagCmd::DisableTag(t) => {
self.tags.insert(t, false);
send_event(self.ev_tx.clone(), TagEvent::TagDisabled(t)).await;
ChangeTag(t)
}
TagCmd::ToggleTag(t) => {
let visible = *self.tags.entry(t).or_insert(false);
if visible {
send_event(self.ev_tx.clone(), TagEvent::TagEnabled(t)).await;
} else {
send_event(self.ev_tx.clone(), TagEvent::TagDisabled(t)).await;
}
tracing::debug!("toggling tag {} to {}", t, !visible);
self.tags.insert(t, !visible);
ChangeTag(t)
@ -283,7 +332,7 @@ impl NiriTag {
tag_rx.recv().await.map(Receivable::TagCmd)
})
.await?;
tracing::debug!("received {:?}", recvd);
tracing::debug!("manager received {:?}", recvd);
let res = self.handle_recvd(recvd).await;
match res {