> ## Documentation Index
> Fetch the complete documentation index at: https://webview.js.org/llms.txt
> Use this file to discover all available pages before exploring further.

# BrowserWindow — Native OS Window Management API

> BrowserWindow wraps a native OS window. Control size, position, visibility, decorations, cursors, progress bars, file dialogs, and menus.

`BrowserWindow` wraps a native OS window and provides full control over its appearance, behavior, and content. You create a `BrowserWindow` through the application factory — never via `new BrowserWindow()` directly — and then attach a [`Webview`](/api/webview) to it to display web content.

```ts theme={null}
import { Application } from '@webviewjs/webview';

const app = new Application();
await app.whenReady();

const win = app.createBrowserWindow({ title: 'Hello', width: 1280, height: 720 });
const webview = win.createWebview({ url: 'https://example.com' });
```

***

## Creation Options

Pass a `BrowserWindowOptions` object to `app.createBrowserWindow()` or `app.createChildBrowserWindow()`.

### Basic

| Option    | Type      | Default       | Description                                                                                               |
| --------- | --------- | ------------- | --------------------------------------------------------------------------------------------------------- |
| `title`   | `string`  | `"WebviewJS"` | Window title bar text                                                                                     |
| `width`   | `number`  | `800`         | Initial window width in physical pixels (or logical if `logical: true`)                                   |
| `height`  | `number`  | `600`         | Initial window height in physical pixels (or logical if `logical: true`)                                  |
| `x`       | `number`  | —             | Initial horizontal position of the window's top-left corner                                               |
| `y`       | `number`  | —             | Initial vertical position of the window's top-left corner                                                 |
| `logical` | `boolean` | `false`       | When `true`, interpret `width`, `height`, `x`, and `y` as logical (CSS) pixels instead of physical pixels |

### Behavior

| Option                   | Type      | Default | Description                                                      |
| ------------------------ | --------- | ------- | ---------------------------------------------------------------- |
| `resizable`              | `boolean` | `true`  | Allow the user to resize the window                              |
| `visible`                | `boolean` | `true`  | Show the window immediately on creation                          |
| `decorations`            | `boolean` | `true`  | Show the native title bar and window border                      |
| `transparent`            | `boolean` | `false` | Make the window background transparent                           |
| `maximized`              | `boolean` | `false` | Start the window in a maximized state                            |
| `maximizable`            | `boolean` | `true`  | Allow the user to maximize the window                            |
| `minimizable`            | `boolean` | `true`  | Allow the user to minimize the window                            |
| `focused`                | `boolean` | `true`  | Give the window keyboard focus on creation                       |
| `alwaysOnTop`            | `boolean` | `false` | Keep the window above all other windows                          |
| `alwaysOnBottom`         | `boolean` | `false` | Keep the window below all other windows                          |
| `contentProtection`      | `boolean` | `false` | Prevent the window from being captured by screen-recording tools |
| `visibleOnAllWorkspaces` | `boolean` | `false` | Show the window on every virtual desktop / workspace             |

### Fullscreen

| Option       | Type             | Default | Description                                                                                                                         |
| ------------ | ---------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `fullscreen` | `FullscreenType` | —       | Start the window in fullscreen mode. `'Exclusive'` uses an exclusive display mode; `'Borderless'` is a fullscreen borderless window |

### Menu

| Option     | Type          | Default | Description                                                                |
| ---------- | ------------- | ------- | -------------------------------------------------------------------------- |
| `menu`     | `MenuOptions` | —       | Per-window menu that overrides the global application menu for this window |
| `showMenu` | `boolean`     | —       | When `true`, display the global application menu on this window            |

See the [Menus guide](/guides/menus) for the `MenuOptions` shape.

### Windows-specific options

