diff --git a/README.md b/README.md index b845a61..dd14b50 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,7 @@ NEDM is a modern, feature-rich Wayland compositor built on top of wlroots, evolv ### Desktop Integration -- **Wallpaper Support**: wallpaper with multiple scaling modes - - Fill, fit, stretch, center, and tile modes - - Configurable background colors +- **Wallpaper Support**: FOR NOW USE THIRD PARTY APP LIKE SWWW CURRENT SETUP IS BROKEN - **Layer Shell Protocol**: Support for notification daemons and overlays ### Modern Wayland Features diff --git a/keybinding.c b/keybinding.c index 6b11fda..f9e7915 100644 --- a/keybinding.c +++ b/keybinding.c @@ -26,6 +26,7 @@ #include "server.h" #include "util.h" #include "view.h" +#include "wallpaper.h" #include "workspace.h" char *keybinding_action_string[] = {FOREACH_KEYBINDING(GENERATE_STRING)}; @@ -1951,7 +1952,7 @@ keybinding_configure_message(struct nedm_server *server, void keybinding_configure_wallpaper(struct nedm_server *server, struct nedm_wallpaper_config *config) { - if(config->image_path != NULL) { + if(config->image_path != NULL && strcmp(config->image_path, "assets/nedm.png") != 0) { free(server->wallpaper_config.image_path); server->wallpaper_config.image_path = strdup(config->image_path); } @@ -1960,6 +1961,10 @@ keybinding_configure_wallpaper(struct nedm_server *server, server->wallpaper_config.bg_color[1] = config->bg_color[1]; server->wallpaper_config.bg_color[2] = config->bg_color[2]; server->wallpaper_config.bg_color[3] = config->bg_color[3]; + + // Refresh wallpapers on all outputs with new configuration + nedm_wallpaper_refresh_all_outputs(server); + ipc_send_event(server, "{\"event_name\":\"configure_wallpaper\"}"); } diff --git a/meson.build b/meson.build index 8959f40..bbe0c7c 100644 --- a/meson.build +++ b/meson.build @@ -63,6 +63,7 @@ cairo = dependency('cairo') pango = dependency('pango') pangocairo = dependency('pangocairo') fontconfig = dependency('fontconfig') +gdkpixbuf = dependency('gdk-pixbuf-2.0') libinput = dependency('libinput') libevdev = dependency('libevdev') libudev = dependency('libudev') @@ -201,6 +202,7 @@ nedm_dependencies_dict = { 'pango': [pango,true], 'cairo': [cairo,true], 'pangocairo': [pangocairo,true], + 'gdkpixbuf': [gdkpixbuf,true], 'math': [math,true], } @@ -218,6 +220,7 @@ reproducible_build_versions = { 'pango': '1.56.4', 'cairo': '1.18.4', 'pangocairo': '1.56.4', + 'gdkpixbuf': '2.42.8', 'math': '-1' } diff --git a/wallpaper.c b/wallpaper.c index 627af13..4441f85 100644 --- a/wallpaper.c +++ b/wallpaper.c @@ -17,6 +17,7 @@ #include #include #include +#include struct wallpaper_buffer { struct wlr_buffer base; @@ -146,20 +147,84 @@ bool nedm_wallpaper_load_image(struct nedm_wallpaper *wallpaper, const char *pat return false; } - // Load the image using Cairo + // First try to load as PNG directly for better performance wallpaper->image_surface = cairo_image_surface_create_from_png(path); - if (cairo_surface_status(wallpaper->image_surface) != CAIRO_STATUS_SUCCESS) { - wlr_log(WLR_ERROR, "Failed to load wallpaper image: %s", path); - if (wallpaper->image_surface) { - cairo_surface_destroy(wallpaper->image_surface); - wallpaper->image_surface = NULL; + if (cairo_surface_status(wallpaper->image_surface) == CAIRO_STATUS_SUCCESS) { + // PNG loaded successfully + wallpaper->image_width = cairo_image_surface_get_width(wallpaper->image_surface); + wallpaper->image_height = cairo_image_surface_get_height(wallpaper->image_surface); + wlr_log(WLR_INFO, "Loaded PNG wallpaper: %s (%dx%d)", path, + wallpaper->image_width, wallpaper->image_height); + wallpaper->loaded = true; + return true; + } + + // PNG failed, clean up and try with GdkPixbuf for other formats + if (wallpaper->image_surface) { + cairo_surface_destroy(wallpaper->image_surface); + wallpaper->image_surface = NULL; + } + + GError *error = NULL; + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &error); + if (!pixbuf) { + wlr_log(WLR_ERROR, "Failed to load wallpaper image: %s - %s", + path, error ? error->message : "unknown error"); + if (error) { + g_error_free(error); } return false; } // Get image dimensions - wallpaper->image_width = cairo_image_surface_get_width(wallpaper->image_surface); - wallpaper->image_height = cairo_image_surface_get_height(wallpaper->image_surface); + wallpaper->image_width = gdk_pixbuf_get_width(pixbuf); + wallpaper->image_height = gdk_pixbuf_get_height(pixbuf); + + // Convert pixbuf to Cairo format + int channels = gdk_pixbuf_get_n_channels(pixbuf); + int rowstride = gdk_pixbuf_get_rowstride(pixbuf); + guchar *pixels = gdk_pixbuf_get_pixels(pixbuf); + + // Create Cairo surface + cairo_format_t format = channels >= 4 ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24; + wallpaper->image_surface = cairo_image_surface_create(format, + wallpaper->image_width, wallpaper->image_height); + + if (cairo_surface_status(wallpaper->image_surface) != CAIRO_STATUS_SUCCESS) { + wlr_log(WLR_ERROR, "Failed to create Cairo surface for wallpaper"); + g_object_unref(pixbuf); + return false; + } + + cairo_surface_flush(wallpaper->image_surface); + unsigned char *cairo_data = cairo_image_surface_get_data(wallpaper->image_surface); + int cairo_stride = cairo_image_surface_get_stride(wallpaper->image_surface); + + // Copy and convert pixel data + for (int y = 0; y < wallpaper->image_height; y++) { + guchar *src_row = pixels + y * rowstride; + unsigned char *dst_row = cairo_data + y * cairo_stride; + + for (int x = 0; x < wallpaper->image_width; x++) { + if (channels >= 4) { + // RGBA to BGRA (Cairo uses BGRA internally) + dst_row[x * 4 + 0] = src_row[x * channels + 2]; // B + dst_row[x * 4 + 1] = src_row[x * channels + 1]; // G + dst_row[x * 4 + 2] = src_row[x * channels + 0]; // R + dst_row[x * 4 + 3] = src_row[x * channels + 3]; // A + } else { + // RGB to BGRx (Cairo uses BGRx for RGB24) + dst_row[x * 4 + 0] = src_row[x * channels + 2]; // B + dst_row[x * 4 + 1] = src_row[x * channels + 1]; // G + dst_row[x * 4 + 2] = src_row[x * channels + 0]; // R + dst_row[x * 4 + 3] = 0xFF; // Alpha = opaque + } + } + } + + cairo_surface_mark_dirty(wallpaper->image_surface); + + g_object_unref(pixbuf); wlr_log(WLR_INFO, "Loaded wallpaper: %s (%dx%d)", path, wallpaper->image_width, wallpaper->image_height); @@ -336,4 +401,18 @@ void nedm_wallpaper_init(struct nedm_server *server) { (void)server; // Wallpapers are created per-output, so nothing to initialize globally wlr_log(WLR_INFO, "Wallpaper subsystem initialized"); +} + +void nedm_wallpaper_refresh_all_outputs(struct nedm_server *server) { + struct nedm_output *output; + wl_list_for_each(output, &server->outputs, link) { + if (output->wallpaper) { + // Destroy existing wallpaper + nedm_wallpaper_destroy(output->wallpaper); + output->wallpaper = NULL; + } + // Create new wallpaper with updated configuration + nedm_wallpaper_create_for_output(output); + } + wlr_log(WLR_INFO, "Refreshed wallpapers for all outputs"); } \ No newline at end of file diff --git a/wallpaper.h b/wallpaper.h index 0a3d9da..d8033d7 100644 --- a/wallpaper.h +++ b/wallpaper.h @@ -51,5 +51,6 @@ void nedm_wallpaper_destroy(struct nedm_wallpaper *wallpaper); void nedm_wallpaper_create_for_output(struct nedm_output *output); void nedm_wallpaper_render(struct nedm_wallpaper *wallpaper); bool nedm_wallpaper_load_image(struct nedm_wallpaper *wallpaper, const char *path); +void nedm_wallpaper_refresh_all_outputs(struct nedm_server *server); #endif \ No newline at end of file