diff --git a/files/icons/awesome4.toml b/files/icons/awesome4.toml index 3a3dba42c2..d2894b5b34 100644 --- a/files/icons/awesome4.toml +++ b/files/icons/awesome4.toml @@ -58,6 +58,7 @@ pomodoro_paused = "\uf04c" # fa-pause pomodoro_started = "\uf04b" # fa-play pomodoro_stopped = "\uf04d" # fa-stop resolution = "\uf096" # fa-square-o +scratchpad = "\uf2d2" # fa-window-restore tasks = "\uf0ae" # fa-tasks tea = "\uf0f4" # fa-coffee thermometer = "\uf2c8" # fa-thermometer-3 diff --git a/files/icons/awesome5.toml b/files/icons/awesome5.toml index 1e9558bbf9..4f5cd4dfb1 100644 --- a/files/icons/awesome5.toml +++ b/files/icons/awesome5.toml @@ -58,6 +58,7 @@ pomodoro_paused = "\uf04c" # fa-pause pomodoro_started = "\uf04b" # fa-play pomodoro_stopped = "\uf04d" # fa-stop resolution = "\uf096" # fa-square-o +scratchpad = "\uf2d2" # fa-window-restore tasks = "\uf0ae" tea = "\uf0f4" thermometer = "\uf2c8" diff --git a/files/icons/awesome6.toml b/files/icons/awesome6.toml index ab4c380e7c..6bf68ae13d 100644 --- a/files/icons/awesome6.toml +++ b/files/icons/awesome6.toml @@ -62,6 +62,7 @@ pomodoro_paused = "\uf04c" # fa-pause pomodoro_started = "\uf04b" # fa-play pomodoro_stopped = "\uf04d" # fa-stop resolution = "\uf096" # fa-square-o +scratchpad = "\uf2d2" # fa-window-restore tasks = "\uf0ae" tea = "\uf0f4" thermometer = "\uf2c8" diff --git a/files/icons/emoji.toml b/files/icons/emoji.toml index d2dfaabd13..c46951e4bd 100644 --- a/files/icons/emoji.toml +++ b/files/icons/emoji.toml @@ -54,6 +54,7 @@ pomodoro_paused = "⏸️" pomodoro_started = "▶️" pomodoro_stopped = "⏹️" resolution = "🔳" +scratchpad = "🗔" tasks = "✅" tea = "☕" thermometer = "🌡️" diff --git a/files/icons/material-nf.toml b/files/icons/material-nf.toml index 7e6198489a..b5d8e94613 100644 --- a/files/icons/material-nf.toml +++ b/files/icons/material-nf.toml @@ -91,6 +91,7 @@ pomodoro_paused = "\U000f03e4" # nf-md-pause pomodoro_started = "\U000f040a" # nf-md-play pomodoro_stopped = "\U000f04db" # nf-md-stop resolution = "\U000f0293" # nf-md-fullscreen +scratchpad = "\U000f05b2" # nf-md-window_restore tasks = "\U000f05c7" # nf-md-playlist_check tea = "\U000f0d9e" # nf-md-tea thermometer = [ diff --git a/files/icons/material.toml b/files/icons/material.toml index 3c90cf420d..0b7c2232ed 100644 --- a/files/icons/material.toml +++ b/files/icons/material.toml @@ -75,6 +75,7 @@ pomodoro_paused = "\ue034" # pause pomodoro_started = "\ue037" # play_arrow pomodoro_stopped = "\uef6a" # play_disabled ef6a | TODO: broken? resolution = "\uf152" # crop-square-rounded +scratchpad = "\ue883" # flip_to_front tasks = "\ue8f9" # work tea = "\uefef" # coffee thermometer = "\ue1ff" # device_thermostat | TODO: broken? diff --git a/src/blocks.rs b/src/blocks.rs index 149ee352df..28fadd9c4e 100644 --- a/src/blocks.rs +++ b/src/blocks.rs @@ -188,6 +188,7 @@ define_blocks!( privacy, rofication, service_status, + scratchpad, sound, speedtest, keyboard_layout, diff --git a/src/blocks/scratchpad.rs b/src/blocks/scratchpad.rs new file mode 100644 index 0000000000..93610542a7 --- /dev/null +++ b/src/blocks/scratchpad.rs @@ -0,0 +1,86 @@ +//! Scratchpad indicator +//! +//! # Configuration +//! +//! Key | Values | Default +//! ----|--------|-------- +//! `format` | A string to customise the output of this block | ` $icon $count.eng(range:1..) |` +//! +//! Placeholder | Value | Type | Unit +//! ------------|--------------------------------------------|--------|----- +//! `icon` | A static icon | Icon | - +//! `count` | Number of windows in scratchpad | Number | - +//! +//! # Example +//! +//! ```toml +//! [[block]] +//! block = "scratchpad" +//! ``` +//! +//! # Icons Used +//! - `scratchpad` + +use swayipc_async::{Connection, Event as SwayEvent, EventType, Node, WindowChange}; + +use super::prelude::*; + +#[derive(Deserialize, Debug, SmartDefault)] +#[serde(deny_unknown_fields, default)] +pub struct Config { + pub format: FormatConfig, +} + +fn count_scratchpad_windows(node: &Node) -> usize { + node.find_as_ref(|n| n.name.as_deref() == Some("__i3_scratch")) + .map_or(0, |node| node.floating_nodes.len()) +} + +pub async fn run(config: &Config, api: &CommonApi) -> Result<()> { + let format = config + .format + .with_default(" $icon $count.eng(range:1..) |")?; + + let connection_for_events = Connection::new() + .await + .error("failed to open connection with swayipc")?; + + let mut connection_for_tree = Connection::new() + .await + .error("failed to open connection with swayipc")?; + + let mut events = connection_for_events + .subscribe(&[EventType::Window]) + .await + .error("could not subscribe to window events")?; + + loop { + let mut widget = Widget::new().with_format(format.clone()); + + let root_node = connection_for_tree + .get_tree() + .await + .error("could not get windows tree")?; + let count = count_scratchpad_windows(&root_node); + + widget.set_values(map! { + "icon" => Value::icon("scratchpad"), + "count" => Value::number(count), + }); + + api.set_widget(widget)?; + + loop { + let event = events + .next() + .await + .error("swayipc channel closed")? + .error("bad event")?; + + match event { + SwayEvent::Window(e) if e.change == WindowChange::Move => break, + _ => continue, + } + } + } +} diff --git a/src/icons.rs b/src/icons.rs index 98e2cee229..76a7aa3bbb 100644 --- a/src/icons.rs +++ b/src/icons.rs @@ -84,6 +84,7 @@ impl Default for Icons { "pomodoro_started" => "STARTED", "pomodoro_stopped" => "STOPPED", "resolution" => "RES", + "scratchpad" => "[]", "tasks" => "TSK", "tea" => "TEA", "thermometer" => "TEMP",