fix(panes): only the main window may drive the tray; clamp fallback defaults

1. pane:sync was accepted from ANY renderer with the preload bridge. Pane
   windows are same-origin top-level frames, so preload's isMainFrame gate hands
   them the bridge too — which means a pane window (or any allowed pop-up) could
   send pane:sync and overwrite the tray's registry, most simply by pushing an
   empty list and emptying the menu.

   Exactly one renderer owns the pane registry. It is now accepted from that one
   only: event.sender must be the main window's webContents.

2. sanitizeWindowBounds returned sizing.defaultWidth/Height unclamped. The min
   clamp only runs when `saved` parses, so a caller whose defaults undercut its
   own minimums would get a window below the floor on precisely the paths where
   nothing is saved — first launch, or a corrupt config — and a correctly sized
   one everywhere else.

   That is the worst shape a bug can have: invisible in the common case, and
   visible only to a new user. The fallback is clamped to the floor now, with a
   test.

window-bounds: 14/14.
Signed-off-by: topkoa <topkoa@gmail.com>
This commit is contained in:
topkoa
2026-07-12 21:18:05 -04:00
parent 313d1e5d5b
commit 030559dd38
3 changed files with 39 additions and 2 deletions
+15
View File
@@ -95,3 +95,18 @@ test('omitting sizing keeps the main window behaviour exactly as before', () =>
const out = sanitizeWindowBounds({ x: 10, y: 10, width: 50, height: 20 }, [PRIMARY]);
assert.deepEqual(out, { x: 10, y: 10, width: MIN_WIDTH, height: MIN_HEIGHT, maximized: false });
});
test('custom sizing: defaults below the configured minimum are clamped up', () => {
// A caller whose defaults undercut its own floor. The min clamp only runs on
// saved bounds, so without clamping the fallback too, the floor would hold
// everywhere EXCEPT first launch and a corrupt config — i.e. only for new users.
const silly = { minWidth: 240, minHeight: 180, defaultWidth: 100, defaultHeight: 50 };
assert.deepEqual(
sanitizeWindowBounds(undefined, [PRIMARY], silly),
{ width: 240, height: 180, maximized: false },
);
assert.deepEqual(
sanitizeWindowBounds({ x: 0, y: 0, width: 'bad', height: 'bad' }, [PRIMARY], silly),
{ width: 240, height: 180, maximized: false },
);
});