# Chroma

Super-fast, lightweight and efficient wallpaper daemon for Wayland compositors
with multi-monitor & hotplugging support. Born from my woes with Hyprpaper,
swaybg and most ironically _SWWW_ (now called AWWW for some awful reason), which
turned out to be NOT a solution to my Wayland wallpaper woes. Smaller, faster,
cleaner and somehow still more feature-rich...

## Features

Chroma combines simplicity with powerful performance optimizations and
comprehensive monitor management. Here's what makes Chroma stand out:

### Core Functionality

- **Memory-efficient**: Smart caching and resource management
  - **Optimized rendering**: VBO dirty flagging and reduced GPU overhead
- **Multi-monitor support**: Automatically detects and manages wallpapers for
  all connected displays
  - **Configurable scaling modes**: Fill, fit, stretch, and center options per
    monitor
- **Hotplugging**: Dynamically handles monitor connection/disconnection events
- **Per-output configuration**: Set different wallpapers and settings for each
  monitor
  - **Global and per-output settings**: Override defaults for specific monitors
  - **Performance tuning**: Adjustable downsampling limits and quality
    thresholds
- **Multiple image formats**: Supports JPEG, PNG, BMP, TGA, PSD, GIF, HDR, PIC,
  PPM, PGM
- **EGL/OpenGL rendering**: Hardware-accelerated wallpaper rendering
- **Simple Configuration file**: Easy setup with TOML config files
- **Signal handling**: Graceful shutdown and configuration reload (SIGHUP)
- **Intelligent downsampling**: Automatically reduces large image resolution to
  save memory (up to 94% memory savings for 8K images)
- **Advanced filtering**: Nearest, linear, bilinear, and trilinear filtering
  options

## Usage

### Requirements

#### Dependencies

- **Wayland**: wayland-client, wayland-egl
- **Graphics**: EGL, OpenGL
- **System**: glibc, libm, libdl

#### Development Dependencies

- GCC or Clang compiler
- Make
- pkg-config
- Wayland development headers
- EGL/OpenGL development headers

See [development section](#development) for more details. This section might get
outdated at any given moment, so refer to the Nix shell if in doubt.

### Building

#### Quick Build

```bash
# Check dependencies
make check-deps

# Build the daemon
make

# Or build debug version
make debug

# Alternatively, create a static build
make static
```

### Installation

```bash
# Install to /usr/local (default)
sudo make install

# Install to /usr
sudo make PREFIX=/usr install

# Create systemd service file
make systemd-service

# Create sample configuration
make sample-config
```

### Configuration

#### Configuration File

Chroma looks for configuration files in this order:

1. `$XDG_CONFIG_HOME/chroma/chroma.toml`
2. `~/.config/chroma/chroma.toml`
3. `./chroma.toml` (current directory)

#### Sample Configuration

```toml
# Default wallpaper for outputs without specific mapping
default_image = "~/.config/chroma/default.jpg"

# Output-specific wallpapers
# Format: [[output]] with name and image keys
[[output]]
name = "DP-1"
image = "~/Pictures/monitor1.jpg"

[[output]]
name = "DP-2"
image = "~/Pictures/monitor2.png"

[[output]]
name = "HDMI-A-1"
image = "~/Pictures/hdmi_wallpaper.jpg"

# You can also match outputs by description using the desc: prefix
# This is useful when output names change between reboots
# Format: output."desc:DESCRIPTION_PREFIX" = "/path/to/image.jpg"
[[output]]
name = "desc:Samsung"
image = "~/Pictures/samsung_wallpaper.jpg"

[[output]]
name = "desc:LG Ultra"
image = "~/Pictures/lg_wallpaper.jpg"
```

### Finding Output Names

Use `wlr-randr` or similar tools to find your output names:

```bash
wlr-randr
```

### Command Line Options

```plaintext
Usage: chroma [OPTIONS]

Options:
  -c, --config FILE    Configuration file path
  -d, --daemon         Run as daemon
  -v, --verbose        Verbose logging
  -h, --help          Show help
  --version           Show version information

Examples:
  chroma -c ~/.config/chroma/chroma.toml
  chroma --daemon
```

### Running Manually

```bash
# Run in foreground
chroma

# Run as daemon
chroma --daemon

# Use custom config
chroma -c /path/to/config.conf
```

### Systemd Service

```bash
# Enable and start the service
systemctl --user enable chroma.service
systemctl --user start chroma.service

# Check status
systemctl --user status chroma.service

# View logs
journalctl --user -u chroma.service -f

# Reload configuration
systemctl --user reload chroma.service
```

### Auto-start with Desktop Session

```bash
# Enable the service for auto-start
systemctl --user enable chroma.service

# The service will start automatically with your graphical session
```

### Supported Wayland Compositors

Chroma works with any Wayland compositor that supports:

- `wl_compositor` interface
- `wl_output` interface
- `zwlr_layer_shell_v1` (wlr-layer-shell-unstable-v1) interface
- EGL window surface creation

The wlr-layer-shell protocol is required for creating wallpaper surfaces on the
background layer. Tested only on Hyprland, but should work fine with any
wlroots-based compositor or any compositor that implements the wlr-layer-shell
protocol.

## Contributing

You might want to contribute to Chroma for a variety of reasons. I usually will
not judge, however, there are some conventions I expect you to adhere to. Mainly
I would like for you to follow the project's **code style**:

- C11 standard (I really wished for C99)
- 2-space indentation (use `make format`)
- No tabs (except for the Makefile, obviously)
- Function names: `chroma_function_name`
- Constants: `CHROMA_CONSTANT_NAME`

Once your changes are done, fork this repository and create a feature branch.
This is not a strict requirement but I'd rather not deal with rebase failures.
Create your feature branch, make your changes, _test thoroughly_ and submit your
pull request when you are done. With your pull request, I'd _really_ like a tiny
snippet of text that explains your motive of changes. While I can infer what you
are trying to do, I'd rather _know_ what was going on in your head.

### Development

A Nix shell is provided within the repository. You may use both `nix-shell` and
`nix develop` to enter a development shell with all of the required dependencies
for _dynamic linking_. Additionally, [Direnv](https://direnv.net) users may use
`direnv allow` to use the shell provided by the repository.

A few convenience commands are provided by the Makefile, which you may invoke at
your own discretion.

#### Building Debug Version

```bash
make debug
```

#### Code Formatting

```bash
make format  # requires clang-format
```

#### Static Analysis

```bash
make analyze  # requires cppcheck
```

## License

<!--markdownlint-disable MD059 -->

This project is made available under Mozilla Public License (MPL) version 2.0.
See [LICENSE](LICENSE) for more details on the exact conditions. An online copy
is provided [here](https://www.mozilla.org/en-US/MPL/2.0/).

<!--markdownlint-enable MD059 -->
