From 816e4dc24ef67d7648e149c0860fe1734d61c7ad Mon Sep 17 00:00:00 2001
From: Linus Rath <139418639+rathlinus@users.noreply.github.com>
Date: Wed, 4 Nov 2026 13:22:00 +0100
Subject: [PATCH] fix: measure the window controls again after a resize, so the
desktop toolbar keeps its buttons at 800 px
---
lib/__tests__/window-controls-host.test.tsx | 22 +++++++++++++++++++++
lib/window-controls-overlay.ts | 10 +++++++++-
2 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/lib/__tests__/window-controls-host.test.tsx b/lib/__tests__/window-controls-host.test.tsx
index ee7075b60..a0d7267de 100644
--- a/lib/__tests__/window-controls-host.test.tsx
+++ b/lib/__tests__/window-controls-host.test.tsx
@@ -333,6 +333,28 @@ describe('the window controls over the app', () => {
expect(root.hasAttribute(CONTROLS_LEFT_ATTRIBUTE)).toBe(true);
});
+ // mail-p2-16: the desktop app sends geometrychange while the page still has
+ // its old width; the controls' share came out of that and stayed wrong.
+ it('measures again with the new width once the window has resized', () => {
+ const before = window.innerWidth;
+ const fake = overlayAt(0, before - 137);
+ render();
+ expect(rightInset()).toBe('137px');
+ act(() => {
+ (fake as unknown as { getTitlebarAreaRect: () => object }).getTitlebarAreaRect = () => ({ x: 0, y: 0, width: 800 - 137, height: 56 });
+ fake.dispatchEvent(new Event('geometrychange'));
+ });
+ act(() => {
+ Object.defineProperty(window, 'innerWidth', { value: 800, configurable: true, writable: true });
+ window.dispatchEvent(new Event('resize'));
+ });
+ try {
+ expect(rightInset()).toBe('137px');
+ } finally {
+ Object.defineProperty(window, 'innerWidth', { value: before, configurable: true, writable: true });
+ }
+ });
+
it('follows geometrychange, and takes everything back when the overlay goes', () => {
const fake = overlayAt(0, window.innerWidth - 138);
render();
diff --git a/lib/window-controls-overlay.ts b/lib/window-controls-overlay.ts
index d679f023f..a7b2fd302 100644
--- a/lib/window-controls-overlay.ts
+++ b/lib/window-controls-overlay.ts
@@ -104,7 +104,15 @@ export function watchTitlebarArea(listener: (area: TitlebarArea | null) => void)
if (!current) return () => {};
const onChange = () => listener(readTitlebarArea());
current.addEventListener('geometrychange', onChange);
- return () => current.removeEventListener('geometrychange', onChange);
+ // Electron sends geometrychange before the page has its new width, so the
+ // controls' share (width minus the strip) came out of the old width: 393 px
+ // at 1024, 361 at 800, the toolbar folding with room to spare (mail-p2-16).
+ // The resize that follows has the new width.
+ window.addEventListener('resize', onChange);
+ return () => {
+ current.removeEventListener('geometrychange', onChange);
+ window.removeEventListener('resize', onChange);
+ };
}
const ROW_CANDIDATES = '[data-window-top-row], [data-composer-header], header, div.h-14, div.min-h-14, div.h-12, div.h-16, div.min-h-16';