mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-07-01 02:31:04 +02:00
docs: add some rustdoc comments throughout
This commit is contained in:
parent
5d319e91f2
commit
78e30b39fe
16 changed files with 84 additions and 2 deletions
|
@ -7,6 +7,8 @@ use gtk::prelude::*;
|
||||||
use gtk::{Application, ApplicationWindow, Orientation};
|
use gtk::{Application, ApplicationWindow, Orientation};
|
||||||
use tracing::{debug, info};
|
use tracing::{debug, info};
|
||||||
|
|
||||||
|
/// Creates a new window for a bar,
|
||||||
|
/// sets it up and adds its widgets.
|
||||||
pub fn create_bar(
|
pub fn create_bar(
|
||||||
app: &Application,
|
app: &Application,
|
||||||
monitor: &Monitor,
|
monitor: &Monitor,
|
||||||
|
@ -53,6 +55,7 @@ pub fn create_bar(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Loads the configured modules onto a bar.
|
||||||
fn load_modules(
|
fn load_modules(
|
||||||
left: >k::Box,
|
left: >k::Box,
|
||||||
center: >k::Box,
|
center: >k::Box,
|
||||||
|
@ -101,6 +104,8 @@ fn load_modules(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds modules into a provided GTK box,
|
||||||
|
/// which should be one of its left, center or right containers.
|
||||||
fn add_modules(content: >k::Box, modules: Vec<ModuleConfig>, info: &ModuleInfo) -> Result<()> {
|
fn add_modules(content: >k::Box, modules: Vec<ModuleConfig>, info: &ModuleInfo) -> Result<()> {
|
||||||
macro_rules! add_module {
|
macro_rules! add_module {
|
||||||
($module:expr, $name:literal) => {{
|
($module:expr, $name:literal) => {{
|
||||||
|
@ -127,6 +132,7 @@ fn add_modules(content: >k::Box, modules: Vec<ModuleConfig>, info: &ModuleInfo
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets up GTK layer shell for a provided aplication window.
|
||||||
fn setup_layer_shell(win: &ApplicationWindow, monitor: &Monitor, position: &BarPosition) {
|
fn setup_layer_shell(win: &ApplicationWindow, monitor: &Monitor, position: &BarPosition) {
|
||||||
gtk_layer_shell::init_for_window(win);
|
gtk_layer_shell::init_for_window(win);
|
||||||
gtk_layer_shell::set_monitor(win, monitor);
|
gtk_layer_shell::set_monitor(win, monitor);
|
||||||
|
|
|
@ -11,6 +11,7 @@ pub struct Collection<TKey, TData> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<TKey: PartialEq, TData> Collection<TKey, TData> {
|
impl<TKey: PartialEq, TData> Collection<TKey, TData> {
|
||||||
|
/// Creates a new empty collection.
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
keys: vec![],
|
keys: vec![],
|
||||||
|
@ -18,6 +19,7 @@ impl<TKey: PartialEq, TData> Collection<TKey, TData> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Inserts a new key/value pair at the end of the collection.
|
||||||
pub fn insert(&mut self, key: TKey, value: TData) {
|
pub fn insert(&mut self, key: TKey, value: TData) {
|
||||||
self.keys.push(key);
|
self.keys.push(key);
|
||||||
self.values.push(value);
|
self.values.push(value);
|
||||||
|
@ -25,6 +27,8 @@ impl<TKey: PartialEq, TData> Collection<TKey, TData> {
|
||||||
assert_eq!(self.keys.len(), self.values.len());
|
assert_eq!(self.keys.len(), self.values.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets a reference of the value for the specified key
|
||||||
|
/// if it exists in the collection.
|
||||||
pub fn get(&self, key: &TKey) -> Option<&TData> {
|
pub fn get(&self, key: &TKey) -> Option<&TData> {
|
||||||
let index = self.keys.iter().position(|k| k == key);
|
let index = self.keys.iter().position(|k| k == key);
|
||||||
match index {
|
match index {
|
||||||
|
@ -33,6 +37,8 @@ impl<TKey: PartialEq, TData> Collection<TKey, TData> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets a mutable reference for the value with the specified key
|
||||||
|
/// if it exists in the collection.
|
||||||
pub fn get_mut(&mut self, key: &TKey) -> Option<&mut TData> {
|
pub fn get_mut(&mut self, key: &TKey) -> Option<&mut TData> {
|
||||||
let index = self.keys.iter().position(|k| k == key);
|
let index = self.keys.iter().position(|k| k == key);
|
||||||
match index {
|
match index {
|
||||||
|
@ -41,6 +47,9 @@ impl<TKey: PartialEq, TData> Collection<TKey, TData> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Removes the key/value from the collection
|
||||||
|
/// if it exists
|
||||||
|
/// and returns the removed value.
|
||||||
pub fn remove(&mut self, key: &TKey) -> Option<TData> {
|
pub fn remove(&mut self, key: &TKey) -> Option<TData> {
|
||||||
assert_eq!(self.keys.len(), self.values.len());
|
assert_eq!(self.keys.len(), self.values.len());
|
||||||
|
|
||||||
|
@ -53,26 +62,32 @@ impl<TKey: PartialEq, TData> Collection<TKey, TData> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the length of the collection.
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.keys.len()
|
self.keys.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets a reference to the first value in the collection.
|
||||||
pub fn first(&self) -> Option<&TData> {
|
pub fn first(&self) -> Option<&TData> {
|
||||||
self.values.first()
|
self.values.first()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the values as a slice.
|
||||||
pub fn as_slice(&self) -> &[TData] {
|
pub fn as_slice(&self) -> &[TData] {
|
||||||
self.values.as_slice()
|
self.values.as_slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks whether the collection is empty.
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.keys.is_empty()
|
self.keys.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets an iterator for the collection.
|
||||||
pub fn iter(&self) -> Iter<'_, TData> {
|
pub fn iter(&self) -> Iter<'_, TData> {
|
||||||
self.values.iter()
|
self.values.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets a mutable iterator for the collection
|
||||||
pub fn iter_mut(&mut self) -> IterMut<'_, TData> {
|
pub fn iter_mut(&mut self) -> IterMut<'_, TData> {
|
||||||
self.values.iter_mut()
|
self.values.iter_mut()
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,8 @@ const fn default_bar_height() -> i32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
|
/// Attempts to load the config file from file,
|
||||||
|
/// parse it and return a new instance of `Self`.
|
||||||
pub fn load() -> Result<Self> {
|
pub fn load() -> Result<Self> {
|
||||||
let config_path = if let Ok(config_path) = env::var("IRONBAR_CONFIG") {
|
let config_path = if let Ok(config_path) = env::var("IRONBAR_CONFIG") {
|
||||||
let path = PathBuf::from(config_path);
|
let path = PathBuf::from(config_path);
|
||||||
|
@ -87,6 +89,10 @@ impl Config {
|
||||||
Self::load_file(&config_path)
|
Self::load_file(&config_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attempts to discover the location of the config file
|
||||||
|
/// by checking each valid format's extension.
|
||||||
|
///
|
||||||
|
/// Returns the path of the first valid match, if any.
|
||||||
fn try_find_config() -> Result<PathBuf> {
|
fn try_find_config() -> Result<PathBuf> {
|
||||||
let config_dir = config_dir().wrap_err("Failed to locate user config dir")?;
|
let config_dir = config_dir().wrap_err("Failed to locate user config dir")?;
|
||||||
|
|
||||||
|
@ -110,6 +116,8 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Loads the config file at the specified path
|
||||||
|
/// and parses it into `Self` based on its extension.
|
||||||
fn load_file(path: &Path) -> Result<Self> {
|
fn load_file(path: &Path) -> Result<Self> {
|
||||||
let file = fs::read(path).wrap_err("Failed to read config file")?;
|
let file = fs::read(path).wrap_err("Failed to read config file")?;
|
||||||
let extension = path
|
let extension = path
|
||||||
|
|
|
@ -86,6 +86,10 @@ enum IconLocation {
|
||||||
File(PathBuf),
|
File(PathBuf),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attempts to get the location of an icon.
|
||||||
|
///
|
||||||
|
/// Handles icons that are part of a GTK theme, icons specified as path
|
||||||
|
/// and icons for steam games.
|
||||||
fn get_icon_location(theme: &IconTheme, app_id: &str, size: i32) -> Option<IconLocation> {
|
fn get_icon_location(theme: &IconTheme, app_id: &str, size: i32) -> Option<IconLocation> {
|
||||||
let has_icon = theme
|
let has_icon = theme
|
||||||
.lookup_icon(app_id, size, IconLookupFlags::empty())
|
.lookup_icon(app_id, size, IconLookupFlags::empty())
|
||||||
|
|
|
@ -26,6 +26,10 @@ impl<'a> MakeWriter<'a> for MakeFileWriter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Installs tracing into the current application.
|
||||||
|
///
|
||||||
|
/// The returned `WorkerGuard` must remain in scope
|
||||||
|
/// for the lifetime of the application for logging to file to work.
|
||||||
pub fn install_tracing() -> Result<WorkerGuard> {
|
pub fn install_tracing() -> Result<WorkerGuard> {
|
||||||
let fmt_layer = fmt::layer().with_target(true);
|
let fmt_layer = fmt::layer().with_target(true);
|
||||||
let filter_layer = EnvFilter::try_from_default_env().or_else(|_| EnvFilter::try_new("info"))?;
|
let filter_layer = EnvFilter::try_from_default_env().or_else(|_| EnvFilter::try_new("info"))?;
|
||||||
|
|
|
@ -95,6 +95,7 @@ async fn main() -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates each of the bars across each of the (configured) outputs.
|
||||||
fn create_bars(app: &Application, display: &Display, config: &Config) -> Result<()> {
|
fn create_bars(app: &Application, display: &Display, config: &Config) -> Result<()> {
|
||||||
let outputs = {
|
let outputs = {
|
||||||
let sway = get_client();
|
let sway = get_client();
|
||||||
|
@ -120,6 +121,7 @@ fn create_bars(app: &Application, display: &Display, config: &Config) -> Result<
|
||||||
|
|
||||||
info!("Creating bar on '{}'", monitor_name);
|
info!("Creating bar on '{}'", monitor_name);
|
||||||
|
|
||||||
|
// TODO: Could we use an Arc<Config> here to avoid cloning?
|
||||||
config.monitors.as_ref().map_or_else(
|
config.monitors.as_ref().map_or_else(
|
||||||
|| create_bar(app, &monitor, monitor_name, config.clone()),
|
|| create_bar(app, &monitor, monitor_name, config.clone()),
|
||||||
|config| {
|
|config| {
|
||||||
|
|
|
@ -10,13 +10,17 @@ use tokio::task::spawn_blocking;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct FocusedModule {
|
pub struct FocusedModule {
|
||||||
|
/// Whether to show icon on the bar.
|
||||||
#[serde(default = "crate::config::default_true")]
|
#[serde(default = "crate::config::default_true")]
|
||||||
show_icon: bool,
|
show_icon: bool,
|
||||||
|
/// Whether to show app name on the bar.
|
||||||
#[serde(default = "crate::config::default_true")]
|
#[serde(default = "crate::config::default_true")]
|
||||||
show_title: bool,
|
show_title: bool,
|
||||||
|
|
||||||
|
/// Icon size in pixels.
|
||||||
#[serde(default = "default_icon_size")]
|
#[serde(default = "default_icon_size")]
|
||||||
icon_size: i32,
|
icon_size: i32,
|
||||||
|
/// GTK icon theme to use.
|
||||||
icon_theme: Option<String>,
|
icon_theme: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,17 @@ use tokio::task::spawn_blocking;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct LauncherModule {
|
pub struct LauncherModule {
|
||||||
|
/// List of app IDs (or classes) to always show regardles of open state,
|
||||||
|
/// in the order specified.
|
||||||
favorites: Option<Vec<String>>,
|
favorites: Option<Vec<String>>,
|
||||||
|
/// Whether to show application names on the bar.
|
||||||
#[serde(default = "crate::config::default_false")]
|
#[serde(default = "crate::config::default_false")]
|
||||||
show_names: bool,
|
show_names: bool,
|
||||||
|
/// Whether to show application icons on the bar.
|
||||||
#[serde(default = "crate::config::default_true")]
|
#[serde(default = "crate::config::default_true")]
|
||||||
show_icons: bool,
|
show_icons: bool,
|
||||||
|
|
||||||
|
/// Name of the GTK icon theme to use.
|
||||||
icon_theme: Option<String>,
|
icon_theme: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,15 +23,20 @@ use tracing::error;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct MpdModule {
|
pub struct MpdModule {
|
||||||
|
/// TCP or Unix socket address.
|
||||||
#[serde(default = "default_socket")]
|
#[serde(default = "default_socket")]
|
||||||
host: String,
|
host: String,
|
||||||
|
/// Format of current song info to display on the bar.
|
||||||
#[serde(default = "default_format")]
|
#[serde(default = "default_format")]
|
||||||
format: String,
|
format: String,
|
||||||
|
/// Icon to display when playing.
|
||||||
#[serde(default = "default_icon_play")]
|
#[serde(default = "default_icon_play")]
|
||||||
icon_play: Option<String>,
|
icon_play: Option<String>,
|
||||||
|
/// Icon to display when paused.
|
||||||
#[serde(default = "default_icon_pause")]
|
#[serde(default = "default_icon_pause")]
|
||||||
icon_pause: Option<String>,
|
icon_pause: Option<String>,
|
||||||
|
|
||||||
|
/// Path to root of music directory.
|
||||||
#[serde(default = "default_music_dir")]
|
#[serde(default = "default_music_dir")]
|
||||||
music_dir: PathBuf,
|
music_dir: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,9 @@ use tracing::{error, instrument};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct ScriptModule {
|
pub struct ScriptModule {
|
||||||
|
/// Path to script to execute.
|
||||||
path: String,
|
path: String,
|
||||||
|
/// Time in milliseconds between executions.
|
||||||
#[serde(default = "default_interval")]
|
#[serde(default = "default_interval")]
|
||||||
interval: u64,
|
interval: u64,
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ use tokio::time::sleep;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct SysInfoModule {
|
pub struct SysInfoModule {
|
||||||
|
/// List of formatting strings.
|
||||||
format: Vec<String>,
|
format: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,10 @@ use tracing::{debug, trace};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct WorkspacesModule {
|
pub struct WorkspacesModule {
|
||||||
|
/// Map of actual workspace names to custom names.
|
||||||
name_map: Option<HashMap<String, String>>,
|
name_map: Option<HashMap<String, String>>,
|
||||||
|
|
||||||
|
/// Whether to display icons for all monitors.
|
||||||
#[serde(default = "crate::config::default_false")]
|
#[serde(default = "crate::config::default_false")]
|
||||||
all_monitors: bool,
|
all_monitors: bool,
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,9 @@ pub struct Popup {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Popup {
|
impl Popup {
|
||||||
|
/// Creates a new popup window.
|
||||||
|
/// This includes setting up gtk-layer-shell
|
||||||
|
/// and an empty `gtk::Box` container.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
name: &str,
|
name: &str,
|
||||||
app: &Application,
|
app: &Application,
|
||||||
|
|
|
@ -9,6 +9,11 @@ use std::time::Duration;
|
||||||
use tokio::spawn;
|
use tokio::spawn;
|
||||||
use tracing::{error, info};
|
use tracing::{error, info};
|
||||||
|
|
||||||
|
/// Attempts to load CSS file at the given path
|
||||||
|
/// and attach if to the current GTK application.
|
||||||
|
///
|
||||||
|
/// Installs a file watcher and reloads CSS when
|
||||||
|
/// write changes are detected on the file.
|
||||||
pub fn load_css(style_path: PathBuf) {
|
pub fn load_css(style_path: PathBuf) {
|
||||||
let provider = CssProvider::new();
|
let provider = CssProvider::new();
|
||||||
|
|
||||||
|
|
|
@ -55,11 +55,13 @@ pub struct SwayOutput {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Broadcaster<T> = Arc<Mutex<UnboundedBroadcast<T>>>;
|
||||||
|
|
||||||
pub struct SwayClient {
|
pub struct SwayClient {
|
||||||
client: ksway::Client,
|
client: ksway::Client,
|
||||||
|
|
||||||
workspace_bc: Arc<Mutex<UnboundedBroadcast<WorkspaceEvent>>>,
|
workspace_bc: Broadcaster<WorkspaceEvent>,
|
||||||
window_bc: Arc<Mutex<UnboundedBroadcast<WindowEvent>>>,
|
window_bc: Broadcaster<WindowEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SwayClient {
|
impl SwayClient {
|
||||||
|
@ -189,15 +191,20 @@ pub fn get_client() -> Arc<Mutex<SwayClient>> {
|
||||||
Arc::clone(&CLIENT)
|
Arc::clone(&CLIENT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Crossbeam channel wrapper
|
||||||
|
/// which sends messages to all receivers.
|
||||||
pub struct UnboundedBroadcast<T> {
|
pub struct UnboundedBroadcast<T> {
|
||||||
channels: Vec<crossbeam_channel::Sender<T>>,
|
channels: Vec<crossbeam_channel::Sender<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: 'static + Clone + Send + Sync> UnboundedBroadcast<T> {
|
impl<T: 'static + Clone + Send + Sync> UnboundedBroadcast<T> {
|
||||||
|
/// Creates a new broadcaster.
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self { channels: vec![] }
|
Self { channels: vec![] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new sender/receiver pair.
|
||||||
|
/// The sender is stored locally and the receiver is returned.
|
||||||
pub fn subscribe(&mut self) -> Receiver<T> {
|
pub fn subscribe(&mut self) -> Receiver<T> {
|
||||||
let (tx, rx) = crossbeam_channel::unbounded();
|
let (tx, rx) = crossbeam_channel::unbounded();
|
||||||
|
|
||||||
|
@ -206,6 +213,7 @@ impl<T: 'static + Clone + Send + Sync> UnboundedBroadcast<T> {
|
||||||
rx
|
rx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attempts to send a messsge to all receivers.
|
||||||
pub fn send(&self, message: T) -> Result<(), crossbeam_channel::SendError<T>> {
|
pub fn send(&self, message: T) -> Result<(), crossbeam_channel::SendError<T>> {
|
||||||
for c in &self.channels {
|
for c in &self.channels {
|
||||||
c.send(message.clone())?;
|
c.send(message.clone())?;
|
||||||
|
|
|
@ -3,6 +3,9 @@ use color_eyre::Result;
|
||||||
use ksway::IpcCommand;
|
use ksway::IpcCommand;
|
||||||
|
|
||||||
impl SwayNode {
|
impl SwayNode {
|
||||||
|
/// Gets either the `app_id` or `class`
|
||||||
|
/// depending on whether this is a native Wayland
|
||||||
|
/// or xwayland application.
|
||||||
pub fn get_id(&self) -> &str {
|
pub fn get_id(&self) -> &str {
|
||||||
self.app_id.as_ref().map_or_else(
|
self.app_id.as_ref().map_or_else(
|
||||||
|| {
|
|| {
|
||||||
|
@ -17,11 +20,15 @@ impl SwayNode {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks whether this application
|
||||||
|
/// is running under xwayland.
|
||||||
pub fn is_xwayland(&self) -> bool {
|
pub fn is_xwayland(&self) -> bool {
|
||||||
self.shell == Some(String::from("xwayland"))
|
self.shell == Some(String::from("xwayland"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Recursively checks the provided node for any child application nodes.
|
||||||
|
/// Returns a list of any found application nodes.
|
||||||
fn check_node(node: SwayNode, window_nodes: &mut Vec<SwayNode>) {
|
fn check_node(node: SwayNode, window_nodes: &mut Vec<SwayNode>) {
|
||||||
if node.name.is_some() && (node.node_type == "con" || node.node_type == "floating_con") {
|
if node.name.is_some() && (node.node_type == "con" || node.node_type == "floating_con") {
|
||||||
window_nodes.push(node);
|
window_nodes.push(node);
|
||||||
|
@ -37,6 +44,7 @@ fn check_node(node: SwayNode, window_nodes: &mut Vec<SwayNode>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SwayClient {
|
impl SwayClient {
|
||||||
|
/// Gets a flat vector of all currently open windows.
|
||||||
pub fn get_open_windows(&mut self) -> Result<Vec<SwayNode>> {
|
pub fn get_open_windows(&mut self) -> Result<Vec<SwayNode>> {
|
||||||
let root_node = self.ipc(IpcCommand::GetTree)?;
|
let root_node = self.ipc(IpcCommand::GetTree)?;
|
||||||
let root_node = serde_json::from_slice(&root_node)?;
|
let root_node = serde_json::from_slice(&root_node)?;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue