Metal: harden fringe and clear_frame against cycle-less calls
Wrap mtl_draw_fringe_bitmap and mtl_clear_frame in the same self-contained immediate frame used by draw_glyph_string (begin, draw, commit with deferred present) so they are not silently dropped when invoked outside update_begin/end (clear_garbaged_frames runs before the update cycle; fringe updates can arrive immediately too). Also make the fringe clear run even when the bitmap is empty (a clear-only call). Note: a tiny stale shard can still remain in the echo-area fringe corner after a multi-line message shrinks the minibuffer back. Root cause is that NS repaints uncovered regions through its expose path (drawRect: re-renders from the glyph matrices), which the Metal layer does not have yet; tracked in TODO.org.
This commit is contained in:
parent
333c1a582e
commit
6663cfcd5f
1 changed files with 38 additions and 12 deletions
|
|
@ -2498,10 +2498,24 @@ mtl_clear_frame (struct frame *f)
|
|||
{
|
||||
MtlFrameData *fd = mtl_get_frame_data (f);
|
||||
if (!fd) return;
|
||||
|
||||
/* clear_garbaged_frames calls this BEFORE update_begin (no encoder), e.g.
|
||||
when the minibuffer resizes back after a two-line message. The redraw
|
||||
that follows assumes the frame is really clear and only paints rows with
|
||||
content, so silently dropping this fill left stale pixels behind (a
|
||||
leftover continuation arrow in the echo area's fringe). Run it as a
|
||||
committed immediate frame with a deferred present, like
|
||||
mtl_draw_glyph_string. */
|
||||
BOOL immediate = (fd.encoder == nil);
|
||||
if (immediate) [fd beginFrame];
|
||||
|
||||
NSRect bounds = fd.metalLayer ? CGRectMake (0, 0,
|
||||
fd.metalLayer.frame.size.width,
|
||||
fd.metalLayer.frame.size.height) : NSZeroRect;
|
||||
[fd fillRect:bounds color:ns_color_to_pixel (FRAME_BACKGROUND_COLOR (f))];
|
||||
|
||||
if (immediate)
|
||||
[fd endFramePresent:NO];
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2808,7 +2822,15 @@ static void mtl_draw_fringe_bitmap (struct window *w,
|
|||
(void)row;
|
||||
struct frame *f = WINDOW_XFRAME (w);
|
||||
MtlFrameData *fd = mtl_get_frame_data (f);
|
||||
if (!fd || !fd.encoder) return;
|
||||
if (!fd) return;
|
||||
|
||||
/* Like mtl_draw_glyph_string: fringe updates can arrive outside the
|
||||
update_begin/end cycle (e.g. clearing the continuation arrow when the
|
||||
echo area shrinks back to one line). Dropping them left stale bitmaps
|
||||
behind; wrap the draw in its own committed frame with a deferred
|
||||
present. */
|
||||
BOOL immediate = (fd.encoder == nil);
|
||||
if (immediate) [fd beginFrame];
|
||||
|
||||
struct face *face = p->face;
|
||||
unsigned long bg = face ? face->background
|
||||
|
|
@ -2823,12 +2845,12 @@ static void mtl_draw_fringe_bitmap (struct window *w,
|
|||
[fd fillRect:NSMakeRect (p->x, p->y, p->wd, p->h) color:bg];
|
||||
}
|
||||
|
||||
if (!p->bits || p->wd <= 0 || p->h <= 0)
|
||||
return;
|
||||
|
||||
if (p->bits && p->wd > 0 && p->h > 0)
|
||||
{
|
||||
unsigned long color;
|
||||
if (!p->cursor_p)
|
||||
color = face ? face->foreground : ns_color_to_pixel (FRAME_FOREGROUND_COLOR (f));
|
||||
color = face ? face->foreground
|
||||
: ns_color_to_pixel (FRAME_FOREGROUND_COLOR (f));
|
||||
else if (p->overlay_p)
|
||||
color = bg;
|
||||
else
|
||||
|
|
@ -2838,6 +2860,10 @@ static void mtl_draw_fringe_bitmap (struct window *w,
|
|||
atX:p->x y:p->y color:color];
|
||||
}
|
||||
|
||||
if (immediate)
|
||||
[fd endFramePresent:NO];
|
||||
}
|
||||
|
||||
static void mtl_define_fringe_bitmap (int w, unsigned short *b, int h, int wd)
|
||||
{ (void)w; (void)b; (void)h; (void)wd; }
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue