@@ -13,56 +13,82 @@ const initLyricIpc = (): void => {
1313 // 歌词窗口
1414 let lyricWin : BrowserWindow | null = null ;
1515
16+ /**
17+ * 窗口是否存活
18+ * @param win 窗口实例
19+ * @returns 是否存活
20+ */
21+ const isWinAlive = ( win : BrowserWindow | null ) : win is BrowserWindow =>
22+ ! ! win && ! win . isDestroyed ( ) ;
23+
1624 // 切换桌面歌词
1725 ipcMain . on ( "toggle-desktop-lyric" , ( _event , val : boolean ) => {
1826 if ( val ) {
19- if ( ! lyricWin ) {
27+ if ( ! isWinAlive ( lyricWin ) ) {
2028 lyricWin = lyricWindow . create ( ) ;
29+ // 监听关闭,置空引用,防止后续调用报错
30+ lyricWin ?. on ( "closed" , ( ) => {
31+ lyricWin = null ;
32+ } ) ;
33+ // 设置位置
34+ const { x, y } = store . get ( "lyric" ) ;
35+ const xPos = Number ( x ) ;
36+ const yPos = Number ( y ) ;
37+ if ( Number . isFinite ( xPos ) && Number . isFinite ( yPos ) ) {
38+ lyricWin ?. setPosition ( Math . round ( xPos ) , Math . round ( yPos ) ) ;
39+ }
2140 } else {
22- lyricWin ?. show ( ) ;
41+ lyricWin . show ( ) ;
42+ }
43+ if ( isWinAlive ( lyricWin ) ) {
44+ lyricWin . setAlwaysOnTop ( true , "screen-saver" ) ;
2345 }
24- lyricWin ?. setAlwaysOnTop ( true , "screen-saver" ) ;
2546 } else {
2647 // 关闭:不销毁窗口,直接隐藏,保留位置与状态
27- if ( ! lyricWin ) return ;
48+ if ( ! isWinAlive ( lyricWin ) ) return ;
2849 lyricWin . hide ( ) ;
2950 }
3051 } ) ;
3152
53+ // 向主窗口发送事件
54+ ipcMain . on ( "send-to-main" , ( _ , eventName , ...args ) => {
55+ mainWin ?. webContents . send ( eventName , ...args ) ;
56+ } ) ;
57+
3258 // 更新歌词窗口数据
3359 ipcMain . on ( "update-desktop-lyric-data" , ( _ , lyricData ) => {
34- if ( ! lyricData || ! lyricWin ) return ;
35- lyricWin ? .webContents . send ( "update-desktop-lyric-data" , lyricData ) ;
60+ if ( ! lyricData || ! isWinAlive ( lyricWin ) ) return ;
61+ lyricWin . webContents . send ( "update-desktop-lyric-data" , lyricData ) ;
3662 } ) ;
3763
3864 // 更新歌词窗口配置
3965 ipcMain . on ( "update-desktop-lyric-option" , ( _ , option ) => {
40- if ( ! option || ! lyricWin ) return ;
41- lyricWin ? .webContents . send ( "desktop-lyric-option-change" , option ) ;
66+ if ( ! option || ! isWinAlive ( lyricWin ) ) return ;
67+ lyricWin . webContents . send ( "desktop-lyric-option-change" , option ) ;
4268 } ) ;
4369
4470 // 播放状态更改
4571 ipcMain . on ( "play-status-change" , ( _ , status ) => {
46- if ( ! status || ! lyricWin ) return ;
47- lyricWin ? .webContents . send ( "update-desktop-lyric-data" , { playStatus : status } ) ;
72+ if ( ! isWinAlive ( lyricWin ) ) return ;
73+ lyricWin . webContents . send ( "update-desktop-lyric-data" , { playStatus : status } ) ;
4874 } ) ;
4975
5076 // 音乐名称更改
5177 ipcMain . on ( "play-song-change" , ( _ , title ) => {
52- if ( ! title || ! lyricWin ) return ;
53- lyricWin ? .webContents . send ( "update-desktop-lyric-data" , { playName : title } ) ;
78+ if ( ! title || ! isWinAlive ( lyricWin ) ) return ;
79+ lyricWin . webContents . send ( "update-desktop-lyric-data" , { playName : title } ) ;
5480 } ) ;
5581
5682 // 音乐歌词更改
5783 ipcMain . on ( "play-lyric-change" , ( _ , lyricData ) => {
58- if ( ! lyricData || ! lyricWin ) return ;
59- lyricWin ? .webContents . send ( "update-desktop-lyric-data" , lyricData ) ;
84+ if ( ! lyricData || ! isWinAlive ( lyricWin ) ) return ;
85+ lyricWin . webContents . send ( "update-desktop-lyric-data" , lyricData ) ;
6086 } ) ;
6187
6288 // 获取窗口位置
6389 ipcMain . handle ( "get-window-bounds" , ( ) => {
64- if ( ! lyricWin ) return { } ;
65- return lyricWin ? .getBounds ( ) ;
90+ if ( ! isWinAlive ( lyricWin ) ) return { } ;
91+ return lyricWin . getBounds ( ) ;
6692 } ) ;
6793
6894 // 获取屏幕尺寸
@@ -71,24 +97,40 @@ const initLyricIpc = (): void => {
7197 return { width, height } ;
7298 } ) ;
7399
100+ // 获取多屏虚拟边界(支持负坐标)
101+ ipcMain . handle ( "get-virtual-screen-bounds" , ( ) => {
102+ const displays = screen . getAllDisplays ( ) ;
103+ const bounds = displays . map ( ( d ) => d . workArea ) ;
104+ const minX = Math . min ( ...bounds . map ( ( b ) => b . x ) ) ;
105+ const minY = Math . min ( ...bounds . map ( ( b ) => b . y ) ) ;
106+ const maxX = Math . max ( ...bounds . map ( ( b ) => b . x + b . width ) ) ;
107+ const maxY = Math . max ( ...bounds . map ( ( b ) => b . y + b . height ) ) ;
108+ return { minX, minY, maxX, maxY } ;
109+ } ) ;
110+
74111 // 移动窗口
75112 ipcMain . on ( "move-window" , ( _ , x , y , width , height ) => {
76- if ( ! lyricWin ) return ;
113+ if ( ! isWinAlive ( lyricWin ) ) return ;
77114 lyricWin . setBounds ( { x, y, width, height } ) ;
78115 // 保存配置
79116 store . set ( "lyric" , { ...store . get ( "lyric" ) , x, y, width, height } ) ;
80- // 保持置顶
81- lyricWin ?. setAlwaysOnTop ( true , "screen-saver" ) ;
82117 } ) ;
83118
84119 // 更新高度
85120 ipcMain . on ( "update-window-height" , ( _ , height ) => {
86- if ( ! lyricWin ) return ;
121+ if ( ! isWinAlive ( lyricWin ) ) return ;
87122 const { width } = lyricWin . getBounds ( ) ;
88123 // 更新窗口高度
89124 lyricWin . setBounds ( { width, height } ) ;
90125 } ) ;
91126
127+ // 请求歌词数据及配置
128+ ipcMain . on ( "request-desktop-lyric-data" , ( ) => {
129+ if ( ! isWinAlive ( lyricWin ) ) return ;
130+ // 触发窗口更新
131+ mainWin ?. webContents . send ( "request-desktop-lyric-data" ) ;
132+ } ) ;
133+
92134 // 获取配置
93135 ipcMain . handle ( "get-desktop-lyric-option" , ( ) => {
94136 return store . get ( "lyric" ) ;
@@ -98,7 +140,7 @@ const initLyricIpc = (): void => {
98140 ipcMain . on ( "set-desktop-lyric-option" , ( _ , option , callback : boolean = false ) => {
99141 store . set ( "lyric" , option ) ;
100142 // 触发窗口更新
101- if ( callback && lyricWin ) {
143+ if ( callback && isWinAlive ( lyricWin ) ) {
102144 lyricWin . webContents . send ( "desktop-lyric-option-change" , option ) ;
103145 }
104146 mainWin ?. webContents . send ( "desktop-lyric-option-change" , option ) ;
@@ -111,14 +153,14 @@ const initLyricIpc = (): void => {
111153
112154 // 关闭桌面歌词
113155 ipcMain . on ( "closeDesktopLyric" , ( ) => {
114- if ( ! lyricWin ) return ;
156+ if ( ! isWinAlive ( lyricWin ) ) return ;
115157 lyricWin . hide ( ) ;
116158 mainWin ?. webContents . send ( "closeDesktopLyric" ) ;
117159 } ) ;
118160
119161 // 锁定/解锁桌面歌词
120162 ipcMain . on ( "toogleDesktopLyricLock" , ( _ , isLock : boolean ) => {
121- if ( ! lyricWin ) return ;
163+ if ( ! isWinAlive ( lyricWin ) ) return ;
122164 // 是否穿透
123165 if ( isLock ) {
124166 lyricWin . setIgnoreMouseEvents ( true , { forward : true } ) ;
0 commit comments