The win7 skin is frameless so 7.css can draw the Aero caption, and on GTK that means undecorated, which takes the window manager's resize borders and corner grips with it. All three win7 windows were completely unresizable. electrobun 1.18.1 offers nothing to re-enable, verified against the shipped binary rather than assumed: libNativeWrapper exports startWindowMove/ stopWindowMove with no resize counterpart, imports gtk_window_begin_move_drag but not gtk_window_begin_resize_drag, dragRegions.ts implements moving only, and BrowserWindow has neither setResizable nor min-size options. But the window is still programmatically resizable, so only the input affordance is missing: eight handles overlay the frame and drag it through a new windowGetFrame/windowSetFrame pair on the shared windowControlHandlers factory, which gives all three window kinds resize with no per-window wiring. Three things that would have made this quietly wrong: - dragRegions.ts starts a window MOVE from a mousedown listener on document, never checks defaultPrevented, and is not suppressed by a pointerdown handler either (the compatibility mousedown still fires). Every handle carries app-region-no-drag, which short-circuits its check first. - deltas come from screenX, not clientX: a north/west resize moves the window origin under a stationary pointer, so client coords feed that back into the next delta and the window runs away. - the min-size clamp re-anchors the opposite edge; clamping width alone lets x keep tracking the pointer, walking the window off-screen while it looks frozen. This is a stopgap and the point is that it is removable on sight. The frame math is a dependency-free module so scripts/resize-math-probe.ts asserts all eight edges without a window (verified it catches the unanchored-clamp bug: x jumps to 5100 instead of parking at 460). scripts/check-electrobun-resize.ts scans the installed electrobun for the primitives this is waiting on and prints the removal checklist when they appear; it runs from postinstall so a version bump surfaces it, never fails an install, and is silent otherwise. Both trigger paths were simulated. The component header carries the full checklist; docs cover the platform consequence and the dragRegions traps. Harness diffs exactly 0 in both themes; hover and menu probes still clean. Not yet exercised with a real pointer — that needs a live window. Co-Authored-By: Claude <noreply@anthropic.com>
74 lines
2.7 KiB
HTML
74 lines
2.7 KiB
HTML
<!-- .window.glass is 7.css's Aero frame (radius, 1px border, inset highlight,
|
|
drop shadow, backdrop blur); .active is what un-greys the title bar and its
|
|
control glyphs — every .title-bar-controls rule is keyed on it. -->
|
|
<div class="window glass w7-frame flex h-screen flex-col" [class.active]="windowFocused()">
|
|
@if (!rpc.available) {
|
|
<div class="flex flex-1 items-center justify-center">
|
|
<div class="max-w-sm rounded-lg border border-border bg-card p-6 text-center shadow-sm">
|
|
<ng-icon name="mynaXCircle" size="1.5rem" class="text-destructive" />
|
|
<p class="mt-2 text-sm font-medium">{{ i18n.t('app.notConnectedTitle') }}</p>
|
|
<p class="mt-1 text-xs text-muted-foreground">
|
|
{{ i18n.t('app.notConnectedBody') }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
} @else {
|
|
<!-- the window is frameless, so this IS the chrome -->
|
|
<app-title-bar [title]="appName" (closeRequested)="closeWindow()" />
|
|
|
|
<!-- 7.css's .window-body: the recessed inner panel, with the 6px inset and
|
|
its own border that give a Win7 window its depth. -->
|
|
<div class="window-body flex min-h-0 flex-1 flex-col overflow-hidden">
|
|
<app-tab-bar />
|
|
|
|
<main class="flex min-h-0 flex-1 divide-x divide-border">
|
|
<app-file-panel side="left" />
|
|
<app-file-panel side="right" />
|
|
</main>
|
|
|
|
<app-transfer-bar />
|
|
<app-status-bar />
|
|
</div>
|
|
}
|
|
|
|
<!-- modal block: the connection-manager window owns the app until closed -->
|
|
@if (managerOpen()) {
|
|
<div
|
|
class="fixed inset-0 z-60 flex items-center justify-center bg-black/40"
|
|
(mousedown)="focusManager()"
|
|
>
|
|
<div class="rounded-lg border border-border bg-card px-5 py-4 text-center shadow-xl">
|
|
<ng-icon name="mynaServers" size="1.25rem" class="text-muted-foreground" />
|
|
<p class="mt-1.5 text-xs text-muted-foreground">{{ i18n.t('app.managerOpen') }}</p>
|
|
<button
|
|
class="mt-3 rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90"
|
|
>
|
|
{{ i18n.t('app.showConnections') }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- dialogs -->
|
|
@if (dialogs.prompt(); as req) {
|
|
<app-prompt-dialog [request]="req" />
|
|
}
|
|
@if (dialogs.confirm(); as req) {
|
|
<app-confirm-dialog [request]="req" />
|
|
}
|
|
@if (dialogs.chmod(); as req) {
|
|
<app-chmod-dialog [request]="req" />
|
|
}
|
|
@if (dialogs.overwrite(); as req) {
|
|
<app-overwrite-dialog [request]="req" />
|
|
}
|
|
|
|
<!-- STOPGAP: the frameless window has no WM resize borders, so we draw our
|
|
own handles. Delete with the rest of the hack — checklist in
|
|
window-resize/window-resize.ts. -->
|
|
<app-window-resize />
|
|
|
|
<app-context-menu />
|
|
<app-toasts />
|
|
</div>
|