Files
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

141 lines
3.2 KiB
TypeScript

import {
DESKTOP_WINDOW_BASE_Z_INDEX,
DESKTOP_WINDOW_CASCADE_OFFSET,
DESKTOP_WINDOW_MIN_HEIGHT,
DESKTOP_WINDOW_MIN_WIDTH,
DESKTOP_WINDOW_TOP_MARGIN
} from "./constants";
import { clampWindowRect, resolveDesktopBottomInset } from "./placement";
import type { DesktopSize, WindowQuickLayoutTarget, WindowRect } from "./types";
export function resolveWindowLayoutFrame(desktopSize: DesktopSize): WindowRect {
return {
x: 0,
y: DESKTOP_WINDOW_TOP_MARGIN,
width: Math.max(DESKTOP_WINDOW_MIN_WIDTH, desktopSize.width),
height: Math.max(
DESKTOP_WINDOW_MIN_HEIGHT,
desktopSize.height -
resolveDesktopBottomInset(desktopSize) -
DESKTOP_WINDOW_TOP_MARGIN
)
};
}
export function resolveQuickLayoutRect(
target: WindowQuickLayoutTarget,
desktopSize: DesktopSize
): WindowRect {
const frame = resolveWindowLayoutFrame(desktopSize);
switch (target) {
case "left":
return {
...frame,
width: Math.round(frame.width / 4)
};
case "right": {
const width = Math.round(frame.width / 4);
return {
...frame,
x: frame.x + frame.width - width,
width
};
}
case "top":
return {
...frame,
height: Math.round(frame.height / 2)
};
case "bottom": {
const height = Math.round(frame.height / 2);
return {
...frame,
y: frame.y + frame.height - height,
height
};
}
}
}
export function resolveFullscreenRect(desktopSize: DesktopSize): WindowRect {
return {
x: 0,
y: DESKTOP_WINDOW_TOP_MARGIN,
width: Math.max(DESKTOP_WINDOW_MIN_WIDTH, desktopSize.width),
height: Math.max(
DESKTOP_WINDOW_MIN_HEIGHT,
desktopSize.height - DESKTOP_WINDOW_TOP_MARGIN
)
};
}
export function resolveLowerRightAnchoredRect({
anchor,
desktopSize,
width,
height
}: {
anchor: WindowRect;
desktopSize: DesktopSize;
width: number;
height: number;
}): WindowRect {
return clampWindowRect(
{
x: anchor.x + DESKTOP_WINDOW_CASCADE_OFFSET,
y: anchor.y + DESKTOP_WINDOW_CASCADE_OFFSET,
width,
height
},
desktopSize
);
}
export function appendWindowToStack(
stack: readonly string[],
id: string
): string[] {
return stack.includes(id) ? [...stack] : [...stack, id];
}
export function focusWindowInStack(
stack: readonly string[],
id: string
): string[] {
if (!stack.includes(id)) {
return appendWindowToStack(stack, id);
}
return [...stack.filter((windowId) => windowId !== id), id];
}
export function removeWindowFromStack(
stack: readonly string[],
id: string
): string[] {
return stack.filter((windowId) => windowId !== id);
}
export function replaceWindowStack(
stack: readonly string[],
nextIds: readonly string[]
): string[] {
const nextIdSet = new Set(nextIds);
const existing = stack.filter((id) => nextIdSet.has(id));
const existingSet = new Set(existing);
const appended = nextIds.filter((id) => !existingSet.has(id));
return [...existing, ...appended];
}
export function deriveWindowZIndex(
stack: readonly string[],
id: string,
baseZIndex = DESKTOP_WINDOW_BASE_Z_INDEX
): number {
const index = stack.indexOf(id);
return baseZIndex + Math.max(0, index);
}