Skip to main content

Overview

The WindowsController is responsible for creating, tracking, and managing all types of windows in Flow Browser. It uses specialized type managers to handle different window types with type-safe APIs.
Import: import { windowsController } from '@/controllers/windows-controller'The controller is a singleton instance exported as windowsController.

Window Types

Flow Browser supports four window types, each with its own manager:

Browser

Main browsing windows (normal and popup)

Settings

Settings/preferences window (singleton)

Onboarding

First-run onboarding wizard (singleton)

Extension Popup

Extension popup windows

Type Managers

Each window type has a dedicated WindowTypeManager that provides type-safe methods:
class WindowsController {
  public browser: WindowTypeManager<typeof BrowserWindow>;
  public settings: WindowTypeManager<typeof SettingsWindow>;
  public onboarding: WindowTypeManager<typeof OnboardingWindow>;
  public extensionPopup: WindowTypeManager<typeof ExtensionPopupWindow>;
}

Browser Windows

The browser type manager handles both normal and popup browser windows.

Create a Browser Window

// Create a normal browser window
const browserWindow = windowsController.browser.new('normal');

// Create a popup window
const popupWindow = windowsController.browser.new('popup', {
  width: 800,
  height: 600,
  x: 100,
  y: 100
});

Get Browser Windows

// Get all browser windows
const allBrowserWindows = windowsController.browser.getAll();

// Get focused browser window
const focusedBrowser = windowsController.browser.getFocused();

// Get browser window by ID
const browserById = windowsController.browser.getById(windowId);

// Get browser window from WebContents
const browserFromWC = windowsController.browser.getFromWebContents(webContents);

Settings Window

Settings is a singleton window - only one can be open at a time.
// Get existing settings window or create new one
const settingsWindow = windowsController.settings.getSingletonWindow();

// Check if settings window exists
const existingSettings = windowsController.settings.getExistingSingletonWindow();
if (!existingSettings) {
  console.log('Settings window is not open');
}

Onboarding Window

Onboarding is also a singleton window shown on first launch.
// Show onboarding window
const onboardingWindow = windowsController.onboarding.getSingletonWindow();

// Check if onboarding is active
const isOnboarding = windowsController.onboarding.getExistingSingletonWindow() !== null;

Extension Popup Windows

Extension popups are created when users click extension icons.
// Create extension popup (typically handled internally)
const popup = windowsController.extensionPopup.new(extensionId, popupUrl);

// Get all extension popups
const allPopups = windowsController.extensionPopup.getAll();

Core Methods

Window Retrieval

getFocused()

Get the currently focused window of any type.
public getFocused(): BaseWindow | null
Example:
const focusedWindow = windowsController.getFocused();
if (focusedWindow) {
  console.log(`Focused window type: ${focusedWindow.type}`);
  console.log(`Focused window ID: ${focusedWindow.id}`);
}

getWindowById()

Retrieve any window by its numeric ID.
public getWindowById(id: number): BaseWindow | null

getWindowFromWebContents()

Find the window containing a specific WebContents.
public getWindowFromWebContents(webContents: WebContents): BaseWindow | null
Example:
// In an IPC handler
ipcMain.handle('some-action', (event) => {
  const window = windowsController.getWindowFromWebContents(event.sender);
  if (window) {
    console.log(`Request from window ${window.id}`);
  }
});

getAllWindows()

Get all windows of all types.
public getAllWindows(): BaseWindow[]
Example:
const allWindows = windowsController.getAllWindows();
console.log(`Total windows open: ${allWindows.length}`);

allWindows.forEach(window => {
  console.log(`${window.type} window (ID: ${window.id})`);
});

WindowTypeManager API

Each type manager provides these methods:

Standard Methods

new()
Method
Create a new window instance
public new(...args: ConstructorParameters<C>): InstanceType<C>
Note: Throws error if window type is a singleton.
getAll()
Method
Get all windows of this type
public getAll(): InstanceType<C>[]
getFocused()
Method
Get focused window of this type (or null)
public getFocused(): InstanceType<C> | null
getById()
Method
Get window of this type by ID
public getById(id: number): InstanceType<C> | null
getFromWebContents()
Method
Get window of this type from WebContents
public getFromWebContents(webContents: WebContents): InstanceType<C> | null

Singleton Methods

