From 5c21bc23843997c7f799174bd7ff4eee142abcaf Mon Sep 17 00:00:00 2001 From: vian Date: Sun, 27 Sep 2026 00:13:41 +0530 Subject: [PATCH 1/2] fix: make macOS window transparency opt-in again --- src/app/main/app.ts | 5 +++ src/ui/main/rootWindow.spec.ts | 43 ++++++++++++++++++++ src/ui/main/rootWindow.ts | 73 ++++++++++++++++++++++++++-------- 3 files changed, 104 insertions(+), 17 deletions(-) diff --git a/src/app/main/app.ts b/src/app/main/app.ts index fa7e3e5c77..73822405a7 100644 --- a/src/app/main/app.ts +++ b/src/app/main/app.ts @@ -19,6 +19,7 @@ import { SETTINGS_CLEAR_PERMITTED_SCREEN_CAPTURE_PERMISSIONS, SETTINGS_NTLM_CREDENTIALS_CHANGED, SETTINGS_SET_HARDWARE_ACCELERATION_OPT_IN_CHANGED, + SETTINGS_SET_IS_TRANSPARENT_WINDOW_ENABLED_CHANGED, SETTINGS_SET_IS_VIDEO_CALL_SCREEN_CAPTURE_FALLBACK_ENABLED_CHANGED, } from '../../ui/actions'; import { askForClearScreenCapturePermission } from '../../ui/main/dialogs'; @@ -365,6 +366,10 @@ export const setupApp = (): void => { relaunchApp(); }); + listen(SETTINGS_SET_IS_TRANSPARENT_WINDOW_ENABLED_CHANGED, () => { + relaunchApp(); + }); + listen( SETTINGS_SET_IS_VIDEO_CALL_SCREEN_CAPTURE_FALLBACK_ENABLED_CHANGED, (action) => { diff --git a/src/ui/main/rootWindow.spec.ts b/src/ui/main/rootWindow.spec.ts index c3d71c3904..561633aa61 100644 --- a/src/ui/main/rootWindow.spec.ts +++ b/src/ui/main/rootWindow.spec.ts @@ -516,3 +516,46 @@ describe('isInsideSomeScreen', () => { ).toBe(false); }); }); + +describe('getRootWindowAppearanceOptions', () => { + const { getRootWindowAppearanceOptions } = require('./rootWindow'); + + it('keeps the default macOS window opaque', () => { + expect( + getRootWindowAppearanceOptions({ + platform: 'darwin', + isTransparentWindowEnabled: false, + shouldUseDarkColors: true, + }) + ).toEqual({ backgroundColor: '#2f343d' }); + }); + + it('enables macOS vibrancy only when transparency is enabled', () => { + expect( + getRootWindowAppearanceOptions({ + platform: 'darwin', + isTransparentWindowEnabled: true, + shouldUseDarkColors: false, + }) + ).toEqual({ + transparent: true, + backgroundColor: '#00000000', + vibrancy: 'sidebar', + visualEffectState: 'active', + }); + }); + + it('preserves transparent client chrome on Linux', () => { + expect( + getRootWindowAppearanceOptions({ + platform: 'linux', + isTransparentWindowEnabled: false, + shouldUseDarkColors: false, + }) + ).toEqual({ + transparent: true, + backgroundColor: '#00000000', + hasShadow: true, + }); + }); +}); diff --git a/src/ui/main/rootWindow.ts b/src/ui/main/rootWindow.ts index d393b05a56..72f4ec9a8b 100644 --- a/src/ui/main/rootWindow.ts +++ b/src/ui/main/rootWindow.ts @@ -1,6 +1,7 @@ import path from 'path'; import type { + BrowserWindowConstructorOptions, ContextMenuParams, Rectangle, NativeImage, @@ -22,6 +23,7 @@ import { APP_MAIN_WINDOW_TITLE_SET, } from '../../app/actions'; import { setupRootWindowReload } from '../../app/main/dev'; +import { getPersistedValues } from '../../app/main/persistence'; import { select, watch, listen, dispatchLocal, dispatch } from '../../store'; import type { RootState } from '../../store/rootReducer'; import { @@ -88,9 +90,55 @@ const platformTitleBarStyle = : 'default'; const isMac = process.platform === 'darwin'; -// Linux client chrome is a plain rectangle under most WMs. Transparent + CSS -// radius paints soft outer corners. Windows already gets DWM rounding — leave it. -const usesLinuxClientChromeRounding = process.platform === 'linux'; + +export const getRootWindowAppearanceOptions = ({ + platform, + isTransparentWindowEnabled, + shouldUseDarkColors, +}: { + platform: NodeJS.Platform; + isTransparentWindowEnabled: boolean; + shouldUseDarkColors: boolean; +}): BrowserWindowConstructorOptions => { + if (platform === 'darwin') { + if (isTransparentWindowEnabled) { + return { + transparent: true, + backgroundColor: '#00000000', + vibrancy: 'sidebar', + visualEffectState: 'active', + }; + } + + return { + backgroundColor: shouldUseDarkColors ? '#2f343d' : '#ffffff', + }; + } + + if (platform === 'linux') { + // Linux client chrome is a plain rectangle under most WMs. Transparent + + // CSS radius paints soft outer corners. Windows gets DWM rounding. + return { + transparent: true, + backgroundColor: '#00000000', + hasShadow: true, + }; + } + + return {}; +}; + +const isMacTransparencyEnabled = (): boolean => { + if (!isMac) { + return false; + } + + try { + return getPersistedValues().isTransparentWindowEnabled === true; + } catch { + return false; + } +}; export const createRootWindow = (): void => { _rootWindow = new BrowserWindow({ @@ -102,20 +150,11 @@ export const createRootWindow = (): void => { ...(isMac ? { trafficLightPosition: { x: 12, y: 13 } } : {}), show: false, webPreferences, - ...(isMac - ? { - transparent: true, - vibrancy: 'sidebar', - visualEffectState: 'active', - } - : {}), - ...(usesLinuxClientChromeRounding - ? { - transparent: true, - backgroundColor: '#00000000', - hasShadow: true, - } - : {}), + ...getRootWindowAppearanceOptions({ + platform: process.platform, + isTransparentWindowEnabled: isMacTransparencyEnabled(), + shouldUseDarkColors: nativeTheme.shouldUseDarkColors, + }), }); // Block navigation to smb:// protocol From 8a2ba3176fff26817a57179e4aaea1bb2bfb1469 Mon Sep 17 00:00:00 2001 From: vian Date: Sun, 27 Sep 2026 00:28:43 +0530 Subject: [PATCH 2/2] fix: persist transparency before relaunch --- src/app/main/app.ts | 6 +++++- src/ui/main/rootWindow.ts | 9 +++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/app/main/app.ts b/src/app/main/app.ts index 73822405a7..5b69433353 100644 --- a/src/app/main/app.ts +++ b/src/app/main/app.ts @@ -13,7 +13,7 @@ import electronBuilderJson from '../../../electron-builder.json'; // eslint-disable-next-line import/order, @typescript-eslint/no-unused-vars import packageJson from '../../../package.json'; import { JITSI_SERVER_CAPTURE_SCREEN_PERMISSIONS_CLEARED } from '../../jitsi/actions'; -import { dispatch, listen } from '../../store'; +import { dispatch, listen, select } from '../../store'; import { readSetting } from '../../store/readSetting'; import { SETTINGS_CLEAR_PERMITTED_SCREEN_CAPTURE_PERMISSIONS, @@ -32,6 +32,8 @@ import { APP_VERSION_SET, APP_SCREEN_CAPTURE_FALLBACK_FORCED_SET, } from '../actions'; +import { selectPersistableValues } from '../selectors'; +import { flushPersistedValues, persistValues } from './persistence'; export const packageJsonInformation = { productName: packageJson.productName, @@ -367,6 +369,8 @@ export const setupApp = (): void => { }); listen(SETTINGS_SET_IS_TRANSPARENT_WINDOW_ENABLED_CHANGED, () => { + persistValues(select(selectPersistableValues)); + flushPersistedValues(); relaunchApp(); }); diff --git a/src/ui/main/rootWindow.ts b/src/ui/main/rootWindow.ts index 72f4ec9a8b..8358d825b8 100644 --- a/src/ui/main/rootWindow.ts +++ b/src/ui/main/rootWindow.ts @@ -23,7 +23,6 @@ import { APP_MAIN_WINDOW_TITLE_SET, } from '../../app/actions'; import { setupRootWindowReload } from '../../app/main/dev'; -import { getPersistedValues } from '../../app/main/persistence'; import { select, watch, listen, dispatchLocal, dispatch } from '../../store'; import type { RootState } from '../../store/rootReducer'; import { @@ -133,11 +132,9 @@ const isMacTransparencyEnabled = (): boolean => { return false; } - try { - return getPersistedValues().isTransparentWindowEnabled === true; - } catch { - return false; - } + return select( + ({ isTransparentWindowEnabled }) => isTransparentWindowEnabled === true + ); }; export const createRootWindow = (): void => {