diff --git a/src/main/services/WindowService.ts b/src/main/services/WindowService.ts index 2ec8de6a3e2..3dd14587f5c 100644 --- a/src/main/services/WindowService.ts +++ b/src/main/services/WindowService.ts @@ -5,6 +5,7 @@ import { is } from '@electron-toolkit/utils' import { loggerService } from '@logger' import { isDev, isLinux, isMac, isWin } from '@main/constant' import { getFilesDir } from '@main/utils/file' +import { getWindowsBackgroundMaterial } from '@main/utils/windowUtil' import { MIN_WINDOW_HEIGHT, MIN_WINDOW_WIDTH } from '@shared/config/constant' import { IpcChannel } from '@shared/IpcChannel' import { app, BrowserWindow, nativeImage, nativeTheme, screen, shell } from 'electron' @@ -56,6 +57,12 @@ export class WindowService { fullScreen: false, maximize: false }) + const windowsBackgroundMaterial = getWindowsBackgroundMaterial() + let mainWindowBackgroundColor: string | undefined + + if (!isMac && !windowsBackgroundMaterial) { + mainWindowBackgroundColor = nativeTheme.shouldUseDarkColors ? '#181818' : '#FFFFFF' + } this.mainWindow = new BrowserWindow({ x: mainWindowState.x, @@ -81,7 +88,8 @@ export class WindowService { // On Linux, allow using system title bar if setting is enabled frame: isLinux && configManager.getUseSystemTitleBar() ? true : false }), - backgroundColor: isMac ? undefined : nativeTheme.shouldUseDarkColors ? '#181818' : '#FFFFFF', + ...(windowsBackgroundMaterial ? { backgroundMaterial: windowsBackgroundMaterial } : {}), + ...(mainWindowBackgroundColor ? { backgroundColor: mainWindowBackgroundColor } : {}), darkTheme: nativeTheme.shouldUseDarkColors, ...(isLinux ? { icon: linuxIcon } : {}), webPreferences: { diff --git a/src/main/utils/__tests__/windowUtil.test.ts b/src/main/utils/__tests__/windowUtil.test.ts new file mode 100644 index 00000000000..557b1f36122 --- /dev/null +++ b/src/main/utils/__tests__/windowUtil.test.ts @@ -0,0 +1,69 @@ +import { afterEach, describe, expect, it, vi } from 'vitest' + +const originalGetSystemVersion = process.getSystemVersion + +async function loadWindowUtil({ isWin, systemVersion = '' }: { isWin: boolean; systemVersion?: string }) { + vi.resetModules() + vi.doMock('../../constant', () => ({ + isDev: false, + isWin + })) + + const getSystemVersionMock = vi.fn(() => systemVersion) + Object.defineProperty(process, 'getSystemVersion', { + value: getSystemVersionMock, + configurable: true + }) + + const windowUtil = await import('../windowUtil') + return { ...windowUtil } +} + +afterEach(() => { + vi.resetModules() + vi.restoreAllMocks() + vi.doUnmock('../../constant') + + Object.defineProperty(process, 'getSystemVersion', { + value: originalGetSystemVersion, + configurable: true + }) +}) + +describe('getWindowsBackgroundMaterial', () => { + it('returns mica on Windows 11 22H2 and newer', async () => { + const { getWindowsBackgroundMaterial } = await loadWindowUtil({ + isWin: true, + systemVersion: '10.0.22621' + }) + + expect(getWindowsBackgroundMaterial()).toBe('mica') + }) + + it('returns undefined below the Windows 11 22H2 build threshold', async () => { + const { getWindowsBackgroundMaterial } = await loadWindowUtil({ + isWin: true, + systemVersion: '10.0.22000' + }) + + expect(getWindowsBackgroundMaterial()).toBeUndefined() + }) + + it('returns undefined when the system version cannot be parsed', async () => { + const { getWindowsBackgroundMaterial } = await loadWindowUtil({ + isWin: true, + systemVersion: 'Windows 11' + }) + + expect(getWindowsBackgroundMaterial()).toBeUndefined() + }) + + it('returns undefined on non-Windows platforms', async () => { + const { getWindowsBackgroundMaterial } = await loadWindowUtil({ + isWin: false, + systemVersion: '10.0.22621' + }) + + expect(getWindowsBackgroundMaterial()).toBeUndefined() + }) +}) diff --git a/src/main/utils/windowUtil.ts b/src/main/utils/windowUtil.ts index 454ce917f55..90c021464ca 100644 --- a/src/main/utils/windowUtil.ts +++ b/src/main/utils/windowUtil.ts @@ -2,6 +2,9 @@ import type { BrowserWindow } from 'electron' import { isDev, isWin } from '../constant' +// see: https://www.electronjs.org/zh/docs/latest/api/base-window#winsetbackgroundmaterialmaterial-windows +const WINDOWS_11_22H2_BUILD = 22621 + function isTilingWindowManager() { if (process.platform === 'darwin') { return false @@ -74,4 +77,19 @@ export const replaceDevtoolsFont = (browserWindow: BrowserWindow) => { } } +const isWindowsMicaSupported = () => { + if (!isWin) { + return false + } + + const systemVersion = process.getSystemVersion() + const buildNumber = Number.parseInt(systemVersion.split('.')[2] ?? '', 10) + + return Number.isFinite(buildNumber) && buildNumber >= WINDOWS_11_22H2_BUILD +} + +export const getWindowsBackgroundMaterial = () => { + return isWindowsMicaSupported() ? 'mica' : undefined +} + export { isTilingWindowManager }