mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-04-19 19:34:24 +02:00
feat: ipc server and cli
This commit is contained in:
parent
93baf8f568
commit
f5bdc5a027
10 changed files with 427 additions and 6 deletions
122
Cargo.lock
generated
122
Cargo.lock
generated
|
@ -52,6 +52,55 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstream"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"anstyle-parse",
|
||||||
|
"anstyle-query",
|
||||||
|
"anstyle-wincon",
|
||||||
|
"colorchoice",
|
||||||
|
"is-terminal",
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee"
|
||||||
|
dependencies = [
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.71"
|
version = "1.0.71"
|
||||||
|
@ -395,6 +444,48 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "4.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "80672091db20273a15cf9fdd4e47ed43b5091ec9841bf4c6145c9dfbbcae09ed"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
"clap_derive",
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1458a1df40e1e2afebb7ab60ce55c1fa8f431146205aa5f4887e0b111c27636"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"clap_lex",
|
||||||
|
"strsim",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_derive"
|
||||||
|
version = "4.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f"
|
||||||
|
dependencies = [
|
||||||
|
"heck 0.4.1",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote 1.0.28",
|
||||||
|
"syn 2.0.18",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "color-eyre"
|
name = "color-eyre"
|
||||||
version = "0.6.2"
|
version = "0.6.2"
|
||||||
|
@ -422,6 +513,12 @@ dependencies = [
|
||||||
"tracing-error",
|
"tracing-error",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorchoice"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "concurrent-queue"
|
name = "concurrent-queue"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
|
@ -515,6 +612,16 @@ dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ctrlc"
|
||||||
|
version = "3.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2a011bbe2c35ce9c1f143b7af6f94f29a167beb4cd1d29e6740ce836f723120e"
|
||||||
|
dependencies = [
|
||||||
|
"nix 0.26.2",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling"
|
name = "darling"
|
||||||
version = "0.14.4"
|
version = "0.14.4"
|
||||||
|
@ -1453,7 +1560,9 @@ dependencies = [
|
||||||
"async_once",
|
"async_once",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
"clap",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
|
"ctrlc",
|
||||||
"dirs",
|
"dirs",
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
@ -1470,6 +1579,7 @@ dependencies = [
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"smithay-client-toolkit",
|
"smithay-client-toolkit",
|
||||||
"stray",
|
"stray",
|
||||||
"strip-ansi-escapes",
|
"strip-ansi-escapes",
|
||||||
|
@ -1489,6 +1599,18 @@ dependencies = [
|
||||||
"zbus",
|
"zbus",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is-terminal"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi 0.3.1",
|
||||||
|
"io-lifetimes",
|
||||||
|
"rustix",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
|
|
17
Cargo.toml
17
Cargo.toml
|
@ -4,9 +4,12 @@ version = "0.12.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "Customisable GTK Layer Shell wlroots/sway bar"
|
description = "Customisable GTK Layer Shell wlroots/sway bar"
|
||||||
|
repository = "https://github.com/jakestanger/ironbar"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = [
|
default = [
|
||||||
|
"cli",
|
||||||
|
"ipc",
|
||||||
"http",
|
"http",
|
||||||
"config+all",
|
"config+all",
|
||||||
"clipboard",
|
"clipboard",
|
||||||
|
@ -17,8 +20,11 @@ default = [
|
||||||
"upower",
|
"upower",
|
||||||
"workspaces+all"
|
"workspaces+all"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
cli = ["dep:clap", "ipc"]
|
||||||
|
ipc = ["dep:serde_json"]
|
||||||
|
|
||||||
http = ["dep:reqwest"]
|
http = ["dep:reqwest"]
|
||||||
upower = ["upower_dbus", "zbus", "futures-lite"]
|
|
||||||
|
|
||||||
"config+all" = ["config+json", "config+yaml", "config+toml", "config+corn", "config+ron"]
|
"config+all" = ["config+json", "config+yaml", "config+toml", "config+corn", "config+ron"]
|
||||||
"config+json" = ["universal-config/json"]
|
"config+json" = ["universal-config/json"]
|
||||||
|
@ -40,6 +46,8 @@ sys_info = ["sysinfo", "regex"]
|
||||||
|
|
||||||
tray = ["stray"]
|
tray = ["stray"]
|
||||||
|
|
||||||
|
upower = ["upower_dbus", "zbus", "futures-lite"]
|
||||||
|
|
||||||
workspaces = ["futures-util"]
|
workspaces = ["futures-util"]
|
||||||
"workspaces+all" = ["workspaces", "workspaces+sway", "workspaces+hyprland"]
|
"workspaces+all" = ["workspaces", "workspaces+sway", "workspaces+hyprland"]
|
||||||
"workspaces+sway" = ["workspaces", "swayipc-async"]
|
"workspaces+sway" = ["workspaces", "swayipc-async"]
|
||||||
|
@ -67,11 +75,18 @@ wayland-protocols = { version = "0.30.0", features = ["unstable", "client"] }
|
||||||
wayland-protocols-wlr = { version = "0.1.0", features = ["client"] }
|
wayland-protocols-wlr = { version = "0.1.0", features = ["client"] }
|
||||||
smithay-client-toolkit = { version = "0.17.0", default-features = false, features = ["calloop"] }
|
smithay-client-toolkit = { version = "0.17.0", default-features = false, features = ["calloop"] }
|
||||||
universal-config = { version = "0.4.0", default_features = false }
|
universal-config = { version = "0.4.0", default_features = false }
|
||||||
|
ctrlc = "3.4.0"
|
||||||
|
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
async_once = "0.2.6"
|
async_once = "0.2.6"
|
||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
|
|
||||||
|
# cli
|
||||||
|
clap = { version = "4.2.7", optional = true, features = ["derive"] }
|
||||||
|
|
||||||
|
# ipc
|
||||||
|
serde_json = { version = "1.0.96", optional = true }
|
||||||
|
|
||||||
# http
|
# http
|
||||||
reqwest = { version = "0.11.18", optional = true }
|
reqwest = { version = "0.11.18", optional = true }
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::send;
|
||||||
use tokio::spawn;
|
use tokio::spawn;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
/// MPSC async -> sync channel.
|
/// MPSC async -> GTK sync channel.
|
||||||
/// The sender uses `tokio::sync::mpsc`
|
/// The sender uses `tokio::sync::mpsc`
|
||||||
/// while the receiver uses `glib::MainContext::channel`.
|
/// while the receiver uses `glib::MainContext::channel`.
|
||||||
///
|
///
|
||||||
|
|
19
src/cli/mod.rs
Normal file
19
src/cli/mod.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
use crate::ipc::commands::Command;
|
||||||
|
use crate::ipc::responses::Response;
|
||||||
|
use clap::Parser;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Parser, Debug, Serialize, Deserialize)]
|
||||||
|
#[command(version)]
|
||||||
|
pub struct Args {
|
||||||
|
#[command(subcommand)]
|
||||||
|
pub command: Option<Command>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_response(response: Response) {
|
||||||
|
match response {
|
||||||
|
Response::Ok => println!("ok"),
|
||||||
|
Response::OkValue { value } => println!("ok\n{value}"),
|
||||||
|
Response::Err { message } => eprintln!("error\n{}", message.unwrap_or_default()),
|
||||||
|
}
|
||||||
|
}
|
28
src/ipc/client.rs
Normal file
28
src/ipc/client.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
use super::Ipc;
|
||||||
|
use crate::ipc::{Command, Response};
|
||||||
|
use color_eyre::Result;
|
||||||
|
use color_eyre::{Help, Report};
|
||||||
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
use tokio::net::UnixStream;
|
||||||
|
|
||||||
|
impl Ipc {
|
||||||
|
/// Sends a command to the IPC server.
|
||||||
|
/// The server response is returned.
|
||||||
|
pub async fn send(&self, command: Command) -> Result<Response> {
|
||||||
|
let mut stream = match UnixStream::connect(&self.path).await {
|
||||||
|
Ok(stream) => Ok(stream),
|
||||||
|
Err(err) => Err(Report::new(err)
|
||||||
|
.wrap_err("Failed to connect to Ironbar IPC server")
|
||||||
|
.suggestion("Is Ironbar running?")),
|
||||||
|
}?;
|
||||||
|
|
||||||
|
let write_buffer = serde_json::to_vec(&command)?;
|
||||||
|
stream.write_all(&write_buffer).await?;
|
||||||
|
|
||||||
|
let mut read_buffer = vec![0; 1024];
|
||||||
|
let bytes = stream.read(&mut read_buffer).await?;
|
||||||
|
|
||||||
|
let response = serde_json::from_slice(&read_buffer[..bytes])?;
|
||||||
|
Ok(response)
|
||||||
|
}
|
||||||
|
}
|
14
src/ipc/commands.rs
Normal file
14
src/ipc/commands.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
use clap::Subcommand;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
#[derive(Subcommand, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
pub enum Command {
|
||||||
|
/// Return "ok"
|
||||||
|
Ping,
|
||||||
|
|
||||||
|
/// Open the GTK inspector
|
||||||
|
Inspect,
|
||||||
|
}
|
||||||
|
|
33
src/ipc/mod.rs
Normal file
33
src/ipc/mod.rs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
mod client;
|
||||||
|
pub mod commands;
|
||||||
|
pub mod responses;
|
||||||
|
mod server;
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use tracing::warn;
|
||||||
|
|
||||||
|
pub use commands::Command;
|
||||||
|
pub use responses::Response;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Ipc {
|
||||||
|
path: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ipc {
|
||||||
|
/// Creates a new IPC instance.
|
||||||
|
/// This can be used as both a server and client.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let ipc_socket_file = std::env::var("XDG_RUNTIME_DIR")
|
||||||
|
.map_or_else(|_| PathBuf::from("/tmp"), PathBuf::from)
|
||||||
|
.join("ironbar-ipc.sock");
|
||||||
|
|
||||||
|
if format!("{}", ipc_socket_file.display()).len() > 100 {
|
||||||
|
warn!("The IPC socket file's absolute path exceeds 100 bytes, the socket may fail to create.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Self {
|
||||||
|
path: ipc_socket_file,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
src/ipc/responses.rs
Normal file
17
src/ipc/responses.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
pub enum Response {
|
||||||
|
Ok,
|
||||||
|
Err { message: Option<String> },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Response {
|
||||||
|
/// Creates a new `Response::Error`.
|
||||||
|
pub fn error(message: &str) -> Self {
|
||||||
|
Self::Err {
|
||||||
|
message: Some(message.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
119
src/ipc/server.rs
Normal file
119
src/ipc/server.rs
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
use super::Ipc;
|
||||||
|
use crate::bridge_channel::BridgeChannel;
|
||||||
|
use crate::ipc::{Command, Response};
|
||||||
|
use crate::ironvar::get_variable_manager;
|
||||||
|
use crate::{read_lock, send_async, try_send, write_lock};
|
||||||
|
use color_eyre::{Report, Result};
|
||||||
|
use glib::Continue;
|
||||||
|
use std::fs;
|
||||||
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
use tokio::net::{UnixListener, UnixStream};
|
||||||
|
use tokio::spawn;
|
||||||
|
use tokio::sync::mpsc;
|
||||||
|
use tokio::sync::mpsc::{Receiver, Sender};
|
||||||
|
use tracing::{debug, error, info, warn};
|
||||||
|
|
||||||
|
impl Ipc {
|
||||||
|
/// Starts the IPC server on its socket.
|
||||||
|
///
|
||||||
|
/// Once started, the server will begin accepting connections.
|
||||||
|
pub fn start(&self) {
|
||||||
|
let bridge = BridgeChannel::<Command>::new();
|
||||||
|
let cmd_tx = bridge.create_sender();
|
||||||
|
let (res_tx, mut res_rx) = mpsc::channel(32);
|
||||||
|
|
||||||
|
let path = self.path.clone();
|
||||||
|
|
||||||
|
if path.exists() {
|
||||||
|
warn!("Socket already exists. Did Ironbar exit abruptly?");
|
||||||
|
warn!("Attempting IPC shutdown to allow binding to address");
|
||||||
|
self.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
spawn(async move {
|
||||||
|
info!("Starting IPC on {}", path.display());
|
||||||
|
|
||||||
|
let listener = match UnixListener::bind(&path) {
|
||||||
|
Ok(listener) => listener,
|
||||||
|
Err(err) => {
|
||||||
|
error!(
|
||||||
|
"{:?}",
|
||||||
|
Report::new(err).wrap_err("Unable to start IPC server")
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match listener.accept().await {
|
||||||
|
Ok((stream, _addr)) => {
|
||||||
|
if let Err(err) =
|
||||||
|
Self::handle_connection(stream, &cmd_tx, &mut res_rx).await
|
||||||
|
{
|
||||||
|
error!("{err:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
error!("{err:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
bridge.recv(move |command| {
|
||||||
|
let res = Self::handle_command(command);
|
||||||
|
try_send!(res_tx, res);
|
||||||
|
Continue(true)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes an incoming connections,
|
||||||
|
/// reads the command message, and sends the response.
|
||||||
|
///
|
||||||
|
/// The connection is closed once the response has been written.
|
||||||
|
async fn handle_connection(
|
||||||
|
mut stream: UnixStream,
|
||||||
|
cmd_tx: &Sender<Command>,
|
||||||
|
res_rx: &mut Receiver<Response>,
|
||||||
|
) -> Result<()> {
|
||||||
|
let (mut stream_read, mut stream_write) = stream.split();
|
||||||
|
|
||||||
|
let mut read_buffer = vec![0; 1024];
|
||||||
|
let bytes = stream_read.read(&mut read_buffer).await?;
|
||||||
|
|
||||||
|
let command = serde_json::from_slice::<Command>(&read_buffer[..bytes])?;
|
||||||
|
|
||||||
|
debug!("Received command: {command:?}");
|
||||||
|
|
||||||
|
send_async!(cmd_tx, command);
|
||||||
|
let res = res_rx
|
||||||
|
.recv()
|
||||||
|
.await
|
||||||
|
.unwrap_or(Response::Err { message: None });
|
||||||
|
let res = serde_json::to_vec(&res)?;
|
||||||
|
|
||||||
|
stream_write.write_all(&res).await?;
|
||||||
|
stream_write.shutdown().await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes an input command, runs it and returns with the appropriate response.
|
||||||
|
///
|
||||||
|
/// This runs on the main thread, allowing commands to interact with GTK.
|
||||||
|
fn handle_command(command: Command) -> Response {
|
||||||
|
match command {
|
||||||
|
Command::Inspect => {
|
||||||
|
gtk::Window::set_interactive_debugging(true);
|
||||||
|
Response::Ok
|
||||||
|
}
|
||||||
|
Command::Ping => Response::Ok,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shuts down the IPC server,
|
||||||
|
/// removing the socket file in the process.
|
||||||
|
pub fn shutdown(&self) {
|
||||||
|
fs::remove_file(&self.path).ok();
|
||||||
|
}
|
||||||
|
}
|
62
src/main.rs
62
src/main.rs
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
mod bar;
|
mod bar;
|
||||||
mod bridge_channel;
|
mod bridge_channel;
|
||||||
|
#[cfg(feature = "cli")]
|
||||||
|
mod cli;
|
||||||
mod clients;
|
mod clients;
|
||||||
mod config;
|
mod config;
|
||||||
mod desktop_file;
|
mod desktop_file;
|
||||||
|
@ -9,6 +11,8 @@ mod dynamic_string;
|
||||||
mod error;
|
mod error;
|
||||||
mod gtk_helpers;
|
mod gtk_helpers;
|
||||||
mod image;
|
mod image;
|
||||||
|
#[cfg(feature = "ipc")]
|
||||||
|
mod ipc;
|
||||||
mod logging;
|
mod logging;
|
||||||
mod macros;
|
mod macros;
|
||||||
mod modules;
|
mod modules;
|
||||||
|
@ -20,6 +24,9 @@ mod unique_id;
|
||||||
use crate::bar::create_bar;
|
use crate::bar::create_bar;
|
||||||
use crate::config::{Config, MonitorConfig};
|
use crate::config::{Config, MonitorConfig};
|
||||||
use crate::style::load_css;
|
use crate::style::load_css;
|
||||||
|
use cfg_if::cfg_if;
|
||||||
|
#[cfg(feature = "cli")]
|
||||||
|
use clap::Parser;
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use color_eyre::Report;
|
use color_eyre::Report;
|
||||||
use dirs::config_dir;
|
use dirs::config_dir;
|
||||||
|
@ -32,8 +39,9 @@ use std::future::Future;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::mpsc;
|
||||||
use tokio::runtime::Handle;
|
use tokio::runtime::Handle;
|
||||||
use tokio::task::block_in_place;
|
use tokio::task::{block_in_place, spawn_blocking};
|
||||||
|
|
||||||
use crate::error::ExitCode;
|
use crate::error::ExitCode;
|
||||||
use clients::wayland::{self, WaylandClient};
|
use clients::wayland::{self, WaylandClient};
|
||||||
|
@ -47,6 +55,32 @@ const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let _guard = logging::install_logging();
|
let _guard = logging::install_logging();
|
||||||
|
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(feature = "cli")] {
|
||||||
|
run_with_args().await
|
||||||
|
} else {
|
||||||
|
start_ironbar().await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "cli")]
|
||||||
|
async fn run_with_args() {
|
||||||
|
let args = cli::Args::parse();
|
||||||
|
|
||||||
|
match args.command {
|
||||||
|
Some(command) => {
|
||||||
|
let ipc = ipc::Ipc::new();
|
||||||
|
match ipc.send(command).await {
|
||||||
|
Ok(res) => cli::handle_response(res),
|
||||||
|
Err(err) => error!("{err:?}"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
None => start_ironbar().await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn start_ironbar() {
|
||||||
info!("Ironbar version {}", VERSION);
|
info!("Ironbar version {}", VERSION);
|
||||||
info!("Starting application");
|
info!("Starting application");
|
||||||
|
|
||||||
|
@ -64,6 +98,13 @@ async fn main() {
|
||||||
|
|
||||||
running.set(true);
|
running.set(true);
|
||||||
|
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(feature = "ipc")] {
|
||||||
|
let ipc = ipc::Ipc::new();
|
||||||
|
ipc.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let display = Display::default().map_or_else(
|
let display = Display::default().map_or_else(
|
||||||
|| {
|
|| {
|
||||||
let report = Report::msg("Failed to get default GTK display");
|
let report = Report::msg("Failed to get default GTK display");
|
||||||
|
@ -112,14 +153,27 @@ async fn main() {
|
||||||
if style_path.exists() {
|
if style_path.exists() {
|
||||||
load_css(style_path);
|
load_css(style_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let (tx, rx) = mpsc::channel();
|
||||||
|
|
||||||
|
spawn_blocking(move || {
|
||||||
|
rx.recv().expect("to receive from channel");
|
||||||
|
|
||||||
|
info!("Shutting down");
|
||||||
|
|
||||||
|
#[cfg(feature = "ipc")]
|
||||||
|
ipc.shutdown();
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
ctrlc::set_handler(move || tx.send(()).expect("Could not send signal on channel."))
|
||||||
|
.expect("Error setting Ctrl-C handler");
|
||||||
});
|
});
|
||||||
|
|
||||||
// Ignore CLI args
|
// Ignore CLI args
|
||||||
// Some are provided by swaybar_config but not currently supported
|
// Some are provided by swaybar_config but not currently supported
|
||||||
app.run_with_args(&Vec::<&str>::new());
|
app.run_with_args(&Vec::<&str>::new());
|
||||||
|
|
||||||
info!("Shutting down");
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates each of the bars across each of the (configured) outputs.
|
/// Creates each of the bars across each of the (configured) outputs.
|
||||||
|
|
Loading…
Add table
Reference in a new issue