Skip to content
This repository was archived by the owner on Oct 31, 2025. It is now read-only.

Commit d50c5eb

Browse files
committed
swww-query: support json printing
1 parent 1333015 commit d50c5eb

File tree

6 files changed

+82
-19
lines changed

6 files changed

+82
-19
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ image = { version = "0.25", default-features = false, features = [
2929
"tiff",
3030
"webp",
3131
] }
32+
json = { version = "0.12", default-features = false }
3233
resvg = { version = "0.45" }
3334
rustix = { version = "1.1", default-features = false, features = [ "fs" ] }
3435
fast_image_resize = "5.3"

client/src/cli.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,10 @@ pub struct Query {
265265
#[arg(short, long, default_value = "false")]
266266
pub all: bool,
267267

268+
/// Print the information in `json` format
269+
#[arg(short, long, default_value = "false")]
270+
pub json: bool,
271+
268272
/// The daemon's namespace.
269273
///
270274
/// The resulting namespace will be 'swww-daemon' appended to what you pass in this argument.

client/src/main.rs

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ use std::{str::FromStr, time::Duration};
22

33
use clap::Parser;
44
use common::cache;
5-
use common::ipc::{self, Answer, Client, IpcSocket, RequestSend};
5+
use common::ipc::{self, Answer, BgInfo, Client, IpcSocket, RequestSend};
66
use common::mmap::Mmap;
77

88
mod imgproc;
99
use imgproc::*;
1010

1111
mod cli;
1212
use cli::{CliImage, Filter, ResizeStrategy, Swww};
13+
use json::stringify_pretty;
1314

1415
fn main() -> Result<(), String> {
1516
let swww = Swww::parse();
@@ -42,8 +43,9 @@ fn main() -> Result<(), String> {
4243
}
4344
};
4445

45-
for namespace in namespaces {
46-
let socket = IpcSocket::connect(&namespace).map_err(|err| err.to_string())?;
46+
let mut infos = Vec::new();
47+
for namespace in &namespaces {
48+
let socket = IpcSocket::connect(namespace).map_err(|err| err.to_string())?;
4749
loop {
4850
RequestSend::Ping.send(&socket)?;
4951
let bytes = socket.recv().map_err(|err| err.to_string())?;
@@ -58,22 +60,66 @@ fn main() -> Result<(), String> {
5860
std::thread::sleep(Duration::from_millis(1));
5961
}
6062

61-
process_swww_args(&swww, &namespace)?;
63+
if let Some(info) = process_swww_args(&swww, namespace)? {
64+
infos.push(info);
65+
}
66+
}
67+
68+
if !infos.is_empty() {
69+
if let Swww::Query(query) = swww
70+
&& query.json
71+
{
72+
use json::object;
73+
let mut buf = String::new();
74+
for (namespace, infos) in namespaces.iter().zip(infos) {
75+
let mut arr = json::JsonValue::new_array();
76+
for info in infos {
77+
let displaying = match info.img {
78+
ipc::BgImg::Color(color) => {
79+
object! { color: format!("#{:x}", u32::from_ne_bytes(color)) }
80+
}
81+
ipc::BgImg::Img(img) => {
82+
object! { image: img.as_ref() }
83+
}
84+
};
85+
_ = arr.push(object! {
86+
name: info.name.as_ref(),
87+
width: info.dim.0,
88+
height: info.dim.1,
89+
scale: info.scale_factor.to_f32(),
90+
displaying: displaying
91+
});
92+
}
93+
buf = format!("{buf}\n\"{namespace}\": {},", stringify_pretty(arr, 4));
94+
}
95+
buf.pop(); // delete trailing comma
96+
println!("{{{buf}\n}}");
97+
} else {
98+
for (namespace, infos) in namespaces.iter().zip(infos) {
99+
for info in infos {
100+
println!("{namespace}: {info}");
101+
}
102+
}
103+
}
62104
}
63105
Ok(())
64106
}
65107

66-
fn process_swww_args(args: &Swww, namespace: &str) -> Result<(), String> {
108+
fn process_swww_args(args: &Swww, namespace: &str) -> Result<Option<Box<[BgInfo]>>, String> {
67109
let request = match make_request(args, namespace)? {
68110
Some(request) => request,
69-
None => return Ok(()),
111+
None => return Ok(None),
70112
};
71113
let socket = IpcSocket::connect(namespace).map_err(|err| err.to_string())?;
72114
request.send(&socket)?;
73115
let bytes = socket.recv().map_err(|err| err.to_string())?;
74116
drop(socket);
75117
match Answer::receive(bytes) {
76-
Answer::Info(info) => info.iter().for_each(|i| println!("{namespace}: {i}")),
118+
Answer::Info(infos) => {
119+
if let Swww::Query(_) = args {
120+
return Ok(Some(infos));
121+
}
122+
}
77123
Answer::Ok => {
78124
if let Swww::Kill(_) = args {
79125
#[cfg(debug_assertions)]
@@ -83,7 +129,7 @@ fn process_swww_args(args: &Swww, namespace: &str) -> Result<(), String> {
83129
let path = IpcSocket::<Client>::path(namespace);
84130
for _ in 0..tries {
85131
if rustix::fs::access(&path, rustix::fs::Access::EXISTS).is_err() {
86-
return Ok(());
132+
return Ok(None);
87133
}
88134
std::thread::sleep(Duration::from_millis(100));
89135
}
@@ -94,10 +140,10 @@ fn process_swww_args(args: &Swww, namespace: &str) -> Result<(), String> {
94140
}
95141
}
96142
Answer::Ping(_) => {
97-
return Ok(());
143+
return Ok(None);
98144
}
99145
}
100-
Ok(())
146+
Ok(None)
101147
}
102148

103149
fn make_request(args: &Swww, namespace: &str) -> Result<Option<RequestSend>, String> {
@@ -405,5 +451,6 @@ fn restore_output(output: &str, namespace: &str) -> Result<(), String> {
405451
transition_wave: (0.0, 0.0),
406452
}),
407453
namespace,
408-
)
454+
)?;
455+
Ok(())
409456
}

common/src/ipc/types.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,14 @@ impl Scale {
177177
}
178178
}
179179
}
180+
181+
#[must_use]
182+
pub fn to_f32(&self) -> f32 {
183+
match self {
184+
Scale::Output(i) | Scale::Preferred(i) => i.get() as f32,
185+
Scale::Fractional(f) => f.get() as f32 / 120.0,
186+
}
187+
}
180188
}
181189

182190
impl PartialEq for Scale {
@@ -193,14 +201,7 @@ impl PartialEq for Scale {
193201

194202
impl fmt::Display for Scale {
195203
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
196-
write!(
197-
f,
198-
"{}",
199-
match self {
200-
Scale::Output(i) | Scale::Preferred(i) => i.get() as f32,
201-
Scale::Fractional(f) => f.get() as f32 / 120.0,
202-
}
203-
)
204+
write!(f, "{}", self.to_f32())
204205
}
205206
}
206207

doc/swww-query.1.scd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ swww-query
1111
*-a*,*--all*
1212
Send this command to all active *swww-daemon* namespaces.
1313

14+
*-j*,*--j*
15+
Print the information in *json* format.
16+
1417
*-n*,*--namespace* <namespace>
1518
Which wayland namespace to send this command to.
1619

0 commit comments

Comments
 (0)