Metal: animated cursor uses the real frame color, no double cursor

When the animation layer is enabled, draw the cursor only in the
compositor (skip the static one in mtl_draw_window_cursor) so there is
no double cursor, and feed the animator the real FRAME_CURSOR_COLOR
instead of the hardcoded cyan used for the trail and cursor quads.
This commit is contained in:
Andros Fenollosa 2026-06-02 14:39:43 +02:00
parent 4b29e4bc8f
commit 277b69ddca
2 changed files with 40 additions and 28 deletions

View file

@ -99,6 +99,7 @@ typedef struct mtl_spring {
/* Cursor state */
@property (nonatomic, assign) float curTargetX, curTargetY; /* Emacs target */
@property (nonatomic, assign) float curTargetW, curTargetH;
@property (nonatomic, assign) unsigned long cursorColor; /* real frame cursor color */
@property (nonatomic, assign) MtlSpring1D springX, springY; /* animated pos */
@property (nonatomic, assign) BOOL cursorDirty;

View file

@ -1269,6 +1269,10 @@ easing_apply (MtlScrollEasing mode, float t)
float cy = anim.cursorMode == MTL_CURSOR_SPRING ? anim.springY.pos : anim.curTargetY;
float cw = anim.curTargetW, ch = anim.curTargetH;
/* Real frame cursor color (fed by mtl_draw_window_cursor), not cyan. */
float ccr, ccg, ccb;
unpack_color (anim.cursorColor ? anim.cursorColor : 0x88C0D0, &ccr, &ccg, &ccb);
/* 2. Torpedo trail */
if (anim.cursorMode == MTL_CURSOR_TORPEDO && anim.trailCount > 0)
{
@ -1280,7 +1284,7 @@ easing_apply (MtlScrollEasing mode, float t)
float tx = anim->trailX[slot], ty = anim->trailY[slot];
float x0=tx, y0=ty, x1=tx+cw, y1=ty+ch;
typedef struct { float x,y,r,g,b,a; } RV;
float r2=0x88/255.f,g2=0xC0/255.f,b2=0xD0/255.f;
float r2=ccr,g2=ccg,b2=ccb;
RV v[6] = {
{x0,y0,r2,g2,b2,alpha},{x1,y0,r2,g2,b2,alpha},{x0,y1,r2,g2,b2,alpha},
{x1,y0,r2,g2,b2,alpha},{x1,y1,r2,g2,b2,alpha},{x0,y1,r2,g2,b2,alpha},
@ -1294,7 +1298,7 @@ easing_apply (MtlScrollEasing mode, float t)
/* 3. Cursor (spring-interpolated position) */
{
float x0=cx, y0=cy, x1=cx+cw, y1=cy+ch;
float fr=0x88/255.f,fg=0xC0/255.f,fb=0xD0/255.f;
float fr=ccr,fg=ccg,fb=ccb;
typedef struct { float x,y,r,g,b,a; } RV;
RV v[6] = {
{x0,y0,fr,fg,fb,1},{x1,y0,fr,fg,fb,1},{x0,y1,fr,fg,fb,1},
@ -2117,6 +2121,10 @@ mtl_draw_window_cursor (struct window *w,
unsigned long cc = ns_color_to_pixel (FRAME_CURSOR_COLOR (f));
int cwidth = w->phys_cursor_width;
/* With the animation layer OFF, draw the cursor straight into the static
texture (like NS). With it ON, the compositor draws the animated cursor on
top, so skip the static one here to avoid a double cursor. */
if (!g_mtl_animations_enabled)
switch (cursor_type)
{
case DEFAULT_CURSOR:
@ -2141,11 +2149,14 @@ mtl_draw_window_cursor (struct window *w,
break;
}
/* Keep the animator target in sync for when the animation layer is enabled.
With animations off this has no visible effect. */
/* Feed the animator the target position and the real cursor color so the
compositor can draw the animated cursor (no hardcoded cyan). */
if (g_mtl_animations_enabled && fd.animator)
{
fd.animator.cursorColor = cc;
[fd.animator setCursorX:fx y:fy width:cwidth height:h];
}
}
static void
mtl_draw_vertical_window_border (struct window *w, int x, int y0, int y1)