8000 Enable set wallpaper from cron in Linux, fix #21 by ssrlive · Pull Request #33 · reujab/wallpaper.rs · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Enable set wallpaper from cron in Linux, fix #21 #33

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
65 changes: 65 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: Rust

on:
push:
branches:
- '**'
pull_request:
branches:
- '**'

env:
CARGO_TERM_COLOR: always

jobs:
build_n_test:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable

- name: rustfmt
if: ${{ !cancelled() }}
run: cargo fmt --all -- --check

- name: check
if: ${{ !cancelled() }}
run: cargo check --verbose

- name: clippy
if: ${{ !cancelled() }}
run: cargo clippy --all-targets --all-features -- -D warnings

- name: Build
if: ${{ !cancelled() }}
run: |
cargo build --verbose
cargo clean
cargo build --verbose --tests --all-features

- name: Abort on error
if: ${{ failure() }}
run: echo "Some of jobs failed" && false

semver:
name: Check semver
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Check semver
if: ${{ !cancelled() }}
uses: obi1kenobi/cargo-semver-checks-action@v2
- name: Abort on error
if: ${{ failure() }}
run: echo "Semver check failed" && false
24 changes: 17 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,30 @@ categories = ["api-bindings"]
license = "Unlicense"

[dependencies]
dirs = { version = "1", optional = true }
thiserror = "1"
reqwest = { version = "0.11", optional = true, features = ["blocking"] }
dirs = { version = "5", optional = true }
thiserror = "2"
reqwest = { version = "0.12", optional = true, features = ["blocking"] }

[target.'cfg(unix)'.dependencies]
enquote = "1"

[target.'cfg(all(unix, not(target_os = "macos")))'.dependencies]
rust-ini = "0.12"
dirs = "1"
rust-ini = "0.21"
dirs = "5"

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["winuser"] }
winreg = "0.9"
windows-sys = { version = "0.59", features = ["Win32_UI_WindowsAndMessaging"] }
winreg = "0.53"

[dev-dependencies]
rand = "0.8"
clap = { version = "4", features = ["derive"] }

[features]
from_url = ["dirs", "reqwest"]
cron = []

[[example]]
name = "random_wallpaper"
path = "examples/random_wallpaper.rs"
required-features = ["cron"]
31 changes: 31 additions & 0 deletions examples/random_wallpaper.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// When the compile mode is NOT debug (i.e., release mode), the target
// will be built as a GUI application on Windows, NOT a console application.
// So, we can run it as a scheduled task without a console window pop-up.
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

/// Set my wallpaper to a random picture from a directory
#[derive(clap::Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
/// Path of picture directory
#[arg(short, long, value_name = "DIR")]
picture_dir: std::path::PathBuf,
}

fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
let args: Args = clap::Parser::parse();

let paths: Vec<_> = std::fs::read_dir(&args.picture_dir)?
.map(|r| r.map(|d| d.path()).map_err(|e| e.to_string()))
.collect::<Result<_, _>>()?;

use rand::seq::SliceRandom;
let selected_wallpaper = paths
.choose(&mut rand::thread_rng())
.ok_or("No wallpaper found")?
.to_str()
.ok_or("Invalid path")?;

