From e066efb373c274ec3c6fbaeb6d85190aefbda97d Mon Sep 17 00:00:00 2001 From: kimjiwon <948756589@qq.com> Date: Sun, 12 Apr 2026 13:29:02 +0800 Subject: [PATCH] add main-process cursor presence sync for locked lyric window --- src/main/lyric.ts | 52 ++++++++++++++++++++++++++++++ src/renderer/views/lyric/index.vue | 16 +++++++++ 2 files changed, 68 insertions(+) diff --git a/src/main/lyric.ts b/src/main/lyric.ts index 045378a..7e059bf 100644 --- a/src/main/lyric.ts +++ b/src/main/lyric.ts @@ -10,6 +10,54 @@ let isDragging = false; // 添加窗口大小变化防护 let originalSize = { width: 0, height: 0 }; +let mousePresenceTimer: ReturnType | null = null; +let lastMouseInside: boolean | null = null; + +const isPointInsideWindow = ( + point: { x: number; y: number }, + bounds: { x: number; y: number; width: number; height: number } +) => { + return ( + point.x >= bounds.x && + point.x < bounds.x + bounds.width && + point.y >= bounds.y && + point.y < bounds.y + bounds.height + ); +}; + +const stopMousePresenceTracking = () => { + if (mousePresenceTimer) { + clearInterval(mousePresenceTimer); + mousePresenceTimer = null; + } + lastMouseInside = null; +}; + +const emitMousePresence = () => { + if (!lyricWindow || lyricWindow.isDestroyed()) return; + + const mousePoint = screen.getCursorScreenPoint(); + const bounds = lyricWindow.getBounds(); + const isInside = isPointInsideWindow(mousePoint, bounds); + + if (isInside === lastMouseInside) return; + + lastMouseInside = isInside; + lyricWindow.webContents.send('lyric-mouse-presence', isInside); +}; + +const startMousePresenceTracking = () => { + if (mousePresenceTimer) return; + + emitMousePresence(); + mousePresenceTimer = setInterval(() => { + if (!lyricWindow || lyricWindow.isDestroyed()) { + stopMousePresenceTracking(); + return; + } + emitMousePresence(); + }, 50); +}; const createWin = () => { console.log('Creating lyric window'); @@ -102,6 +150,7 @@ const createWin = () => { // 监听窗口关闭事件 lyricWindow.on('closed', () => { + stopMousePresenceTracking(); if (lyricWindow) { lyricWindow.destroy(); lyricWindow = null; @@ -135,6 +184,7 @@ export const loadLyricWindow = (ipcMain: IpcMain, mainWin: BrowserWindow): void } lyricWindow.focus(); lyricWindow.show(); + startMousePresenceTracking(); return true; } return false; @@ -169,6 +219,7 @@ export const loadLyricWindow = (ipcMain: IpcMain, mainWin: BrowserWindow): void win.once('ready-to-show', () => { console.log('Lyric window ready to show'); win.show(); + startMousePresenceTracking(); }); }); @@ -197,6 +248,7 @@ export const loadLyricWindow = (ipcMain: IpcMain, mainWin: BrowserWindow): void ipcMain.on('close-lyric', () => { if (lyricWindow && !lyricWindow.isDestroyed()) { + stopMousePresenceTracking(); lyricWindow.webContents.send('lyric-window-close'); mainWin.webContents.send('lyric-control-back', 'close'); mainWin.webContents.send('lyric-window-closed'); diff --git a/src/renderer/views/lyric/index.vue b/src/renderer/views/lyric/index.vue index a653007..dceeaa0 100644 --- a/src/renderer/views/lyric/index.vue +++ b/src/renderer/views/lyric/index.vue @@ -341,6 +341,7 @@ const displayMode = computed(() => lyricSetting.value.displayMode); const showTranslation = computed(() => lyricSetting.value.showTranslation); let hideControlsTimer: number | null = null; +let removeMousePresenceListener: (() => void) | null = null; const isHovering = ref(false); @@ -782,10 +783,25 @@ onMounted(() => { // 通知主窗口歌词窗口已就绪,请求发送完整歌词数据 windowData.electron.ipcRenderer.send('lyric-ready'); + + removeMousePresenceListener = window.ipcRenderer.on( + 'lyric-mouse-presence', + (isInside: boolean) => { + isHovering.value = isInside; + + if (lyricSetting.value.isLock) { + windowData.electron.ipcRenderer.send('set-ignore-mouse', !isInside); + } + } + ); }); onUnmounted(() => { window.removeEventListener('resize', updateContainerHeight); + if (removeMousePresenceListener) { + removeMousePresenceListener(); + removeMousePresenceListener = null; + } }); const checkTheme = () => {