| Option                       | Type            | Description                                    |
| ---------------------------- | --------------- | ---------------------------------------------- |
| `windowsOwnerWindow`         | `bigint`        | HWND of the owner window                       |
| `windowsTaskbarIcon`         | `TrayIconImage` | Custom taskbar icon for this window            |
| `windowsNoRedirectionBitmap` | `boolean`       | Disable the redirection bitmap (DWM)           |
| `windowsDragAndDrop`         | `boolean`       | Enable OLE drag-and-drop                       |
| `windowsSkipTaskbar`         | `boolean`       | Hide the window from the taskbar               |
| `windowsClassName`           | `string`        | Custom Win32 `WNDCLASS` name                   |
| `windowsUndecoratedShadow`   | `boolean`       | Add a DWM drop shadow to an undecorated window |

### macOS-specific options

| Option                           | Type      | Description                                          |
| -------------------------------- | --------- | ---------------------------------------------------- |
| `macosMovableByWindowBackground` | `boolean` | Allow dragging the window by clicking its background |
| `macosTitlebarTransparent`       | `boolean` | Make the title bar transparent                       |
| `macosTitleHidden`               | `boolean` | Hide the window title text                           |
| `macosTitlebarHidden`            | `boolean` | Hide the title bar entirely                          |
| `macosTitlebarButtonsHidden`     | `boolean` | Hide the traffic-light buttons                       |
| `macosFullsizeContentView`       | `boolean` | Extend content behind the title bar                  |
| `macosDisallowHidpi`             | `boolean` | Opt out of HiDPI scaling                             |
| `macosHasShadow`                 | `boolean` | Toggle the window drop shadow                        |
| `macosTabbingIdentifier`         | `string`  | Group windows into a tab bar with this identifier    |

### iOS-specific options

| Option                          | Type                   | Description                                                                             |
| ------------------------------- | ---------------------- | --------------------------------------------------------------------------------------- |
| `iosScaleFactor`                | `number`               | Override the display scale factor                                                       |
| `iosValidOrientations`          | `IosValidOrientations` | Allowed device orientations (`LandscapeAndPortrait`, `Landscape`, `Portrait`)           |
| `iosPrefersHomeIndicatorHidden` | `boolean`              | Request that the home indicator be hidden                                               |
| `iosDeferredSystemGestureEdges` | `number`               | Bitmask of edges to defer system gestures on (top `1`, left `2`, bottom `4`, right `8`) |
| `iosPrefersStatusBarHidden`     | `boolean`              | Request that the status bar be hidden                                                   |

***

## Creating a Webview

Attach a browser view to the window by calling `createWebview()`. It returns a [`Webview`](/api/webview) object you use to control the content.

```ts theme={null}
win.createWebview(options?: WebviewOptions): Webview
```

Hold a strong reference to the returned `Webview` for as long as you need it. Do not discard the wrapper into a temporary variable.

```ts theme={null}
// ✅ Keep the reference
const webview = win.createWebview({ url: 'https://example.com' });

// ❌ Avoid — the wrapper may be garbage-collected
win.createWebview({ url: 'https://example.com' });
```

See [Webview](/api/webview) for the full `WebviewOptions` reference.

***

## Window State Methods

Control visibility and window chrome at runtime:

```ts theme={null}
win.setTitle(title: string): void
win.setVisible(visible: boolean): void
win.show(): void
win.hide(): void
win.close(): void
win.setMinimized(value: boolean): void
win.setMaximized(value: boolean): void
win.setFullscreen(type: FullscreenType | null): void  // null exits fullscreen
win.focus(): void
win.requestRedraw(): void
```

***

## Size and Position

All size and position methods accept an optional `logical` boolean. When `true`, values are interpreted as logical (CSS / device-independent) pixels. When `false` (the default), values are physical pixels.

```ts theme={null}
// Inner size: content area without the title bar and borders
win.getInnerSize(logical?: boolean): Dimensions   // { width, height }

// Outer size: full window frame including decorations
win.getOuterSize(logical?: boolean): Dimensions

// Set size; returns the new dimensions after the OS applies constraints, or null
win.setSize(width: number, height: number, logical?: boolean): Dimensions | null

// Minimum and maximum size constraints
win.setMinSize(width: number, height: number, logical?: boolean): void
win.setMaxSize(width: number, height: number, logical?: boolean): void

// Position of the window's top-left corner on screen
win.getPosition(logical?: boolean): Position      // { x, y }
win.setPosition(x: number, y: number, logical?: boolean): void

// Center on the current monitor
win.center(): void

// Current device-pixel ratio (e.g. 2.0 on a Retina display)
win.scaleFactor(): number
```

