Skip to main content

Output composition reference

Every node and helper of output composition, all exported from shoji_wm. Props marked signal accept a plain value or a signal; reading a signal there re-evaluates the composition when it changes.

COMPOSITOR.rendering.composition​

COMPOSITOR.rendering.composition = (output: OutputInfo) => CompositionRenderable;

Called per output. Return a JSX tree of the nodes below (fragments and arrays nest freely; null, false and undefined draw nothing). Leave it unset, or return <DefaultComposition />, for the default stacking. A composition with no nodes draws nothing at all, so return the default rather than null.

Nodes​

Children draw back to front: later siblings are on top.

<Layers>​

Layer-shell surfaces of the output.

PropType
layerssignal LayerName | LayerName[]"background", "bottom", "top", "overlay", listed back to front.

Each layer's surfaces keep their own order (newest in front). Layers may appear in several nodes or in any order, e.g. Top below the windows.

<Windows>​

PropType
windowssignal (WaylandWindow | string)[]Exactly these windows (objects or ids), in stacking order, drawn even when hidden (as they would look shown). Omit for the output's own stack.
offsetX, offsetYsignal numberShift the windows, in logical pixels.

Without windows, the node is the output's own stack: what the output shows, with closing windows and decoration popups. That stack is the one the fullscreen fast path and direct scanout apply to, and only at the root of the composition. With windows, windows outside the composition's area are skipped.

<LayerPopups>​

Popups of layer-shell surfaces (bar menus and tooltips), all layers. No props.

<TextureView>​

A render texture drawn flat.

PropType
textureRenderTextureFrom renderTexture.
x, y, width, heightsignal numberWhere, in logical pixels of the composition. Omitted: the whole area. The texture stretches to fit.
opacitysignal number0 to 1 (default 1).

<Solid>​

A solid fill.

PropType
colorsignal CompositionColor"#rgb", "#rgba", "#rrggbb", "#rrggbbaa", or [r, g, b, a] in 0 to 1.
x, y, width, heightsignal numberAs for <TextureView>.

<Scene3D>​

A 3D scene of <Plane>s, rendered offscreen with a depth buffer and drawn as one layer of the composition.

PropType
camerasignal Camera{ projection, view } matrices; see cameras.
x, y, width, heightsignal numberThe scene's viewport. Omitted: the whole area.
clearColorsignal CompositionColorBehind the planes (default transparent).
antialiassignal boolean4x multisampled edges (default true).

Planes are drawn far to near; translucent planes blend over what lies behind them. Fully transparent parts of a texture (a window texture's empty shadow margin) do not hide what is behind them. Planes at the same depth fight; keep overlapping planes apart in z.

<Plane>​

A textured rectangle, only inside <Scene3D>.

PropType
textureRenderTextureWhat the plane shows.
width, heightsignal numberSize in world units, centred on the plane's origin.
transformsignal Transform3D | Mat4Placement in the world (default identity: facing the camera at the origin).
opacitysignal number0 to 1 (default 1).
doubleSidedsignal booleanDraw the back face too (default true).

<DefaultComposition />​

The default stacking: Layers[background, bottom], Windows, Layers[top, overlay], LayerPopups.

renderTexture(options)​

renderTexture({
content: CompositionRenderable, // the nodes to render
key?: string, // keeps the GPU texture across re-evaluations
width?: number, height?: number, // logical size (default: the output's)
scale?: number, // pixel density (default: the output's scale)
clearColor?: CompositionColor, // default transparent
}): RenderTexture

The content is laid out like the output: layers and windows appear at their usual places relative to the output's top-left corner, clipped to the texture's size. A texture renders once per frame, however often it is used, and incrementally. Without key, textures are told apart by call order.

3D helpers​

transform3d(matrix?)​

Starts a Transform3D, built like CSS transform: each call applies in the local space of the calls before it. Angles are in degrees.

Method
translate(x, y = 0, z = 0)Move.
rotateX(deg), rotateY(deg), rotateZ(deg)Turn about an axis.
scale(x, y = x, z = 1)Scale.
multiply(other)Apply another Transform3D or Mat4.
.matrixThe column-major Mat4.

Transforms are immutable, so a shared base can branch:

const cube = transform3d().translate(0, 0, -half).rotateY(angle);
const front = cube.translate(0, 0, half);
const right = cube.rotateY(90).translate(0, 0, half);

Cameras​

Helper
screenCamera(output | { width, height }, { fov = 45, distance = 0 })Maps z = 0 onto the output 1:1. distance pulls the camera back (zooms out).
perspective(fovY, aspect, near, far)OpenGL-style projection matrix; fovY in degrees.
lookAt(eye, target, up = [0, 1, 0])View matrix of a camera at eye looking at target.
multiplyMat4(a, b)a × b, column-major.
outputLogicalSize(output){ width, height } of an output in logical pixels.

A hand-built camera:

const { width, height } = outputLogicalSize(output);
const camera = {
projection: perspective(50, width / height, 1, 10_000),
view: lookAt([0, 300, 1600], [0, 0, 0]),
};

Picking​

Helper
projectPoint(camera, viewport, [x, y, z])Where a world point lands, { x, y, depth } in logical pixels from the viewport's top-left corner (depth: smaller is nearer), or null behind the camera.
pickPlane(camera, viewport, planes, x, y)Index of the nearest plane under (x, y), or null. planes take the same width, height and transform as their <Plane>s.

viewport is { width, height } of the <Scene3D>. With an input grab, this makes a 3D layout clickable:

const { width, height } = outputLogicalSize(output);
const hit = pickPlane(screenCamera(output), { width, height }, planes,
event.position.x - output.position.x, event.position.y - output.position.y);

Types​

Type
CompositionRenderableWhat a composition function returns.
RenderTextureResult of renderTexture.
Camera{ projection: Mat4; view: Mat4 }.
Mat416 numbers, column-major (WebGL/glMatrix layout).
LayerName"background" | "bottom" | "top" | "overlay".
CompositionColorHex string ("#rgb" to "#rrggbbaa") or [r, g, b, a] in 0 to 1 (straight alpha).