notashelf /
a838f8673118a493c9618804f424df1a682cd147
chroma
publicLightweight wallpaper daemon for Wayland
clone
ssh://git@git.notashelf.dev:33/notashelf/chroma.gitCommit a838f8673118
tarballunverified3 files changed+42-30
@@ -212,6 +212,7 @@ int chroma_surface_create(chroma_state_t *state, chroma_output_t *output); void chroma_surface_destroy(chroma_output_t *output); int chroma_buffer_create(chroma_state_t *state, chroma_output_t *output); void chroma_buffer_destroy(chroma_output_t *output);+void chroma_buffer_unmap(chroma_output_t *output); int chroma_render_wallpaper(chroma_state_t *state, chroma_output_t *output); // Layer shell functions@@ -137,9 +137,7 @@ static int assign_wallpaper_to_output(chroma_state_t *state, old_filter_quality != output->filter_quality || old_anchor != output->anchor || old_anchor_x != output->anchor_x || old_anchor_y != output->anchor_y)) {- chroma_log("DEBUG",- "Configuration changed for output %u",- output->id);+ chroma_log("DEBUG", "Configuration changed for output %u", output->id); } } else { output->config_loaded = false;@@ -158,8 +156,8 @@ static int assign_wallpaper_to_output(chroma_state_t *state, // Render wallpaper int ret = chroma_render_wallpaper(state, output); if (ret != CHROMA_OK) {- chroma_log("ERROR", "Failed to render wallpaper for output %u: %s", output->id,- chroma_error_string(ret));+ chroma_log("ERROR", "Failed to render wallpaper for output %u: %s",+ output->id, chroma_error_string(ret)); return ret; } @@ -33,6 +33,22 @@ void chroma_buffer_destroy(chroma_output_t *output) { } } +// Unmap client-side memory while keeping the wl_buffer proxy alive.+// The compositor retains its own fd reference and mapping, so the+// wallpaper remains visible after this call.+void chroma_buffer_unmap(chroma_output_t *output) {+ if (!output || !output->shm_data) {+ return;+ }++ if (munmap(output->shm_data, output->shm_size) < 0) {+ chroma_log("WARN", "munmap failed: %s", strerror(errno));+ }+ output->shm_data = NULL;+ output->shm_size = 0;+ output->shm_stride = 0;+}+ // Create shared memory buffer for an output int chroma_buffer_create(chroma_state_t *state, chroma_output_t *output) { if (!state || !output || !state->shm) {@@ -80,8 +96,7 @@ int chroma_buffer_create(chroma_state_t *state, chroma_output_t *output) { // Fill with black memset(data, 0, size); - struct wl_shm_pool *pool =- wl_shm_create_pool(state->shm, fd, (int32_t)size);+ struct wl_shm_pool *pool = wl_shm_create_pool(state->shm, fd, (int32_t)size); if (!pool) { chroma_log("ERROR", "wl_shm_create_pool failed"); munmap(data, size);@@ -109,8 +124,7 @@ int chroma_buffer_create(chroma_state_t *state, chroma_output_t *output) { } // Sample a pixel from image data (grayscale, grayscale+alpha, RGB, or RGBA)-static inline uint32_t sample_pixel(const chroma_image_t *image, int x,- int y) {+static inline uint32_t sample_pixel(const chroma_image_t *image, int x, int y) { if (!image || !image->data || x < 0 || y < 0 || x >= image->width || y >= image->height) { return 0xFF000000; // black with full alpha@@ -147,8 +161,7 @@ static inline uint32_t sample_pixel(const chroma_image_t *image, int x, } // Draw scaled image into the shared memory buffer-static void draw_scaled_image(chroma_output_t *output,- chroma_image_t *image) {+static void draw_scaled_image(chroma_output_t *output, chroma_image_t *image) { if (!output || !image || !output->shm_data) { return; }@@ -263,10 +276,8 @@ static void draw_scaled_image(chroma_output_t *output, default: { if (img_w <= out_w && img_h <= out_h) { // Image fits entirely - position with anchor- float offset_x =- (anchor_x / 100.0f) * ((float)out_w - (float)img_w);- float offset_y =- (anchor_y / 100.0f) * ((float)out_h - (float)img_h);+ float offset_x = (anchor_x / 100.0f) * ((float)out_w - (float)img_w);+ float offset_y = (anchor_y / 100.0f) * ((float)out_h - (float)img_h); for (int y = 0; y < img_h; y++) { for (int x = 0; x < img_w; x++) {@@ -279,10 +290,8 @@ static void draw_scaled_image(chroma_output_t *output, } } else { // Image is larger than output - clip with anchor- float src_offset_x =- (anchor_x / 100.0f) * ((float)img_w - (float)out_w);- float src_offset_y =- (anchor_y / 100.0f) * ((float)img_h - (float)out_h);+ float src_offset_x = (anchor_x / 100.0f) * ((float)img_w - (float)out_w);+ float src_offset_y = (anchor_y / 100.0f) * ((float)img_h - (float)out_h); if (src_offset_x < 0) src_offset_x = 0;@@ -333,19 +342,16 @@ int chroma_surface_create(chroma_state_t *state, chroma_output_t *output) { } // Configure layer surface- zwlr_layer_surface_v1_set_size(output->layer_surface,- (uint32_t)output->width,+ zwlr_layer_surface_v1_set_size(output->layer_surface, (uint32_t)output->width, (uint32_t)output->height);- zwlr_layer_surface_v1_set_anchor(- output->layer_surface,- ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |- ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |- ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |- ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT);+ zwlr_layer_surface_v1_set_anchor(output->layer_surface,+ ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |+ ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |+ ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |+ ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, -1); zwlr_layer_surface_v1_set_keyboard_interactivity(- output->layer_surface,- ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE);+ output->layer_surface, ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE); // Add layer surface listener zwlr_layer_surface_v1_add_listener(@@ -417,11 +423,18 @@ int chroma_render_wallpaper(chroma_state_t *state, chroma_output_t *output) { wl_surface_damage_buffer(output->surface, 0, 0, output->width, output->height); wl_surface_commit(output->surface);- wl_display_flush(state->display);+ if (wl_display_flush(state->display) < 0) {+ chroma_log("ERROR", "Failed to flush Wayland display for output %u: %s",+ output->id, strerror(errno));+ return CHROMA_ERROR_WAYLAND;+ } chroma_log("INFO", "Rendered wallpaper to output %u (%dx%d)", output->id, output->width, output->height); + // Unmap client-side memory; compositor keeps its own fd reference+ chroma_buffer_unmap(output);+ // Release image reference and free CPU data if no longer needed if (output->image) { chroma_image_t *image = output->image;