Set images as wallpaper

- Hard-coded image path
This commit is contained in:
Candifloss 2025-12-17 00:04:38 +05:30
parent eb3c45bf91
commit 432ddc5ca6

View File

@ -1,4 +1,4 @@
use anyhow::Result;
use anyhow::{Context, Result};
use std::thread;
use std::time::Duration;
use x11rb::wrapper::ConnectionExt as _;
@ -6,12 +6,16 @@ use x11rb::{
connection::Connection,
protocol::xproto::{
AtomEnum, ChangeWindowAttributesAux, CloseDown, ConnectionExt, CreateGCAux, EventMask,
PropMode, Rectangle,
ImageFormat, PropMode,
},
rust_connection::RustConnection,
};
fn main() -> Result<()> {
// Path to wallpaper image.
// This is hardcoded for now and will later be replaced by config loading.
let image_path = "/path/to/image";
// Connect to the running graphical session, the X11 server.
let (conn, screen_num) = RustConnection::connect(None)?;
// Select the current screen.
@ -54,30 +58,54 @@ fn main() -> Result<()> {
let pixmap = conn.generate_id()?;
conn.create_pixmap(depth, pixmap, root, width, height)?;
// Fill the pixmap with the pixels to be set as the background.
// For now, allocate a solid color (RGB 26,132,74 scaled to X11 16-bit format).
let color = conn
.alloc_color(screen.default_colormap, 26 * 257, 132 * 257, 74 * 257)?
.reply()?
.pixel;
// Load the wallpaper image from disk.
let img =
image::open(image_path).with_context(|| format!("Failed to open image: {image_path}"))?;
// Create a Graphics Context (GC), which defines how drawing is done.
// It stores drawing parameters such as color, fill style, etc.
// Convert the image into RGBA8 (4 bytes per pixel).
// Predictable, CPU-friendly format to work on.
let img = img.to_rgba8();
// Resize the image to exactly match the screen size.
// This uses a simple "fill" strategy (no aspect ratio preservation).
let img = image::imageops::resize(
&img,
width.into(),
height.into(),
image::imageops::FilterType::Lanczos3,
);
// Extract raw pixel bytes from the image buffer.
let mut pixel_data = img.into_raw();
// Image libraries produce RGBA, but X11 TrueColor visuals typically use
// BGRX/BGRA byte order on little-endian systems.
// Swap red and blue channels to match the servers native pixel layout.
// Without this conversion, colors appear incorrect.
for pixel in pixel_data.chunks_exact_mut(4) {
pixel.swap(0, 2); // Swap Red and Blue channels
}
// Create a Graphics Context (GC).
// A GC is required by X11 for image uploads, even though most of its
// drawing settings are unused when using put_image.
let gc = conn.generate_id()?;
// Associate the GC with the pixmap and configure its foreground color.
conn.create_gc(gc, pixmap, &CreateGCAux::new().foreground(color))?;
conn.create_gc(gc, pixmap, &CreateGCAux::new())?;
// Paint a solid-color rectangle onto the pixmap using the GC.
// This is only for the solid-color case and will be replaced when using real images.
conn.poly_fill_rectangle(
pixmap, // BG Image (pixmap)
gc, // The Graphics Context to paint on
&[Rectangle {
x: 0,
y: 0, // Start from top-left corner
// Upload the image pixels into the pixmap.
// This writes the final wallpaper image into server memory.
// No scaling or color conversion happens here; the data must already be correct.
conn.put_image(
ImageFormat::Z_PIXMAP,
pixmap, // drawable: Destination pixmap (wallpaper image)
gc, // Graphics Context (required by X11)
width,
height, // Set rectangle dimensions = screen width, height
}],
height, // width/height: size of the uploaded image region in pixels
0,
0, // dst_x/dst_y: Destination offset inside the pixmap (top-left corner)
0, // left_pad: legacy bitmap padding, always 0 for modern images
depth, // depth: must match the root windows depth (usually 24 or 32)
&pixel_data, // data: raw BGRA/BGRX pixel buffer
)?;
// Grab and lock the X server to prevent other clients from observing or reacting to intermediate state.
@ -113,7 +141,7 @@ fn main() -> Result<()> {
let atom_root = conn.intern_atom(false, b"_XROOTPMAP_ID")?.reply()?.atom;
let atom_setroot = conn.intern_atom(false, b"_XSETROOT_ID")?.reply()?.atom;
// Set root window properties that publish the wallpaper pixmap location to consumers.
// Set root window properties that publish the wallpaper pixmap location to other clients.
conn.change_property32(
PropMode::REPLACE,
root,