Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions lmtt/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,14 @@ enum WallpaperCommand {
#[arg(long)]
no_publish: bool,
},
/// Remove the current user's per-output wallpaper override
Unset {
#[arg(long)]
output: String,
/// Do not refresh the greeter-readable snapshot
#[arg(long)]
no_publish: bool,
},
/// Resolve the effective wallpaper for an output
Resolve {
#[arg(long, default_value = "default")]
Expand Down Expand Up @@ -248,6 +256,21 @@ fn cmd_wallpaper(command: WallpaperCommand) -> Result<()> {
publish_current(&profile)?;
}
}
WallpaperCommand::Unset { output, no_publish } => {
let profile_path = appearance_profiles::user_profile_path()
.ok_or_else(|| anyhow::anyhow!("cannot determine the user config directory"))?;
let mut profile = Profile::load(&profile_path)?.unwrap_or_default();
if profile.output.remove(&output).is_none() {
// Idempotent: nothing to write or republish.
println!("No wallpaper override for {output}");
} else {
write_profile(&profile_path, &profile)?;
println!("Removed the wallpaper override for {output}");
if !no_publish {
publish_current(&profile)?;
}
}
}
WallpaperCommand::Resolve {
output,
description,
Expand Down
108 changes: 108 additions & 0 deletions lmtt/tests/wallpaper_unset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
//! `lmtt wallpaper unset` against a throwaway XDG tree, publish skipped.
use std::path::{Path, PathBuf};
use std::process::{Command, Output};

fn sandbox() -> PathBuf {
let dir = std::env::temp_dir().join(format!("lmtt-unset-{}", std::process::id()));
std::fs::remove_dir_all(&dir).ok();
std::fs::create_dir_all(dir.join("config")).unwrap();
std::fs::create_dir_all(dir.join("cache")).unwrap();
dir
}

fn lmtt(sandbox: &Path, args: &[&str]) -> Output {
Command::new(env!("CARGO_BIN_EXE_lmtt"))
.args(args)
.env("HOME", sandbox)
.env("XDG_CONFIG_HOME", sandbox.join("config"))
.env("XDG_CACHE_HOME", sandbox.join("cache"))
.env("XDG_DATA_HOME", sandbox.join("data"))
.env_remove("WAYLAND_DISPLAY")
.output()
.expect("run lmtt")
}

fn ok(out: &Output) -> String {
assert!(
out.status.success(),
"lmtt failed ({}): {}",
out.status,
String::from_utf8_lossy(&out.stderr)
);
String::from_utf8_lossy(&out.stdout).into_owned()
}

#[test]
fn unset_removes_only_that_override_and_is_idempotent() {
let sb = sandbox();
let image = sb.join("wall.png");
std::fs::write(&image, b"set only canonicalizes; publish is skipped").unwrap();
let image = image.to_str().unwrap();
let profile = sb.join("config/appearance-profiles/default.toml");

ok(&lmtt(&sb, &["wallpaper", "set", image, "--no-publish"]));
ok(&lmtt(
&sb,
&[
"wallpaper",
"set",
image,
"--output",
"desc:Test Monitor",
"--no-publish",
],
));
ok(&lmtt(
&sb,
&[
"wallpaper",
"set",
image,
"--output",
"DP-9",
"--no-publish",
],
));
let text = std::fs::read_to_string(&profile).unwrap();
assert!(text.contains("desc:Test Monitor"), "{text}");
assert!(text.contains("DP-9"), "{text}");

let out = ok(&lmtt(
&sb,
&[
"wallpaper",
"unset",
"--output",
"desc:Test Monitor",
"--no-publish",
],
));
assert!(out.contains("Removed"), "{out}");
let text = std::fs::read_to_string(&profile).unwrap();
assert!(!text.contains("desc:Test Monitor"), "{text}");
assert!(text.contains("DP-9"), "other overrides survive: {text}");
assert!(
text.contains("[background]"),
"the global rule survives: {text}"
);

// Idempotent: exit 0, nothing rewritten.
let before = std::fs::metadata(&profile).unwrap().modified().unwrap();
let out = ok(&lmtt(
&sb,
&[
"wallpaper",
"unset",
"--output",
"desc:Test Monitor",
"--no-publish",
],
));
assert!(out.contains("No wallpaper override"), "{out}");
assert_eq!(
std::fs::metadata(&profile).unwrap().modified().unwrap(),
before
);

std::fs::remove_dir_all(&sb).ok();
}
Loading