Implement Wayland clip icon + menu rendering

- Clip/drawer icons: reuse wl_appicon_paint (tile rendering)
- Menu entries: solid background fill (grey normal, blue selected)
  with placeholder text line. Full text rendering TODO.
- Menu frame: beveled border (light top/left, dark bottom/right)
- All rendering commits to scene graph via wlr_scene_buffer_set_buffer
This commit is contained in:
Levi Neely 2026-05-13 14:20:24 +02:00
parent 7e1da342be
commit 582e527aea
1 changed files with 83 additions and 10 deletions

View File

@ -193,6 +193,7 @@
#include "../../wmspec.h" /* Phase 30+: get_window_image_from_x11 */
#include "../../icon.h" /* WIcon, TILE_* */
#include "../../appicon.h" /* WAppIcon */
#include "../../menu.h" /* WMenu, WMenuEntry */
#include "../backend.h"
#include "wl_backend.h"
@ -6349,15 +6350,87 @@ static void wl_event_handle_signal_exit(void)
static void wl_noop_icon_select(WIcon *icon) { (void)icon; }
static void wl_noop_icon_change_title(WIcon *icon, WWindow *wwin) { (void)icon; (void)wwin; }
static void wl_noop_clip_icon_paint(WAppIcon *aicon) { (void)aicon; }
static void wl_noop_drawer_icon_paint(WAppIcon *aicon) { (void)aicon; }
static void wl_clip_icon_paint(WAppIcon *aicon) { wl_appicon_paint(aicon); }
static void wl_drawer_icon_paint(WAppIcon *aicon) { wl_appicon_paint(aicon); }
static void wl_noop_balloon_init(WScreen *scr) { (void)scr; }
static void wl_noop_do_kaboom(WScreen *scr, WNativeWindow win, int x, int y)
{ (void)scr; (void)win; (void)x; (void)y; }
static void wl_noop_menu_paint_entry(WMenu *menu, int index, int selected)
{ (void)menu; (void)index; (void)selected; }
static void wl_noop_menu_draw_frame(WScreen *scr, WNativeWindow win, int y, int w, int h, int type)
{ (void)scr; (void)win; (void)y; (void)w; (void)h; (void)type; }
static void wl_menu_paint_entry(WMenu *menu, int index, int selected)
{
if (!menu || !menu->menu || !menu->menu->window)
return;
struct wl_frame_buf *fb = frame_buf_find((WNativeWindow)menu->menu->window);
if (!fb || !fb->image)
return;
WScreen *scr = menu->frame->screen_ptr;
WMenuEntry *entry = menu->entries[index];
int y = menu->entry_height * index;
int h = menu->entry_height;
int w = fb->width;
uint32_t *dst = (uint32_t *)pixman_image_get_data(fb->image);
int stride = pixman_image_get_stride(fb->image) / 4;
/* Background color */
uint32_t bg;
if (selected) {
bg = 0xFF4A6984; /* selection blue */
} else {
bg = 0xFFAEAAAE; /* menu grey */
}
/* Fill entry background */
for (int row = y; row < y + h && row < fb->height; row++)
for (int col = 0; col < w; col++)
dst[row * stride + col] = bg;
/* Text color */
uint32_t fg = selected ? 0xFFFFFFFF : (entry->flags.enabled ? 0xFF000000 : 0xFF666666);
/* Simple 1px text placeholder: draw a line where text would be */
int text_y = y + h / 2;
int text_len = entry->text ? strlen(entry->text) * 7 : 0;
if (text_len > w - 16) text_len = w - 16;
if (text_y < fb->height) {
for (int col = 8; col < 8 + text_len && col < w; col++)
dst[text_y * stride + col] = fg;
}
(void)scr;
wlr_scene_buffer_set_buffer(fb->scene_buf, &fb->base);
}
static void wl_menu_draw_frame(WScreen *scr, WNativeWindow win, int y, int w, int h, int type)
{
struct wl_frame_buf *fb = frame_buf_find(win);
if (!fb || !fb->image)
return;
uint32_t *dst = (uint32_t *)pixman_image_get_data(fb->image);
int stride = pixman_image_get_stride(fb->image) / 4;
uint32_t dark = 0xFF555555;
uint32_t light = 0xFFDDDDDD;
/* Right edge */
for (int row = y; row < y + h && row < fb->height; row++)
if (w - 1 < fb->width)
dst[row * stride + (w - 1)] = dark;
/* Bottom edge */
if (y + h - 1 < fb->height)
for (int col = 0; col < w && col < fb->width; col++)
dst[(y + h - 1) * stride + col] = dark;
/* Left edge */
for (int row = y; row < y + h && row < fb->height; row++)
dst[row * stride] = light;
/* Top edge */
if (y < fb->height)
for (int col = 0; col < w && col < fb->width; col++)
dst[y * stride + col] = light;
(void)scr; (void)type;
wlr_scene_buffer_set_buffer(fb->scene_buf, &fb->base);
}
static void wl_noop_draw_bevel(WNativeWindow d, unsigned int width, unsigned int height,
WTexSolid *texture, int relief)
@ -6670,12 +6743,12 @@ const WMBackend wl_backend = {
.event_handle_signal_exit = wl_event_handle_signal_exit,
.icon_select = wl_noop_icon_select,
.icon_change_title = wl_noop_icon_change_title,
.clip_icon_paint = wl_noop_clip_icon_paint,
.drawer_icon_paint = wl_noop_drawer_icon_paint,
.clip_icon_paint = wl_clip_icon_paint,
.drawer_icon_paint = wl_drawer_icon_paint,
.balloon_init = wl_noop_balloon_init,
.do_kaboom = wl_noop_do_kaboom,
.menu_paint_entry = wl_noop_menu_paint_entry,
.menu_draw_frame = wl_noop_menu_draw_frame,
.menu_paint_entry = wl_menu_paint_entry,
.menu_draw_frame = wl_menu_draw_frame,
.draw_bevel = wl_noop_draw_bevel,
.appmenu_send = wl_noop_appmenu_send,
.display_get_name = wl_display_get_name,