<Tip>
  Divide physical pixel values by `win.scaleFactor()` to convert them to logical pixels, which match CSS `px` units in the webview.
</Tip>

***

## Cursor Control

```ts theme={null}
win.setCursor(cursor: CursorType): void
win.setCursorVisible(visible: boolean): void

// Position in logical pixels, relative to the window's top-left corner
win.setCursorPosition(x: number, y: number): void

// Make the window transparent to mouse input (Windows and macOS only)
win.setIgnoreCursorEvents(ignore: boolean): void
```

### CursorType values

All 35 `CursorType` values are available:

`Default` · `Crosshair` · `Hand` · `Arrow` · `Move` · `Text` · `Wait` · `Help` · `Progress` · `NotAllowed` · `ContextMenu` · `Cell` · `VerticalText` · `Alias` · `Copy` · `NoDrop` · `Grab` · `Grabbing` · `ZoomIn` · `ZoomOut` · `ResizeEast` · `ResizeNorth` · `ResizeNorthEast` · `ResizeNorthWest` · `ResizeSouth` · `ResizeSouthEast` · `ResizeSouthWest` · `ResizeWest` · `ResizeEastWest` · `ResizeNorthSouth` · `ResizeNorthEastSouthWest` · `ResizeNorthWestSouthEast` · `ResizeColumn` · `ResizeRow` · `AllScroll`

```ts theme={null}
import { CursorType } from '@webviewjs/webview';

win.setCursor(CursorType.Hand);
```

***

## Decorations and Behavior

```ts theme={null}
win.setResizable(resizable: boolean): void
win.setMinimizable(minimizable: boolean): void
win.setMaximizable(maximizable: boolean): void
win.setClosable(closable: boolean): void
win.setAlwaysOnTop(always: boolean): void
win.setAlwaysOnBottom(always: boolean): void
win.setContentProtection(enabled: boolean): void
win.setDecorations(decorated: boolean): void

// Hide the window from the taskbar (Windows and Linux only)
win.setSkipTaskbar(skip: boolean): void

// Override the OS color theme for this window
win.theme: Theme           // current theme (read-only getter)
win.setTheme(theme: Theme): void
```

`Theme` values: `Theme.Light`, `Theme.Dark`, `Theme.System`.

***

## Icon and Progress Bar

### Window icon

Set the window's icon from an RGBA pixel buffer:

```ts theme={null}
win.setWindowIcon(icon: Uint8Array | number[], width?: number, height?: number): void
win.removeWindowIcon(): void
```

`icon` is a raw byte array of `width × height × 4` bytes in RGBA order (red, green, blue, alpha, each 0–255).

### Progress bar

Display a progress bar in the window's taskbar button (Windows) or dock icon (macOS):

```ts theme={null}
win.setProgressBar(progress: JsProgressBar): void
```

```ts theme={null}
interface JsProgressBar {
  state?: ProgressBarState;
  progress?: number; // 0–100
}
```

| `ProgressBarState` | Description                    |
| ------------------ | ------------------------------ |
| `None`             | Remove the progress indicator  |
| `Normal`           | Standard progress fill         |
| `Indeterminate`    | Animated indeterminate spinner |
| `Paused`           | Paused / yellow state          |
| `Error`            | Error / red state              |

```ts theme={null}
import { ProgressBarState } from '@webviewjs/webview';

win.setProgressBar({ state: ProgressBarState.Normal, progress: 42 });
```

***

## File Dialogs

Open a native file picker and get the selected paths. This call **blocks** until the user dismisses the dialog and returns the selected paths synchronously:

```ts theme={null}
win.openFileDialog(options?: FileDialogOptions): string[]
```

```ts theme={null}
interface FileDialogOptions {
  multiple?: boolean;             // Allow selecting more than one file
  title?: string;                 // Dialog title
  defaultPath?: string;           // Initial directory or file path
  filters?: Array<{
    name: string;                 // e.g. "Images"
    extensions: string[];         // e.g. ["png", "jpg", "webp"]
  }>;
}
```

```ts theme={null}
const paths = win.openFileDialog({
  multiple: true,
  title: 'Open images',
  filters: [{ name: 'Images', extensions: ['png', 'jpg', 'webp'] }],
});
console.log(paths); // ['/home/user/photo.png', ...]
```

***

## Monitor Info

Query information about the displays attached to the system:

```ts theme={null}
win.currentMonitor(): Monitor | null    // monitor the window is currently on
win.primaryMonitor(): Monitor | null    // the system's primary monitor
win.availableMonitors(): Monitor[]      // all connected monitors
```

Each `Monitor` object has:

```ts theme={null}
interface Monitor {
  name?: string;
  scaleFactor: number;
  size: Dimensions;            // { width, height } in physical pixels
  position: Position;          // { x, y } relative to the virtual screen
  videoModes: VideoMode[];     // available resolution/refresh-rate combinations
}
```

***

## Custom Protocols

Register a URL-scheme handler to serve your own content to the webview. You **must** call `registerProtocol()` before calling `createWebview()` on the same window.

```ts theme={null}
win.registerProtocol(
  name: string,
  handler: (request: Request) => Response | CustomProtocolResponse | Promise<Response | CustomProtocolResponse>
): void
```

The handler receives a standard [Fetch API `Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) and should return a standard `Response` (compatible with Hono, itty-router, and any Fetch-API framework) or a legacy `CustomProtocolResponse` plain object.

```ts theme={null}
// Serve a local file tree under app://localhost/
win.registerProtocol('app', async (request) => {
  const url = new URL(request.url);
  const body = await readFile('./dist' + url.pathname);
  return new Response(body, {
    headers: { 'Content-Type': 'text/html' },
  });
});

const webview = win.createWebview({ url: 'app://localhost/index.html' });
```

See the [Custom Protocols guide](/guides/custom-protocols) for a complete walkthrough.

***

## State Properties

Read the current window state through these properties and methods:

```ts theme={null}
win.width: number        // inner width in physical pixels
win.height: number       // inner height in physical pixels
win.x: number            // outer x position in physical pixels
win.y: number            // outer y position in physical pixels
win.title: string        // current window title

win.isFocused(): boolean
win.isVisible(): boolean
win.isDecorated(): boolean
win.isClosable(): boolean
win.isMaximizable(): boolean
win.isMinimizable(): boolean
win.isMaximized(): boolean
win.isMinimized(): boolean
win.isResizable(): boolean
```

***

## Window Events

`BrowserWindow` extends Node.js `EventEmitter`. All positional values (`x`, `y`, `width`, `height`, `deltaX`, `deltaY`) are in **physical pixels** at the current DPI. Divide by `win.scaleFactor()` to convert to logical (CSS) pixels.

### Event reference

| Event                  | Payload fields                         | Description                                                                                                    |
| ---------------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `move`                 | `x`, `y`                               | Window moved to a new position                                                                                 |
| `resize`               | `width`, `height`                      | Window was resized                                                                                             |
| `close`                | —                                      | Window received a close request                                                                                |
| `focus`                | —                                      | Window gained keyboard focus                                                                                   |
| `blur`                 | —                                      | Window lost keyboard focus                                                                                     |
| `mouse-enter`          | `x`, `y`                               | Pointer entered the window                                                                                     |
| `mouse-leave`          | —                                      | Pointer left the window                                                                                        |
| `mouse-move`           | `x`, `y`                               | Pointer moved inside the window                                                                                |
| `mouse-down`           | `x`, `y`, `button`                     | Mouse button pressed (`0`=left, `1`=middle, `2`=right)                                                         |
| `mouse-up`             | `x`, `y`, `button`                     | Mouse button released                                                                                          |
| `scroll`               | `deltaX`, `deltaY`                     | Scroll or trackpad gesture. Physical device deltas are passed through; line-scroll deltas are multiplied by 20 |
| `key-down`             | `key`, `code`, `modifiers`, `isRepeat` | Key pressed. `modifiers`: `1`=Shift, `2`=Ctrl, `4`=Alt, `8`=Meta                                               |
| `key-up`               | `key`, `code`, `modifiers`, `isRepeat` | Key released                                                                                                   |
| `file-drop`            | `files`                                | Files dropped onto the window                                                                                  |
| `file-hover`           | `files`                                | Files dragged over the window                                                                                  |
| `file-hover-cancelled` | —                                      | File drag left the window without a drop                                                                       |
| `scale-factor-changed` | `scaleFactor`                          | DPI scale factor changed                                                                                       |
| `theme-changed`        | `text` (`'light'` \| `'dark'`)         | OS theme changed                                                                                               |
| `ime`                  | `text`, `phase`                        | IME input event. Phases: `enabled`, `preedit`, `commit`, `disabled`                                            |
| `touch`                | `x`, `y`, `touchId`, `phase`           | Touch event. Phases: `started`, `moved`, `ended`, `cancelled`                                                  |

### Usage example

```ts theme={null}
win.on('resize', ({ width, height }) => {
  console.log(`Window resized to ${width}×${height} (physical px)`);
});

win.on('key-down', ({ key, code, modifiers, isRepeat }) => {
  if (key === 'F5') webview.reload();
});

win.on('file-drop', ({ files }) => {
  console.log('Dropped files:', files);
});

win.on('close', () => {
  app.exit();
});

win.on('theme-changed', ({ text }) => {
  console.log(`System theme is now: ${text}`);
});

win.on('mouse-down', ({ x, y, button }) => {
  const logical = { x: x / win.scaleFactor(), y: y / win.scaleFactor() };
  console.log(`Button ${button} at logical (${logical.x}, ${logical.y})`);
});
```

***

## Identity and Native Handles

```ts theme={null}
win.id(): number        // stable numeric ID within this process
win.isChild: boolean    // true if created with createChildBrowserWindow()
win.getNativeHandle(): bigint
```

`getNativeHandle()` returns the platform-native handle as a `bigint` pointer value:

| Platform | Handle type  |
| -------- | ------------ |
| Windows  | `HWND`       |
| macOS    | `NSView`     |
| X11      | `XID`        |
| Wayland  | `wl_surface` |

Returns `0n` when no supported handle is available for the current platform. Treat this as a **borrowed** value — do not destroy it or pass ownership to native code.

***

## Platform-Specific Extensions

### Windows

```ts theme={null}
win.setEnable(enabled: boolean): void
win.setTaskbarIcon(icon: Uint8Array | number[], width?: number, height?: number): void
win.removeTaskbarIcon(): void
win.setUndecoratedShadow(shadow: boolean): void
win.getNativeHandleAnyThread(): bigint
```

### macOS

```ts theme={null}
win.simpleFullscreen(): boolean
win.setSimpleFullscreen(fullscreen: boolean): boolean
win.hasShadow(): boolean
win.setHasShadow(value: boolean): void
win.setTabbingIdentifier(identifier: string): void
win.tabbingIdentifier(): string
win.isDocumentEdited(): boolean
win.setDocumentEdited(edited: boolean): void
```

### Linux (Wayland)

```ts theme={null}
win.getWaylandSurface(): bigint  // returns 0n on non-Wayland platforms
```

### Android

```ts theme={null}
win.androidContentRect(): AndroidContentRect  // { left, top, right, bottom }
win.androidConfig(): string                   // diagnostic configuration string
```

***

## Disposal

Call `win.dispose()` when you want to release a window before `app.exit()`:

```ts theme={null}
win.dispose(): void
win.isDisposed(): boolean
```

You can also use the `using` declaration for automatic cleanup:

```ts theme={null}
{
  using win = app.createBrowserWindow({ title: 'Temporary' });
  // ... use the window ...
} // win.dispose() called automatically
```

Disposal is **idempotent** — calling it more than once is safe. Disposing a window also disposes all `Webview` instances attached to it. `app.exit()` disposes every window owned by the application.
