Set images as wallpaper
- Hard-coded image path
This commit is contained in:
parent
eb3c45bf91
commit
432ddc5ca6
74
src/main.rs
74
src/main.rs
@ -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 server’s 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 window’s 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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user