From 6a8813531f0bb33687983a254bf29597de2d9e98 Mon Sep 17 00:00:00 2001 From: alger Date: Tue, 11 Mar 2025 23:28:04 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9E=20fix:=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=AD=8C=E8=AF=8D=E7=AA=97=E5=8F=A3=E6=8B=96=E5=8A=A8=E5=8F=98?= =?UTF-8?q?=E5=A4=A7=E9=97=AE=E9=A2=98=E5=92=8C=E5=A4=9A=E5=B1=8F=E5=B9=95?= =?UTF-8?q?=E6=94=AF=E6=8C=81=EF=BC=8C=E4=BC=98=E5=8C=96=E5=AD=97=E4=BD=93?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixed: #77 --- src/main/lyric.ts | 147 ++++++++++++++++++++++++----- src/renderer/views/lyric/index.vue | 34 +++++-- 2 files changed, 148 insertions(+), 33 deletions(-) diff --git a/src/main/lyric.ts b/src/main/lyric.ts index 1faf498..ca499f9 100644 --- a/src/main/lyric.ts +++ b/src/main/lyric.ts @@ -5,6 +5,12 @@ import path, { join } from 'path'; const store = new Store(); let lyricWindow: BrowserWindow | null = null; +// 跟踪拖动状态 +let isDragging = false; + +// 添加窗口大小变化防护 +let originalSize = { width: 0, height: 0 }; + const createWin = () => { console.log('Creating lyric window'); @@ -15,32 +21,73 @@ const createWin = () => { y?: number; width?: number; height?: number; + displayId?: number; }) || {}; - const { x, y, width, height } = windowBounds; - // 获取屏幕尺寸 - const { width: screenWidth, height: screenHeight } = screen.getPrimaryDisplay().workAreaSize; + const { x, y, width, height, displayId } = windowBounds; - // 验证保存的位置是否有效 - const validPosition = - x !== undefined && y !== undefined && x >= 0 && y >= 0 && x < screenWidth && y < screenHeight; + // 获取所有屏幕的信息 + const displays = screen.getAllDisplays(); + let isValidPosition = false; + let targetDisplay = displays[0]; // 默认使用主显示器 + + // 如果有显示器ID,尝试按ID匹配 + if (displayId) { + const matchedDisplay = displays.find((d) => d.id === displayId); + if (matchedDisplay) { + targetDisplay = matchedDisplay; + console.log('Found matching display by ID:', displayId); + } + } + + // 验证位置是否在任何显示器的范围内 + if (x !== undefined && y !== undefined) { + for (const display of displays) { + const { bounds } = display; + if ( + x >= bounds.x - 50 && // 允许一点偏移,避免卡在边缘 + x < bounds.x + bounds.width + 50 && + y >= bounds.y - 50 && + y < bounds.y + bounds.height + 50 + ) { + isValidPosition = true; + targetDisplay = display; + break; + } + } + } // 确保宽高合理 const defaultWidth = 800; const defaultHeight = 200; - const validWidth = width && width > 0 ? width : defaultWidth; - const validHeight = height && height > 0 ? height : defaultHeight; + const maxWidth = 1600; // 设置最大宽度限制 + const maxHeight = 800; // 设置最大高度限制 + + const validWidth = width && width > 0 && width <= maxWidth ? width : defaultWidth; + const validHeight = height && height > 0 && height <= maxHeight ? height : defaultHeight; + + // 确定窗口位置 + let windowX = isValidPosition ? x : undefined; + let windowY = isValidPosition ? y : undefined; + + // 如果位置无效,默认在当前显示器中居中 + if (windowX === undefined || windowY === undefined) { + windowX = targetDisplay.bounds.x + (targetDisplay.bounds.width - validWidth) / 2; + windowY = targetDisplay.bounds.y + (targetDisplay.bounds.height - validHeight) / 2; + } lyricWindow = new BrowserWindow({ width: validWidth, height: validHeight, - x: validPosition ? x : undefined, - y: validPosition ? y : undefined, + x: windowX, + y: windowY, frame: false, show: false, transparent: true, hasShadow: false, alwaysOnTop: true, + resizable: true, + // 添加跨屏幕支持选项 webPreferences: { preload: join(__dirname, '../preload/index.js'), sandbox: false, @@ -58,6 +105,9 @@ const createWin = () => { // 监听窗口大小变化事件,保存新的尺寸 lyricWindow.on('resize', () => { + // 如果正在拖动,忽略大小调整事件 + if (isDragging) return; + if (lyricWindow && !lyricWindow.isDestroyed()) { const [width, height] = lyricWindow.getSize(); const [x, y] = lyricWindow.getPosition(); @@ -154,28 +204,75 @@ export const loadLyricWindow = (ipcMain: IpcMain, mainWin: BrowserWindow): void } }); + // 开始拖动时设置标志 + ipcMain.on('lyric-drag-start', () => { + isDragging = true; + if (lyricWindow && !lyricWindow.isDestroyed()) { + // 记录原始窗口大小 + const [width, height] = lyricWindow.getSize(); + originalSize = { width, height }; + + // 在拖动时暂时禁用大小调整 + lyricWindow.setResizable(false); + } + }); + + // 结束拖动时清除标志 + ipcMain.on('lyric-drag-end', () => { + isDragging = false; + if (lyricWindow && !lyricWindow.isDestroyed()) { + // 确保窗口大小恢复原样 + lyricWindow.setSize(originalSize.width, originalSize.height); + + // 拖动结束后恢复可调整大小 + lyricWindow.setResizable(true); + } + }); + // 处理拖动移动 ipcMain.on('lyric-drag-move', (_, { deltaX, deltaY }) => { - if (!lyricWindow || lyricWindow.isDestroyed()) return; + if (!lyricWindow || lyricWindow.isDestroyed() || !isDragging) return; const [currentX, currentY] = lyricWindow.getPosition(); - const { width: screenWidth, height: screenHeight } = screen.getPrimaryDisplay().workAreaSize; - const [windowWidth, windowHeight] = lyricWindow.getSize(); - // 计算新位置,确保窗口不会移出屏幕 - const newX = Math.max(0, Math.min(currentX + deltaX, screenWidth - windowWidth)); - const newY = Math.max(0, Math.min(currentY + deltaY, screenHeight - windowHeight)); + // 使用记录的原始大小,而不是当前大小 + const windowWidth = originalSize.width; + const windowHeight = originalSize.height; - lyricWindow.setPosition(newX, newY); + // 计算新位置 + const newX = currentX + deltaX; + const newY = currentY + deltaY; - // 保存新位置,但只保存位置信息,不使用getBounds()避免在Windows下引起尺寸变化 - const bounds = { - x: newX, - y: newY, - width: windowWidth, // 使用当前保存的宽度 - height: windowHeight // 使用当前保存的高度 - }; - store.set('lyricWindowBounds', bounds); + try { + // 获取当前鼠标所在的显示器 + const mousePoint = screen.getCursorScreenPoint(); + const currentDisplay = screen.getDisplayNearestPoint(mousePoint); + + // 拖动期间使用setBounds确保大小不变,使用false避免动画卡顿 + lyricWindow.setBounds( + { + x: newX, + y: newY, + width: windowWidth, + height: windowHeight + }, + false + ); + + // 更新存储的位置 + const windowBounds = { + x: newX, + y: newY, + width: windowWidth, + height: windowHeight, + displayId: currentDisplay.id // 记录当前显示器ID,有助于多屏幕处理 + }; + store.set('lyricWindowBounds', windowBounds); + } catch (error) { + console.error('Error during window drag:', error); + // 出错时尝试使用更简单的方法 + lyricWindow.setPosition(newX, newY); + } }); // 添加鼠标穿透事件处理 diff --git a/src/renderer/views/lyric/index.vue b/src/renderer/views/lyric/index.vue index 0a2ad17..ab3dc9c 100644 --- a/src/renderer/views/lyric/index.vue +++ b/src/renderer/views/lyric/index.vue @@ -494,6 +494,8 @@ watch( // 添加拖动相关变量 const isDragging = ref(false); const startPosition = ref({ x: 0, y: 0 }); +const lastMoveTime = ref(0); +const moveThrottleMs = 10; // 限制拖动事件发送频率,提高性能 // 处理鼠标按下事件 const handleMouseDown = (e: MouseEvent) => { @@ -501,7 +503,8 @@ const handleMouseDown = (e: MouseEvent) => { if ( lyricSetting.value.isLock || (e.target as HTMLElement).closest('.control-buttons') || - (e.target as HTMLElement).closest('.font-size-controls') + (e.target as HTMLElement).closest('.font-size-controls') || + (e.target as HTMLElement).closest('.play-controls') ) { return; } @@ -511,23 +514,38 @@ const handleMouseDown = (e: MouseEvent) => { isDragging.value = true; startPosition.value = { x: e.screenX, y: e.screenY }; + lastMoveTime.value = performance.now(); + + // 发送拖动开始信号到主进程 + windowData.electron.ipcRenderer.send('lyric-drag-start'); // 添加全局鼠标事件监听 const handleMouseMove = (e: MouseEvent) => { if (!isDragging.value) return; + // 时间节流,避免过于频繁的更新 + const now = performance.now(); + if (now - lastMoveTime.value < moveThrottleMs) return; + lastMoveTime.value = now; + const deltaX = e.screenX - startPosition.value.x; const deltaY = e.screenY - startPosition.value.y; - // 发送移动事件到主进程 - windowData.electron.ipcRenderer.send('lyric-drag-move', { deltaX, deltaY }); - startPosition.value = { x: e.screenX, y: e.screenY }; + // 只有在实际移动时才发送事件 + if (Math.abs(deltaX) > 0 || Math.abs(deltaY) > 0) { + // 发送移动事件到主进程 + windowData.electron.ipcRenderer.send('lyric-drag-move', { deltaX, deltaY }); + startPosition.value = { x: e.screenX, y: e.screenY }; + } }; const handleMouseUp = () => { if (!isDragging.value) return; isDragging.value = false; + // 发送拖动结束信号到主进程 + windowData.electron.ipcRenderer.send('lyric-drag-end'); + // 移除事件监听 document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mouseup', handleMouseUp); @@ -573,7 +591,7 @@ const handleNext = () => { }; -