feat: add set as wallpaper functionality
Add ability to set current image as desktop wallpaper with keyboard shortcut 'W' and icon button in Properties panel. Supports COSMIC, GNOME, KDE, XFCE, and tiling window managers via automatic detection and fallback mechanism. Implementation uses wallpaper crate with custom COSMIC config file integration and gsettings/feh fallbacks.
This commit is contained in:
parent
ca7661fa3e
commit
220a886acc
12 changed files with 399 additions and 24 deletions
|
|
@ -110,3 +110,35 @@ impl DocumentContent {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Set an image file as desktop wallpaper.
|
||||
///
|
||||
/// This function attempts multiple methods in order:
|
||||
/// 1. COSMIC Desktop (direct config file modification)
|
||||
/// 2. wallpaper crate (KDE, XFCE, Windows, macOS)
|
||||
/// 3. gsettings (GNOME)
|
||||
/// 4. feh (tiling window managers)
|
||||
///
|
||||
/// The operation is performed asynchronously and logs success/failure.
|
||||
pub fn set_as_wallpaper(path: &Path) {
|
||||
// Canonicalize to absolute path
|
||||
let abs_path = match path.canonicalize() {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
log::error!("Failed to canonicalize path {}: {}", path.display(), e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Convert to string
|
||||
let path_str = match abs_path.to_str() {
|
||||
Some(s) => s.to_string(),
|
||||
None => {
|
||||
log::error!("Invalid UTF-8 in path: {}", abs_path.display());
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Delegate to utils with concrete string type
|
||||
utils::set_as_wallpaper(&path_str);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,109 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// src/app/document/utils.rs
|
||||
//
|
||||
// Utility functions for document operations.
|
||||
|
||||
/// Set an image as desktop wallpaper using multiple fallback methods.
|
||||
///
|
||||
/// Expects an absolute path as string.
|
||||
pub fn set_as_wallpaper(path_str: &str) {
|
||||
log::info!("Attempting to set wallpaper: {}", path_str);
|
||||
|
||||
// Method 1: Try COSMIC Desktop (direct config file modification)
|
||||
if let Some(home) = dirs::home_dir() {
|
||||
let cosmic_config = home.join(".config/cosmic/com.system76.CosmicBackground/v1/all");
|
||||
|
||||
if cosmic_config.exists() {
|
||||
let config_content = format!(
|
||||
r#"(
|
||||
output: "all",
|
||||
source: Path("{}"),
|
||||
filter_by_theme: true,
|
||||
rotation_frequency: 300,
|
||||
filter_method: Lanczos,
|
||||
scaling_mode: Zoom,
|
||||
sampling_method: Alphanumeric,
|
||||
)"#,
|
||||
path_str
|
||||
);
|
||||
|
||||
match std::fs::write(&cosmic_config, config_content) {
|
||||
Ok(_) => {
|
||||
log::info!("✓ Wallpaper set via COSMIC config file");
|
||||
return;
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("Failed to write COSMIC config: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method 2: Try wallpaper crate (supports KDE, XFCE, Windows, macOS)
|
||||
match wallpaper::set_from_path(path_str) {
|
||||
Ok(_) => {
|
||||
log::info!("✓ Wallpaper set successfully via wallpaper crate");
|
||||
return;
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("wallpaper crate failed: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Method 3: Try GNOME via gsettings
|
||||
let uri = format!("file://{}", path_str);
|
||||
log::info!("Trying gsettings with URI: {}", uri);
|
||||
|
||||
match std::process::Command::new("gsettings")
|
||||
.args(&[
|
||||
"set",
|
||||
"org.gnome.desktop.background",
|
||||
"picture-uri",
|
||||
&uri,
|
||||
])
|
||||
.output()
|
||||
{
|
||||
Ok(output) if output.status.success() => {
|
||||
log::info!("✓ Wallpaper set via gsettings (light mode)");
|
||||
|
||||
// Also set dark mode wallpaper
|
||||
let _ = std::process::Command::new("gsettings")
|
||||
.args(&[
|
||||
"set",
|
||||
"org.gnome.desktop.background",
|
||||
"picture-uri-dark",
|
||||
&uri,
|
||||
])
|
||||
.output();
|
||||
return;
|
||||
}
|
||||
Ok(output) => {
|
||||
log::warn!(
|
||||
"gsettings failed: {}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("gsettings command failed: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Method 4: Try feh (common on tiling WMs like i3, sway)
|
||||
match std::process::Command::new("feh")
|
||||
.args(&["--bg-scale", path_str])
|
||||
.output()
|
||||
{
|
||||
Ok(output) if output.status.success() => {
|
||||
log::info!("✓ Wallpaper set via feh");
|
||||
return;
|
||||
}
|
||||
Ok(_) => {
|
||||
log::warn!("feh failed");
|
||||
}
|
||||
Err(_) => {
|
||||
log::warn!("feh not available");
|
||||
}
|
||||
}
|
||||
|
||||
log::error!("✗ All methods failed to set wallpaper");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue