BrowserWindow
Create and control top-level application windows in the Bunmaska main process - the drop-in equivalent of Electron's BrowserWindow.
Create and control top-level application windows. BrowserWindow is Bunmaska’s drop-in equivalent of Electron’s class of the same name: it extends Node’s EventEmitter, owns a WebContents for all page-related operations, and is backed by NSWindow on macOS and a GTK4 GtkWindow on Linux (no Windows).
Like Electron, you cannot use this module until the app ready event has fired.
// In the main process.
import { app, BrowserWindow } from 'bunmaska';
app.whenReady().then(() => {
const win = new BrowserWindow({ width: 800, height: 600 });
win.loadURL('https://github.com');
// Or a local file:
// win.loadFile('index.html');
});
Constructor
new BrowserWindow([options])
Creates a new window. All options are optional; unspecified options fall back to Bunmaska’s defaults (800x600, title "Bunmaska", shown immediately, resizable).
The supported options are a deliberately small subset of Electron’s BrowserWindowConstructorOptions:
widthnumber - content width in pixels. Default800.heightnumber - content height in pixels. Default600.titlestring - initial window title. Default"Bunmaska".showboolean - show the window immediately on creation. Defaulttrue.resizableboolean - whether the user can resize the window. Defaulttrue.frameboolean - draw the OS frame/title bar.falseopens a frameless window.fullscreenboolean - open in fullscreen. Defaultfalse.webPreferencesobject - per-window renderer preferences. The only supported key ispreload: an absolute-resolved path to a script run in an isolated world (Electron’scontextIsolation: true) before the page’s own scripts. It is read synchronously at construction; an unreadable path throws.
import { BrowserWindow } from 'bunmaska';
import { join } from 'node:path';
const win = new BrowserWindow({
width: 1024,
height: 768,
title: 'My App',
frame: false,
webPreferences: {
preload: join(import.meta.dir, 'preload.ts'),
},
});
There is no BrowserWindowConstructorOptions mega-bag here - if an option isn’t in the list above, it isn’t wired yet. See Not in Bunmaska (yet).
Methods
Objects created with new BrowserWindow have the following instance methods.
win.loadURL(url)
loadURL(url: string): void
Navigates the window’s web contents to a URL (remote http(s):// or local file://). Delegates to webContents.loadURL. Unlike Electron, this returns void, not a Promise - await navigation via webContents events if you need to.
const win = new BrowserWindow();
win.loadURL('https://example.com');
win.loadFile(filePath)
loadFile(filePath: string): void
Loads a local HTML file into the window’s web contents. Delegates to webContents.loadFile. Returns void.
const win = new BrowserWindow();
win.loadFile('index.html');
win.setTitle(title)
setTitle(title: string): void
Changes the title of the native window.
win.setTitle('Editing - untitled.txt');
win.getTitle()
getTitle(): string
Returns the current title of the native window. (As in Electron, this can differ from the page’s document.title.)
console.log(win.getTitle());
win.setSize(width, height)
setSize(width: number, height: number): void
Resizes the window to width by height. There is no animate argument.
win.setSize(1280, 720);
win.getSize()
getSize(): [number, number]
Returns the window’s [width, height] in pixels (derived from getBounds()).
const [w, h] = win.getSize();
win.getBounds()
getBounds(): { x: number; y: number; width: number; height: number }
Returns the window’s bounds as a rectangle. Linux reports x/y as 0 (GTK4/Wayland forbid introspecting global window coordinates), so treat position as best-effort there.
const { x, y, width, height } = win.getBounds();
win.setResizable(resizable)
setResizable(resizable: boolean): void
Enables or disables user resizing. On macOS this flips the NSResizableWindowMask style bit; on Linux it calls gtk_window_set_resizable.
win.setResizable(false);
win.isResizable()
isResizable(): boolean
Returns whether the window is user-resizable (tracked from the constructor option and setResizable).
if (!win.isResizable()) { /* ... */ }
win.setMinimumSize(width, height)
setMinimumSize(width: number, height: number): void
Constrains the window’s minimum content size.
win.setMinimumSize(400, 300);
win.getMinimumSize()
getMinimumSize(): [number, number]
Returns the window’s minimum [width, height], or [0, 0] if none was set.
const [minW, minH] = win.getMinimumSize();
win.setOpacity(opacity)
setOpacity(opacity: number): void
Sets window opacity, clamped to [0, 1] (1 = fully opaque). Backed by -[NSWindow setAlphaValue:] on macOS and gtk_widget_set_opacity on Linux. (This is wired on both platforms - unlike Electron, where setOpacity is a no-op on Linux.)
win.setOpacity(0.85);
win.getOpacity()
getOpacity(): number
Returns the last-set opacity in [0, 1].
console.log(win.getOpacity()); // 0.85
win.center()
center(): void
Centers the window on the current screen. macOS only in practice: on Linux this is a deliberate no-op, since GTK4 removed programmatic positioning and Wayland forbids clients from moving themselves (the compositor places the window).
win.center();
win.show()
show(): void
Shows the window and brings it to the front. Emits show (and, via the focus path, may emit focus).
const win = new BrowserWindow({ show: false });
win.once('ready-to-show', () => win.show());
win.hide()
hide(): void
Hides the window. Emits hide.
win.hide();
win.isVisible()
isVisible(): boolean
Returns whether the window is currently visible.
if (win.isVisible()) win.hide();
win.focus()
focus(): void
Gives the window keyboard focus and brings it forward.
win.focus();
win.isFocused()
isFocused(): boolean
Returns whether the window is the key/active window.
if (win.isFocused()) { /* ... */ }
win.minimize()
minimize(): void
Minimizes the window to the Dock/taskbar.
win.minimize();
win.isMinimized()
isMinimized(): boolean
Returns whether the window is minimized.
if (win.isMinimized()) win.restore();
win.restore()
restore(): void
Restores the window from a minimized state.
win.restore();
win.maximize()
maximize(): void
Maximizes (macOS: zooms) the window. On macOS it no-ops if already zoomed.
win.maximize();
win.unmaximize()
unmaximize(): void
Restores the window from a maximized state.
win.unmaximize();
win.isMaximized()
isMaximized(): boolean
Returns whether the window is maximized (macOS: zoomed).
console.log(win.isMaximized());
win.setFullScreen(flag)
setFullScreen(flag: boolean): void
Enters or leaves fullscreen mode. On macOS this toggles native fullscreen (only when the state actually needs to change); on Linux it calls gtk_window_fullscreen / unfullscreen.
win.setFullScreen(true);
win.isFullScreen()
isFullScreen(): boolean
Returns whether the window is in fullscreen mode.
if (win.isFullScreen()) win.setFullScreen(false);
win.setAlwaysOnTop(flag)
setAlwaysOnTop(flag: boolean): void
Sets whether the window floats above other windows. macOS only: backed by -[NSWindow setLevel:] (floating level). On Linux this is a best-effort no-op - GTK4 dropped the keep-above hint and offers no portable client API.
win.setAlwaysOnTop(true); // honored on macOS, no-op on Linux
win.close()
close(): void
Tries to close the window, routing through the same path as the user clicking the title-bar close button. A close listener may veto it via event.preventDefault(). If not vetoed, the closed event fires.
win.on('close', (e) => {
if (hasUnsavedChanges) e.preventDefault();
});
win.close();
win.destroy()
destroy(): void
Force-closes the window without consulting close listeners. The closed event still fires.
win.destroy();
win.isDestroyed()
isDestroyed(): boolean
Returns whether the window has been closed/destroyed. After closed, drop your reference and stop using the instance.
if (!win.isDestroyed()) win.focus();
Static methods
BrowserWindow.getAllWindows()
static getAllWindows(): BrowserWindow[]
Returns all open windows in creation order.
import { BrowserWindow } from 'bunmaska';
for (const win of BrowserWindow.getAllWindows()) {
win.close();
}
BrowserWindow.fromId(id)
static fromId(id: number): BrowserWindow | undefined
Returns the window with the given id, or undefined if none. Note: unlike Electron (which returns null), the miss value here is undefined.
const win = BrowserWindow.fromId(1);
win?.focus();
Events
BrowserWindow is an EventEmitter. The following events are emitted.
Event: ‘closed’
Emitted when the window has been closed. After receiving it, remove your reference to the window and stop using it.
win.on('closed', () => {
console.log('window gone');
});
Event: ‘close’
Returns: event - an object with preventDefault() and a defaultPrevented getter.
Emitted when the window is about to close. Calling event.preventDefault() vetoes the close and keeps the window open. This is the hook for “unsaved changes?” prompts.
win.on('close', (event) => {
if (hasUnsavedWork()) {
event.preventDefault();
}
});
Event: ‘focus’
Emitted when the window gains focus. (Also drives app’s browser-window-focus.)
win.on('focus', () => console.log('focused'));
Event: ‘blur’
Emitted when the window loses focus. (Also drives app’s browser-window-blur.)
win.on('blur', () => console.log('blurred'));
Event: ‘show’
Emitted when the window is shown.
Event: ‘hide’
Emitted when the window is hidden.
Event: ‘resize’
Emitted after the window has been resized.
Event: ‘maximize’
Emitted when the window is maximized.
Event: ‘unmaximize’
Emitted when the window leaves a maximized state.
Event: ‘minimize’
Emitted when the window is minimized.
Event: ‘restore’
Emitted when the window is restored from a minimized state.
Event: ‘ready-to-show’
Emitted when the page has been rendered (while not yet shown) and the window can be displayed without a visual flash. The standard pattern is to construct with show: false and show on this event.
const win = new BrowserWindow({ show: false });
win.once('ready-to-show', () => win.show());
win.loadURL('https://example.com');
Properties
win.id Readonly
A process-unique number identifying the window, matching Electron’s BrowserWindow.id. Used as the key for BrowserWindow.fromId.
const win = new BrowserWindow();
console.log(win.id); // e.g. 1
win.webContents Readonly
The WebContents this window owns. All page-related operations (navigation, IPC, JS execution) go through it. See the WebContents reference for its methods and events.
const win = new BrowserWindow();
win.webContents.on('did-finish-load', () => {
win.webContents.executeJavaScript('document.title');
});
Not in Bunmaska (yet)
Bunmaska implements the window-management core but omits large swaths of Electron’s BrowserWindow surface. Notable gaps:
setPosition/getPosition/setBounds/setContentBounds/getContentBounds/getNormalBounds- no positional setters; onlysetSizeandgetBounds/getSizeexist. (On Linux, position is fundamentally constrained by GTK4/Wayland anyway.)setContentSize/getContentSize/getMaximumSize/setMaximumSize- only the minimum-size pair andsetSizeare wired.setMovable/setMinimizable/setMaximizable/setClosable/setFocusableand their getters - the constraint setters beyondsetResizableare absent.setBackgroundColor/getBackgroundColor,setHasShadow/hasShadow,setVibrancy- no appearance/material APIs.setIcon,setProgressBar,flashFrame,setSkipTaskbar,setKiosk/isKiosk,setMenu/removeMenu- taskbar/dock/menu-bar and kiosk controls are not implemented.capturePage,getNativeWindowHandle,getMediaSourceId,moveTop/moveAbove,setAspectRatio- missing.- Parent/child & modal windows - no
parent/modalconstructor options, and nosetParentWindow/getParentWindow/getChildWindows. Child and modal windows don’t exist yet. - macOS tabbing, Touch Bar, simple-fullscreen, represented file, traffic-light positioning, content protection - none of the macOS-only flair (
setSimpleFullScreen,addTabbedWindow,setTouchBar,setRepresentedFilename,setWindowButtonVisibility,setContentProtection, …) is wired. BrowserWindow.getFocusedWindow/fromWebContents- onlygetAllWindowsandfromIdare exposed as statics.- Events -
page-title-updated,enter-full-screen/leave-full-screen,move/moved,will-resize/resized,always-on-top-changed, and the various platform-specific gesture events (swipe,rotate-gesture,app-command, …) are not emitted. The implemented set is the lifecycle list above. - Constructor options - beyond the seven documented keys (plus
webPreferences.preload), the rest ofBrowserWindowConstructorOptions(e.g.backgroundColor,transparent,alwaysOnTop,parent,modal,minWidth/minHeight,titleBarStyle, the fullwebPreferencesbag) is ignored.
If you need one of these, it’s genuinely not there - not hidden behind a flag.