diff --git a/src/main/presenter/tabPresenter.ts b/src/main/presenter/tabPresenter.ts index 3b5d2504a..27053a0e7 100644 --- a/src/main/presenter/tabPresenter.ts +++ b/src/main/presenter/tabPresenter.ts @@ -10,6 +10,7 @@ import { getContextMenuLabels } from '@shared/i18n' import { app } from 'electron' import { addWatermarkToNativeImage } from '@/lib/watermark' import { stitchImagesVertically } from '@/lib/scrollCapture' +import { presenter } from './' export class TabPresenter implements ITabPresenter { // 全局标签页实例存储 @@ -533,6 +534,12 @@ export class TabPresenter implements ITabPresenter { // Once did-finish-load happens, emit first content loaded webContents.once('did-finish-load', () => { eventBus.sendToMain(WINDOW_EVENTS.FIRST_CONTENT_LOADED, windowId) + setTimeout(() => { + const windowPresenter = presenter.windowPresenter as any + if (windowPresenter && typeof windowPresenter.focusActiveTab === 'function') { + windowPresenter.focusActiveTab(windowId, 'initial') + } + }, 300) }) } diff --git a/src/main/presenter/windowPresenter/index.ts b/src/main/presenter/windowPresenter/index.ts index a041f2f26..60686d86d 100644 --- a/src/main/presenter/windowPresenter/index.ts +++ b/src/main/presenter/windowPresenter/index.ts @@ -26,6 +26,16 @@ export class WindowPresenter implements IWindowPresenter { private isQuitting: boolean = false // 当前获得焦点的窗口 ID (内部记录) private focusedWindowId: number | null = null + // 窗口聚焦状态管理 + private windowFocusStates = new Map< + number, + { + lastFocusTime: number + shouldFocus: boolean + isNewWindow: boolean + hasInitialFocus: boolean + } + >() constructor(configPresenter: ConfigPresenter) { this.windows = new Map() @@ -310,7 +320,6 @@ export class WindowPresenter implements IWindowPresenter { this.handleWindowRestore(targetWindow.id).catch((error) => { console.error(`Error handling restore logic after showing window ${targetWindow!.id}:`, error) }) - this.focusActiveTab(targetWindow.id) } /** @@ -375,19 +384,69 @@ export class WindowPresenter implements IWindowPresenter { return focusedWindow ? focusedWindow.id === windowId : false } + /** + * 检查是否应该聚焦标签页 + * @param windowId 窗口 ID + * @param reason 聚焦原因 + */ + private shouldFocusTab( + windowId: number, + reason: 'focus' | 'restore' | 'show' | 'initial' + ): boolean { + const state = this.windowFocusStates.get(windowId) + if (!state) { + return true + } + const now = Date.now() + if (now - state.lastFocusTime < 100) { + console.log(`Skipping focus for window ${windowId}, too frequent (${reason})`) + return false + } + switch (reason) { + case 'initial': + return !state.hasInitialFocus + case 'focus': + return state.shouldFocus + case 'restore': + case 'show': + return state.isNewWindow || state.shouldFocus + default: + return false + } + } + /** * 将焦点传递给指定窗口的活动标签页 * @param windowId 窗口 ID + * @param reason 聚焦原因 */ - private focusActiveTab(windowId: number): void { + public focusActiveTab( + windowId: number, + reason: 'focus' | 'restore' | 'show' | 'initial' = 'focus' + ): void { + if (!this.shouldFocusTab(windowId, reason)) { + return + } try { setTimeout(async () => { const tabPresenterInstance = presenter.tabPresenter as TabPresenter const tabsData = await tabPresenterInstance.getWindowTabsData(windowId) const activeTab = tabsData.find((tab) => tab.isActive) if (activeTab) { - console.log(`Focusing active tab ${activeTab.id} in window ${windowId}`) + console.log( + `Focusing active tab ${activeTab.id} in window ${windowId} (reason: ${reason})` + ) await tabPresenterInstance.switchTab(activeTab.id) + const state = this.windowFocusStates.get(windowId) + if (state) { + state.lastFocusTime = Date.now() + if (reason === 'initial') { + state.hasInitialFocus = true + } + if (reason === 'focus' || reason === 'initial') { + state.isNewWindow = false + } + } } }, 50) } catch (error) { @@ -531,6 +590,13 @@ export class WindowPresenter implements IWindowPresenter { const windowId = shellWindow.id this.windows.set(windowId, shellWindow) // 将窗口实例存入 Map + this.windowFocusStates.set(windowId, { + lastFocusTime: 0, + shouldFocus: true, + isNewWindow: true, + hasInitialFocus: false + }) + shellWindowState.manage(shellWindow) // 管理窗口状态 // 应用内容保护设置 @@ -558,7 +624,7 @@ export class WindowPresenter implements IWindowPresenter { if (!shellWindow.isDestroyed()) { shellWindow.webContents.send('window-focused', windowId) } - this.focusActiveTab(windowId) + this.focusActiveTab(windowId, 'focus') }) // 窗口失去焦点 @@ -606,7 +672,7 @@ export class WindowPresenter implements IWindowPresenter { this.handleWindowRestore(windowId).catch((error) => { console.error(`Error handling restore logic for window ${windowId}:`, error) }) - this.focusActiveTab(windowId) + this.focusActiveTab(windowId, 'restore') eventBus.sendToMain(WINDOW_EVENTS.WINDOW_RESTORED, windowId) } shellWindow.on('restore', handleRestore) @@ -717,6 +783,7 @@ export class WindowPresenter implements IWindowPresenter { shellWindow.removeListener('restore', handleRestore) this.windows.delete(windowIdBeingClosed) // 从 Map 中移除 + this.windowFocusStates.delete(windowIdBeingClosed) shellWindowState.unmanage() // 停止管理窗口状态 eventBus.sendToMain(WINDOW_EVENTS.WINDOW_CLOSED, windowIdBeingClosed) console.log(