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::thread;
use std::time::Duration; use std::time::Duration;
use x11rb::wrapper::ConnectionExt as _; use x11rb::wrapper::ConnectionExt as _;
@ -6,12 +6,16 @@ use x11rb::{
connection::Connection, connection::Connection,
protocol::xproto::{ protocol::xproto::{
AtomEnum, ChangeWindowAttributesAux, CloseDown, ConnectionExt, CreateGCAux, EventMask, AtomEnum, ChangeWindowAttributesAux, CloseDown, ConnectionExt, CreateGCAux, EventMask,
PropMode, Rectangle, ImageFormat, PropMode,
}, },
rust_connection::RustConnection, rust_connection::RustConnection,
}; };
fn main() -> Result<()> { 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. // Connect to the running graphical session, the X11 server.
let (conn, screen_num) = RustConnection::connect(None)?; let (conn, screen_num) = RustConnection::connect(None)?;
// Select the current screen. // Select the current screen.
@ -54,30 +58,54 @@ fn main() -> Result<()> {
let pixmap = conn.generate_id()?; let pixmap = conn.generate_id()?;
conn.create_pixmap(depth, pixmap, root, width, height)?; conn.create_pixmap(depth, pixmap, root, width, height)?;
// Fill the pixmap with the pixels to be set as the background. // Load the wallpaper image from disk.
// For now, allocate a solid color (RGB 26,132,74 scaled to X11 16-bit format). let img =
let color = conn image::open(image_path).with_context(|| format!("Failed to open image: {image_path}"))?;
.alloc_color(screen.default_colormap, 26 * 257, 132 * 257, 74 * 257)?
.reply()?
.pixel;
// Create a Graphics Context (GC), which defines how drawing is done. // Convert the image into RGBA8 (4 bytes per pixel).
// It stores drawing parameters such as color, fill style, etc. // 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()?; let gc = conn.generate_id()?;
// Associate the GC with the pixmap and configure its foreground color. conn.create_gc(gc, pixmap, &CreateGCAux::new())?;
conn.create_gc(gc, pixmap, &CreateGCAux::new().foreground(color))?;
// Paint a solid-color rectangle onto the pixmap using the GC. // Upload the image pixels into the pixmap.
// This is only for the solid-color case and will be replaced when using real images. // This writes the final wallpaper image into server memory.
conn.poly_fill_rectangle( // No scaling or color conversion happens here; the data must already be correct.
pixmap, // BG Image (pixmap) conn.put_image(
gc, // The Graphics Context to paint on ImageFormat::Z_PIXMAP,
&[Rectangle { pixmap, // drawable: Destination pixmap (wallpaper image)
x: 0, gc, // Graphics Context (required by X11)
y: 0, // Start from top-left corner width,
width, height, // width/height: size of the uploaded image region in pixels
height, // Set rectangle dimensions = screen width, height 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. // 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_root = conn.intern_atom(false, b"_XROOTPMAP_ID")?.reply()?.atom;
let atom_setroot = conn.intern_atom(false, b"_XSETROOT_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( conn.change_property32(
PropMode::REPLACE, PropMode::REPLACE,
root, root,