From 9e207160596442a7428253530e147ea2e9dfa125 Mon Sep 17 00:00:00 2001 From: Charles Vien Date: Tue, 31 Mar 2026 14:39:00 -0700 Subject: [PATCH] Stop second-instance from unconditionally stealing window focus --- apps/code/src/main/deep-links.ts | 17 ++++++++++++++--- .../src/main/services/notification/service.ts | 1 + .../code/src/main/services/task-link/service.ts | 1 + apps/code/src/main/window.ts | 12 +++++++++++- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/apps/code/src/main/deep-links.ts b/apps/code/src/main/deep-links.ts index b2f6d454b..57dd605cd 100644 --- a/apps/code/src/main/deep-links.ts +++ b/apps/code/src/main/deep-links.ts @@ -2,8 +2,11 @@ import { app } from "electron"; import { container } from "./di/container"; import { MAIN_TOKENS } from "./di/tokens"; import type { DeepLinkService } from "./services/deep-link/service"; +import { logger } from "./utils/logger"; import { focusMainWindow } from "./window"; +const log = logger.scope("deep-links"); + let pendingDeepLinkUrl: string | null = null; function getDeepLinkService(): DeepLinkService { @@ -18,6 +21,7 @@ export function registerDeepLinkHandlers(): void { // Handle deep link URLs on macOS app.on("open-url", (event, url) => { event.preventDefault(); + log.info("open-url event received", { url, appReady: app.isReady() }); if (!app.isReady()) { pendingDeepLinkUrl = url; @@ -25,11 +29,16 @@ export function registerDeepLinkHandlers(): void { } getDeepLinkService().handleUrl(url); - focusMainWindow(); + focusMainWindow("open-url deep link"); }); // Handle deep link URLs on Windows/Linux (second instance sends URL via command line) app.on("second-instance", (_event, commandLine) => { + log.info("second-instance event received", { + commandLine: commandLine.join(" "), + argCount: commandLine.length, + }); + const url = commandLine.find( (arg) => arg.startsWith("posthog-code://") || @@ -37,10 +46,12 @@ export function registerDeepLinkHandlers(): void { arg.startsWith("array://"), ); if (url) { + log.info("Deep link URL found in second-instance args", { url }); getDeepLinkService().handleUrl(url); + focusMainWindow("second-instance deep link"); + } else { + log.warn("second-instance fired with no deep link URL, ignoring focus"); } - - focusMainWindow(); }); } diff --git a/apps/code/src/main/services/notification/service.ts b/apps/code/src/main/services/notification/service.ts index 5f31f5f7b..20fb903aa 100644 --- a/apps/code/src/main/services/notification/service.ts +++ b/apps/code/src/main/services/notification/service.ts @@ -31,6 +31,7 @@ export class NotificationService { const notification = new Notification({ title, body, silent }); notification.on("click", () => { + log.info("Notification clicked, focusing window", { title, taskId }); const mainWindow = getMainWindow(); if (mainWindow) { if (mainWindow.isMinimized()) { diff --git a/apps/code/src/main/services/task-link/service.ts b/apps/code/src/main/services/task-link/service.ts index 36333e699..7eb0481ab 100644 --- a/apps/code/src/main/services/task-link/service.ts +++ b/apps/code/src/main/services/task-link/service.ts @@ -70,6 +70,7 @@ export class TaskLinkService extends TypedEventEmitter { } // Focus the window + log.info("Deep link focusing window", { taskId, taskRunId }); const mainWindow = getMainWindow(); if (mainWindow) { if (mainWindow.isMinimized()) { diff --git a/apps/code/src/main/window.ts b/apps/code/src/main/window.ts index 6bdd895bc..edb4e5f54 100644 --- a/apps/code/src/main/window.ts +++ b/apps/code/src/main/window.ts @@ -6,8 +6,11 @@ import { buildApplicationMenu } from "./menu"; import { setMainWindowGetter } from "./trpc/context"; import { trpcRouter } from "./trpc/router"; import { isDevBuild } from "./utils/env"; +import { logger } from "./utils/logger"; import { type WindowStateSchema, windowStateStore } from "./utils/store"; +const log = logger.scope("window"); + declare const MAIN_WINDOW_VITE_DEV_SERVER_URL: string | undefined; declare const MAIN_WINDOW_VITE_NAME: string; @@ -63,8 +66,15 @@ export function getMainWindow(): BrowserWindow | null { return mainWindow; } -export function focusMainWindow(): void { +export function focusMainWindow(reason: string): void { if (mainWindow) { + log.info("focusMainWindow called", { + reason, + isMinimized: mainWindow.isMinimized(), + isFocused: mainWindow.isFocused(), + isVisible: mainWindow.isVisible(), + stack: new Error().stack, + }); if (mainWindow.isMinimized()) mainWindow.restore(); mainWindow.focus(); }