From 26da45c34cb072cdf9db256d8b6e015bc10aef81 Mon Sep 17 00:00:00 2001 From: jelveh Date: Tue, 21 Jul 2026 15:05:31 -0700 Subject: [PATCH] fix(gui): keep the minimize-morph ghost icon square (contain-fit) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The icon clone previously mapped rect-onto-rect over the window, which stretched the square icon anamorphically. A covering square was tried and jittered: it protruded past the card's short edge and the halo popped in mid-crossfade. Contain-fit resolves both: the ghost scales uniformly (always square), sized to the window's short edge and centered — its side tracks the card's short edge exactly for the whole flight (both interpolate linearly between the same endpoints on the same curve), so the card's rectangular flanks melt away around a steady, undistorted icon. --- src/gui/src/UI/UIWindow.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/gui/src/UI/UIWindow.js b/src/gui/src/UI/UIWindow.js index ccadf20c0..3182f49a0 100644 --- a/src/gui/src/UI/UIWindow.js +++ b/src/gui/src/UI/UIWindow.js @@ -4077,7 +4077,23 @@ $.fn.hideWindow = async function (options) { ghost.style.transformOrigin = 'top left'; ghost.style.willChange = 'transform, opacity'; ghost.style.opacity = '0'; - ghost.style.transform = `translate(${win_rect.left - icon_rect.left}px, ${win_rect.top - icon_rect.top}px) scale(${win_rect.width / icon_rect.width}, ${win_rect.height / icon_rect.height})`; + // UNIFORM start scale so the icon stays square (a + // rect-onto-rect mapping stretches it), sized to fit + // INSIDE the window (contain, centered) — a covering + // square would protrude past the card's short edge + // and the protruding halo pops in mid-crossfade + // (visible jitter). Contained, the ghost's side + // tracks the card's short edge exactly for the whole + // flight (both interpolate linearly between the same + // start and end sizes), so the card's rectangular + // flanks simply melt away around a steady square. + const ghost_scale = Math.min( + win_rect.width / icon_rect.width, + win_rect.height / icon_rect.height, + ); + const ghost_left = win_rect.left + (win_rect.width - icon_rect.width * ghost_scale) / 2; + const ghost_top = win_rect.top + (win_rect.height - icon_rect.height * ghost_scale) / 2; + ghost.style.transform = `translate(${ghost_left - icon_rect.left}px, ${ghost_top - icon_rect.top}px) scale(${ghost_scale})`; document.body.appendChild(ghost); icon.style.visibility = 'hidden';