Window

Sampled window state and window-management effects.

The size here is the logical drawing size: it matches mouse coordinates and raylib drawing units, and on a HiDPI display it is smaller than the actual framebuffer in pixels. scale! is the factor between the two, and it is what makes the resolution of a Capture explainable: a capture is taken from the framebuffer, so a 960 x 640 window on a display with a scale of 2 records 1920 x 1280 pixels.

suggest_* effects request geometry that the window manager may alter or decline; a later Snapshot is authoritative. set_* effects change state controlled by the host.

suggest_size! : { width : I32, height : I32 } => {}

Suggest a new logical window size to the window manager.

Non-positive dimensions are ignored. The backend or window manager controls the resulting geometry: observe the latest accepted size through a later Snapshot.

Legal in init!, update!, and tasks; refused in render!.

suggest_min_size! : { width : I32, height : I32 } => {}

Suggest the smallest size the window can be dragged down to.

Each negative dimension is clamped to 0, leaving that axis unconstrained. A minimum only binds on a resizable window, so pair it with App.default.with_resizable(Bool.True). The window manager may apply target-specific constraints; Snapshot remains the authoritative sample.

Legal in init!, update!, and tasks; refused in render!.

set_target_fps! : I32 => {}

Set raylib's CPU-side frame-rate cap.

Values at or below zero render uncapped. This neither selects a software renderer nor controls VSync.

Legal in init!, update!, and tasks; refused in render!.

scale! : () => { x : F32, y : F32 }

How many framebuffer pixels one logical unit is, per axis.

Legal in any callback, render! included. Reading a factor the backend already holds costs nothing and allocates nothing.

1 on an ordinary display and 2 on a doubled HiDPI one; the two axes can differ. Multiply a Snapshot size or a Draw.FrameSize by this to get the pixel resolution a Capture records at.

monitors! : () => List(Monitor)

Every display the windowing backend can currently see.

The list is as long as the operating system's monitor count, and that count is the bound: the host asks for it, builds exactly that many entries, and never retains any of them. Monitors come and go while an app runs, so a result describes the moment it was taken; ask again rather than caching one for the life of the process.

Legal in init!, update!, and tasks; refused in render!.

suggest_position! : { x : I32, y : I32 } => {}

Suggest where the window's top-left corner should sit, in virtual-desktop coordinates.

The window manager controls the resulting geometry, and a position outside every monitor may be adjusted or ignored. Pair it with monitors! to place a window on a chosen display.

Legal in init!, update!, and tasks; refused in render!.

suggest_monitor! : I32 => {}

Suggest which monitor the window should move to, by Monitor.index.

An index outside the connected set is ignored: which monitors exist can change between reading monitors! and acting on one, so a stale index is an ordinary race rather than a fault to report.

Legal in init!, update!, and tasks; refused in render!.

Snapshot : {
    size : { width : I32, height : I32 },
    focused : Bool,
    minimized : Bool,
    close_requested : Bool,
}

The window's logical drawing size, whether it has keyboard focus, whether it is minimized, and whether the user asked it to close.

size is in the same logical units as mouse positions and every drawing call, not in framebuffer pixels; multiply by Window.scale! for those. A minimized window still runs the frame loop, so an app that should idle while minimized has to check this. These three are state samples: the latest value when the cycle began.

close_requested is an interval event. It is Bool.True on the one cycle after the user clicked the window's close button (or the system asked the app to quit), and only when the app chose App.Config.with_close_request(Deliver); under the default Exit the host closes the window itself and update! never sees the request. Several requests between two cycles arrive as one, and a request is never lost: the next input includes it. The exit key is separate -- it closes the app directly -- so set with_exit_key(NoExitKey) as well if the app must see every way out.

ClipboardReadError : [PermissionDenied, Unavailable, TooLarge, Busy]

Why the clipboard held no text for read_clipboard!.

Unavailable is an empty clipboard, non-text content, or a backend that refused. TooLarge is content past what the host will copy into a Str, and Busy is another process holding the clipboard.

Monitor : {
    index : I32,
    name : Str,
    size : { width : I32, height : I32 },
    position : { x : I32, y : I32 },
    refresh_hz : I32,
}

One display the windowing backend can currently see.

index is the argument suggest_monitor! takes. size and refresh_hz describe the video mode the monitor is running now, not what it is capable of, and position is its top-left corner in the same virtual-desktop coordinates suggest_position! uses -- so suggest_position!(monitor.position) puts the window in the corner of that monitor.

Clipboard

Window.Clipboard :: # (opaque)

Opaque clipboard authority supplied by App.Io. Reads need ClipboardRead and writes need ClipboardWrite.

for_host : Authority -> Clipboard

Private platform construction; no application can manufacture the argument.

read_text! : Clipboard => Try(Str, ClipboardReadError)

Read the system clipboard as text.

Legal in init!, update!, and tasks; refused in render!. The windowing backend only responds on the thread that owns the window, and the read is a pointer copy rather than I/O, so this does not wait.

Content that is not text, or is larger than the host will copy into a Str, is refused rather than truncated.

set_text! : Clipboard, Str => Try({}, [PermissionDenied])

Replace the system clipboard contents.

Read it back with Window.Clipboard.read_text!.

Legal in init!, update!, and tasks; refused in render!.