Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Unit/browser tests can't exercise real capture (native screen recording, a physi
**Launch the app**

- Normal: `npm run dev` — Vite serves the renderer and `vite-plugin-electron` opens the Electron window. The main process logs `Global shortcut registered: CommandOrControl+Shift+O` when ready (Ctrl/Cmd+Shift+O toggles the HUD).
- The app is single-instance: a lock dir at `%TEMP%/openscreen-single-instance-<user>.lock` (macOS: `$TMPDIR`). If a stale Electron process holds it, a new launch quits silently (exit 0, no window). Kill leftover `electron` processes and delete that lock dir before relaunching.
- The app is single-instance through `app.requestSingleInstanceLock()`, which keys on the `userData` path. If a leftover Electron process still holds it, a new launch quits silently (exit 0, no window) — kill leftover `electron` processes before relaunching. The lock is held by the OS and dies with the process, so there is nothing to clean up on disk. A dev build and the installed `Openscreen` resolve different `userData` paths and can run side by side.
- **From a git worktree** (no `node_modules`/native binaries): junction/symlink `node_modules` from the main checkout (deps are usually identical — check `package-lock.json`), and copy the prebuilt native capture binaries from `electron/native/bin/<platform>/` (gitignored — rebuilding needs the full VS/Xcode toolchain). Then `npm run dev` works normally.

**Granting access**
Expand Down
7 changes: 1 addition & 6 deletions electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
import { mainT, setMainLocale } from "./i18n";
import { getSelectedDesktopSource, registerIpcHandlers } from "./ipc/handlers";
import { installMainProcessErrorGuards } from "./main-process-errors";
import { acquireStableInstanceLock } from "./singleInstanceLock";
import { registerSttIpc } from "./stt";
import {
createCountdownOverlayWindow,
Expand Down Expand Up @@ -134,9 +133,7 @@ function showMainWindow() {

// CLI runs skip the single-instance lock so `openscreen export/record` works
// while the GUI app is open (they share nothing but the recordings directory).
const stableInstanceLock = cliCommand ? null : acquireStableInstanceLock();
const hasElectronSingleInstanceLock = cliCommand ? false : app.requestSingleInstanceLock();
const hasSingleInstanceLock = Boolean(stableInstanceLock && hasElectronSingleInstanceLock);
const hasSingleInstanceLock = cliCommand ? false : app.requestSingleInstanceLock();

if (cliCommand) {
runCli(cliCommand);
Expand All @@ -145,7 +142,6 @@ if (cliCommand) {
showMainWindow();
});
} else {
stableInstanceLock?.release();
app.quit();
}

Expand Down Expand Up @@ -518,7 +514,6 @@ app.on("activate", () => {

app.on("will-quit", () => {
unregisterAllGlobalShortcuts();
stableInstanceLock?.release();
});

const appReady = !cliCommand && hasSingleInstanceLock ? app.whenReady() : null;
Expand Down
52 changes: 0 additions & 52 deletions electron/singleInstanceLock.test.ts

This file was deleted.

104 changes: 0 additions & 104 deletions electron/singleInstanceLock.ts

This file was deleted.

8 changes: 5 additions & 3 deletions technical-documentation/architecture/export-pipeline.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,11 @@ Each cost hours and each produced a confident, wrong conclusion.
against the new renderer. It read as "export IPC not registered" once
and as "the bench flag does nothing" once. The bench now refuses to
run against one.
9. **The installed app (`openscreen.exe`) holds the same single-instance
lock as the dev build.** A launch exits 0 and reports nothing —
silently.
9. **A second instance of the same build quits silently.** The lock keys
on the `userData` path, so another dev build already running makes a
launch exit 0 and report nothing. The installed app
(`openscreen.exe`) resolves a different `userData` path and does not
conflict.

## A truncated project file is unopenable, not partially readable

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ The first frames of a 4-second export cost 358/113/28/350 ms — 10.3 ms/frame o
- Electron cannot transfer an ArrayBuffer renderer→main. The transfer list takes `MessagePort[]`; transferring a buffer silently drops the whole message ([electron#34905](https://github.com/electron/electron/issues/34905)) — it works renderer→renderer.
- `Buffer.from(typedArray)` copies. Wrapping (`Buffer.from(buf.buffer, byteOffset, byteLength)`) measured +31 %.
- A stale `dist-electron` bundle runs the *previous* main process against the new renderer. It read as "export IPC not registered" once and as "the bench flag does nothing" once. The bench now refuses to run against one.
- The installed app (`openscreen.exe`) holds the same single-instance lock as the dev build. A launch exits 0 and reports nothing — silently.
- A second instance of the same build quits silently: the lock keys on the `userData` path, so another dev build already running makes a launch exit 0 and report nothing. The installed app (`openscreen.exe`) resolves a different `userData` path and does not conflict.

## What the numbers mean

Expand Down
2 changes: 1 addition & 1 deletion technical-documentation/testing/manual-e2e-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Sections marked **v1.8.0** cover what this release changed: chat-driven editing
## How to run this

1. Drive the real Electron app with computer-use, not a browser shim. Start a dev build with `npm run dev`, or launch the packaged build under test.
2. The app is single-instance. If a stale process holds the lock, stop the leftover Electron/OpenScreen process and remove the per-user lock directory before relaunching; a second launch can exit successfully without opening a window.
2. The app is single-instance per `userData` path. If a leftover Electron/OpenScreen process still holds the lock, stop that process before relaunching; a second launch can exit successfully without opening a window. The lock is held by the OS and is released when the process dies, so there is nothing to delete on disk.
3. From a worktree, link or junction `node_modules` to the main checkout and provide the prebuilt native capture binaries for the platform before starting the dev build.
4. Grant computer-use access to the process name that actually owns the window: `electron.exe` or `Electron.app` for a dev build, and `Openscreen.exe` or `Openscreen.app` for a packaged build. Do not grant access only to the installed app name when testing a dev build.
5. Read [AGENTS.md](../../AGENTS.md) for the computer-use mechanics, screenshot permissions, tray interaction, and cleanup procedure. Read one check, perform it, observe the result, then continue; close each modal or popover with `Esc` before the next check.
Expand Down
7 changes: 3 additions & 4 deletions tests/e2e/gif-export.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,9 @@ async function launchApp(userDataDir: string, tmpDir: string) {
env: {
...process.env,
ELECTRON_USER_DATA_DIR: userDataDir,
// `acquireStableInstanceLock` keys its lock directory off `os.tmpdir()` and
// the *user id* — not off userData — so a dev instance running from any
// worktree would otherwise make this launch quit instantly (exit code 0, no
// window, no stderr). Giving the app its own temp dir gives it its own lock.
// Keep this run's scratch files out of the shared temp dir so a dev instance
// cannot collide with them. The single-instance lock keys on userData, which
// `--user-data-dir` above already makes private to this launch.
TMPDIR: tmpDir,
TMP: tmpDir,
TEMP: tmpDir,
Expand Down
Loading