diff --git a/src/main/windows/WindowManager.ts b/src/main/windows/WindowManager.ts index c91d7a3..18e95c5 100644 --- a/src/main/windows/WindowManager.ts +++ b/src/main/windows/WindowManager.ts @@ -126,18 +126,35 @@ export function getRecordingTipWindow(): BrowserWindow { * Phase 1: prepare → 측정 * Phase 2: resize → show */ +// RecordingTip 측정 리스너 관리 (race condition 방지) +let _tipMeasuredHandler: ((_event: Electron.IpcMainEvent, data: { width: number; height: number }) => void) | null = null +let _tipHidden = false + export function showRecordingTip( state: string, params?: { text?: string; errorMessage?: string } ): void { const win = getRecordingTipWindow() + _tipHidden = false + + // 이전 측정 리스너 제거 (중복 방지) + if (_tipMeasuredHandler) { + ipcMain.removeListener('window:tipMeasured', _tipMeasuredHandler) + _tipMeasuredHandler = null + } // Phase 1: prepare (크기 측정) win.webContents.send('window:tipPrepare', { state, ...params }) // tipMeasured 이벤트를 한번만 처리 - const handler = (_event: Electron.IpcMainEvent, data: { width: number; height: number }) => { - ipcMain.removeListener('window:tipMeasured', handler) + _tipMeasuredHandler = (_event: Electron.IpcMainEvent, data: { width: number; height: number }) => { + if (_tipMeasuredHandler) { + ipcMain.removeListener('window:tipMeasured', _tipMeasuredHandler) + _tipMeasuredHandler = null + } + + // hide가 이미 호출되었으면 show하지 않음 + if (_tipHidden) return // 커서 위치에 표시 const cursorPos = screen.getCursorScreenPoint() @@ -162,10 +179,18 @@ export function showRecordingTip( win.webContents.send('window:tipShow', { state }) } - ipcMain.on('window:tipMeasured', handler) + ipcMain.on('window:tipMeasured', _tipMeasuredHandler) } export function hideRecordingTip(): void { + _tipHidden = true + + // pending 측정 리스너 제거 (늦게 도착하면 다시 show되는 버그 방지) + if (_tipMeasuredHandler) { + ipcMain.removeListener('window:tipMeasured', _tipMeasuredHandler) + _tipMeasuredHandler = null + } + if (recordingTipWindow && !recordingTipWindow.isDestroyed()) { recordingTipWindow.hide() }