v152 · window shape api · method
IsolatedWebApp.setShape()
Sets the shape of the calling IWA’s window to the union of the given rectangles, in Device Independent Pixels. Only areas covered by at least one rectangle stay visible and interactive. Pass an empty array to restore the default rectangular window.
- The calling context must be an allowlisted Isolated Web App on ChromeOS — otherwise
window.chromeosisnulland this method is unreachable. - The window must be in the
unframeddisplay mode — otherwise the returned promise rejects withInvalidStateError. - The origin must hold the
window-managementpermission (itself a prerequisite for enteringunframed).
Syntax
// WebIDL (specification):
partial interface IsolatedWebApp {
Promise<undefined> setShape(sequence<DOMRectReadOnly> rects);
};
// Call form:
await window.chromeos.isolatedWebApp.setShape(rects);
Source: spec §3.3 API Extension.
Parameters
rects |
A sequence<DOMRectReadOnly> — an array of rectangles (plain objects with x, y, width, height, or DOMRect/DOMRectReadOnly instances) in Device Independent Pixels in the OS window’s local coordinate space. Constraints, in evaluation order:
|
|---|
Return value
A Promise<undefined>. It resolves once the host operating system has been asked to apply the union of the (converted) rectangles to the window. With an empty array, the union is empty and the window returns to its default rectangular shape. The method returns the promise synchronously; validation failures that are detected before the parallel step reject that same promise (they do not throw synchronously).
Exceptions
All failure modes are promise rejections (no synchronous throw):
| Rejection | Condition |
|---|---|
InvalidStateError | The window’s display mode is not unframed (checked both when the method is called and again in the parallel step before application). |
InvalidStateError | No OS window is associated with the current global object at application time. |
TypeError | rects has more than 10,000 entries. |
TypeError | Any rectangle has a non-finite x, y, width, or height. |
TypeError | Any rectangle has width < 0 or height < 0. |
TypeError | The array is non-empty but no rectangle meets the 10×10 minimum size (the anti-invisible-window guard). |
Application algorithm
The specification’s steps, in order:
- Create a new promise; let window be the current global object.
- If window’s display mode is not
unframed, reject withInvalidStateErrorand return. - If
rectshas more than 10,000 entries, reject withTypeErrorand return. - For each rectangle: reject with
TypeErroron non-finite members or negativewidth/height; note whether any rectangle is ≥ 10×10; append a converted rectangle (members truncated to integers, clamped to int32) to the working list. - If the array is non-empty and no rectangle met the 10×10 minimum, reject with
TypeErrorand return. - In parallel: resolve the OS window for the global object (reject
InvalidStateErrorif none); re-check the display mode is stillunframed(rejectInvalidStateErrorif not); ask the host OS to set the window’s shape to the union of the converted rectangles, interpreted in the window’s DIP coordinate space. - Resolve the promise with
undefined.
Lifecycle and state transitions
| Apply | Each fulfilled call replaces the window’s custom shape wholesale with the new union of rectangles — calls are not additive across invocations. |
|---|---|
| Reset | setShape([]) clears the custom shape; the window returns to its default rectangular form. |
| Idempotence | Calling with the same rectangles repeatedly is safe and produces the same shape. |
| Display-mode coupling | The unframed display mode is fixed for the lifetime of the window (per Manifest Incubations), so an unframed window cannot silently become ineligible mid-life; the spec still re-checks the mode in the parallel application step as a defense. |
| Policy-forced removal | If an administrator blocks window management via WindowManagementBlockedForUrls, Chrome removes any custom window shape and falls back to another available display mode (ChromeStatus summary). |
| No events | The API fires no events; shape changes are observable only visually (or via the demo pattern of re-reading window geometry through the Window Management API). |
Examples
A donut-style overlay panel anchored to the window’s bottom edge, with the required minimum-size rectangle:
const iwa = window.chromeos?.isolatedWebApp;
if (!iwa) throw new Error("Not an allowlisted IWA");
// Window is 800x600 DIPs. Show only a 800x120 strip at the bottom
// and a 200x200 floating badge at the top-right.
await iwa.setShape([
new DOMRect(0, 480, 800, 120), // main strip (>= 10x10 ✓)
new DOMRect(600, 0, 200, 200), // floating badge
]);
Resetting to the default rectangular window:
await window.chromeos.isolatedWebApp.setShape([]);
Handling the documented rejection paths:
try {
await iwa.setShape([{ x: 0, y: 0, width: 4, height: 4 }]);
} catch (e) {
// TypeError: no rectangle meets the 10x10 minimum-size guard.
}
try {
await iwa.setShape(new Array(10_001).fill(new DOMRect(0, 0, 10, 10)));
} catch (e) {
// TypeError: more than 10,000 rectangles.
}
Source: spec §3.4; explainer — example usage; Set-Shape-demo src/main.ts.
Browser compatibility
Interim table (no BCD or web-features entry exists; compiled from the linked primary sources, 2026-07-28):
| Browser | Support | Evidence |
|---|---|---|
| Chrome (ChromeOS) | 152+, allowlisted IWAs only | milestone=152 listing; Intent to Ship |
| Chrome (other platforms) | Not available | Intent to Ship (“not available in any other platform”) |
| Edge | Not available | ChromeOS-only Blink extension (explainer) |
| Firefox / Safari | No signal | ChromeStatus record vendor views |
Security and privacy
- Minimum-size guard. The 10×10 requirement on at least one rectangle exists specifically so the window cannot be made invisible or near-invisible (spec §3.1).
- Clickjacking surface. Non-rectangular windows can occlude other applications in confusing ways; the allowlist plus the
window-managementpermission grant are the mitigations (explainer, security section). - Input conversion. Coordinates are truncated to integers and clamped to int32 before reaching OS primitives, so extreme floating-point inputs cannot smuggle out-of-range values to the compositor.
- Validation is total. Every documented failure mode rejects the promise — a malformed call never partially applies a shape.
Sources
- ChromeOS APIs for Isolated Web Apps — the specification defining this method (§3.4)
- Window Shape API explainer — requirements, security analysis, and example usage
- Geometry Interfaces —
DOMRectReadOnly— the input rectangle type - Window Management API — the
window-managementpermission this method requires - Set-Shape-demo — official demo IWA using this method