Merge pull request #105 from got-feedBack/feat/start-fullscreen
Some checks failed
Addon CI / addon (arm64, macos-14, mac) (push) Waiting to run
Addon CI / addon (x64, ubuntu-22.04, linux) (push) Waiting to run
Addon CI / addon (x64, windows-latest, win) (push) Waiting to run
Ship CI / CI (push) Waiting to run
Nightly / setup (push) Has been cancelled
Nightly / build (arm64, macos-14, mac) (push) Has been cancelled
Nightly / build (x64, ubuntu-22.04, linux) (push) Has been cancelled
Nightly / build (x64, windows-latest, win) (push) Has been cancelled
Nightly / publish (push) Has been cancelled

feat: add "start in fullscreen" window preference
This commit is contained in:
Byron Gamatos 2026-07-13 14:44:48 +02:00 committed by GitHub
commit ffd56922f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 50 additions and 4 deletions

View File

@ -33,6 +33,12 @@ export const IPC_MAINTENANCE_RESTART = 'maintenance:restart' as const;
// powerSaveBlocker here instead. See got-feedback/feedback#686.
export const IPC_POWER_SET_SCREEN_AWAKE = 'power:setScreenAwake' as const;
// Main-window fullscreen-at-launch preference. Renderer (Settings → System)
// reads/writes it; main persists it in the desktop config and applies it on
// window creation.
export const IPC_WINDOW_GET_START_FULLSCREEN = 'window:getStartFullscreen' as const;
export const IPC_WINDOW_SET_START_FULLSCREEN = 'window:setStartFullscreen' as const;
// Detachable panes (feedBack core's window.feedBack.panes).
//
// Deliberately tiny. The renderer OPENS its own pane windows with window.open() —

View File

@ -117,6 +117,8 @@ import {
IPC_UPDATE_CHECK_NOW,
IPC_UPDATE_APPLY,
IPC_POWER_SET_SCREEN_AWAKE,
IPC_WINDOW_GET_START_FULLSCREEN,
IPC_WINDOW_SET_START_FULLSCREEN,
} from './ipc-channels';
import { initAudioBridge, shutdownAudio } from './audio-bridge';
import { initDebugLogging, isDebugEnabled } from './debug-log';
@ -469,6 +471,7 @@ function createWindow(port: number): void {
getDesktopConfig().windowBounds,
screen.getAllDisplays().map((d) => d.workArea),
);
const startFullscreen = getDesktopConfig().startFullscreen === true;
mainWindow = new BrowserWindow({
x: restored.x,
y: restored.y,
@ -476,17 +479,20 @@ function createWindow(port: number): void {
height: restored.height,
minWidth: MIN_WIDTH,
minHeight: MIN_HEIGHT,
fullscreen: startFullscreen,
title: 'fee[dB]ack',
backgroundColor: '#0f172a', // slate-900 to match Slopsmith UI
webPreferences: rendererWebPreferences,
});
if (restored.maximized) mainWindow.maximize();
if (restored.maximized && !startFullscreen) mainWindow.maximize();
// Persist geometry on close. getNormalBounds() so a maximized session
// saves the underlying windowed size, restored + re-maximized next launch.
// ponytail: fullscreen is deliberately not persisted (launching straight
// into fullscreen is jarring, especially on macOS) and we save on close
// only — a crash loses the last session's geometry; add debounced
// Fullscreen is NOT auto-persisted from the live window state (launching
// straight into fullscreen is jarring, especially on macOS); it launches
// fullscreen ONLY when the user opts in via Settings → System → "Start in
// fullscreen" (config.startFullscreen, applied above). We save geometry on
// close only — a crash loses the last session's geometry; add debounced
// resize/move saving if that ever matters.
mainWindow.on('close', () => {
if (!mainWindow || mainWindow.isDestroyed()) return;
@ -1272,6 +1278,23 @@ async function startup(): Promise<void> {
return { success: true, enabled: on, urls: getLanUrls() };
});
ipcMain.handle(IPC_WINDOW_GET_START_FULLSCREEN, () => getDesktopConfig().startFullscreen === true);
ipcMain.handle(IPC_WINDOW_SET_START_FULLSCREEN, (_event, on: unknown) => {
const value = on === true;
setDesktopConfig({ startFullscreen: value });
// Live-apply so the toggle is responsive, not silent-until-relaunch.
// Works on the first toggle on Windows/Linux. On macOS the FIRST enter on
// a window created windowed is dropped by AppKit (its native-fullscreen
// state machine isn't engaged until the window has been fullscreen once —
// creating with `fullscreen: true` engages it), so there it takes effect
// on next launch instead; the core Settings note tells macOS users that.
// Reliable live both ways once the window has entered fullscreen once.
if (mainWindow && !mainWindow.isDestroyed() && mainWindow.isFullScreen() !== value) {
mainWindow.setFullScreen(value);
}
return value;
});
// Auto-update (Velopack). The renderer Settings panel reads the persisted
// channel from localStorage and calls setChannel() on boot — we default
// to 'stable' here so the first check runs against the safest feed even

View File

@ -30,6 +30,8 @@ import {
IPC_UPDATE_EVENT_AVAILABLE,
IPC_UPDATE_EVENT_DOWNLOADED,
IPC_POWER_SET_SCREEN_AWAKE,
IPC_WINDOW_GET_START_FULLSCREEN,
IPC_WINDOW_SET_START_FULLSCREEN,
IPC_MAINTENANCE_GET_PATHS,
IPC_MAINTENANCE_RESET,
IPC_MAINTENANCE_RESTART,
@ -580,6 +582,14 @@ const feedBackDesktopApi = {
power: {
setScreenAwake: (keep: boolean) => ipcRenderer.invoke(IPC_POWER_SET_SCREEN_AWAKE, keep),
},
// Main-window preferences the renderer can't own because the main process
// must read them at window-creation time. Today: start-in-fullscreen, wired
// by feedBack core's Settings → System "Start in fullscreen" toggle
// (setupWindowOptions()). Both methods return the resulting boolean.
window: {
getStartFullscreen: (): Promise<boolean> => ipcRenderer.invoke(IPC_WINDOW_GET_START_FULLSCREEN),
setStartFullscreen: (on: boolean): Promise<boolean> => ipcRenderer.invoke(IPC_WINDOW_SET_START_FULLSCREEN, on),
},
// Detachable panes. The renderer opens its own pane windows with window.open()
// — it moves a live DOM node into them and needs a handle on the new document
// to do it — and Electron turns that into a real BrowserWindow, which main

View File

@ -38,6 +38,13 @@ interface DesktopConfig {
// Last main-window geometry, restored (after sanitization against the
// current display layout) on next launch — see window-bounds.ts.
windowBounds?: SavedWindowBounds;
// When true, the main window launches in fullscreen and the System-settings
// toggle that drives it is shown. Opt-in (default off) — this deliberately
// reverses createWindow()'s historical "never launch fullscreen" default,
// but only for users who ask for it. Persisted here (not renderer
// localStorage) because the main process must read it at window creation,
// before the renderer exists.
startFullscreen?: boolean;
// Per-pane pop-out window geometry, keyed by pane id, plus its always-on-top
// flag. Sanitized against the display layout on restore, exactly like
// windowBounds — see pane-hosts.ts. Lives in the desktop config rather than