From dda08172d956913b8b5aaad3f3567180b27b5f9f Mon Sep 17 00:00:00 2001 From: Siddharth Date: Thu, 20 Nov 2025 18:45:06 -0700 Subject: [PATCH] sunset windows support --- .github/workflows/build.yml | 29 +--------- README.md | 1 - dist-electron/main.js | 39 +------------ dist-electron/preload.mjs | 9 --- electron-builder.json5 | 19 ------- electron/electron-env.d.ts | 3 - electron/ipc/handlers.ts | 26 --------- electron/main.ts | 9 +-- electron/preload.ts | 9 --- electron/windows.ts | 12 +--- package.json | 5 +- src/components/video-editor/VideoEditor.tsx | 4 +- .../video-editor/WindowControls.tsx | 57 ------------------- src/lib/exporter/videoExporter.ts | 4 +- 14 files changed, 12 insertions(+), 214 deletions(-) delete mode 100644 src/components/video-editor/WindowControls.tsx diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 50d861d..a3b5cee 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,34 +6,7 @@ on: workflow_dispatch: jobs: - build-windows: - runs-on: windows-latest - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Setup Node.js - uses: actions/setup-node@v3 - with: - node-version: '22' - - - name: Install dependencies - run: npm ci - - - name: Install app dependencies - run: npx electron-builder install-app-deps - - - name: Build Windows app - run: npm run build:win - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Upload Windows build - uses: actions/upload-artifact@v4 - with: - name: windows-installer - path: release/**/*.exe - retention-days: 30 + build-macos: runs-on: macos-latest diff --git a/README.md b/README.md index b78e636..5f9ed6e 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,6 @@ OpenScreen is 100% free for personal and commercial use. Use it, modify it, dist - Motion blur and exponential easing for smoother pan and zoom effects **Note:** -- OpenScreen is designed to support both Windows and macOS. We did not use any native APIs specific to one OS, so it should work on both. However, it hasn't been fully tested on Windows yet, if you run into issues, please let me know! - After you install the app, you'll need to grant it accessibility and screen recording permissions for it to work properly. diff --git a/dist-electron/main.js b/dist-electron/main.js index ed37626..22982c9 100644 --- a/dist-electron/main.js +++ b/dist-electron/main.js @@ -41,21 +41,13 @@ function createHudOverlayWindow() { return win; } function createEditorWindow() { - const isMac = process.platform === "darwin"; const win = new BrowserWindow({ width: 1200, height: 800, minWidth: 800, minHeight: 600, - // On macOS, use hiddenInset for native controls; on Windows, frameless - ...isMac ? { - titleBarStyle: "hiddenInset", - trafficLightPosition: { x: 12, y: 12 } - } : { - frame: false, - icon: void 0 - // No app icon on Windows - }, + titleBarStyle: "hiddenInset", + trafficLightPosition: { x: 12, y: 12 }, transparent: false, resizable: true, alwaysOnTop: false, @@ -369,28 +361,6 @@ function registerIpcHandlers(createEditorWindow2, createSourceSelectorWindow2, g }; } }); - ipcMain.handle("minimize-window", () => { - const mainWin = getMainWindow(); - if (mainWin) { - mainWin.minimize(); - } - }); - ipcMain.handle("maximize-window", () => { - const mainWin = getMainWindow(); - if (mainWin) { - if (mainWin.isMaximized()) { - mainWin.unmaximize(); - } else { - mainWin.maximize(); - } - } - }); - ipcMain.handle("close-window", () => { - const mainWin = getMainWindow(); - if (mainWin) { - mainWin.close(); - } - }); } const __dirname = path.dirname(fileURLToPath(import.meta.url)); const RECORDINGS_DIR = path.join(app.getPath("userData"), "recordings"); @@ -469,11 +439,6 @@ function createSourceSelectorWindowWrapper() { return sourceSelectorWindow; } app.on("window-all-closed", () => { - if (process.platform !== "darwin") { - cleanupMouseTracking(); - app.quit(); - mainWindow = null; - } }); app.on("activate", () => { if (BrowserWindow.getAllWindows().length === 0) { diff --git a/dist-electron/preload.mjs b/dist-electron/preload.mjs index 51a8efa..5c862ea 100644 --- a/dist-electron/preload.mjs +++ b/dist-electron/preload.mjs @@ -47,14 +47,5 @@ electron.contextBridge.exposeInMainWorld("electronAPI", { }, saveExportedVideo: (videoData, fileName) => { return electron.ipcRenderer.invoke("save-exported-video", videoData, fileName); - }, - minimizeWindow: () => { - return electron.ipcRenderer.invoke("minimize-window"); - }, - maximizeWindow: () => { - return electron.ipcRenderer.invoke("maximize-window"); - }, - closeWindow: () => { - return electron.ipcRenderer.invoke("close-window"); } }); diff --git a/electron-builder.json5 b/electron-builder.json5 index 2776b20..49774ba 100644 --- a/electron-builder.json5 +++ b/electron-builder.json5 @@ -26,25 +26,6 @@ "icon": "icons/icons/mac/icon.icns", "artifactName": "${productName}-Mac-${version}-Installer.${ext}" }, - "win": { - "target": [ - { - "target": "nsis", - "arch": [ - "x64" - ] - } - ], - "icon": "icons/icons/win/icon.ico", - "artifactName": "${productName}-Windows-${version}-Setup.${ext}", - "requestedExecutionLevel": "asInvoker" - }, - "nsis": { - "oneClick": false, - "perMachine": false, - "allowToChangeInstallationDirectory": true, - "deleteAppDataOnUninstall": false - }, "linux": { "target": [ "AppImage" diff --git a/electron/electron-env.d.ts b/electron/electron-env.d.ts index 6ac2284..0853fc1 100644 --- a/electron/electron-env.d.ts +++ b/electron/electron-env.d.ts @@ -38,9 +38,6 @@ interface Window { onStopRecordingFromTray: (callback: () => void) => () => void openExternalUrl: (url: string) => Promise<{ success: boolean; error?: string }> saveExportedVideo: (videoData: ArrayBuffer, fileName: string) => Promise<{ success: boolean; path?: string; message?: string }> - minimizeWindow: () => Promise - maximizeWindow: () => Promise - closeWindow: () => Promise } } diff --git a/electron/ipc/handlers.ts b/electron/ipc/handlers.ts index e7a7956..81e8af5 100644 --- a/electron/ipc/handlers.ts +++ b/electron/ipc/handlers.ts @@ -178,30 +178,4 @@ export function registerIpcHandlers( } } }) - - // Window control handlers for frameless window - ipcMain.handle('minimize-window', () => { - const mainWin = getMainWindow() - if (mainWin) { - mainWin.minimize() - } - }) - - ipcMain.handle('maximize-window', () => { - const mainWin = getMainWindow() - if (mainWin) { - if (mainWin.isMaximized()) { - mainWin.unmaximize() - } else { - mainWin.maximize() - } - } - }) - - ipcMain.handle('close-window', () => { - const mainWin = getMainWindow() - if (mainWin) { - mainWin.close() - } - }) } diff --git a/electron/main.ts b/electron/main.ts index 04d15b6..2051eb8 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -109,15 +109,10 @@ function createSourceSelectorWindowWrapper() { return sourceSelectorWindow } -// Quit when all windows are closed, except on macOS. There, it's common -// for applications and their menu bar to stay active until the user quits +// On macOS, applications and their menu bar stay active until the user quits // explicitly with Cmd + Q. app.on('window-all-closed', () => { - if (process.platform !== 'darwin') { - cleanupMouseTracking() - app.quit() - mainWindow = null - } + // Keep app running (macOS behavior) }) app.on('activate', () => { diff --git a/electron/preload.ts b/electron/preload.ts index b8d29a7..2b94f79 100644 --- a/electron/preload.ts +++ b/electron/preload.ts @@ -49,13 +49,4 @@ contextBridge.exposeInMainWorld('electronAPI', { saveExportedVideo: (videoData: ArrayBuffer, fileName: string) => { return ipcRenderer.invoke('save-exported-video', videoData, fileName) }, - minimizeWindow: () => { - return ipcRenderer.invoke('minimize-window') - }, - maximizeWindow: () => { - return ipcRenderer.invoke('maximize-window') - }, - closeWindow: () => { - return ipcRenderer.invoke('close-window') - }, }) \ No newline at end of file diff --git a/electron/windows.ts b/electron/windows.ts index 03720f4..42875ee 100644 --- a/electron/windows.ts +++ b/electron/windows.ts @@ -47,21 +47,13 @@ export function createHudOverlayWindow(): BrowserWindow { } export function createEditorWindow(): BrowserWindow { - const isMac = process.platform === 'darwin' - const win = new BrowserWindow({ width: 1200, height: 800, minWidth: 800, minHeight: 600, - // On macOS, use hiddenInset for native controls; on Windows, frameless - ...(isMac ? { - titleBarStyle: 'hiddenInset', - trafficLightPosition: { x: 12, y: 12 }, - } : { - frame: false, - icon: undefined, // No app icon on Windows - }), + titleBarStyle: 'hiddenInset', + trafficLightPosition: { x: 12, y: 12 }, transparent: false, resizable: true, alwaysOnTop: false, diff --git a/package.json b/package.json index fc49c3f..24d80ab 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,7 @@ "build": "tsc && vite build && electron-builder", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview", - "build:mac": "tsc && vite build && electron-builder --mac", - "build:win": "tsc && vite build && electron-builder --win --x64" + "build:mac": "tsc && vite build && electron-builder --mac" }, "dependencies": { "@fix-webm-duration/fix": "^1.0.1", @@ -57,4 +56,4 @@ "vite-plugin-electron-renderer": "^0.14.5" }, "main": "dist-electron/main.js" -} +} \ No newline at end of file diff --git a/src/components/video-editor/VideoEditor.tsx b/src/components/video-editor/VideoEditor.tsx index c1bb49b..8b75b20 100644 --- a/src/components/video-editor/VideoEditor.tsx +++ b/src/components/video-editor/VideoEditor.tsx @@ -9,7 +9,7 @@ import PlaybackControls from "./PlaybackControls"; import TimelineEditor from "./timeline/TimelineEditor"; import { SettingsPanel } from "./SettingsPanel"; import { ExportDialog } from "./ExportDialog"; -import { WindowControls } from "./WindowControls"; + import type { Span } from "dnd-timeline"; import { DEFAULT_ZOOM_DEPTH, @@ -275,7 +275,7 @@ export default function VideoEditor() { style={{ WebkitAppRegion: 'drag' } as React.CSSProperties} >
- +
diff --git a/src/components/video-editor/WindowControls.tsx b/src/components/video-editor/WindowControls.tsx deleted file mode 100644 index 4845d17..0000000 --- a/src/components/video-editor/WindowControls.tsx +++ /dev/null @@ -1,57 +0,0 @@ -export function WindowControls() { - // Only show custom controls on Windows - const isWindows = navigator.userAgent.includes('Windows'); - - if (!isWindows) { - return null; - } - - const handleMinimize = () => { - window.electronAPI?.minimizeWindow?.(); - }; - - const handleMaximize = () => { - window.electronAPI?.maximizeWindow?.(); - }; - - const handleClose = () => { - window.electronAPI?.closeWindow?.(); - }; - - return ( -
- {/* Minimize - Horizontal Line */} - - - {/* Maximize - Square */} - - - {/* Close - X */} - -
- ); -} diff --git a/src/lib/exporter/videoExporter.ts b/src/lib/exporter/videoExporter.ts index a3619d4..e299b69 100644 --- a/src/lib/exporter/videoExporter.ts +++ b/src/lib/exporter/videoExporter.ts @@ -119,9 +119,7 @@ export class VideoExporter { const canvas = this.renderer!.getCanvas(); - // CRITICAL FIX for Windows: Explicitly specify colorSpace when creating VideoFrame from canvas - // Without this, VideoFrame.colorSpace can be null on Windows, causing "Cannot read properties of null" error - // Using BT.709 with sRGB transfer (IEC 61966-2-1) which is standard for HD video + // @ts-ignore - TypeScript definitions may not include all VideoFrameInit properties const exportFrame = new VideoFrame(canvas, { timestamp,