From 78ef3c39d5a649063255f6f99aa0050a2dcf92a0 Mon Sep 17 00:00:00 2001 From: Johannes Millan Date: Tue, 10 Mar 2026 18:57:49 +0100 Subject: [PATCH] fix(electron): always show app border unless in fullscreen Previously the 1px border only appeared with the custom title bar enabled. Now it shows for all Electron windows and is hidden during fullscreen via IPC-driven body class toggling. --- electron/main-window.ts | 13 +++++++++++++ electron/shared-with-frontend/ipc-events.const.ts | 2 ++ src/app/app.constants.ts | 1 + src/app/core/ipc-events.ts | 7 +++++++ src/app/core/theme/global-theme.service.ts | 7 +++++++ src/styles/page.scss | 2 +- 6 files changed, 31 insertions(+), 1 deletion(-) diff --git a/electron/main-window.ts b/electron/main-window.ts index 32f5aebc6a..1261953edd 100644 --- a/electron/main-window.ts +++ b/electron/main-window.ts @@ -259,6 +259,19 @@ export const createWindow = async ({ } }); + // Notify renderer of fullscreen state changes (used for app border visibility) + mainWin.on('enter-full-screen', () => { + mainWin.webContents.send(IPC.ENTER_FULL_SCREEN); + }); + mainWin.on('leave-full-screen', () => { + mainWin.webContents.send(IPC.LEAVE_FULL_SCREEN); + }); + mainWin.webContents.on('did-finish-load', () => { + if (mainWin.isFullScreen()) { + mainWin.webContents.send(IPC.ENTER_FULL_SCREEN); + } + }); + // Listen for theme changes to update title bar overlay color and symbol if (isUseCustomWindowTitleBar && !IS_MAC) { ipcMain.on(IPC.UPDATE_TITLE_BAR_DARK_MODE, (ev, isDarkMode: boolean) => { diff --git a/electron/shared-with-frontend/ipc-events.const.ts b/electron/shared-with-frontend/ipc-events.const.ts index 60413d08fe..7ca8751bb1 100644 --- a/electron/shared-with-frontend/ipc-events.const.ts +++ b/electron/shared-with-frontend/ipc-events.const.ts @@ -53,6 +53,8 @@ export enum IPC { ANY_FILE_DOWNLOADED = 'ANY_FILE_DOWNLOADED', FULL_SCREEN_BLOCKER = 'FULL_SCREEN_BLOCKER', + ENTER_FULL_SCREEN = 'ENTER_FULL_SCREEN', + LEAVE_FULL_SCREEN = 'LEAVE_FULL_SCREEN', GET_PATH = 'GET_PATH', GET_BACKUP_PATH = 'GET_BACKUP_PATH', diff --git a/src/app/app.constants.ts b/src/app/app.constants.ts index 0ca9ef3833..0cf25ff48b 100644 --- a/src/app/app.constants.ts +++ b/src/app/app.constants.ts @@ -44,6 +44,7 @@ export enum BodyClass { isAndroidKeyboardShown = 'isAndroidKeyboardShown', isAndroidKeyboardHidden = 'isAndroidKeyboardHidden', + isFullScreen = 'isFullScreen', isAddTaskBarOpen = 'isAddTaskBarOpen', // iOS-specific classes diff --git a/src/app/core/ipc-events.ts b/src/app/core/ipc-events.ts index bef76d8221..01010af4e0 100644 --- a/src/app/core/ipc-events.ts +++ b/src/app/core/ipc-events.ts @@ -24,6 +24,13 @@ export const ipcSuspend$: Observable = IS_ELECTRON ? ipcEvent$(IPC.SUSPEND).pipe() : EMPTY; +export const ipcEnterFullScreen$: Observable = IS_ELECTRON + ? ipcEvent$(IPC.ENTER_FULL_SCREEN).pipe() + : EMPTY; +export const ipcLeaveFullScreen$: Observable = IS_ELECTRON + ? ipcEvent$(IPC.LEAVE_FULL_SCREEN).pipe() + : EMPTY; + export const ipcShowAddTaskBar$: Observable = IS_ELECTRON ? ipcEvent$(IPC.SHOW_ADD_TASK_BAR).pipe() : EMPTY; diff --git a/src/app/core/theme/global-theme.service.ts b/src/app/core/theme/global-theme.service.ts index df9d643fbf..eb874af70f 100644 --- a/src/app/core/theme/global-theme.service.ts +++ b/src/app/core/theme/global-theme.service.ts @@ -26,6 +26,7 @@ import { combineLatest, fromEvent, Observable, of } from 'rxjs'; import { IS_FIREFOX } from '../../util/is-firefox'; import { ImexViewService } from '../../imex/imex-meta/imex-view.service'; import { IS_MOUSE_PRIMARY, IS_TOUCH_PRIMARY } from '../../util/is-mouse-primary'; +import { ipcEnterFullScreen$, ipcLeaveFullScreen$ } from '../ipc-events'; import { IS_ANDROID_WEB_VIEW } from '../../util/is-android-web-view'; import { androidInterface } from '../../features/android/android-interface'; @@ -282,6 +283,12 @@ export class GlobalThemeService { this.document.body.classList.add(BodyClass.isElectron); this.document.body.classList.add(BodyClass.isAdvancedFeatures); this.document.body.classList.remove(BodyClass.isNoAdvancedFeatures); + ipcEnterFullScreen$.pipe(takeUntilDestroyed(this._destroyRef)).subscribe(() => { + this.document.body.classList.add(BodyClass.isFullScreen); + }); + ipcLeaveFullScreen$.pipe(takeUntilDestroyed(this._destroyRef)).subscribe(() => { + this.document.body.classList.remove(BodyClass.isFullScreen); + }); } else { this.document.body.classList.add(BodyClass.isWeb); this._chromeExtensionInterfaceService.onReady$.pipe(take(1)).subscribe(() => { diff --git a/src/styles/page.scss b/src/styles/page.scss index 5304c0444c..7467df50f8 100644 --- a/src/styles/page.scss +++ b/src/styles/page.scss @@ -122,7 +122,7 @@ body { } } - &.isObsidianStyleHeader.isElectron { + &.isElectron:not(.isFullScreen) { border: 1px solid var(--divider-color); } }