Available only for singleton window types (settings, onboarding):
getSingletonWindow()
Method
Get existing singleton or create new one
public getSingletonWindow(...args: ConstructorParameters<C>): InstanceType<C>
getExistingSingletonWindow()
Method
Get existing singleton (returns null if not open)
public getExistingSingletonWindow(): InstanceType<C> | null

Events

The WindowsController extends TypedEventEmitter with these events:
window-added
[id: number, window: BaseWindow]
Emitted when a new window is created
window-removed
[id: number, window: BaseWindow]
Emitted when a window is destroyed
window-focused
[id: number, window: BaseWindow]
Emitted when a window gains focus
Example:
windowsController.on('window-added', (id, window) => {
  console.log(`New ${window.type} window created: ${id}`);
});

windowsController.on('window-removed', (id, window) => {
  console.log(`Window ${id} closed`);
});

windowsController.on('window-focused', (id, window) => {
  console.log(`Window ${id} focused`);
});

BrowserWindow Specifics

The BrowserWindow class (not to be confused with Electron’s BrowserWindow) provides additional browser-specific functionality:

Properties

class BrowserWindow extends BaseWindow {
  public browserWindowType: 'normal' | 'popup';
  public viewManager: ViewManager;
  public coreWebContents: WebContents[];
  public omnibox: Omnibox;
}

Browser Window Events

page-bounds-changed
[bounds: PageBounds]
Emitted when the page content area changes size
current-space-changed
[spaceId: string]
Emitted when the window switches spaces
enter-full-screen
[]
Emitted when entering fullscreen mode
leave-full-screen
[]
Emitted when exiting fullscreen mode

ViewManager

The ViewManager handles WebContentsView management for tabs:
const browserWindow = windowsController.browser.getFocused();
if (browserWindow) {
  // ViewManager automatically handles adding/removing tab views
  const viewManager = browserWindow.viewManager;
  
  // Views are managed by TabsController, but can be accessed here
}

Omnibox

The Omnibox manages the address bar/search functionality:
const browserWindow = windowsController.browser.getFocused();
if (browserWindow) {
  const omnibox = browserWindow.omnibox;
  // Omnibox methods available here
}

Advanced Usage

Type Checking

Use isInstanceOf() to check window types:
const window = windowsController.getFocused();

if (windowsController.browser.isInstanceOf(window)) {
  // TypeScript knows this is a BrowserWindow
  console.log(window.browserWindowType);
}

if (windowsController.settings.isInstanceOf(window)) {
  // TypeScript knows this is a SettingsWindow
  console.log('Settings window is focused');
}

Filtering Windows

const window = windowsController.getWindowById(someId);

// Returns BrowserWindow or null
const browserWindow = windowsController.browser.filterInstance(window);

if (browserWindow) {
  // Safe to use as BrowserWindow
  console.log(browserWindow.viewManager);
}

Creating Browser Windows with Options

import { browserWindowsController } from '@/controllers/windows-controller/interfaces/browser';

// The browser interface provides convenient access
const window = browserWindowsController.create('normal', {
  width: 1920,
  height: 1080,
  x: 0,
  y: 0
});

// Or use instantCreate for immediate creation
const popupWindow = browserWindowsController.instantCreate('popup', {
  width: 600,
  height: 400
});

Window Lifecycle

Creation Flow

  1. Call manager.new() or manager.getSingletonWindow()
  2. Window constructor creates Electron BrowserWindow
  3. Window is added to controller via _addWindow()
  4. window-added event is emitted
  5. Window loads appropriate UI
  6. Window is shown after load (if configured)

Destruction Flow

  1. Window’s destroy() method is called
  2. Electron BrowserWindow is closed
  3. destroyed event is emitted on window
  4. Controller removes window via _removeWindow()
  5. window-removed event is emitted

Best Practices

Don’t call _addWindow() or _removeWindow() directly. These are internal methods used by window type managers.
Use type managers instead of direct window creation to maintain type safety and proper lifecycle management.
// Good
const window = windowsController.browser.new('normal');

// Bad - loses type safety and lifecycle tracking
const window = new BrowserWindow('normal');

Tabs Controller

Manage tabs within browser windows

Spaces Controller

Space management for organizing tabs

Window API

Window class implementation

Browser API

Browser controller implementation

Build docs developers (and LLMs) love