Implement Wayland text rendering + frame titlebar/resizebar

Text rendering uses the existing WINGs PangoFT2 backend — WMDrawString
renders directly into the frame buffer's pixman_image_t.

- Menu entries: real text via PangoFT2 (entry text + shortcut labels)
- Dock/clip icon titles: rendered with icon_title_font
- Frame titlebar: solid background + centered title text
- Frame resizebar: beveled grey bar

All text is anti-aliased (PangoFT2 alpha compositing onto pixman).
This commit is contained in:
Levi Neely 2026-05-13 14:27:11 +02:00
parent 582e527aea
commit b663ab8360
1 changed files with 108 additions and 19 deletions

View File

@ -6199,8 +6199,17 @@ static void wl_appicon_paint(WAppIcon *aicon)
/* 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 */
WMDrawable d = (WMDrawable)(uintptr_t)fb->image;
int fh = WMFontHeight(scr->icon_title_font);
int tw = WMWidthOfString(scr->icon_title_font, icon->icon_name,
strlen(icon->icon_name));
int tx = (size - tw) / 2;
if (tx < 2) tx = 2;
int ty = fh; /* baseline near top */
WMColor *color = scr->icon_title_color;
if (color)
WMDrawString(scr->wmscreen, d, color, scr->icon_title_font,
tx, ty, icon->icon_name, strlen(icon->icon_name));
}
RReleaseImage(tile);
@ -6375,29 +6384,34 @@ static void wl_menu_paint_entry(WMenu *menu, int index, int selected)
/* Background color */
uint32_t bg;
if (selected) {
bg = 0xFF4A6984; /* selection blue */
bg = 0xFF4A6984;
} else {
bg = 0xFFAEAAAE; /* menu grey */
bg = 0xFFAEAAAE;
}
/* 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);
/* Draw text using WINGs font backend (renders via PangoFT2 → pixman) */
WMColor *color = selected ? scr->select_text_color :
(entry->flags.enabled ? scr->mtext_color : scr->dtext_color);
WMFont *font = scr->menu_entry_font;
WMDrawable d = (WMDrawable)(uintptr_t)fb->image;
/* 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;
if (entry->text && font && color) {
int text_y = y + 3 + WMFontHeight(font) - 1;
WMDrawString(scr->wmscreen, d, color, font,
8, text_y, entry->text, strlen(entry->text));
}
if (entry->rtext && entry->cascade < 0 && font && color) {
int tw = WMWidthOfString(font, entry->rtext, strlen(entry->rtext));
int text_y = y + 3 + WMFontHeight(font) - 1;
WMDrawString(scr->wmscreen, d, color, font,
w - 8 - tw, text_y, entry->rtext, strlen(entry->rtext));
}
(void)scr;
wlr_scene_buffer_set_buffer(fb->scene_buf, &fb->base);
}
@ -6460,8 +6474,83 @@ static unsigned long wl_keysym_from_name(const char *name)
return (unsigned long)xkb_keysym_from_name(name, XKB_KEYSYM_NO_FLAGS);
}
static void wl_noop_frame_paint_resizebar(WFrameWindow *fwin) { (void)fwin; }
static void wl_noop_frame_paint_titlebar(WFrameWindow *fwin, int state) { (void)fwin; (void)state; }
static void wl_frame_paint_resizebar(WFrameWindow *fwin)
{
if (!fwin->resizebar || !fwin->resizebar->window)
return;
struct wl_frame_buf *fb = frame_buf_find((WNativeWindow)fwin->resizebar->window);
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 bg = 0xFFAEAAAE;
uint32_t light = 0xFFDDDDDD;
uint32_t dark = 0xFF555555;
/* Fill background */
for (int row = 0; row < fb->height; row++)
for (int col = 0; col < fb->width; col++)
dst[row * stride + col] = bg;
/* Top highlight */
for (int col = 0; col < fb->width; col++)
dst[col] = light;
/* Bottom shadow */
if (fb->height > 1)
for (int col = 0; col < fb->width; col++)
dst[(fb->height - 1) * stride + col] = dark;
wlr_scene_buffer_set_buffer(fb->scene_buf, &fb->base);
}
static void wl_frame_paint_titlebar(WFrameWindow *fwin, int state)
{
if (!fwin->titlebar || !fwin->titlebar->window)
return;
struct wl_frame_buf *fb = frame_buf_find((WNativeWindow)fwin->titlebar->window);
if (!fb || !fb->image)
return;
WScreen *scr = fwin->screen_ptr;
uint32_t *dst = (uint32_t *)pixman_image_get_data(fb->image);
int stride = pixman_image_get_stride(fb->image) / 4;
/* Background: use texture color or default */
uint32_t bg;
if (fwin->title_texture[state] &&
fwin->title_texture[state]->any.type == WTEX_SOLID) {
unsigned long px = fwin->title_texture[state]->solid.normal.pixel;
bg = 0xFF000000 | (px & 0xFFFFFF);
} else {
bg = (state == 0) ? 0xFF4A6984 : 0xFF808080; /* focused blue / unfocused grey */
}
for (int row = 0; row < fb->height; row++)
for (int col = 0; col < fb->width; col++)
dst[row * stride + col] = bg;
/* Draw title text */
if (fwin->title && fwin->font && fwin->title_color[state]) {
char *title = ShrinkString(*fwin->font, fwin->title, fb->width - 12);
int titlelen = strlen(title);
int tw = WMWidthOfString(*fwin->font, title, titlelen);
int x;
switch (fwin->flags.justification) {
case WTJ_LEFT: x = 6; break;
case WTJ_RIGHT: x = fb->width - tw - 6; break;
default: x = (fb->width - tw) / 2; break;
}
int fh = WMFontHeight(*fwin->font);
int y = (fb->height - fh) / 2 + fh;
WMDrawable d = (WMDrawable)(uintptr_t)fb->image;
WMDrawString(scr->wmscreen, d, fwin->title_color[state],
*fwin->font, x, y, title, titlelen);
wfree(title);
}
wlr_scene_buffer_set_buffer(fb->scene_buf, &fb->base);
}
static WNativeWindow wl_noop_prop_get_client_leader(WNativeWindow window) { (void)window; return WNATIVE_NONE; }
static int wl_noop_prop_get_window_state(WNativeWindow window) { (void)window; return -1; }
@ -6757,8 +6846,8 @@ const WMBackend wl_backend = {
.pixmap_create_from_xbm = wl_noop_pixmap_create_from_xbm,
.pixmap_create = wl_noop_pixmap_create,
.keysym_from_name = wl_keysym_from_name,
.frame_paint_resizebar = wl_noop_frame_paint_resizebar,
.frame_paint_titlebar = wl_noop_frame_paint_titlebar,
.frame_paint_resizebar = wl_frame_paint_resizebar,
.frame_paint_titlebar = wl_frame_paint_titlebar,
.prop_get_client_leader = wl_noop_prop_get_client_leader,
.prop_get_window_state = wl_noop_prop_get_window_state,
.setup_modifier_lock_masks = wl_noop_setup_modifier_lock_masks,