Skip to content

MidHunterX/Expression

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

banner

Expression

Expression is a highly customizable, time-aware wallpaper engine for Linux. It allows you to automate desktop wallpaper changes based on the current hour, randomly or evenly spread wallpapers from grouped directories, and define overrides for special times like sleep, lunch, or focus hours. Whether you want a subtle visual timetable or an expressive ambience that changes with your day, Expression makes your desktop emotionally intelligent.

"This is the best 24-hour automatic wallpaper setter you could've ever asked for." - sis

β›² Features

Main Features

  • Supports multiple wallpaper setters (swww, feh)
  • 24-hour wallpaper cycling
  • Set specific wallpaper on specific hour
  • Set random wallpaper from a group of wallpapers for a specific hour
  • Distribute wallpapers from a group evenly across the hour
  • Override with special wallpaper based on a timetable (e.g., lunch, sleep)
  • Per group config overrides
  • Execute custom scripts on wallpaper change

πŸš€ Installation

Step 1: Prerequisites

  • Make sure you have a supported wallpaper setter (swww, feh) installed
  • cargo and rustup should be installed for building the project

Step 2: Build and Install

Clone the repository

git clone https://github.com/MidHunterX/Expression.git
cd Expression

Build the project

cargo build --release

Create config directory if it doesn't exist

mkdir -p ~/.config/expression

Copy the binary to your local/global bin directory. Be sure to have ~/.local/bin in your PATH environment variable if you are doing the following command.

cp target/release/expression ~/.local/bin/

Step 3: Configure

Create a configuration file: ~/.config/expression/config.toml with the following content

[general]
backend = "swww"

[directories]
wallpaper = "~/Pictures/wallpaper_dir/"

πŸ‘Ÿ Usage

Run Expression as a daemon:

expression &

Run Expression with debug logs:

RUST_LOG=debug expression

πŸ”§ Configuration

Expression uses a TOML configuration file located at:

~/.config/expression/config.toml

Minimal Config

[general]
backend = "swww"

[directories]
wallpaper = "~/Pictures/wallpaper_dir"

Full Config

[general]
# Supported backends: swww, feh
backend = "swww"
# Enable/Disable special collection feature
enable_special = true
# Way to select wallpaper from a group: random, spread
group_selection_strategy = "random"
# Command to execute on wallpaper change
# Examples:
# execute_on_change = "~/.scripts/custom_script.sh"
execute_on_change = "notify-send 'Wallpaper Changed'"

[directories]
# Default wallpaper directory
wallpaper = "~/Pictures/wallpaper_dir"
# Override special wallpaper directory (default: wallpaper_dir/special)
special = "~/Pictures/Wallpapers/Special"

[special_entries]
# Wallpaper item (entry/group) names situated inside special collection along with their corresponding hour
# These special wallpaper items always take precedence over other wallpaper items
5 = "rise and shine"
9 = "workout_motivation"
23 = "sleep_time"

πŸ“š Concepts

Expression works by treating wallpapers as a single unit; whether it is a file or multiple files grouped into a directory.

Wallpaper Items

  • Entry – A single wallpaper file named after the hour (e.g., 07.jpg).
  • Group – A directory containing multiple wallpapers, named after the hour (e.g., 07/).
wallpaper_dir/
β”œβ”€β”€ 00.jpg      # Entry for midnight
β”œβ”€β”€ 05.jpg      # Entry for 5:00
β”œβ”€β”€ 07/         # Group for 7:00
β”œβ”€β”€ 21.jpg      # Entry for 21:00
β”œβ”€β”€ 21/         # Group for 21:00
β”‚   β”œβ”€β”€ E.jpg
β”‚   β”œβ”€β”€ Zucc.jpg
β”‚   └── ...
β”œβ”€β”€ 22.jpg      # Entry for 22:00
└── ...

Groups (directories) take precedence over Entries (individual files) by default. When a Group is active, a random wallpaper from within the group is selected by default.

Collections

Definition: Directory with non-numeric name which contains Wallpaper Items (Entry or Group).

By definition, wallpaper_dir itself is a Collection of Wallpapers as well.

wallpaper_dir/
β”‚   special/                    # Special Collection
β”‚   β”œβ”€β”€ rise and shine.gif
β”‚   β”œβ”€β”€ sleep_time.jpg
β”‚   └── workout_motivation.jpg
β”‚
β”‚   collection_1/               # Custom Collection 1
β”‚   β”œβ”€β”€ 00/
β”‚   β”‚   β”œβ”€β”€ Austrian Painter.png
β”‚   β”‚   β”œβ”€β”€ Tiananmen Square.jpg
β”‚   β”‚   β”œβ”€β”€ who_is_in_paris.jpg
β”‚   β”‚   └── ...
β”‚   β”œβ”€β”€ 01.gif
β”‚   β”œβ”€β”€ 02.png
β”‚   └── ...
β”‚
β”‚   Nature Collection by Twice/ # Custom Collection 2
β”‚   └── ...
β”‚
β”œβ”€β”€ 00.jpg  # Entry for midnight
β”œβ”€β”€ 05.jpg  # Entry for 5:00
β”œβ”€β”€ 07/     # Group for 7:00
└── ...

