diff --git a/justfile b/justfile index 156fc98..bcf1437 100644 --- a/justfile +++ b/justfile @@ -8,13 +8,16 @@ yaml-language-server " install-scripts target=(`echo $HOME` + "/.local/bin"): + cargo build --release --manifest-path scripts/randomwallpaper/Cargo.toml + cp scripts/randomwallpaper/target/release/randomwallpaper {{target}}/randomwallpaper + opam install --yes clap cd scripts/playtwitch && dune build chmod -R +w scripts/playtwitch cp scripts/playtwitch/_build/default/playtwitch.exe {{target}}/playtwitch ln -sf \ - `pwd`/scripts/{start-joshuto,withjava,randomwallpaper} \ + `pwd`/scripts/{start-joshuto,withjava} \ {{target}} install-lsps-paru: diff --git a/scripts/randomwallpaper b/scripts/randomwallpaper deleted file mode 100755 index 211135c..0000000 --- a/scripts/randomwallpaper +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -mons=$(xrandr --listactivemonitors | wc -l) -mons=$((mons-1)) - -feh --bg-fill $( - fd -L '\.(png|jpg)' /usr/share/backgrounds/ ~/.local/share/backgrounds/ \ - | shuf | head -n 2 -) diff --git a/scripts/randomwallpaper/.gitignore b/scripts/randomwallpaper/.gitignore new file mode 100644 index 0000000..2c96eb1 --- /dev/null +++ b/scripts/randomwallpaper/.gitignore @@ -0,0 +1,2 @@ +target/ +Cargo.lock diff --git a/scripts/randomwallpaper/Cargo.toml b/scripts/randomwallpaper/Cargo.toml new file mode 100644 index 0000000..83ed40a --- /dev/null +++ b/scripts/randomwallpaper/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "randomwallpaper" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.53" +rand = "0.8.5" +walkdir = "2.3.2" +x11 = { version = "2.19.1", features = ["xinerama", "xlib"] } diff --git a/scripts/randomwallpaper/src/main.rs b/scripts/randomwallpaper/src/main.rs new file mode 100644 index 0000000..a103e6f --- /dev/null +++ b/scripts/randomwallpaper/src/main.rs @@ -0,0 +1,48 @@ +use anyhow::Context; +use rand::prelude::{IteratorRandom, SliceRandom}; +use std::{ + path::{Path, PathBuf}, + process::Command, +}; +use walkdir::{DirEntry, WalkDir}; +use xinerama::head_count; + +mod xinerama; + +fn main() -> anyhow::Result<()> { + let paths = [ + PathBuf::from("/usr/share/backgrounds"), + Path::new(&std::env::var("HOME").context("couldn't get home directory")?) + .join(".local/share/backgrounds"), + ]; + + let wallpapers = paths + .into_iter() + .flat_map(dir_iter) + .flatten() + .filter(|d| { + d.path() + .extension() + .map(|e| ["png", "jpg"].contains(&&*e.to_string_lossy())) + .unwrap_or(false) + }) + .map(DirEntry::into_path); + + let mut wallpapers = wallpapers.choose_multiple( + &mut rand::thread_rng(), + head_count().context("Failed to get head count")? as usize, + ); + + wallpapers.shuffle(&mut rand::thread_rng()); + + Command::new("feh") + .arg("--bg-fill") + .args(&wallpapers) + .status()?; + + Ok(()) +} + +fn dir_iter(p: impl AsRef) -> impl Iterator> { + WalkDir::new(p).follow_links(true).into_iter() +} diff --git a/scripts/randomwallpaper/src/xinerama.rs b/scripts/randomwallpaper/src/xinerama.rs new file mode 100644 index 0000000..44d8ae9 --- /dev/null +++ b/scripts/randomwallpaper/src/xinerama.rs @@ -0,0 +1,36 @@ +use std::mem::MaybeUninit; + +use anyhow::bail; +use x11::{ + xinerama::{XineramaIsActive, XineramaQueryScreens}, + xlib::{XCloseDisplay, XFree, XOpenDisplay}, +}; + +pub fn head_count() -> anyhow::Result { + unsafe { + let display = XOpenDisplay(b":0\0".as_ptr() as _); + if display.is_null() { + bail!("Couldn't open display"); + } + + if XineramaIsActive(display) != 1 { + XCloseDisplay(display); + bail!("Xinerama is inactive"); + } + + let mut screens = MaybeUninit::uninit(); + + let info = XineramaQueryScreens(display, screens.as_mut_ptr()); + if info.is_null() { + XCloseDisplay(display); + bail!("Failed to query screens"); + } + + let count = screens.assume_init(); + + XFree(info as _); + XCloseDisplay(display); + + Ok(count) + } +}