diff --git a/packages/core/src/common/theme.ts b/packages/core/src/common/theme.ts index 73207acfb2b3c..1ce83b953865b 100644 --- a/packages/core/src/common/theme.ts +++ b/packages/core/src/common/theme.ts @@ -18,6 +18,8 @@ import { URI } from 'vscode-uri'; export type ThemeType = 'light' | 'dark' | 'hc' | 'hcLight'; +export type ThemeMode = 'light' | 'dark'; + export interface Theme { readonly id: string; readonly type: ThemeType; @@ -32,6 +34,10 @@ export function isHighContrast(scheme: ThemeType): boolean { return scheme === 'hc' || scheme === 'hcLight'; } +export function getThemeMode(type: ThemeType): ThemeMode { + return (type === 'hc' || type === 'dark') ? 'dark' : 'light'; +} + export interface ThemeChangeEvent { readonly newTheme: Theme; readonly oldTheme?: Theme; diff --git a/packages/core/src/electron-browser/menu/electron-menu-contribution.ts b/packages/core/src/electron-browser/menu/electron-menu-contribution.ts index 9023dc2612021..df3e1f1103f33 100644 --- a/packages/core/src/electron-browser/menu/electron-menu-contribution.ts +++ b/packages/core/src/electron-browser/menu/electron-menu-contribution.ts @@ -30,7 +30,7 @@ import { WindowTitleService } from '../../browser/window/window-title-service'; import '../../../src/electron-browser/menu/electron-menu-style.css'; import { ThemeService } from '../../browser/theming'; -import { ThemeChangeEvent } from '../../common/theme'; +import { getThemeMode, ThemeChangeEvent } from '../../common/theme'; export namespace ElectronCommands { export const TOGGLE_DEVELOPER_TOOLS = Command.toDefaultLocalizedCommand({ @@ -424,6 +424,7 @@ export class ElectronMenuContribution extends BrowserMenuBarContribution impleme protected handleThemeChange(e: ThemeChangeEvent): void { const backgroundColor = window.getComputedStyle(document.body).backgroundColor; window.electronTheiaCore.setBackgroundColor(backgroundColor); + window.electronTheiaCore.setTheme(getThemeMode(e.newTheme.type)); } } diff --git a/packages/core/src/electron-browser/preload.ts b/packages/core/src/electron-browser/preload.ts index 57755899242d8..ea99b1b8c66f0 100644 --- a/packages/core/src/electron-browser/preload.ts +++ b/packages/core/src/electron-browser/preload.ts @@ -27,7 +27,7 @@ import { CHANNEL_REQUEST_RELOAD, CHANNEL_APP_STATE_CHANGED, CHANNEL_SHOW_ITEM_IN_FOLDER, CHANNEL_READ_CLIPBOARD, CHANNEL_WRITE_CLIPBOARD, CHANNEL_KEYBOARD_LAYOUT_CHANGED, CHANNEL_IPC_CONNECTION, InternalMenuDto, CHANNEL_REQUEST_SECONDARY_CLOSE, CHANNEL_SET_BACKGROUND_COLOR, CHANNEL_WC_METADATA, CHANNEL_ABOUT_TO_CLOSE, CHANNEL_OPEN_WITH_SYSTEM_APP, - CHANNEL_OPEN_URL + CHANNEL_OPEN_URL, CHANNEL_SET_THEME } from '../electron-common/electron-api'; // eslint-disable-next-line import/no-extraneous-dependencies @@ -120,6 +120,9 @@ const api: TheiaCoreAPI = { setBackgroundColor: function (backgroundColor): void { ipcRenderer.send(CHANNEL_SET_BACKGROUND_COLOR, backgroundColor); }, + setTheme: function (theme): void { + ipcRenderer.send(CHANNEL_SET_THEME, theme); + }, minimize: function (): void { ipcRenderer.send(CHANNEL_MINIMIZE); }, diff --git a/packages/core/src/electron-common/electron-api.ts b/packages/core/src/electron-common/electron-api.ts index 79035b3e00d37..487cc80eeaefd 100644 --- a/packages/core/src/electron-common/electron-api.ts +++ b/packages/core/src/electron-common/electron-api.ts @@ -17,6 +17,7 @@ import { NativeKeyboardLayout } from '../common/keyboard/keyboard-layout-provider'; import { Disposable } from '../common'; import { FrontendApplicationState, StopReason } from '../common/frontend-application-state'; +import { ThemeMode } from '../common/theme'; export type MenuRole = ('undo' | 'redo' | 'cut' | 'copy' | 'paste' | 'selectAll' | 'about' | 'services' | 'hide' | 'hideOthers' | 'unhide' | 'quit'); @@ -65,6 +66,7 @@ export interface TheiaCoreAPI { getTitleBarStyleAtStartup(): Promise; setTitleBarStyle(style: string): void; setBackgroundColor(backgroundColor: string): void; + setTheme(theme: ThemeMode): void; minimize(): void; isMaximized(): boolean; // TODO: this should really be async, since it blocks the renderer process maximize(): void; @@ -125,6 +127,7 @@ export const CHANNEL_ATTACH_SECURITY_TOKEN = 'AttachSecurityToken'; export const CHANNEL_GET_TITLE_STYLE_AT_STARTUP = 'GetTitleStyleAtStartup'; export const CHANNEL_SET_TITLE_STYLE = 'SetTitleStyle'; export const CHANNEL_SET_BACKGROUND_COLOR = 'SetBackgroundColor'; +export const CHANNEL_SET_THEME = 'SetTheme'; export const CHANNEL_CLOSE = 'Close'; export const CHANNEL_MINIMIZE = 'Minimize'; export const CHANNEL_MAXIMIZE = 'Maximize'; diff --git a/packages/core/src/electron-main/electron-api-main.ts b/packages/core/src/electron-main/electron-api-main.ts index b96942633e0e4..4b601e9f17cec 100644 --- a/packages/core/src/electron-main/electron-api-main.ts +++ b/packages/core/src/electron-main/electron-api-main.ts @@ -55,7 +55,8 @@ import { CHANNEL_WC_METADATA, CHANNEL_ABOUT_TO_CLOSE, CHANNEL_OPEN_WITH_SYSTEM_APP, - CHANNEL_OPEN_URL + CHANNEL_OPEN_URL, + CHANNEL_SET_THEME } from '../electron-common/electron-api'; import { ElectronMainApplication, ElectronMainApplicationContribution } from './electron-main-application'; import { Disposable, DisposableCollection, isOSX, MaybePromise } from '../common'; @@ -176,6 +177,8 @@ export class TheiaMainApi implements ElectronMainApplicationContribution { ipcMain.on(CHANNEL_SET_BACKGROUND_COLOR, (event, backgroundColor) => application.setBackgroundColor(event.sender, backgroundColor)); + ipcMain.on(CHANNEL_SET_THEME, (event, theme) => application.setTheme(theme)); + ipcMain.on(CHANNEL_MINIMIZE, event => { BrowserWindow.fromWebContents(event.sender)?.minimize(); }); diff --git a/packages/core/src/electron-main/electron-main-application.ts b/packages/core/src/electron-main/electron-main-application.ts index 24ba3ac2e4120..682bc2da4d00c 100644 --- a/packages/core/src/electron-main/electron-main-application.ts +++ b/packages/core/src/electron-main/electron-main-application.ts @@ -42,6 +42,7 @@ import { createDisposableListener } from './event-utils'; import { TheiaRendererAPI } from './electron-api-main'; import { StopReason } from '../common/frontend-application-state'; import { dynamicRequire } from '../node/dynamic-require'; +import { ThemeMode } from '../common/theme'; export { ElectronMainApplicationGlobals }; @@ -277,6 +278,10 @@ export class ElectronMainApplication { this.saveState(webContents); } + public setTheme(theme: ThemeMode): void { + nativeTheme.themeSource = theme; + } + protected saveState(webContents: Electron.WebContents): void { const browserWindow = BrowserWindow.fromWebContents(webContents); if (browserWindow) {