diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 32d77b3..3e89a3d 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -191,6 +191,8 @@ #include "../../xmodifier.h" /* Phase 77: wSetModifierMasks */ #include "../../event.h" /* Phase 78: wWaylandKeyPress */ #include "../../wmspec.h" /* Phase 30+: get_window_image_from_x11 */ +#include "../../icon.h" /* WIcon, TILE_* */ +#include "../../appicon.h" /* WAppIcon */ #include "../backend.h" #include "wl_backend.h" @@ -6138,7 +6140,75 @@ static char *wl_get_command_for_window(WNativeWindow win, int elements) static void wl_noop_icon_update_pixmap(WIcon *icon) { (void)icon; } static void wl_noop_icon_paint(WIcon *icon) { (void)icon; } static void wl_noop_appicon_show(WApplication *wapp) { (void)wapp; } -static void wl_noop_appicon_paint(WAppIcon *aicon) { (void)aicon; } +static void wl_appicon_paint(WAppIcon *aicon) +{ + WIcon *icon = aicon->icon; + if (!icon || !icon->core) + return; + + struct wl_frame_buf *fb = frame_buf_find((WNativeWindow)icon->core->window); + if (!fb || !fb->image) + return; + + WScreen *scr = icon->core->screen_ptr; + int size = wPreferences.icon_size; + + /* Compose the tile image */ + RImage *tile = NULL; + switch (icon->tile_type) { + case TILE_CLIP: tile = scr->clip_tile ? RCloneImage(scr->clip_tile) : NULL; break; + case TILE_DRAWER: tile = scr->drawer_tile ? RCloneImage(scr->drawer_tile) : NULL; break; + default: tile = scr->icon_tile ? RCloneImage(scr->icon_tile) : NULL; break; + } + if (!tile) { + /* Fallback: solid grey */ + tile = RCreateImage(size, size, 1); + if (!tile) return; + RColor grey = {0xAE, 0xAA, 0xAE, 0xFF}; + RClearImage(tile, &grey); + } + + /* Composite the app image on top */ + if (icon->file_image) { + RImage *img = icon->file_image; + int theight = icon->show_title ? WMFontHeight(scr->icon_title_font) : 0; + unsigned w = (img->width > size) ? size : img->width; + unsigned h = (img->height + theight > size) ? size - theight : img->height; + int x = (size - (int)w) / 2; + int y = theight + (size - theight - (int)h) / 2; + int sx = ((int)img->width - (int)w) / 2; + int sy = ((int)img->height - (int)h) / 2; + RCombineArea(tile, img, sx, sy, w, h, x, y); + } + + /* Blit RImage (RGBA) → pixman ARGB32 buffer */ + uint32_t *dst = (uint32_t *)pixman_image_get_data(fb->image); + int stride = pixman_image_get_stride(fb->image) / 4; + unsigned char *src = tile->data; + int has_alpha = (tile->format == RRGBAFormat); + + for (int row = 0; row < size && row < fb->height; row++) { + for (int col = 0; col < size && col < fb->width; col++) { + int si = (row * tile->width + col) * (has_alpha ? 4 : 3); + unsigned char r = src[si], g = src[si+1], b = src[si+2]; + unsigned char a = has_alpha ? src[si+3] : 0xFF; + dst[row * stride + col] = ((uint32_t)a << 24) | ((uint32_t)r << 16) | + ((uint32_t)g << 8) | (uint32_t)b; + } + } + + /* Draw title text */ + if (icon->show_title && icon->icon_name && scr->icon_title_font) { + /* Simple: just render text at bottom of icon */ + /* TODO: proper text rendering with pango/pixman */ + } + + RReleaseImage(tile); + + /* Commit to scene graph */ + wlr_scene_buffer_set_buffer(fb->scene_buf, &fb->base); + wlr_scene_node_set_enabled(&fb->scene_buf->node, true); +} static void wl_noop_restore_desktop(WScreen *scr) { (void)scr; } static void wl_noop_wipe_desktop(WScreen *scr) { (void)scr; } @@ -6221,8 +6291,6 @@ static int wl_get_color_for_colormap(unsigned long colormap, {"blue", 0x0000, 0x0000, 0xFFFF}, {"gray", 0xBEBE, 0xBEBE, 0xBEBE}, {"grey", 0xBEBE, 0xBEBE, 0xBEBE}, - {"gray50", 0x7F7F, 0x7F7F, 0x7F7F}, - {"gray80", 0xCCCC, 0xCCCC, 0xCCCC}, {"darkgray",0xA9A9, 0xA9A9, 0xA9A9}, {"darkgrey",0xA9A9, 0xA9A9, 0xA9A9}, {"lightgray",0xD3D3, 0xD3D3, 0xD3D3}, @@ -6242,6 +6310,18 @@ static int wl_get_color_for_colormap(unsigned long colormap, } } + /* grayNN / greyNN (0-100) */ + if ((strncasecmp(color_name, "gray", 4) == 0 || strncasecmp(color_name, "grey", 4) == 0) + && color_name[4] >= '0' && color_name[4] <= '9') { + int pct = atoi(color_name + 4); + if (pct >= 0 && pct <= 100) { + unsigned int v = (pct * 255 + 50) / 100; + color->red = color->green = color->blue = v << 8 | v; + color->pixel = (0xFF << 24) | (v << 16) | (v << 8) | v; + return 1; + } + } + wwarning(_("could not parse color \"%s\" (Wayland)"), color_name); return 0; } @@ -6578,7 +6658,7 @@ const WMBackend wl_backend = { .icon_update_pixmap = wl_noop_icon_update_pixmap, .icon_paint = wl_noop_icon_paint, .appicon_show = wl_noop_appicon_show, - .appicon_paint = wl_noop_appicon_paint, + .appicon_paint = wl_appicon_paint, .restore_desktop = wl_noop_restore_desktop, .wipe_desktop = wl_noop_wipe_desktop, .get_color_for_colormap = wl_get_color_for_colormap, diff --git a/src/dock.c b/src/dock.c index 6f37900..e3d9454 100644 --- a/src/dock.c +++ b/src/dock.c @@ -1315,6 +1315,8 @@ WDock *wDockCreate(WScreen *scr, int type, const char *name) dock->auto_collapse = 1; } + dockIconPaint(btn); + return dock; } @@ -1925,6 +1927,12 @@ WDock *wDockRestoreState(WScreen *scr, WMPropList *dock_state, int type) finish: WMReleasePropList(dock_state); + /* Paint all dock icons (Wayland has no Expose events on map) */ + for (i = 0; i < dock->max_icons; i++) { + if (dock->icon_array[i]) + dockIconPaint(dock->icon_array[i]); + } + return dock; }