wallpaper::set_from_path(selected_wallpaper)?;
Ok(())
}
9 changes: 9 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,12 @@ fn main() {
println!("{:?}", wallpaper::get());
}
```

Here an example that sets random wallpapers from a specific folder, you can install it with
```bash
cargo install wallpaper --example random_wallpaper --features cron
```
Now you can run it with
```bash
random_wallpaper -p /your/wallpapers/folder
```
32 changes: 31 additions & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ pub enum Error {
#[error("Invalid UTF-8: {0}")]
InvalidUtf8(#[from] FromUtf8Error),

#[cfg(all(unix, not(target_os = "macos")))]
#[error("Invalid INI: {0}")]
InvalidIni(#[from] ini::ini::Error),
InvalidIni(#[from] ini::Error),

#[cfg(unix)]
#[error("Enquote error: {0}")]
Enquote(#[from] enquote::Error),

Expand All @@ -34,4 +36,32 @@ pub enum Error {

#[error("Invalid path")]
InvalidPath,

#[error("FromUtf16Error: {0}")]
FromUtf16Error(#[from] std::string::FromUtf16Error),

#[cfg(feature = "from_url")]
#[error("reqwest::Error: {0}")]
Reqwest(#[from] reqwest::Error),

#[error("{0}")]
Other(String),
}

impl From<String> for Error {
fn from(s: String) -> Self {
Error::Other(s)
}
}

impl From<&str> for Error {
fn from(s: &str) -> Self {
Error::Other(s.to_string())
}
}

impl From<&String> for Error {
fn from(s: &String) -> Self {
Error::Other(s.to_string())
}
}
2 changes: 1 addition & 1 deletion src/linux/gnome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ where
)
// Ignore the result because in Gnome < 42 the cmd could fail since
// key "picture-uri-dark" does not exists
.or_else(|_| res)
.or(res)
}

pub fn set_mode(mode: Mode) -> Result<()> {
Expand Down
2 changes: 1 addition & 1 deletion src/linux/lxde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub fn get() -> Result<String> {
.section(Some("*"))
.and_then(|ini| ini.get("wallpaper"))
.ok_or(Error::NoImage("LXDE"))?
.clone())
.to_string())
}

pub fn set<P>(path: P) -> Result<()>
Expand Down
23 changes: 22 additions & 1 deletion src/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,27 @@ where
return gnome::set(&path);
}

#[cfg(feature = "cron")]
{
std::env::set_var("DISPLAY", ":0");
let user_id_str = get_stdout("id", &["-u"])?;
let dbus_address = format!("unix:path=/run/user/{}/bus", user_id_str.trim());
std::env::set_var("DBUS_SESSION_BUS_ADDRESS", dbus_address.clone());

let color_scheme = get_stdout(
"gsettings",
&["get", "org.gnome.desktop.interface", "color-scheme"],
)?;
let org = "org.gnome.desktop.background";
let mode = if color_scheme.trim() == "'prefer-dark'" {
"picture-uri-dark"
} else {
"picture-uri"
};
let file = &enquote::enquote('"', &format!("file://{}", &path));
run("gsettings", &["set", org, mode, file])?;
}

match desktop.as_str() {
"KDE" => kde::set(&path),
"X-Cinnamon" => run(
Expand Down Expand Up @@ -81,7 +102,7 @@ where
),
_ => {
if let Ok(mut child) = Command::new("swaybg")
.args(&["-i", path.as_ref().to_str().ok_or(Error::InvalidPath)?])
.args(["-i", path.as_ref().to_str().ok_or(Error::InvalidPath)?])
.spawn()
{
child.stdout = None;
Expand Down
4 changes: 2 additions & 2 deletions src/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ pub fn get() -> Result<String> {
// Sets the wallpaper from a file.
pub fn set_from_path<P>(path: P) -> Result<()>
where
P: AsRef<Path> + std::fmt::Display,
P: AsRef<std::path::Path> + std::fmt::Display,
{
run(
"osascript",
&[
"-e",
&format!(
r#"tell application "System Events" to tell every desktop to set picture to {}"#,
enquote::enquote('"', path),
enquote::enquote('"', path.as_ref().to_str().ok_or("Invalid path")?)
),
],
)
Expand Down
11 changes: 5 additions & 6 deletions src/windows.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
use crate::{Mode, Result};
use ::core::ffi::c_void;
use std::ffi::OsStr;
use std::io;
use std::iter;
use std::mem;
use std::os::windows::ffi::OsStrExt;
use winapi::ctypes::c_void;
use winapi::um::winuser::SystemParametersInfoW;
use winapi::um::winuser::SPIF_SENDCHANGE;
use winapi::um::winuser::SPIF_UPDATEINIFILE;
use winapi::um::winuser::SPI_GETDESKWALLPAPER;
use winapi::um::winuser::SPI_SETDESKWALLPAPER;
use windows_sys::Win32::UI::WindowsAndMessaging::{
SystemParametersInfoW, SPIF_SENDCHANGE, SPIF_UPDATEINIFILE, SPI_GETDESKWALLPAPER,
SPI_SETDESKWALLPAPER,
};
use winreg::enums::*;
use winreg::RegKey;

Expand Down
0