use anyhow::{Context, Result};
use futures::stream::StreamExt;
use xcb_util::ewmh;
use crate::text::{Attributes, Text};
use crate::widgets::{Widget, WidgetStream};
use crate::xcb::xcb_properties_stream;
pub struct ActiveWindowTitle {
attr: Attributes,
}
impl ActiveWindowTitle {
pub fn new(attr: Attributes) -> ActiveWindowTitle {
ActiveWindowTitle { attr }
}
fn on_change(&self, conn: &ewmh::Connection, screen_idx: i32) -> Vec<Text> {
let title = ewmh::get_active_window(conn, screen_idx)
.get_reply()
.and_then(|active_window| {
let attributes = [(xcb::CW_EVENT_MASK, xcb::EVENT_MASK_PROPERTY_CHANGE)];
xcb::change_window_attributes(conn, active_window, &attributes);
conn.flush();
ewmh::get_wm_name(conn, active_window).get_reply()
})
.map(|reply| reply.string().to_owned())
.unwrap_or_else(|_| "".to_owned());
vec![Text {
attr: self.attr.clone(),
text: title,
stretch: true,
markup: false,
}]
}
}
impl Widget for ActiveWindowTitle {
fn into_stream(self: Box<Self>) -> Result<WidgetStream> {
let properties = &["_NET_ACTIVE_WINDOW", "_NET_WM_NAME"];
let screen_idx = 0; let (conn, stream) =
xcb_properties_stream(properties).context("Initialising ActiveWindowtitle")?;
let stream = stream.map(move |()| Ok(self.on_change(&conn, screen_idx)));
Ok(Box::pin(stream))
}
}