From c8dd05ddf42eea11f802770418b7f9d67f2cffb0 Mon Sep 17 00:00:00 2001 From: ciregenz Date: Fri, 7 Aug 2026 19:00:58 -0700 Subject: [PATCH] [eric] canvas: tiling insets below the top drag strip, so a fullscreen window stops losing its top edge to window-drag --- .../src/app/components/Layout/AppShell.tsx | 4 ++- .../pages/Dashboard/canvas/tiledGeometry.ts | 29 +++++++++++++++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/components/Layout/AppShell.tsx b/frontend/src/app/components/Layout/AppShell.tsx index 753cba04..64b13179 100644 --- a/frontend/src/app/components/Layout/AppShell.tsx +++ b/frontend/src/app/components/Layout/AppShell.tsx @@ -444,7 +444,9 @@ const AppShell: React.FC = () => { {/* Sidebar retired: dashboards switch via the macOS-Spaces top strip; a slim band below the spaces hot zone keeps the frameless window draggable (the sidebar's drag strip is gone). */} {isDashboardViewActive && !v3FlowActive && } - + {/* Tagged so tiling can inset below it: this strip is a window-DRAG region, so anything tiled + underneath it loses those pixels to dragging the OS window instead of taking clicks. */} + {/* Top bar dropped (Arc/Zen): a zero-height anchor left only to float the agent-activity island at top-center; the island renders nothing when idle. */} vp.left + vp.width * 0.75 ? vp.right - r.left + GAP : 0; } +// How far down the top chrome reaches into the viewport. Same shape as edgeInset: absent or +// non-overlapping chrome yields 0, never a bogus inset. +function topInset(vp: DOMRect): number { + let deepest = 0; + document.querySelectorAll('[data-top-chrome]').forEach((el) => { + const r = el.getBoundingClientRect(); + if (!(r.height > 0) || r.bottom <= vp.top) return; + if (r.top > vp.top + vp.height * 0.25) return; + deepest = Math.max(deepest, r.bottom - vp.top); + }); + return deepest; +} + function measureWorkspace(): Workspace { const el = document.querySelector('[data-canvas-viewport]'); const r = el?.getBoundingClientRect(); - if (!r || !(r.width > 0 && r.height > 0)) return { x0: 0, x1: 0, w: window.innerWidth, h: window.innerHeight }; + if (!r || !(r.width > 0 && r.height > 0)) return { x0: 0, x1: 0, y0: 0, w: window.innerWidth, h: window.innerHeight }; // macOS model: a tiled window sits BESIDE the Dock and beside the minimized rail, never under either. return { x0: edgeInset('[data-desktop-dock]', r, 'left'), x1: edgeInset('[data-minimized-rail]', r, 'right'), + y0: topInset(r), w: r.width, h: r.height, }; @@ -77,16 +95,17 @@ function measureWorkspace(): Workspace { export function zoneRect(zone: string): ZoneRect | null { const ws = workspace ?? (workspace = measureWorkspace()); const usableW = ws.w - ws.x0 - ws.x1; + const usableH = ws.h - ws.y0; if (zone === 'fullscreen') { - return { x: ws.x0 + GAP, y: GAP, w: usableW - GAP * 2, h: ws.h - GAP * 2 }; + return { x: ws.x0 + GAP, y: ws.y0 + GAP, w: usableW - GAP * 2, h: usableH - GAP * 2 }; } const z = TILE_ZONES[zone]; if (!z) return null; return { x: ws.x0 + z.x * usableW + GAP, - y: z.y * ws.h + GAP, + y: ws.y0 + z.y * usableH + GAP, w: z.w * usableW - GAP * 2, - h: z.h * ws.h - GAP * 2, + h: z.h * usableH - GAP * 2, }; }