From 30a95a8d96d7427f4b37d8d36f68785ad4788733 Mon Sep 17 00:00:00 2001 From: nyx Date: Fri, 18 Oct 2024 00:04:58 -0400 Subject: [PATCH 01/11] cleanup memory after user switches backends --- src/main.rs | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 56a02a2..5ef630b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,7 @@ lazy_static! { static INIT: Once = Once::new(); +#[derive(Clone, Copy)] pub enum WallpaperBackend { Hyprpaper, Swaybg, @@ -236,5 +237,48 @@ fn start_process(command: &str) -> Result<(), String> { } pub fn set_wallpaper_backend(backend: WallpaperBackend) { - *CURRENT_BACKEND.lock() = backend; + let previous_backend = { + let mut current = CURRENT_BACKEND.lock(); + let prev = *current; + *current = backend; + prev + }; + drop_all_wallpapers(previous_backend); + kill_previous_backend(previous_backend); +} + +fn kill_previous_backend(backend: WallpaperBackend) { + let process_name = match backend { + WallpaperBackend::Hyprpaper => "hyprpaper", + WallpaperBackend::Swaybg => "swaybg", + WallpaperBackend::Swww => "swww", + WallpaperBackend::Wallutils => return, + WallpaperBackend::Feh => return, + }; + + let _ = Command::new("killall") + .arg(process_name) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status(); +} + +fn drop_all_wallpapers(backend: WallpaperBackend) { + match backend { + WallpaperBackend::Hyprpaper => { + let _ = Command::new("hyprctl") + .args(&["hyprpaper", "unload", "all"]) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status(); + } + WallpaperBackend::Swww => { + let _ = Command::new("swww") + .args(&["clear"]) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status(); + } + _ => {} + } } From 73d1f41c6b9a862c9687801b63c5fe7d06d3fc15 Mon Sep 17 00:00:00 2001 From: nyx Date: Fri, 18 Oct 2024 00:28:37 -0400 Subject: [PATCH 02/11] use tokio for true async --- Cargo.lock | 127 +++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/gui.rs | 3 +- src/main.rs | 147 ++++++++++++++++++++++++++-------------------------- 4 files changed, 204 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7c5bc1d..3c878cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,12 +2,42 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + [[package]] name = "bitflags" version = "2.6.0" @@ -20,6 +50,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" + [[package]] name = "cairo-rs" version = "0.18.5" @@ -360,6 +396,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + [[package]] name = "gio" version = "0.18.4" @@ -680,6 +722,7 @@ dependencies = [ "rand", "rayon", "shellexpand", + "tokio", ] [[package]] @@ -739,6 +782,27 @@ dependencies = [ "autocfg", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", +] + [[package]] name = "num_cpus" version = "1.16.0" @@ -749,6 +813,15 @@ dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.20.2" @@ -990,6 +1063,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + [[package]] name = "rustc_version" version = "0.4.1" @@ -1049,6 +1128,15 @@ dependencies = [ "dirs", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + [[package]] name = "slab" version = "0.4.9" @@ -1064,6 +1152,16 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "syn" version = "1.0.109" @@ -1137,6 +1235,35 @@ dependencies = [ "syn 2.0.79", ] +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "toml" version = "0.8.19" diff --git a/Cargo.toml b/Cargo.toml index 53fba79..9f188d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ rayon = "1.7" num_cpus = "1.15" rand = "0.8" crossbeam-channel = "0.5" +tokio = { version = "1.28", features = ["full"] } [profile.release] lto = "fat" diff --git a/src/gui.rs b/src/gui.rs index 22ea3d2..cba3475 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -342,8 +342,9 @@ fn load_images( .unwrap_or("Unknown"); button.set_tooltip_text(Some(file_name)); + let path_clone2 = path_clone.clone(); button.connect_clicked(move |_| { - crate::set_wallpaper(path_clone.clone()); + crate::set_wallpaper(path_clone2.clone()); }); flowbox.insert(&button, -1); diff --git a/src/main.rs b/src/main.rs index 5ef630b..26a1981 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,9 @@ mod gui; use gtk::{prelude::*, Application}; use lazy_static::lazy_static; use parking_lot::Mutex; -use std::{process::Command, process::Stdio, sync::Once}; +use std::sync::Once; +use tokio::process::Command as TokioCommand; +use tokio::runtime::Runtime; lazy_static! { static ref MONITORS: Mutex> = Mutex::new(Vec::new()); @@ -22,6 +24,9 @@ pub enum WallpaperBackend { } fn main() { + let rt = Runtime::new().expect("Failed to create Tokio runtime"); + let _guard = rt.enter(); + let app = Application::builder() .application_id("nnyyxxxx.hyprwall") .build(); @@ -35,7 +40,7 @@ pub fn set_wallpaper(path: String) { match set_wallpaper_internal(&path).await { Ok(_) => println!("Wallpaper set successfully"), Err(e) => { - gui::custom_error_popup("Error setting wallpaper", e.as_str(), true); + gui::custom_error_popup("Error setting wallpaper", &e, true); eprintln!("Error setting wallpaper: {}", e); } } @@ -43,35 +48,39 @@ pub fn set_wallpaper(path: String) { } async fn set_wallpaper_internal(path: &str) -> Result<(), String> { - ensure_backend_running()?; + ensure_backend_running().await?; println!("Attempting to set wallpaper: {}", path); - INIT.call_once(|| match get_monitors() { - Ok(monitors) => *MONITORS.lock() = monitors, - Err(e) => eprintln!("Failed to get monitors: {}", e), + INIT.call_once(|| { + tokio::spawn(async { + match get_monitors().await { + Ok(monitors) => *MONITORS.lock() = monitors, + Err(e) => eprintln!("Failed to get monitors: {}", e), + } + }); }); println!("Found monitors: {:?}", *MONITORS.lock()); match *CURRENT_BACKEND.lock() { - WallpaperBackend::Hyprpaper => set_hyprpaper_wallpaper(path), - WallpaperBackend::Swaybg => set_swaybg_wallpaper(path), - WallpaperBackend::Swww => set_swww_wallpaper(path), - WallpaperBackend::Wallutils => set_wallutils_wallpaper(path), - WallpaperBackend::Feh => set_feh_wallpaper(path), + WallpaperBackend::Hyprpaper => set_hyprpaper_wallpaper(path).await, + WallpaperBackend::Swaybg => set_swaybg_wallpaper(path).await, + WallpaperBackend::Swww => set_swww_wallpaper(path).await, + WallpaperBackend::Wallutils => set_wallutils_wallpaper(path).await, + WallpaperBackend::Feh => set_feh_wallpaper(path).await, } } -fn set_hyprpaper_wallpaper(path: &str) -> Result<(), String> { +async fn set_hyprpaper_wallpaper(path: &str) -> Result<(), String> { let preload_command = format!("hyprctl hyprpaper preload \"{}\"", path); - if !execute_command(&preload_command) { + if !execute_command(&preload_command).await { return Err("Failed to preload wallpaper".to_string()); } for monitor in MONITORS.lock().iter() { let set_command = format!("hyprctl hyprpaper wallpaper \"{},{}\"", monitor, path); - if !execute_command(&set_command) { + if !execute_command(&set_command).await { return Err(format!("Failed to set wallpaper for {}", monitor)); } } @@ -79,56 +88,53 @@ fn set_hyprpaper_wallpaper(path: &str) -> Result<(), String> { Ok(()) } -fn set_swaybg_wallpaper(path: &str) -> Result<(), String> { - Command::new("swaybg") +async fn set_swaybg_wallpaper(path: &str) -> Result<(), String> { + let output = TokioCommand::new("swaybg") .arg("-i") .arg(path) .arg("-m") .arg("fill") - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .spawn() + .output() + .await .map_err(|e| format!("Failed to start swaybg: {}", e))?; - std::thread::sleep(std::time::Duration::from_millis(500)); - if is_process_running("swaybg") { + if output.status.success() { Ok(()) } else { - Err("swaybg failed to start or crashed immediately".to_string()) + Err("swaybg failed to set wallpaper".to_string()) } } -fn set_swww_wallpaper(path: &str) -> Result<(), String> { +async fn set_swww_wallpaper(path: &str) -> Result<(), String> { let set_command = format!("swww img \"{}\"", path); - if !execute_command(&set_command) { + if !execute_command(&set_command).await { return Err("Failed to set wallpaper with swww".to_string()); } Ok(()) } -fn set_wallutils_wallpaper(path: &str) -> Result<(), String> { +async fn set_wallutils_wallpaper(path: &str) -> Result<(), String> { let set_command = format!("setwallpaper \"{}\"", path); - if !execute_command(&set_command) { + if !execute_command(&set_command).await { return Err("Failed to set wallpaper with wallutils".to_string()); } Ok(()) } -fn set_feh_wallpaper(path: &str) -> Result<(), String> { +async fn set_feh_wallpaper(path: &str) -> Result<(), String> { let set_command = format!("feh --bg-fill \"{}\"", path); - if !execute_command(&set_command) { + if !execute_command(&set_command).await { return Err("Failed to set wallpaper with feh".to_string()); } Ok(()) } -fn execute_command(command: &str) -> bool { - match Command::new("sh") +async fn execute_command(command: &str) -> bool { + match TokioCommand::new("sh") .arg("-c") .arg(command) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) .output() + .await { Ok(output) => { if output.status.success() { @@ -150,11 +156,12 @@ fn execute_command(command: &str) -> bool { } } -fn get_monitors() -> Result, String> { +async fn get_monitors() -> Result, String> { println!("Retrieving monitor information"); - let output = Command::new("hyprctl") + let output = TokioCommand::new("hyprctl") .arg("monitors") .output() + .await .map_err(|e| format!("Failed to execute hyprctl monitors: {}", e))?; let monitors: Vec = String::from_utf8_lossy(&output.stdout) @@ -174,62 +181,60 @@ fn get_monitors() -> Result, String> { Ok(monitors) } -fn ensure_backend_running() -> Result<(), String> { +async fn ensure_backend_running() -> Result<(), String> { match *CURRENT_BACKEND.lock() { - WallpaperBackend::Hyprpaper => ensure_hyprpaper_running(), - WallpaperBackend::Swaybg => ensure_swaybg_running(), - WallpaperBackend::Swww => ensure_swww_running(), + WallpaperBackend::Hyprpaper => ensure_hyprpaper_running().await, + WallpaperBackend::Swaybg => ensure_swaybg_running().await, + WallpaperBackend::Swww => ensure_swww_running().await, WallpaperBackend::Wallutils => Ok(()), WallpaperBackend::Feh => Ok(()), } } -fn ensure_hyprpaper_running() -> Result<(), String> { - if !is_process_running("hyprpaper") { +async fn ensure_hyprpaper_running() -> Result<(), String> { + if !is_process_running("hyprpaper").await { println!("hyprpaper is not running. Attempting to start it..."); - start_process("hyprpaper")?; + start_process("hyprpaper").await?; } Ok(()) } -fn ensure_swaybg_running() -> Result<(), String> { - if !is_process_running("swaybg") { +async fn ensure_swaybg_running() -> Result<(), String> { + if !is_process_running("swaybg").await { println!("swaybg is not running. Attempting to start it..."); - start_process("swaybg")?; + start_process("swaybg").await?; } Ok(()) } -fn ensure_swww_running() -> Result<(), String> { - if !is_process_running("swww") { +async fn ensure_swww_running() -> Result<(), String> { + if !is_process_running("swww").await { println!("swww is not running. Attempting to start it..."); - start_process("swww init")?; + start_process("swww init").await?; } Ok(()) } -fn is_process_running(process_name: &str) -> bool { - Command::new("pgrep") +async fn is_process_running(process_name: &str) -> bool { + TokioCommand::new("pgrep") .arg("-x") .arg(process_name) - .stdout(Stdio::null()) .status() + .await .map(|status| status.success()) .unwrap_or(false) } -fn start_process(command: &str) -> Result<(), String> { - Command::new("sh") +async fn start_process(command: &str) -> Result<(), String> { + TokioCommand::new("sh") .arg("-c") .arg(command) - .stdout(Stdio::null()) - .stderr(Stdio::null()) .spawn() .map_err(|e| format!("Failed to start {}: {}", command, e))?; - std::thread::sleep(std::time::Duration::from_secs(1)); + tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; - if is_process_running(command.split_whitespace().next().unwrap_or(command)) { + if is_process_running(command.split_whitespace().next().unwrap_or(command)).await { Ok(()) } else { Err(format!("Failed to start {}", command)) @@ -243,11 +248,13 @@ pub fn set_wallpaper_backend(backend: WallpaperBackend) { *current = backend; prev }; - drop_all_wallpapers(previous_backend); - kill_previous_backend(previous_backend); + tokio::spawn(async move { + drop_all_wallpapers(previous_backend).await; + kill_previous_backend(previous_backend).await; + }); } -fn kill_previous_backend(backend: WallpaperBackend) { +async fn kill_previous_backend(backend: WallpaperBackend) { let process_name = match backend { WallpaperBackend::Hyprpaper => "hyprpaper", WallpaperBackend::Swaybg => "swaybg", @@ -256,28 +263,22 @@ fn kill_previous_backend(backend: WallpaperBackend) { WallpaperBackend::Feh => return, }; - let _ = Command::new("killall") + let _ = TokioCommand::new("killall") .arg(process_name) - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .status(); + .status() + .await; } -fn drop_all_wallpapers(backend: WallpaperBackend) { +async fn drop_all_wallpapers(backend: WallpaperBackend) { match backend { WallpaperBackend::Hyprpaper => { - let _ = Command::new("hyprctl") + let _ = TokioCommand::new("hyprctl") .args(&["hyprpaper", "unload", "all"]) - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .status(); + .status() + .await; } WallpaperBackend::Swww => { - let _ = Command::new("swww") - .args(&["clear"]) - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .status(); + let _ = TokioCommand::new("swww").args(&["clear"]).status().await; } _ => {} } From c40805bb44fb562e27310f6c7579b1d78b0338ba Mon Sep 17 00:00:00 2001 From: nyx Date: Fri, 18 Oct 2024 00:31:18 -0400 Subject: [PATCH 03/11] avoid deprecation --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 26a1981..ff2fd6b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -210,7 +210,7 @@ async fn ensure_swaybg_running() -> Result<(), String> { async fn ensure_swww_running() -> Result<(), String> { if !is_process_running("swww").await { println!("swww is not running. Attempting to start it..."); - start_process("swww init").await?; + start_process("swww-daemon").await?; } Ok(()) } From 3993b9f297720ed1eadc03a5e55d72a281613b85 Mon Sep 17 00:00:00 2001 From: nyx Date: Fri, 18 Oct 2024 00:40:21 -0400 Subject: [PATCH 04/11] fix freezing issues --- src/main.rs | 77 +++++++++++++---------------------------------------- 1 file changed, 19 insertions(+), 58 deletions(-) diff --git a/src/main.rs b/src/main.rs index ff2fd6b..cfaecf6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ mod gui; use gtk::{prelude::*, Application}; use lazy_static::lazy_static; use parking_lot::Mutex; +use std::process::Stdio; use std::sync::Once; use tokio::process::Command as TokioCommand; use tokio::runtime::Runtime; @@ -74,86 +75,46 @@ async fn set_wallpaper_internal(path: &str) -> Result<(), String> { async fn set_hyprpaper_wallpaper(path: &str) -> Result<(), String> { let preload_command = format!("hyprctl hyprpaper preload \"{}\"", path); - if !execute_command(&preload_command).await { - return Err("Failed to preload wallpaper".to_string()); - } + spawn_background_process(&preload_command).await?; for monitor in MONITORS.lock().iter() { let set_command = format!("hyprctl hyprpaper wallpaper \"{},{}\"", monitor, path); - if !execute_command(&set_command).await { - return Err(format!("Failed to set wallpaper for {}", monitor)); - } + spawn_background_process(&set_command).await?; } Ok(()) } async fn set_swaybg_wallpaper(path: &str) -> Result<(), String> { - let output = TokioCommand::new("swaybg") - .arg("-i") - .arg(path) - .arg("-m") - .arg("fill") - .output() - .await - .map_err(|e| format!("Failed to start swaybg: {}", e))?; - - if output.status.success() { - Ok(()) - } else { - Err("swaybg failed to set wallpaper".to_string()) - } + let command = format!("swaybg -i \"{}\" -m fill", path); + spawn_background_process(&command).await } async fn set_swww_wallpaper(path: &str) -> Result<(), String> { - let set_command = format!("swww img \"{}\"", path); - if !execute_command(&set_command).await { - return Err("Failed to set wallpaper with swww".to_string()); - } - Ok(()) + let command = format!("swww img \"{}\"", path); + spawn_background_process(&command).await } async fn set_wallutils_wallpaper(path: &str) -> Result<(), String> { - let set_command = format!("setwallpaper \"{}\"", path); - if !execute_command(&set_command).await { - return Err("Failed to set wallpaper with wallutils".to_string()); - } - Ok(()) + let command = format!("setwallpaper \"{}\"", path); + spawn_background_process(&command).await } async fn set_feh_wallpaper(path: &str) -> Result<(), String> { - let set_command = format!("feh --bg-fill \"{}\"", path); - if !execute_command(&set_command).await { - return Err("Failed to set wallpaper with feh".to_string()); - } - Ok(()) + let command = format!("feh --bg-fill \"{}\"", path); + spawn_background_process(&command).await } -async fn execute_command(command: &str) -> bool { - match TokioCommand::new("sh") +async fn spawn_background_process(command: &str) -> Result<(), String> { + TokioCommand::new("sh") .arg("-c") .arg(command) - .output() - .await - { - Ok(output) => { - if output.status.success() { - true - } else { - eprintln!( - "Command failed: {}\nStderr: {}\nStdout: {}", - command, - String::from_utf8_lossy(&output.stderr).trim(), - String::from_utf8_lossy(&output.stdout).trim() - ); - false - } - } - Err(e) => { - eprintln!("Failed to execute command: {}. Error: {}", command, e); - false - } - } + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn() + .map_err(|e| format!("Failed to execute command '{}': {}", command, e))?; + + Ok(()) } async fn get_monitors() -> Result, String> { From 3b61c4ac6a594da220f31fbb83478dc4acbbd613 Mon Sep 17 00:00:00 2001 From: nyx Date: Fri, 18 Oct 2024 00:41:57 -0400 Subject: [PATCH 05/11] fix swwww spam --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index cfaecf6..cd56931 100644 --- a/src/main.rs +++ b/src/main.rs @@ -169,7 +169,7 @@ async fn ensure_swaybg_running() -> Result<(), String> { } async fn ensure_swww_running() -> Result<(), String> { - if !is_process_running("swww").await { + if !is_process_running("swww-daemon").await { println!("swww is not running. Attempting to start it..."); start_process("swww-daemon").await?; } From 7638174318cce662bc22468932bceb19c140c008 Mon Sep 17 00:00:00 2001 From: nyx Date: Fri, 18 Oct 2024 00:44:52 -0400 Subject: [PATCH 06/11] add new benefit --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index f7e43d3..1c9ac68 100644 --- a/readme.md +++ b/readme.md @@ -15,6 +15,7 @@ An unofficial GUI for setting wallpapers with multiple backends, built with GTK4 - **Performance** - Hyprwall is designed to be performant, it uses a thread pool to load images in parallel and caches images. - **High capacity** - Hyprwall can handle a large number of wallpapers (over 1000 at one time!) without any issues. - **Multiple monitors** - Hyprwall supports setting wallpapers on **Multiple** monitors at once. +- **True async** - Hyprwall is built to be asyncronous, it uses tokio to run commands in this manner massively improving performance. - **Supports swaybg, swww, wallutils, feh, and hyprpaper** - Hyprwall supports a variety of wallpaper backends, so you can use it with your preferred wallpaper tool. ## Requirements From 2745ff2b4c3fd0f1f804231ba291befcf674f510 Mon Sep 17 00:00:00 2001 From: nyx Date: Fri, 18 Oct 2024 00:45:43 -0400 Subject: [PATCH 07/11] fix typo --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 1c9ac68..0db7fda 100644 --- a/readme.md +++ b/readme.md @@ -15,7 +15,7 @@ An unofficial GUI for setting wallpapers with multiple backends, built with GTK4 - **Performance** - Hyprwall is designed to be performant, it uses a thread pool to load images in parallel and caches images. - **High capacity** - Hyprwall can handle a large number of wallpapers (over 1000 at one time!) without any issues. - **Multiple monitors** - Hyprwall supports setting wallpapers on **Multiple** monitors at once. -- **True async** - Hyprwall is built to be asyncronous, it uses tokio to run commands in this manner massively improving performance. +- **True async** - Hyprwall is built to be asynchronous, it uses tokio to run commands in this manner massively improving performance. - **Supports swaybg, swww, wallutils, feh, and hyprpaper** - Hyprwall supports a variety of wallpaper backends, so you can use it with your preferred wallpaper tool. ## Requirements From e785ef5fdff47c501bc6c12f60a2cc25ee4b1282 Mon Sep 17 00:00:00 2001 From: nyx Date: Fri, 18 Oct 2024 00:59:14 -0400 Subject: [PATCH 08/11] fix clippy and swww issues --- src/main.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index cd56931..fb23063 100644 --- a/src/main.rs +++ b/src/main.rs @@ -64,7 +64,8 @@ async fn set_wallpaper_internal(path: &str) -> Result<(), String> { println!("Found monitors: {:?}", *MONITORS.lock()); - match *CURRENT_BACKEND.lock() { + let backend = *CURRENT_BACKEND.lock(); + match backend { WallpaperBackend::Hyprpaper => set_hyprpaper_wallpaper(path).await, WallpaperBackend::Swaybg => set_swaybg_wallpaper(path).await, WallpaperBackend::Swww => set_swww_wallpaper(path).await, @@ -77,7 +78,8 @@ async fn set_hyprpaper_wallpaper(path: &str) -> Result<(), String> { let preload_command = format!("hyprctl hyprpaper preload \"{}\"", path); spawn_background_process(&preload_command).await?; - for monitor in MONITORS.lock().iter() { + let monitors = MONITORS.lock().clone(); + for monitor in monitors.iter() { let set_command = format!("hyprctl hyprpaper wallpaper \"{},{}\"", monitor, path); spawn_background_process(&set_command).await?; } @@ -143,7 +145,8 @@ async fn get_monitors() -> Result, String> { } async fn ensure_backend_running() -> Result<(), String> { - match *CURRENT_BACKEND.lock() { + let backend = *CURRENT_BACKEND.lock(); + match backend { WallpaperBackend::Hyprpaper => ensure_hyprpaper_running().await, WallpaperBackend::Swaybg => ensure_swaybg_running().await, WallpaperBackend::Swww => ensure_swww_running().await, @@ -219,7 +222,7 @@ async fn kill_previous_backend(backend: WallpaperBackend) { let process_name = match backend { WallpaperBackend::Hyprpaper => "hyprpaper", WallpaperBackend::Swaybg => "swaybg", - WallpaperBackend::Swww => "swww", + WallpaperBackend::Swww => "swww-daemon", WallpaperBackend::Wallutils => return, WallpaperBackend::Feh => return, }; @@ -234,12 +237,12 @@ async fn drop_all_wallpapers(backend: WallpaperBackend) { match backend { WallpaperBackend::Hyprpaper => { let _ = TokioCommand::new("hyprctl") - .args(&["hyprpaper", "unload", "all"]) + .args(["hyprpaper", "unload", "all"]) .status() .await; } WallpaperBackend::Swww => { - let _ = TokioCommand::new("swww").args(&["clear"]).status().await; + let _ = TokioCommand::new("swww").args(["clear"]).status().await; } _ => {} } From 49955517c10cee8e04ad3386e421be4d97455166 Mon Sep 17 00:00:00 2001 From: nyx Date: Fri, 18 Oct 2024 01:09:44 -0400 Subject: [PATCH 09/11] fix hyprpaper monitor fetching issues --- src/main.rs | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/main.rs b/src/main.rs index fb23063..3aeb6df 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,6 @@ use gtk::{prelude::*, Application}; use lazy_static::lazy_static; use parking_lot::Mutex; use std::process::Stdio; -use std::sync::Once; use tokio::process::Command as TokioCommand; use tokio::runtime::Runtime; @@ -13,8 +12,6 @@ lazy_static! { static ref CURRENT_BACKEND: Mutex = Mutex::new(WallpaperBackend::Hyprpaper); } -static INIT: Once = Once::new(); - #[derive(Clone, Copy)] pub enum WallpaperBackend { Hyprpaper, @@ -53,17 +50,6 @@ async fn set_wallpaper_internal(path: &str) -> Result<(), String> { println!("Attempting to set wallpaper: {}", path); - INIT.call_once(|| { - tokio::spawn(async { - match get_monitors().await { - Ok(monitors) => *MONITORS.lock() = monitors, - Err(e) => eprintln!("Failed to get monitors: {}", e), - } - }); - }); - - println!("Found monitors: {:?}", *MONITORS.lock()); - let backend = *CURRENT_BACKEND.lock(); match backend { WallpaperBackend::Hyprpaper => set_hyprpaper_wallpaper(path).await, @@ -78,8 +64,15 @@ async fn set_hyprpaper_wallpaper(path: &str) -> Result<(), String> { let preload_command = format!("hyprctl hyprpaper preload \"{}\"", path); spawn_background_process(&preload_command).await?; - let monitors = MONITORS.lock().clone(); - for monitor in monitors.iter() { + let monitors = get_monitors().await?; + + if monitors.is_empty() { + return Err("No monitors detected".to_string()); + } + + *MONITORS.lock() = monitors.clone(); + + for monitor in monitors { let set_command = format!("hyprctl hyprpaper wallpaper \"{},{}\"", monitor, path); spawn_background_process(&set_command).await?; } From eb1003b76e5401ad3bc5ebdaed6f15891eed4bc4 Mon Sep 17 00:00:00 2001 From: nyx Date: Fri, 18 Oct 2024 01:10:56 -0400 Subject: [PATCH 10/11] run fmt --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 3aeb6df..8a2389b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -65,7 +65,7 @@ async fn set_hyprpaper_wallpaper(path: &str) -> Result<(), String> { spawn_background_process(&preload_command).await?; let monitors = get_monitors().await?; - + if monitors.is_empty() { return Err("No monitors detected".to_string()); } From 75f475ceaa7aee6c2bd240fa85f69caf58d272a2 Mon Sep 17 00:00:00 2001 From: nyx Date: Fri, 18 Oct 2024 01:21:54 -0400 Subject: [PATCH 11/11] stop swwww from flooding term with useless msges --- src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8a2389b..675e4b2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -86,7 +86,7 @@ async fn set_swaybg_wallpaper(path: &str) -> Result<(), String> { } async fn set_swww_wallpaper(path: &str) -> Result<(), String> { - let command = format!("swww img \"{}\"", path); + let command = format!("swww img \"{}\" 2>/dev/null", path); spawn_background_process(&command).await } @@ -167,7 +167,7 @@ async fn ensure_swaybg_running() -> Result<(), String> { async fn ensure_swww_running() -> Result<(), String> { if !is_process_running("swww-daemon").await { println!("swww is not running. Attempting to start it..."); - start_process("swww-daemon").await?; + start_process("swww-daemon 2>/dev/null").await?; } Ok(()) }