Wallpaper Objects in Special Collection has the highest priority over everything.

Special Collection

Definition: Collection dir which has the highest priority when selecting wallpapers.

  • By default special should be inside your wallpaper_dir
  • You can change its location by configuring special in [directories]
  • Special wallpaper entries are defined in [special_entries] section in the format of: [hour] = "name"
  • Disable special collection by setting enable_special = false in [general]
[general]
backend = "swww"
enable_special = true

[directories]
wallpaper = "~/Pictures/Wallpapers/24_hour/"
special = "~/Pictures/Wallpapers/Special/"

[special_entries]
5 = "rise and shine"
9 = "workout_motivation"
23 = "sleep_time"

πŸ”₯ Use Cases

24 hour cycle (Fixed Wallpaper)

Want a simple 24 hour timecycle wallpaper like this?

You can set up your wallpaper directory like this:

00.jpg  03.jpg  06.jpg  09.jpg  12.jpg  15.jpg  18.jpg  21.jpg
01.jpg  04.jpg  07.jpg  10.jpg  13.jpg  16.jpg  19.jpg  22.jpg
02.jpg  05.jpg  08.jpg  11.jpg  14.jpg  17.jpg  20.jpg  23.jpg

00.jpg item is used for 00 to 01 and 23.jpg item is used for 23 to 00

Note: numbers without preceeding 0 is valid too. For e.g.: 3.png

Don't like renaming?

Renaming wallpapers numerically can get a little tedious especially when you want to change it into a different time. There's a solution for that. Since directories are also a valid wallpaper item, we can use that to our advantage.

wallpapers/
β”œβ”€β”€ 00/
β”‚   └── Austrian Painter.png
β”œβ”€β”€ 02/
β”‚   └── Tiananmen Square.jpg
β”œβ”€β”€ 03/
β”‚   └── who_is_in_paris.jpg
...

Now you can freely move wallpapers between hours without worrying about filenames.

A Visual Timetable (Wallpaper Override)

I'd like to get notified if its sleep time or its time for lunch via wallpaper. A truly non-intrusive way of communication. Since I work in a transparent terminal most of the time, the change is quite noticeable too. To do this:

  1. Create a directory named special in your wallpaper directory
  2. Put wallpapers for sleep_time and lunch items in special directory
wallpaper_dir/
β”‚   special/
β”‚   β”œβ”€β”€ eating_ramyeon.jpg
β”‚   └── sleep_time.jpg
β”‚
β”œβ”€β”€ 00/
β”‚   └── Austrian Painter.png
...
  1. Now let's configure which time to run these special wallpaper overrides.
# Add the names of item (file/dir) along with the time to your config in special_entries
[special_entries]
13 = "eating_ramyeon"
23 = "sleep_time"

Progressively Sleepy PC (Spread Wallpapers)

Okay the sleep_time wallpaper shows up at exactly 23:00 and then that's about it.

But what if your wallpapers could become progressively sleepier as the hour passes?

Let’s set that up.

  1. Create a sleep_time directory inside the special directory, and add multiple progressively sleepy wallpapers:
wallpaper_dir/
β”‚   special/
β”‚   β”œβ”€β”€ eating_ramyeon.jpg
β”‚   β”œβ”€β”€ sleep_time/
β”‚   β”‚   β”œβ”€β”€ sleepy_1.jpg
β”‚   β”‚   β”œβ”€β”€ sleepy_2.jpg
β”‚   β”‚   β”œβ”€β”€ ...
β”‚   β”‚   └── sleepy_10.jpg
...
  1. Now let's configure that specific group to spread out throughout the sleep hour. Create a file named config.toml inside your group (e.g., sleep_time/) with the following content:
[general]
selection_strategy = "spread"  # Applies spread strategy to the group only
  1. Make sure the name of the directory (e.g., sleep_time) is added to the special_entries section.
[special_entries]
13 = "eating_ramyeon"
23 = "sleep_time"

And just like that, your system gently drifts into dreamland with you πŸŒ™

πŸ“œ License

Expression is licensed under the GNU Affero GPL v3, ensuring all modifications and server-hosted versions remain open-source.

πŸ™Œ Contributing

Contributions are welcome! Feel free to submit issues or pull requests.


Backstory: It's the year 2025 AD (Gregorian Calendar) and I was just a guy who was writing bash script to automate timed wallpapers with the help of swww daemon. But, this is still not what I really envisioned. Adding more features became a hassle. No more duct-taping and workarounds for datastructures! I have to re-write this into a performant compiled language so that I can have more features while being lightweight and resource efficient focusing on Laptop battery life. So, I want a language re-write which focuses on code maintainability, high performance, low resource utilization and scalability. I had one language in mind: C. Simple and Efficient. Since I have a little bit extra features in mind, datastructures, memory management and data processing could get verbose. This led me to try out Rust lang which gives similar performance while giving memory safety by default. Thus, Expression transcended into this world; A 24 hour ambient notification system disguised as a wallpaper setting program engineered to be lightweight, performant while using as little battery as possible.

About

πŸ–ΌοΈ Fast, Advanced and Configurable 24 Hour Wallpaper Selector

Topics

Resources

License

Stars

Watchers

Forks

Languages