From 4b29e4bc8fb38e9557b316d8b5df81da5eb58078 Mon Sep 17 00:00:00 2001 From: Andros Fenollosa Date: Tue, 2 Jun 2026 07:14:30 +0200 Subject: [PATCH] Metal: draw face box / 3D relief (F2) mtl_draw_glyph_string ignored face->box, so boxed faces (mode line with its released-button relief, buttons, etc.) rendered flat. Port ns_dumpglyphs_box_or_relief: compute the box rect and left/right edge presence from the glyph string, then draw the four edges. FACE_SIMPLE_BOX uses box_color; raised/sunken reliefs use highlight/shadow shades of the base (box_color or background) at level 0.4, matching NSColor highlightWithLevel:/shadowWithLevel:. Mode line now shows its 3D border; the bottom/right shadow matches NS. The top/left highlight is a touch brighter than NS (subtle 1px), to refine later. --- src/mtlterm.m | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/mtlterm.m b/src/mtlterm.m index f03f44df9f7..d8e1495980f 100644 --- a/src/mtlterm.m +++ b/src/mtlterm.m @@ -1763,6 +1763,68 @@ int mtl_dgs_nofd_count = 0; /* no fd or encoder */ int mtl_dgs_nofont_count = 0; /* no ctfont */ int mtl_dgs_drawn_count = 0; /* glyphs actually drawn */ +/* Lighten (toward white) or darken (toward black) COLOR by LEVEL [0,1]. + Matches NSColor highlightWithLevel:/shadowWithLevel: closely enough for the + relief shadows. */ +static unsigned long +mtl_shade_color (unsigned long c, double level, bool lighten) +{ + double r = (c >> 16) & 0xff, g = (c >> 8) & 0xff, b = c & 0xff; + if (lighten) { r += (255 - r) * level; g += (255 - g) * level; b += (255 - b) * level; } + else { r *= (1.0 - level); g *= (1.0 - level); b *= (1.0 - level); } + return ((unsigned long) r << 16) | ((unsigned long) g << 8) | (unsigned long) b; +} + +/* Draw the face box / relief around glyph string S (mode line, buttons, etc.). + Ports ns_dumpglyphs_box_or_relief + ns_draw_box/ns_draw_relief with simple + rectangle edges (good enough for the typical 1px relief). */ +static void +mtl_draw_glyph_string_box (struct glyph_string *s, MtlFrameData *fd) +{ + struct face *face = s->face; + if (!face || face->box == FACE_NO_BOX) return; + + int hth = abs (face->box_horizontal_line_width); + int vth = abs (face->box_vertical_line_width); + if (hth == 0 && vth == 0) return; + + struct glyph *last_glyph = s->first_glyph + s->nchars - 1; + int last_x = (s->row->full_width_p && !s->w->pseudo_window_p) + ? WINDOW_RIGHT_EDGE_X (s->w) + : window_box_right (s->w, s->area); + int right_x = (s->row->full_width_p && s->extends_to_end_of_line_p + ? last_x - 1 + : min (last_x, s->x + s->background_width) - 1); + bool left_p = s->first_glyph->left_box_line_p; + bool right_p = last_glyph->right_box_line_p; + + int x = s->x, y = s->y, w = right_x - s->x + 1, h = s->height; + if (w <= 0 || h <= 0) return; + + unsigned long tl, br; /* top/left and bottom/right edge colors */ + if (face->box == FACE_SIMPLE_BOX) + tl = br = face->box_color; + else + { + unsigned long base = face->use_box_color_for_shadows_p + ? face->box_color : face->background; + if (s->hl == DRAW_CURSOR) + base = ns_color_to_pixel (FRAME_CURSOR_COLOR (s->f)); + unsigned long light = mtl_shade_color (base, 0.4, true); + unsigned long dark = mtl_shade_color (base, 0.4, false); + bool raised = (face->box == FACE_RAISED_BOX); + tl = raised ? light : dark; + br = raised ? dark : light; + } + + [fd fillRect:NSMakeRect (x, y, w, hth) color:tl]; /* top */ + [fd fillRect:NSMakeRect (x, y + h - hth, w, hth) color:br]; /* bottom */ + if (left_p) + [fd fillRect:NSMakeRect (x, y, vth, h) color:tl]; /* left */ + if (right_p) + [fd fillRect:NSMakeRect (x + w - vth, y, vth, h) color:br]; /* right */ +} + static void mtl_draw_glyph_string (struct glyph_string *s) { @@ -1879,6 +1941,10 @@ mtl_draw_glyph_string (struct glyph_string *s) ? fg : face->strike_through_color; [fd fillRect:NSMakeRect (s->x, sty, s->width, sth) color:sc]; } + + /* Face box / 3D relief (mode line, buttons, etc.). */ + if (face && face->box != FACE_NO_BOX) + mtl_draw_glyph_string_box (s, fd); } static void