hermes-agent/apps/desktop/electron/window-controls.test.ts
Austin Pickett 68df6d3d50 fix(desktop): WSLg window controls + GPU crash-loop fallback
Two WSLg-specific desktop bugs.

Window controls: getTitleBarOverlayOptions() returned false on WSLg while
the window stayed titleBarStyle:'hidden', so the frameless window had no
min/max/close and the frameless maximize settled offset from the work area.
The RDP host only decorates windows that keep a native frame, so it painted
nothing. Electron's native overlay isn't the fix either: its cluster's hit
region drifts from the rendered buttons under the RAIL compositor. The
renderer now paints its own Windows-style min/max/close driven over a
hermes:window-control IPC channel, and maximizedBoundsCorrection snaps a
maximized window back onto the display work area. Extracts titleBarOverlayOptions
into a tested helper.

Dropped an openNewSessionWindow / hermes🪟openNewSession declaration
with no handler, wired maximizedBoundsCorrection into the maximize event
(it was exported and tested but never called), and passed the correct window
to windowControlState in getWindowState.

GPU crash loop: on WSLg the /dev/dxg un-blocklist forced the vGPU on
unconditionally, and on driver stacks that fail Vulkan init
(samplerYcbcrConversion unsupported) the GPU process segfaulted (exit 139)
in a loop on every launch. decideWslgGpuLaunch now consults a sticky
per-version marker: a session that crash-loops the vGPU records a fallback
so the next launch skips the un-blocklist and rides Chromium's software
path. An app update re-probes the GPU once. New wslg-gpu-fallback.ts holds
the pure, tested marker logic.

Co-authored-by: null-runner <nicholas.mariani@hotmail.it>
2026-07-24 10:44:47 -04:00

166 lines
4.3 KiB
TypeScript

import assert from 'node:assert/strict'
import { describe, test } from 'vitest'
import {
customWindowControlsEnabled,
performWindowControl,
registerWindowControlIpc,
windowControlState
} from './window-controls'
class FakeWindow {
closed = false
focusCalls = 0
maximized = false
minimized = false
close() {
this.closed = true
}
focus() {
this.focusCalls += 1
}
isDestroyed() {
return false
}
isMaximized() {
return this.maximized
}
maximize() {
this.maximized = true
}
minimize() {
this.minimized = true
}
unmaximize() {
this.maximized = false
}
}
describe('performWindowControl', () => {
test('minimizes the sender window', () => {
const win = new FakeWindow()
assert.equal(performWindowControl(win, 'minimize'), true)
assert.equal(win.minimized, true)
})
test('toggles maximize and restore', () => {
const win = new FakeWindow()
assert.equal(performWindowControl(win, 'toggle-maximize'), true)
assert.equal(win.maximized, true)
assert.equal(performWindowControl(win, 'toggle-maximize'), true)
assert.equal(win.maximized, false)
})
test('restores keyboard focus after maximize and restore', () => {
const win = new FakeWindow()
performWindowControl(win, 'toggle-maximize')
assert.equal(win.focusCalls, 1)
performWindowControl(win, 'toggle-maximize')
assert.equal(win.focusCalls, 2)
})
test('closes the sender window', () => {
const win = new FakeWindow()
assert.equal(performWindowControl(win, 'close'), true)
assert.equal(win.closed, true)
})
test('rejects unknown actions and destroyed windows', () => {
const win = new FakeWindow()
assert.equal(performWindowControl(win, 'unknown'), false)
assert.equal(performWindowControl({ ...win, isDestroyed: () => true }, 'minimize'), false)
})
})
test('windowControlState exposes the custom-control and maximize state', () => {
const win = new FakeWindow()
win.maximized = true
assert.deepEqual(windowControlState(win, true), {
customWindowControls: true,
isMaximized: true
})
})
test('custom window controls use the same WSL kernel fallback as the main process', () => {
assert.equal(
customWindowControlsEnabled({ env: {}, kernelRelease: '6.6.87.2-microsoft-standard-WSL2', platform: 'linux' }),
true
)
})
test('custom window controls read WSL env vars without touching the filesystem', () => {
assert.equal(customWindowControlsEnabled({ env: { WSL_INTEROP: '/run/WSL/1_interop' }, platform: 'linux' }), true)
assert.equal(customWindowControlsEnabled({ env: {}, platform: 'linux' }), false)
assert.equal(customWindowControlsEnabled({ env: { WSL_DISTRO_NAME: 'Ubuntu' }, platform: 'darwin' }), false)
})
describe('registerWindowControlIpc', () => {
function fakeIpc() {
const handlers = new Map<string, (event: { sender: unknown }, action: unknown) => void>()
return {
handlers,
on(channel: string, listener: (event: { sender: unknown }, action: unknown) => void) {
handlers.set(channel, listener)
}
}
}
test('registers the hermes:window-control channel', () => {
const ipc = fakeIpc()
registerWindowControlIpc(ipc as Parameters<typeof registerWindowControlIpc>[0], () => new FakeWindow())
assert.equal(ipc.handlers.has('hermes:window-control'), true)
})
test('dispatches the incoming action to performWindowControl on the resolved window', () => {
const ipc = fakeIpc()
const win = new FakeWindow()
const senders: unknown[] = []
registerWindowControlIpc(ipc as Parameters<typeof registerWindowControlIpc>[0], sender => {
senders.push(sender)
return win
})
const handler = ipc.handlers.get('hermes:window-control')
assert.ok(handler)
const sender = { id: 7 }
handler({ sender }, 'toggle-maximize')
assert.equal(win.maximized, true)
assert.deepEqual(senders, [sender])
handler({ sender }, 'minimize')
assert.equal(win.minimized, true)
})
test('ignores non-string actions instead of dispatching them', () => {
const ipc = fakeIpc()
const win = new FakeWindow()
registerWindowControlIpc(ipc as Parameters<typeof registerWindowControlIpc>[0], () => win)
ipc.handlers.get('hermes:window-control')({ sender: {} }, { action: 'minimize' })
assert.equal(win.minimized, false)
})
})