<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://sachahjkl.github.io/gui_toolkit/</id>
  <title>gui_toolkit: releases</title>
  <subtitle>A fast, native, immediate-mode GUI toolkit in Odin</subtitle>
  <link rel="self" type="application/atom+xml" href="https://sachahjkl.github.io/gui_toolkit/feed.xml"/>
  <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/"/>
  <icon>https://sachahjkl.github.io/gui_toolkit/img/logo.png</icon>
  <author><name>Sacha Froment</name><uri>https://froment.software</uri></author>
  <updated>2026-11-07T00:00:00Z</updated>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.96.0</id>
    <title>gui_toolkit 0.96.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.96.0"/>
    <updated>2026-11-07T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.press_hand&lt;/code&gt;&lt;/strong&gt;: the press held on one box goes on on another, with what it keeps (&lt;code&gt;ui.press_data&lt;/code&gt;), for a gesture whose item is built in another place while it lasts: a tab dragged out of a list into a grid of pinned ones, whose boxes have other parents, stays one drag.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.95.0</id>
    <title>gui_toolkit 0.95.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.95.0"/>
    <updated>2026-11-07T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Contrast&lt;/strong&gt;: &lt;code&gt;ui.luminance&lt;/code&gt; and &lt;code&gt;ui.contrast&lt;/code&gt; (WCAG's ratio), &lt;code&gt;ui.to_oklch&lt;/code&gt; / &lt;code&gt;ui.from_oklch&lt;/code&gt; for linear colours, and &lt;code&gt;ui.readable(fg, ground, ratio)&lt;/code&gt;: the colour moved along its OKLCH lightness, its hue and chroma kept, only as far as it must to read on the ground (lighter on a dark one, darker on a light one).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;The system's light / dark, on Windows too, and when it changes&lt;/strong&gt;: &lt;code&gt;platform.dark_mode_preferred()&lt;/code&gt; reads Windows' app mode (AppsUseLightTheme) as it read the portal and GTK on Linux; &lt;code&gt;platform.color_scheme_serial()&lt;/code&gt; moves when the choice may have changed (WM_SETTINGCHANGE &amp;quot;ImmersiveColorSet&amp;quot;, the portal's SettingChanged): an app that follows the system compares one integer a frame.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.94.0</id>
    <title>gui_toolkit 0.94.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.94.0"/>
    <updated>2026-11-07T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Changed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Selected text reads on its selection&lt;/strong&gt;: the selected part of a selectable box's text (labels, paragraphs, rich paragraphs) is painted again over the selection in the theme's new &lt;code&gt;&amp;quot;selection text&amp;quot;&lt;/code&gt; colour (by default the text's). A faint text, a dimmed run, was lost on the selection's colour.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.93.0</id>
    <title>gui_toolkit 0.93.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.93.0"/>
    <updated>2026-11-07T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Changed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;The wheel scrolls as the system says&lt;/strong&gt;: a notch moves &lt;code&gt;platform.wheel_lines()&lt;/code&gt; lines (Windows' setting, lines per notch, characters across; three on Linux), each &lt;code&gt;ui.WHEEL_LINE_PX&lt;/code&gt; (100/3 logical px, a browser's line) at the window's scale, in whole pixels; where the system says a page, a page less a line. Every view scrolls by &lt;code&gt;ui.wheel_step(box, axis)&lt;/code&gt;, text fields too. Before, a notch was 4 em of the box's font whatever the setting.&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Fixed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;A tab is drawn as space&lt;/strong&gt;: &lt;code&gt;font.TAB_SPACES&lt;/code&gt; (4) spaces wide, the same wherever it is (measured as shown), with a space's glyph. Fonts have no glyph for it: it was drawn as a missing one (a box) in code and in tools' output.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.92.0</id>
    <title>gui_toolkit 0.92.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.92.0"/>
    <updated>2026-11-07T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;host.host_adopt&lt;/code&gt;&lt;/strong&gt;, hooks &lt;strong&gt;&lt;code&gt;still&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;after_frame&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;Host.times&lt;/code&gt;&lt;/strong&gt;: a window and a renderer an application made in its own order of start become a host; a window whose picture would not change is not built; what a program does between two frames goes after the picture; the last picture's draw and present times.&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Removed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.Reorder&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;ui.reorder_frame&lt;/code&gt;&lt;/strong&gt; are gone: the drag of a reordered list is kept on the press of the item's box (ui.press_data) and ends with it (the button went up, the box went, the user left the window). The procedures take the item's box key in place of a &lt;code&gt;^Reorder&lt;/code&gt; and an id: &lt;code&gt;reorder_begin(item, moved, threshold, press, slot)&lt;/code&gt;, &lt;code&gt;reorder_dragging(item)&lt;/code&gt;, &lt;code&gt;reorder_item_pos(item, slot, pointer, lo, hi, rate)&lt;/code&gt; (its animation keyed by the item's box too). Lists whose items share ids drag apart, the box's key being its list's.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.Dock.held&lt;/code&gt;&lt;/strong&gt; is gone: &lt;code&gt;ui.dock_held(&amp;amp;d)&lt;/code&gt; asks the press whether the left button holds one of the dock's controls (a tab or a floating panel's title, a handle, a floating panel's corner). It keeps nothing, so it ends with the press (the release, the box held going, the user leaving the window) and says the same at any time of the frame. Write &lt;code&gt;ui.dock_held(&amp;amp;app.dock)&lt;/code&gt; where &lt;code&gt;app.dock.held&lt;/code&gt; was read.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.91.0</id>
    <title>gui_toolkit 0.91.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.91.0"/>
    <updated>2026-11-07T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.lazy_pin&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;ui.lazy_pinned&lt;/code&gt;&lt;/strong&gt;: the view stays on an item, a given distance into it, placed after each layout whatever grows around it; what the last layout found of it says when it has settled.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ui.press_data&lt;/strong&gt;: what a gesture keeps lives on its press: the zero T when the press began, the same while it lasts, gone when it ends by whatever way (release, its box gone, the user leaving the window). A press of the same box again, even in one batch of input, starts from zero.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ui.window_clipboard_get, ui.window_clipboard_set&lt;/strong&gt;: Build_Params' clipboard procedures for the system's clipboard of the build's window, so a program no longer needs a global to reach its window.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;platform.events_waiting&lt;/strong&gt;: whether a window has something for its next poll_events, without waiting. A loop of several windows asks each before it sleeps, because the poll of one window of the thread takes the others' messages.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;host&lt;/strong&gt;: a window as an object, above ui and render. host_open, host_frame (pace, input, resize, builds, picture, present), host_close, and hosts_wait / hosts_due / hosts_frame for several windows on one renderer. Hooks cover what a rich application's frame does of its own: params, input, builds (several in a frame: host_build), hold (no picture this frame), after_build, before_input, dragging, rest_frame. It keeps the orders that matter: input is read with the renderer given back, a step of a resize is that window's alone, buffers keep the monitor's size, and only the first window is paced. examples/hello and examples/todo use it; the way by hand is unchanged.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;render.surface_scope&lt;/strong&gt;: surface_use until the end of the calling scope, so a frame on a second window cannot forget to go back.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ui.view_limit, ui.view_reveal, ui.view_reveal_offset, ui.view_jump, ui.view_shift&lt;/strong&gt;: the verbs of a scroll box's view, for code that wrote view_off, view_target and view_anim by hand. view_reveal says whether the target moved, so a caller decides on scrollbar_reveal itself; view_shift keeps a glide under way and leaves a target at the top there.&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Changed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;A lazy column&lt;/strong&gt; looks each item up once per build, in one map: an item's height is noted after the layout that placed it.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Splitters, dialog grips, floating panel corners, range sliders&lt;/strong&gt;: what their drag starts from is kept on the press (ui.press_data), not in the State's one drag payload. ui.drag_store and ui.drag_load stay, for gestures that read an earlier press (panes).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;render.Window_Target&lt;/strong&gt;: what is one window's is now a struct of its own, included by using in Renderer and Surface, and Wgpu_Window on the WebGPU side; surface_use exchanges them whole, so a new window field needs no list. Field access is unchanged, except that Surface.gen and Surface.space_epoch are now Surface.swap_gen and Surface.swap_space, and Surface.wgpu_backing is a ^Wgpu_Window.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;A row taller than its view keeps its top&lt;/strong&gt;: ui.list, menus, reorder_offset, the focus and the accessibility reveal now follow the rule ui.vlist had, instead of showing the row's bottom.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;A box's name and text&lt;/strong&gt;: copied as they are at each build, without going through the formatter.&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Fixed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;WebGPU second windows&lt;/strong&gt;: a window's frame format now goes with it through surface_use, as its offscreen target does on Direct3D 11.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Scrolling&lt;/strong&gt;: dragging a scroll bar's thumb or stepping a long menu ends a glide under way, which could pull the view back for a frame; a ui.vlist whose rows moved during a glide no longer starts the glide over.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.90.0</id>
    <title>gui_toolkit 0.90.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.90.0"/>
    <updated>2026-11-06T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;render.surface_init&lt;/code&gt; &lt;code&gt;under_children&lt;/code&gt;&lt;/strong&gt;: a composition surface below the window's child windows. A web view moved into a window with a composition surface stayed hidden behind it.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.89.0</id>
    <title>gui_toolkit 0.89.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.89.0"/>
    <updated>2026-11-06T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.tween&lt;/code&gt;&lt;/strong&gt;: a value that reaches its target in a set time, gently at both ends, for what the eye follows from end to end.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;draw.glyph_run_stroke&lt;/code&gt;&lt;/strong&gt;: the outlines of a glyph run as a line of a width.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;font.glyph_ink_extent&lt;/code&gt;, &lt;code&gt;font.run_ink_spans&lt;/code&gt;&lt;/strong&gt;: where the ink of a glyph or a run crosses a band, from the outlines, kept per glyph and band: the gaps of a skipping underline.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.88.0</id>
    <title>gui_toolkit 0.88.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.88.0"/>
    <updated>2026-11-06T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Fixed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Text in a dialog or a popover can be selected&lt;/strong&gt;: their panel took every press, so a plain &lt;code&gt;.Selectable&lt;/code&gt; label in it selected nothing, showed no text cursor, and a label made &lt;code&gt;.Clickable&lt;/code&gt; to get the press counted as a button. The panel is now &lt;code&gt;.Press_Stop&lt;/code&gt; (new &lt;code&gt;Box_Flag&lt;/code&gt;: clickable only so that what is under it gets no press): a press on it is a press on nothing, selectable text in it takes its own, and a selection stays on the surface it started on, whatever is built behind it.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.87.0</id>
    <title>gui_toolkit 0.87.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.87.0"/>
    <updated>2026-11-06T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;push_clip_polygon&lt;/code&gt; takes several contours&lt;/strong&gt;: a point past &lt;code&gt;render.POLYGON_BREAK&lt;/code&gt; ends one, with no edge to the next: a clip with holes.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;draw.Path&lt;/code&gt;&lt;/strong&gt;: lines, quadratic and cubic Bézier curves, arcs and rounded rectangles, flattened to a tolerance, filled (&lt;code&gt;path_fill&lt;/code&gt;, nonzero or even-odd, holes included) or stroked (&lt;code&gt;path_stroke&lt;/code&gt;, round ends and joins, even in translucent colors), with &lt;code&gt;path_contains&lt;/code&gt; for hit tests, &lt;code&gt;path_bounds&lt;/code&gt;, &lt;code&gt;bezier_cubic_at&lt;/code&gt;, &lt;code&gt;bezier_quad_at&lt;/code&gt; and &lt;code&gt;draw.bezier&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;draw.line&lt;/code&gt;, &lt;code&gt;draw.polyline&lt;/code&gt;&lt;/strong&gt;: a line of any angle, with round ends and antialiased edges.&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Changed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;render.release_targets&lt;/code&gt;&lt;/strong&gt; takes the textures to leave: a picture still on screen stays, for the program to carry over to the new generation.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.86.0</id>
    <title>gui_toolkit 0.86.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.86.0"/>
    <updated>2026-11-06T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;platform.drag_silence_limit&lt;/code&gt;&lt;/strong&gt;: for tests, how long a drag may stay silent before it is given up.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;Signal.pointer_clicked&lt;/code&gt;&lt;/strong&gt;: the click was the button's, so the pointer is where it says. &lt;code&gt;clicked&lt;/code&gt; stays true for Enter, Space and a screen reader too.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;platform.cancel_close&lt;/code&gt;&lt;/strong&gt;: takes back a Close the app answered by staying open: &lt;code&gt;is_closed&lt;/code&gt; no longer stays true for good.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Event.lost&lt;/strong&gt;: a Mouse_Release made because the system took the pointer. It is no click, and a middle button lost soon after its press no longer latches autoscroll.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Event.Frame_Press&lt;/strong&gt;: a press on the window's frame or caption (Windows). What the window was doing ends with it: a latched autoscroll waits for the next click anywhere, and a click there came to nobody.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;font.atlas_end_frame&lt;/code&gt;&lt;/strong&gt;: a draw context between frames holds no page (&lt;code&gt;draw.end_frame&lt;/code&gt; calls it): a context that stopped drawing no longer keeps the atlas from reusing pages.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;devtools.stop(srv, s)&lt;/code&gt;&lt;/strong&gt;: for a program that goes on after the server, the &lt;code&gt;ui.State&lt;/code&gt; it served: the clients' edits, the highlight and the accessibility tree asked of it end too.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;Signal.pointer_pressed&lt;/code&gt;&lt;/strong&gt;: the press was the button's, so the pointer is where it says and it is held. &lt;code&gt;pressed&lt;/code&gt; stays true for Enter, Space and a screen reader too. &lt;code&gt;ui.slider&lt;/code&gt; and the colour pickers read it: Enter on them no longer set the value from wherever the pointer was.&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Changed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.Reorder&lt;/code&gt;&lt;/strong&gt; holds the press that drags (&lt;code&gt;held&lt;/code&gt;) in place of &lt;code&gt;active&lt;/code&gt;: a release and a press read in one frame end the drag, as does the box held going away. Read &lt;code&gt;reorder_dragging&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Escape in a dialog&lt;/strong&gt; goes to the dialog on top at the end of the build, and closes it at the next one: read in the frame a new dialog opens, it closed the one under it. &lt;code&gt;open&lt;/code&gt; turns false one build later than it did.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.Autoscroll&lt;/code&gt;&lt;/strong&gt; says where a session is in one field, &lt;code&gt;phase&lt;/code&gt; (&lt;code&gt;Autoscroll_Phase&lt;/code&gt;: &lt;code&gt;Off&lt;/code&gt;, &lt;code&gt;Holding&lt;/code&gt;, &lt;code&gt;Latched&lt;/code&gt;), in place of &lt;code&gt;active&lt;/code&gt;, &lt;code&gt;held&lt;/code&gt; and &lt;code&gt;latched&lt;/code&gt;; every end zeroes it, with the box it scrolls (&lt;code&gt;box&lt;/code&gt;). &lt;code&gt;State.auto_box&lt;/code&gt; and &lt;code&gt;State.auto_pressed&lt;/code&gt; are gone.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;draw.open_plane_frame&lt;/code&gt;&lt;/strong&gt;: &lt;code&gt;ok = false&lt;/code&gt; for a plane being recorded, which draws nothing (&lt;code&gt;Open_Plane.mode&lt;/code&gt; replaces &lt;code&gt;hit&lt;/code&gt;).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;A capture of a frame WebGPU could not get&lt;/strong&gt; (a hidden window's surface) says &lt;code&gt;Failed&lt;/code&gt;: it stayed &lt;code&gt;Pending&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;A box that goes lets go of what held it&lt;/strong&gt;: a press, the focus, a click on the way to a double one. A box of a vlist or a lazy column has only left the view: the focus waits for it there.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;devtools&lt;/code&gt;: what a client started is its own.&lt;/strong&gt; A screencast, a recording and the tree of &lt;code&gt;DOM&lt;/code&gt; have one client: another's &lt;code&gt;Page.startScreencast&lt;/code&gt;, its &lt;code&gt;Toolkit.*Recording&lt;/code&gt;, &lt;code&gt;DOM.undo&lt;/code&gt; / &lt;code&gt;redo&lt;/code&gt; / &lt;code&gt;requestChildNodes&lt;/code&gt; and the like are refused, and its stop and acks change nothing. A recording ends with its client, typed text included; a highlight goes with its client; what a client held down, buttons and keys, goes up when it goes.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;instance.Owner_State&lt;/code&gt;&lt;/strong&gt;: an &lt;code&gt;Owner&lt;/code&gt; says where it is (&lt;code&gt;None&lt;/code&gt;, &lt;code&gt;Claimed&lt;/code&gt;, &lt;code&gt;Serving&lt;/code&gt;, &lt;code&gt;Closing&lt;/code&gt;) in &lt;code&gt;Owner.state&lt;/code&gt;, which replaces &lt;code&gt;Owner.closing&lt;/code&gt;. A second &lt;code&gt;owner_start&lt;/code&gt; answers false and opens nothing, a file descriptor 0 is one like any other, and a window that could not be destroyed no longer points at its Owner.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;config&lt;/code&gt; layers&lt;/strong&gt;: &lt;code&gt;Entry.locked&lt;/code&gt; is gone, &lt;code&gt;is_locked&lt;/code&gt; reads the layer, and an observer sees a policy value locked. &lt;code&gt;.Default&lt;/code&gt; no longer goes over a layer, &lt;code&gt;reset&lt;/code&gt; under a policy changes nothing, &lt;code&gt;load_file&lt;/code&gt; wants the tag of the layer it reads (&lt;code&gt;POLICY_MAGIC&lt;/code&gt; for &lt;code&gt;.Policy&lt;/code&gt;), &lt;code&gt;register&lt;/code&gt; answers how many waiting values it refused, a user's value that its definition refuses stays in the profile, and &lt;code&gt;dirty&lt;/code&gt; counts a change under a higher layer and no longer a file just read. &lt;code&gt;restore&lt;/code&gt; survives an observer that registers.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;A dialog gives the focus back&lt;/strong&gt;: what had the focus when &lt;code&gt;ui.modal&lt;/code&gt; opened has it again when it closes, unless something else took it meanwhile.&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Removed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;render.Pacer.latency&lt;/code&gt;&lt;/strong&gt;: &lt;code&gt;Present_State.max_latency&lt;/code&gt; says what the swap chain has, a new one included.&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Fixed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;A press on a row of an open menu&lt;/strong&gt; leaves the keyboard focus where it was: choosing an item of a field's context menu with the mouse took the focus from the field.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;testkit/session&lt;/code&gt;&lt;/strong&gt;: &lt;code&gt;advance&lt;/code&gt; in a build ends the test (it hung to the test's limit), &lt;code&gt;draw_context&lt;/code&gt; on an attached session says so, &lt;code&gt;Session.damage&lt;/code&gt; is the next frame's only, and the guard against two tests at once is atomic.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.a11y_tree&lt;/code&gt;&lt;/strong&gt; is empty when no tree was made (it answered with the last one), and an active descendant not made in this build is not named.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Title bar regions&lt;/strong&gt; are forgotten with no caption or window too: buttons no build makes any more stayed in &lt;code&gt;chrome_regions&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;A box of the last build&lt;/strong&gt; looked up during a build has no text, name, accessibility or custom data: they pointed into memory the build had freed.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.theme_destroy&lt;/code&gt;&lt;/strong&gt; leaves an empty theme: a palette applied after it appended to freed memory, a second destroy freed it twice.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.color_picker&lt;/code&gt;&lt;/strong&gt;: the text left by the user is written as the picker writes it: a spelling of theirs (&lt;code&gt;#F00&lt;/code&gt;) or what is no colour stayed. &lt;code&gt;Color_Pick.shown&lt;/code&gt; is gone.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Find in page&lt;/strong&gt;: a sweep's wait is a timed wake, not a frame at each refresh, and a sweep during a glide reports the place in the content (the scroll had moved after the layout). Its clock is the build's.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Toasts&lt;/strong&gt; ask for frames only while they fade, and a wake between; &lt;code&gt;ui.set_toast_area&lt;/code&gt; lasts one build, whether &lt;code&gt;toasts_build&lt;/code&gt; ran or not.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Docks&lt;/strong&gt;: two requests in one frame are both done, and the stack's menu of a closed panel closes.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;vlist&lt;/code&gt;&lt;/strong&gt;: &lt;code&gt;vlist_scroll_to&lt;/code&gt; on a list with no box yet is kept for its first build, the wheel ends the wait for a row with the reveal, and a row of no height is not waited for over 600 builds.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;list&lt;/code&gt; and &lt;code&gt;vlist&lt;/code&gt;&lt;/strong&gt;: rows gone from under the active row say &lt;code&gt;changed&lt;/code&gt;; no row is nothing to reveal (&lt;code&gt;reveal&lt;/code&gt; stayed armed); a row selected before the first build comes into view with no other frame asked for.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.text_edit_caret_rect&lt;/code&gt;&lt;/strong&gt; says &lt;code&gt;false&lt;/code&gt; once the editor is built no more.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;text_edit&lt;/code&gt;&lt;/strong&gt;: the column of Up and Down ends with every other move and edit (undo, redo, select all, cut, paste, Ctrl+Backspace, a double click kept it).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;The caret of a &lt;code&gt;line_edit&lt;/code&gt;&lt;/strong&gt; is solid after an arrow key, as a &lt;code&gt;text_edit&lt;/code&gt;'s is: it could stay in the off half of its blink.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Undo in &lt;code&gt;line_edit&lt;/code&gt; and &lt;code&gt;text_edit&lt;/code&gt;&lt;/strong&gt;: a move of the caret ends a step (type, arrow, type was one), and a field's steps go by the build's clock, as a text area's do.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Menus&lt;/strong&gt;: a press of a side button outside closes them; a Right or Enter on a submenu that turned disabled opens nothing later; a menu opened from the keyboard selects its first item once, so a pointer on a disabled row leaves nothing selected; a menu opened from inside a menu's block opens when the block ends, its rows not mixed with the old one's.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.stepper&lt;/code&gt;&lt;/strong&gt;: held with the pointer off its button it waits, as a scroll bar's arrow does.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;A press with no pointer&lt;/strong&gt; (Enter, Space, a screen reader) no longer takes the place of a drag going on (&lt;code&gt;splitter&lt;/code&gt;, &lt;code&gt;pane_split&lt;/code&gt;, the edges of &lt;code&gt;modal_sized&lt;/code&gt;), sets a &lt;code&gt;range_slider&lt;/code&gt; from the pointer, or moves the caret of a &lt;code&gt;line_edit&lt;/code&gt; or a &lt;code&gt;text_edit&lt;/code&gt; to it.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.pane_split&lt;/code&gt;&lt;/strong&gt;: a strip pulled out and pushed back under the snap stays folded when let go, and a screen reader's value on a folded pane says &lt;code&gt;toggled&lt;/code&gt;. What a press was on is one state (&lt;code&gt;Pane_Press&lt;/code&gt;).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.modal_sized&lt;/code&gt;&lt;/strong&gt;: a press on an edge that does not move chooses no size (the size a small window clamped it to stayed for good), and a double click on an edge stays at the preferred size while the button is held.&lt;/li&gt;&lt;li&gt;&lt;code&gt;platform&lt;/code&gt; on Windows: a surrogate pairs only with the unit right after it, a pointer whose end the system no longer describes still ends, a resize made of inner frames has its burst.&lt;/li&gt;&lt;li&gt;Clipboard on Linux: a selection another program cleared is not read back, X11 asks the server who owns what it took, a late answer is not the next read's, a paste leaves no property, an INCR reader that left is given up, &lt;code&gt;XdndSelection&lt;/code&gt; is let go, a large drag goes by INCR, a reader that closes its pipe no longer ends the process on Wayland. Windows: a real window's &lt;code&gt;clipboard_changed&lt;/code&gt; reads the system's clipboard with an offscreen window open.&lt;/li&gt;&lt;li&gt;&lt;code&gt;platform&lt;/code&gt; on Linux: a seat that loses its pointer or keyboard and gets it back works again, a scale change of the output or of Xft.dpi reaches the windows, the display is read again after a change of the output.&lt;/li&gt;&lt;li&gt;&lt;code&gt;platform&lt;/code&gt; on Linux: a window has one state (&lt;code&gt;Show_State&lt;/code&gt;), read back from the server: nothing shown is not visible, a state asked before the map reaches the window manager. &lt;code&gt;set_placement&lt;/code&gt; restores a maximized window on every backend and applies at once on a shown Windows window, an offscreen &lt;code&gt;set_fullscreen(false)&lt;/code&gt; leaves another state alone, &lt;code&gt;toggle_maximize&lt;/code&gt; leaves full screen on Windows.&lt;/li&gt;&lt;li&gt;Accessibility on Linux: the bridge is read by the window's loop, it keeps the whole tree an update changes (&lt;strong&gt;&lt;code&gt;platform.a11y_tree_merge&lt;/code&gt;&lt;/strong&gt;), &lt;code&gt;a11y_state&lt;/code&gt; is &lt;code&gt;Off&lt;/code&gt; until a reader runs (org.a11y.Status), a bus that refuses is asked once.&lt;/li&gt;&lt;li&gt;File dialogs on Linux: a bus without a portal falls back to zenity and kdialog, the portal's answer cannot be missed, its &lt;code&gt;filter&lt;/code&gt; is the user's choice, a lost bus is &lt;code&gt;Failed&lt;/code&gt; and not &lt;code&gt;Cancelled&lt;/code&gt;. &lt;code&gt;idle_inhibit&lt;/code&gt; ends with its window.&lt;/li&gt;&lt;li&gt;Tray on Linux: each icon has its own object, a failed create leaves nothing exported, a panel that restarts gets the icons again (&lt;code&gt;Recreated&lt;/code&gt;), a menu that changes is told (&lt;code&gt;LayoutUpdated&lt;/code&gt;), a notification has a default action, so &lt;code&gt;Notify_Click&lt;/code&gt; can come, and one that closed is not replaced by the next. Windows: an icon a restarting shell refused is added at its next change.&lt;/li&gt;&lt;li&gt;Drag and drop on Linux: a drag says where it is (&lt;code&gt;Drag_Phase&lt;/code&gt;). X11: only the button that began it ends it, Escape gives it up. Both: the limit is one of silence, a target that took a drop has five seconds, the target hears what the source allows and a Move is told, a source that dies ends its drag, a target disabled under a drag says &lt;code&gt;Drop_Leave&lt;/code&gt;, no event of kind &lt;code&gt;None&lt;/code&gt;. A drag script is used up however &lt;code&gt;drag_start&lt;/code&gt; ends. &lt;code&gt;drop_inject&lt;/code&gt; of anything but &lt;code&gt;Drop_Enter&lt;/code&gt; needs a drag over the window.&lt;/li&gt;&lt;li&gt;&lt;code&gt;platform&lt;/code&gt; on Linux: &lt;code&gt;set_cursor&lt;/code&gt; to the cursor the window had takes a custom cursor off the screen, releasing the shown custom cursor shows the window's own, Wayland sends a cursor only for the window under the pointer, &lt;code&gt;set_cursor_custom&lt;/code&gt;'s &lt;code&gt;scale&lt;/code&gt; is used.&lt;/li&gt;&lt;li&gt;&lt;code&gt;platform&lt;/code&gt;: a release comes once and only of a press made here, on every backend; a pointer taken with a button held makes its release on Wayland and when an X11 window is unmapped; X11 says no &lt;code&gt;Mouse_Leave&lt;/code&gt; under a press, as a capture on Windows; a key held when the focus goes makes its &lt;code&gt;Key_Release&lt;/code&gt;. &lt;code&gt;Activate&lt;/code&gt; comes once for a change, and a window is neither &lt;code&gt;focused&lt;/code&gt; nor &lt;code&gt;active&lt;/code&gt; until the system says so.&lt;/li&gt;&lt;li&gt;&lt;code&gt;platform.poll_events&lt;/code&gt;: the batch stays whole while the app reads it. What runs from an event may pump the system (a paste on X11, &lt;code&gt;drag_start&lt;/code&gt;), and &lt;code&gt;w.events&lt;/code&gt; may then move.&lt;/li&gt;&lt;li&gt;&lt;code&gt;platform&lt;/code&gt;: &lt;code&gt;wait_event&lt;/code&gt; sees all that ends it. On Linux the session bus and the accessibility bus (a tray click answered at once), injected events; on Wayland and Windows a repaint asked for; on Windows the events not handed out; after &lt;code&gt;input_pending&lt;/code&gt;, what it kept.&lt;/li&gt;&lt;li&gt;&lt;code&gt;platform&lt;/code&gt; on Linux: a closed window's last notices go to nobody (the X11 window that polled read as minimized), a window closed under a drag or an input method leaves nothing that points at it, a compositor without xdg-shell fails every &lt;code&gt;open_window&lt;/code&gt;, and a server that goes away closes its windows (&lt;code&gt;Display_Link&lt;/code&gt;) instead of leaving a loop that never hears of it.&lt;/li&gt;&lt;li&gt;&lt;code&gt;platform&lt;/code&gt; on X11: typed text follows Shift, AltGr, Caps Lock and the layout (a key is read with the modifiers and the group of its event), a change of keymap is followed, a held key says &lt;code&gt;repeat&lt;/code&gt;. On X11 and Wayland a key keeps its name whatever it types: Shift+1 is &lt;code&gt;N1&lt;/code&gt;, Shift+Tab is &lt;code&gt;Tab&lt;/code&gt;, the keypad without Num Lock is &lt;code&gt;Home&lt;/code&gt;, &lt;code&gt;Left&lt;/code&gt;...&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Focus keys&lt;/strong&gt;: an arrow and a Tab read in one frame both move the focus, and &lt;code&gt;ui.focus_step&lt;/code&gt; says its direction (&lt;code&gt;ui.tab_direction&lt;/code&gt;): a rich paragraph entered backward that way starts at its last link.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;Signal.mods&lt;/code&gt;&lt;/strong&gt; follows &lt;code&gt;Key_Release&lt;/code&gt; and &lt;code&gt;Mouse_Release&lt;/code&gt;: a modifier let go during a drag is no longer held.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.rich_paragraph&lt;/code&gt;&lt;/strong&gt;: Enter and Space choose the link that has the focus wherever the pointer is (they took the link under it, or nothing over plain text), and a screen reader's focus on a link of a paragraph without the focus stays.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;The build lifecycle&lt;/strong&gt;: &lt;code&gt;ui.building()&lt;/code&gt; stays true to the last line of &lt;code&gt;end_build&lt;/code&gt;; &lt;code&gt;end_build&lt;/code&gt; ends the build that is open, whatever &lt;code&gt;use&lt;/code&gt; selected since, and asserts that there is one; &lt;code&gt;ui.destroy&lt;/code&gt; in the middle of a build leaves none open on the thread. &lt;code&gt;end_build&lt;/code&gt; also asserts the list and menu scopes.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Selected text&lt;/strong&gt; is one state (&lt;code&gt;Sel_Phase&lt;/code&gt;): no drag goes on with its selection gone (the text cursor and the frames stayed), &lt;code&gt;select_box&lt;/code&gt; ends a drag, and a press on a button between two presses on a text breaks their double click.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.next&lt;/code&gt; and &lt;code&gt;ui.a11y&lt;/code&gt;&lt;/strong&gt; before what builds nothing (a closed &lt;code&gt;modal&lt;/code&gt;, &lt;code&gt;modal_sized&lt;/code&gt;, &lt;code&gt;ctx_menu&lt;/code&gt; or &lt;code&gt;menu_nested&lt;/code&gt;, a skipped &lt;code&gt;lazy_item&lt;/code&gt;) no longer land on the next box.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;An open menu&lt;/strong&gt; no longer gets the keys something else took first (Ctrl+zoom, autoscroll's Escape).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Autoscroll&lt;/strong&gt;: a move of the window ends a session, as its documentation said. A move read with the release counts against a tap. What ends a session no longer ends the frame's input: a middle press read with it starts the next one, and the Escape it took does not reach an open menu.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;The window the user leaves&lt;/strong&gt; (&lt;code&gt;Event.Activate&lt;/code&gt;, &lt;code&gt;Build_Params.inactive&lt;/code&gt;): an open menu closes, a held button ends with no click, the modifiers are forgotten, a selection stops following the pointer, autoscroll ends. A dock drag cut that way drops nothing.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;A box that goes takes what held it&lt;/strong&gt;: at the end of a build a press, the focus, the first click of a double click and the link of a rich paragraph let go of a box the build did not make. A key that comes back later is another box; a focus given ahead of its box stands. &lt;code&gt;splitter&lt;/code&gt; and &lt;code&gt;pane_split&lt;/code&gt; say &lt;code&gt;finished&lt;/code&gt; when their box is back.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.set_post_wake&lt;/code&gt;&lt;/strong&gt;: the app's wake is called with a &lt;code&gt;nil&lt;/code&gt; user too, and a &lt;code&gt;nil&lt;/code&gt; wake goes back to the window's. Of two windows of a State, posts wake the one that stays when the other is destroyed. A post on a State that is gone is refused.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.post_configure&lt;/code&gt;&lt;/strong&gt; runs every call that waits, not a build's budget of them (the rest were lost), and a closed queue stays closed.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;draw.offscreen_end&lt;/code&gt;&lt;/strong&gt;: closes the layers left open in the target (it answered 0 and left the target open).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;font&lt;/code&gt;&lt;/strong&gt;: the emoji font comes back on the next emoji when whoever shared its id unloaded it.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;font&lt;/code&gt;&lt;/strong&gt;: a word being shaped while the word cache is cleared is shaped again, and no thread keeps the width of a word cleared under it.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;font&lt;/code&gt;&lt;/strong&gt;: a glyph the COLR interpreter was drawing when the settings changed is drawn again with them, and its outlines follow a new provider or tolerance.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;font&lt;/code&gt;&lt;/strong&gt;: &lt;code&gt;glyph_outline&lt;/code&gt; and &lt;code&gt;slug_glyphs&lt;/code&gt; answer on a state never started (they read a nil backend). &lt;code&gt;Text_Backend.face_close&lt;/code&gt;, which nothing called, is gone.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;draw.destroy&lt;/code&gt;&lt;/strong&gt;: in the middle of a recording it no longer leaks the lists of the frame.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;draw&lt;/code&gt;&lt;/strong&gt;: a layer or plane that replays a picture lacking a pending color glyph is not kept: the glyph comes when it is ready.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Frame statistics on WebGPU&lt;/strong&gt;: &lt;code&gt;frame_end(vsync = false)&lt;/code&gt; on a Fifo surface counts the vblank it waits for, a reconfigured surface starts its run over, and &lt;code&gt;vblank_grid&lt;/code&gt; says unknown once the compositor stops answering (Direct3D 11 too). &lt;code&gt;gpu_ms&lt;/code&gt; starts over with a new device.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;draw&lt;/code&gt;&lt;/strong&gt;: a mask layer with no target of its own draws nothing (its drawing landed in the content); &lt;code&gt;Open_Layer&lt;/code&gt; says what it is and what a mask draws in with &lt;code&gt;Layer_Kind&lt;/code&gt; and &lt;code&gt;Mask_Draw&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;draw&lt;/code&gt;&lt;/strong&gt;: a layer or a plane owns what is pushed in it: pops stop at where it started and at the root (they panicked there), what is left pushed ends with it, and layers and planes left open inside one another end in the order they were opened. A recording cannot close a plane of the frame.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;draw&lt;/code&gt;&lt;/strong&gt;: a second &lt;code&gt;end_frame&lt;/code&gt; does nothing (it drew the frame twice).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;render.canvas_read_ready&lt;/code&gt; and &lt;code&gt;canvas_read_finish&lt;/code&gt;&lt;/strong&gt; on a read begun before a device loss: ready at once, and the finish says it failed. They used the old device's objects on the new context.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;2D canvas layers&lt;/strong&gt; nest. A filter pass inside an open layer leaves it open, what is drawn into a layer that could not be made or was freed goes nowhere instead of onto the canvas, and a layer replaced by a filter pass gives its texture back to the pool. &lt;code&gt;canvas_set_opaque&lt;/code&gt; on a source texture no longer outlives it.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;A texture a recovery could not make again&lt;/strong&gt;: &lt;code&gt;Texture_Kind.Failed&lt;/code&gt;, it draws nothing, &lt;code&gt;texture_size&lt;/code&gt; says &lt;code&gt;{0, 0}&lt;/code&gt; and &lt;code&gt;destroy_texture&lt;/code&gt; frees its slot. A frame crashed on one (Direct3D 11), and its slot was lost.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;render.set_fixed_surface&lt;/code&gt;&lt;/strong&gt; survives a device loss: the chain made again had the window's size, and a window larger than it was clipped. A translucent window that fell back to opaque during a recovery tries DirectComposition again at the next one.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;render.readback_poll&lt;/code&gt;&lt;/strong&gt; says &lt;code&gt;Failed&lt;/code&gt; for a read-back whose frame did not run, which stayed &lt;code&gt;Pending&lt;/code&gt; for good, and for an id of another renderer. A renderer destroyed takes its read-backs with it.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;font&lt;/code&gt;&lt;/strong&gt;: a system fallback that goes character by character (fontconfig) no longer cuts a sequence: joiners, selectors and what follows a ZWJ stay with their base.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;font&lt;/code&gt;&lt;/strong&gt;: the Slug store follows what its glyphs depend on: &lt;code&gt;color_glyphs&lt;/code&gt; and &lt;code&gt;color_engine&lt;/code&gt; reach the glyphs of color faces, a new provider is asked for what had no curves, no room is not kept, and keys hold the slot of a face, so what a face leaves goes with it at any generation.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Partial redraw&lt;/strong&gt;: a frame that stopped halfway (Direct3D 11), that had no surface texture (WebGPU) or whose region could not be cleared leaves nothing the next region starts from: the next frame is whole. Their rectangles were lost, or composed onto a blank target.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;A window that cannot be remade&lt;/strong&gt; (Direct3D 11, WebGPU) counts as a device lost: the next &lt;code&gt;frame_begin&lt;/code&gt; tries again, where it drew into nothing and the next clear crashed. A swap chain that &lt;code&gt;ResizeBuffers&lt;/code&gt; finds gone is a loss too, and a size asked while there is no swap chain is kept.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;font&lt;/code&gt;&lt;/strong&gt;: a page reused uploads whole to a context that had it: the old bitmaps no longer stay in its texture between the new ones.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;render.surface_destroy&lt;/code&gt;&lt;/strong&gt; of the Surface in use gives the renderer back its own window first: it tore that window down.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Second windows on WebGPU&lt;/strong&gt;: a window set aside is made again after a recovery and follows &lt;code&gt;set_blend_space&lt;/code&gt;, as on Direct3D 11. Its capture, its clear and its first frame are its own, and &lt;code&gt;surface_destroy&lt;/code&gt; frees its frame statistics.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;font&lt;/code&gt;&lt;/strong&gt;: a color glyph drawn on the color thread whose COLR layers cannot be read shows its outline, as on the drawing thread (it was kept as a bitmap at page 0, out of range when no page exists).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;A device lost on WebGPU&lt;/strong&gt;: it is noticed (wgpu-native reports every loss with the reason &lt;code&gt;Destroyed&lt;/code&gt;, which was taken for the renderer's own release), offscreen too. A recovery makes the new device first: with none to be had the old one stays and frames draw nothing, where they ended the process on a nil device. Calls that end the process on a device gone (&lt;code&gt;QueueSubmit&lt;/code&gt;, &lt;code&gt;DevicePoll&lt;/code&gt;, &lt;code&gt;SurfaceConfigure&lt;/code&gt;, &lt;code&gt;SurfaceGetCurrentTexture&lt;/code&gt;) wait for the recovery.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;font&lt;/code&gt;&lt;/strong&gt;: the id of a font just unloaded, or of a cascade, no longer leaves blank glyphs for the next face in its slot (&lt;code&gt;Font.dead&lt;/code&gt; and &lt;code&gt;State.generation&lt;/code&gt; are gone: an unloaded slot is &lt;code&gt;Font_Kind.None&lt;/code&gt;).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;AT-SPI on Linux&lt;/strong&gt;: the bridge's connection is dispatched once a frame, so what a client asks of the exported object is answered and a lost bus is seen.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;native/a11y&lt;/code&gt;&lt;/strong&gt;: an update that is refused or finds no assistive technology leaves the deferred focus as it was, and one that would give a subtree a second graft node is refused instead of ending the adapter.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;arena.Pool&lt;/code&gt;&lt;/strong&gt;: a slot whose generations are spent is retired instead of wrapping, so a handle never comes back to life, even after 2^32 reuses.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;devtools&lt;/code&gt; input and recordings&lt;/strong&gt;: two &lt;code&gt;Toolkit.click&lt;/code&gt; of one batch are two clicks; a drag cut by &lt;code&gt;Toolkit.stopRecording&lt;/code&gt; gets its &lt;code&gt;up&lt;/code&gt;, a second button no longer breaks a recorded drag, and a right drag replays as one (&lt;code&gt;down&lt;/code&gt; and &lt;code&gt;up&lt;/code&gt; of &lt;code&gt;tools/cdp.mjs&lt;/code&gt; take &lt;code&gt;--button right&lt;/code&gt;). &lt;code&gt;CSS.setStyleTexts&lt;/code&gt; does all of its edits or none, a &lt;code&gt;;&lt;/code&gt; in a string or a comment no longer ends a declaration, and a frame of a screencast that ended no longer touches the one that took its place.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;devtools&lt;/code&gt; connections&lt;/strong&gt;: a connection that sends no request is closed after 5 seconds, an upgrade needs &lt;code&gt;Upgrade: websocket&lt;/code&gt; and version 13, and a frame RFC 6455 does not allow ends the connection instead of being glued to the message under way.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;instance&lt;/code&gt; on Linux&lt;/strong&gt;: &lt;code&gt;acquire&lt;/code&gt; and &lt;code&gt;send&lt;/code&gt; never block past their timeout, with a large message or a full backlog, and an owner that wakes after a sender gave up no longer handles its message as well.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;config.save_user&lt;/code&gt;&lt;/strong&gt; goes through &lt;code&gt;fsx.write_atomic&lt;/code&gt;, flushed: a save that fails never removes the profile, and leaves no temporary file.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;fsx&lt;/code&gt;&lt;/strong&gt;: &lt;code&gt;write_atomic&lt;/code&gt; writes through a temporary file of its own, &lt;code&gt;&amp;lt;path&amp;gt;.&amp;lt;pid&amp;gt;.&amp;lt;thread&amp;gt;.tmp&lt;/code&gt;, so two writers can no longer tear a file; &lt;code&gt;replace&lt;/code&gt; with &lt;code&gt;durable&lt;/code&gt; answers false when the directory could not be synced; &lt;code&gt;read_all&lt;/code&gt; no longer returns a replaced file cut to the old size.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;dbus&lt;/code&gt;: connecting cannot hang the window's thread.&lt;/strong&gt; &lt;code&gt;connect&lt;/code&gt;, the SASL answer and &lt;code&gt;Hello&lt;/code&gt; each have a limit of 5 seconds, and a signal no longer fails the authentication.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;dbus&lt;/code&gt;: a lost bus closes its socket.&lt;/strong&gt; &lt;code&gt;conn_fd&lt;/code&gt; answers -1 from then on, so the window loop no longer spins on a socket at EOF; nothing more is read after a stream that cannot be parsed, a failed send runs the &lt;code&gt;call_async&lt;/code&gt; handlers that wait at the next &lt;code&gt;dispatch&lt;/code&gt;, and &lt;code&gt;platform&lt;/code&gt; falls back as with no bus. A handler of an expired call that calls no longer panics, serial 0 is never used, and &lt;code&gt;conn_close&lt;/code&gt; from a handler asserts. &lt;code&gt;Call_Status.Unsupported&lt;/code&gt;, never produced, is gone.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Read-backs on WebGPU&lt;/strong&gt;: a buffer is released outside the table's lock. Releasing one still being mapped may call its callback, which takes that lock.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;flate&lt;/code&gt;&lt;/strong&gt;: an inflater that failed stays failed (&lt;code&gt;inflate_finish&lt;/code&gt; said &lt;code&gt;Truncated&lt;/code&gt;, and a later push went on from where it stopped), and nothing is written after &lt;code&gt;deflate_finish&lt;/code&gt; (it wrote past the end of the stream).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.find&lt;/code&gt;&lt;/strong&gt;: a sweep left waiting when its page went away kept &lt;code&gt;needs_frame&lt;/code&gt; true for good, and the loop never slept.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.line_edit&lt;/code&gt;, &lt;code&gt;ui.text_edit&lt;/code&gt;&lt;/strong&gt;: the word a double click took collapsed to the pointer at the first frame made with the button down. The drag now goes on by words, as selectable text does.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;draw&lt;/code&gt;&lt;/strong&gt;: an offscreen target left open is dropped at the end of the frame (it was composited, left its transform on the stack and cut the filters of the layers around it), and a plane left open in a recording ends with the recording (it took the frame's stacks down at &lt;code&gt;end_frame&lt;/code&gt;).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Dock drags that lost what they held&lt;/strong&gt;: closing a floating panel while it was dragged ended in a bounds check (&lt;code&gt;docking.odin&lt;/code&gt;), a panel closed while its tab was held came back at the drop, a drag whose button went up while the dock was not built dropped when the dock came back, and Enter on a held tab restarted the drag.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Dialogs on dialogs&lt;/strong&gt;: with two open, the one underneath took the focus away at every frame, so a field of the top one could not keep the keyboard, and Tab went through both. Each dialog now knows where it stands among those of the last build: the top one has the keyboard, the others wait.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;D-Bus&lt;/strong&gt;: &lt;code&gt;r_skip&lt;/code&gt; never returned from a message cut short inside a struct or a dict entry, or from an array of a type that takes no bytes; it ran on the window's thread.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;DevTools&lt;/strong&gt;: &lt;code&gt;Page.startScreencast&lt;/code&gt; on a window served with no &lt;code&gt;ui.State&lt;/code&gt; is refused. It woke the window for good, and an ack dereferenced the missing state.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.85.0</id>
    <title>gui_toolkit 0.85.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.85.0"/>
    <updated>2026-11-06T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.toast_action&lt;/code&gt;&lt;/strong&gt;: a toast that a click acts on, and dismisses, for one that says what can be done.&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Fixed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;The corners of a floating panel&lt;/strong&gt;: its panels, drawn after its frame and square, covered the frame's round corners, whose border stopped short of them. They are clipped to the frame now, and its border goes over them.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.84.0</id>
    <title>gui_toolkit 0.84.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.84.0"/>
    <updated>2026-11-05T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Text per colour stripe&lt;/strong&gt;: &lt;code&gt;font.Settings.subpixel_text&lt;/code&gt; (&lt;code&gt;.Rgb&lt;/code&gt;, &lt;code&gt;.Bgr&lt;/code&gt;) gives text a coverage per stripe of the screen's pixels, sharper at few pixels per letter, on Direct3D 11 with the atlas (DirectWrite) and on WebGPU with Slug (three samples a third of a pixel apart). Blended per channel in the frame's own target; in a layer, or turned, the same text is grey. &lt;code&gt;font.system_subpixel_text&lt;/code&gt; says what the system does, &lt;code&gt;render.text_subpixel_supported&lt;/code&gt; what the renderer can.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;The site says what it is when it is shared&lt;/strong&gt;: a card, Open Graph and Twitter tags on every page, an Atom feed of the versions, a sitemap and a manifest (&lt;code&gt;tools/site_meta.mjs&lt;/code&gt;, at deployment).&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Fixed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Read-backs from several threads&lt;/strong&gt;: the process's table of read-backs was allocated with the allocator of whoever wrote in it first, and freed by whoever emptied it, through an allocator that could be gone. It is on the process's heap.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.83.0</id>
    <title>gui_toolkit 0.83.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.83.0"/>
    <updated>2026-11-05T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;The side buttons of the mouse&lt;/strong&gt;: &lt;code&gt;Mouse_Button.Back&lt;/code&gt; and &lt;code&gt;.Forward&lt;/code&gt; on Windows, X11 and Wayland, &lt;code&gt;ui.mouse_pressed(.Back)&lt;/code&gt;, and &lt;code&gt;back&lt;/code&gt; and &lt;code&gt;forward&lt;/code&gt; over the DevTools protocol.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.82.0</id>
    <title>gui_toolkit 0.82.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.82.0"/>
    <updated>2026-11-05T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Changed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Middle-click autoscroll goes five times faster by default&lt;/strong&gt;: up to 15000 px/s, reached 300 px from the anchor, the speed doubling every 60 px (&lt;code&gt;DEFAULT_AUTOSCROLL&lt;/code&gt;): the curve Wren settled on. It was 2800 px/s at 420 px.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;A &lt;code&gt;target_hz&lt;/code&gt; above the screen's rate is made&lt;/strong&gt;: 120 on a 60 Hz screen is up to 120 frames a second while something moves (none at rest), each on its slot, none waiting for the screen, shown at once (&lt;code&gt;Cadence_Plan.above&lt;/code&gt;): it stayed at the screen's rate. The screen shows the newest: not smoother, but each refresh has fresher input.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.81.0</id>
    <title>gui_toolkit 0.81.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.81.0"/>
    <updated>2026-11-05T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.modal_sized&lt;/code&gt;&lt;/strong&gt;: a dialog of a size of its own, centered and always within the window: it opens at what it prefers, the person resizes it by its edges and corners (the opposite side follows, it stays centered), a double click goes back; the size is the application's to keep. &lt;code&gt;ui.modal&lt;/code&gt; stays in the window too: narrower if it must, higher when what is in it would pass the bottom.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.80.0</id>
    <title>gui_toolkit 0.80.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.80.0"/>
    <updated>2026-11-05T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;The output of frames is the application's to choose&lt;/strong&gt;: &lt;code&gt;Pacer.choices&lt;/code&gt; (a ceiling, a rate; read at the next frame, &lt;code&gt;render.pace_frame&lt;/code&gt; planned with none), and &lt;code&gt;Cadence.uncapped&lt;/code&gt;: no slot, no wait for the screen, every frame shown at once, for a diagnostic or a benchmark. A window at rest stays at rest.&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Changed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;platform.wait_slot&lt;/code&gt;&lt;/strong&gt;: &lt;code&gt;render.pace_frame&lt;/code&gt; no longer sleeps through a frame's slot: input is taken as it arrives (time-stamped, kept for the next &lt;code&gt;poll_events&lt;/code&gt;), a key or a button ends the wait, a pointer that moves and the wheel do not. &lt;code&gt;wait_handle&lt;/code&gt; has &lt;code&gt;until_press&lt;/code&gt;. An offscreen window does not wait.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.79.0</id>
    <title>gui_toolkit 0.79.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.79.0"/>
    <updated>2026-11-05T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.find_sweep&lt;/code&gt;, &lt;code&gt;ui.find_all&lt;/code&gt;, &lt;code&gt;ui.find_pending&lt;/code&gt;, &lt;code&gt;ui.find_refresh&lt;/code&gt;&lt;/strong&gt;: a find in page over a lazy column reads everything once for a needle (when it rests 80 ms, and again if what is built no longer answers), and stays lazy between: &lt;code&gt;lazy_begin(all = find_sweep())&lt;/code&gt;. In opencode native, a frame while finding 40 -&amp;gt; 1.7 ms on a conversation of 150 answers.&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Changed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Text cut with an ellipsis&lt;/strong&gt;: where it is cut is kept (by text, font, size and width): it was measured rune by rune at every frame, through the shaper. A frame at rest in opencode native 1.65 -&amp;gt; 1.10 ms.&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Fixed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;render.pace_frame&lt;/code&gt; waits for the frame's slot&lt;/strong&gt;, after the swap chain and only what is left of it: &lt;code&gt;Frame_Decision.wait_ns&lt;/code&gt; was worked out and not made, so nothing capped the frames of a screen that does not hold the app back. &lt;code&gt;platform.precise_sleep&lt;/code&gt;: a wait under the system's tick.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.78.0</id>
    <title>gui_toolkit 0.78.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.78.0"/>
    <updated>2026-11-04T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;Dock_Options.strip_last&lt;/code&gt;&lt;/strong&gt;: boxes after a stack's fold and menu buttons, the strip's last control (a window's close button stays at the far right; &lt;code&gt;strip_end&lt;/code&gt; comes before them).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.field_num_step&lt;/code&gt;&lt;/strong&gt;: the number at the caret of a focused field stepped as browsers' style editors step it: Up / Down 1, Page Up / Page Down 10, Shift 10, Alt 0.1, Ctrl 100, and the wheel over the field with the same modifiers; its unit and the text around it stay (&lt;code&gt;margin: 10px 5px&lt;/code&gt;, &lt;code&gt;rgba(10, 20, 30, 0.5)&lt;/code&gt;, &lt;code&gt;calc(100% - 12px)&lt;/code&gt;), a number inside a word or a hex colour is none, the number stepped is selected and the step is an edit of the field's history. &lt;code&gt;ui.num_step_text&lt;/code&gt; and &lt;code&gt;ui.num_step_delta&lt;/code&gt; do it on a string and a key press.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.color_picker&lt;/code&gt;&lt;/strong&gt;: a colour picker for a &lt;code&gt;ui.Color_Pick&lt;/code&gt; the app owns (&lt;code&gt;color_pick_set&lt;/code&gt;, &lt;code&gt;color_pick_rgba&lt;/code&gt;, &lt;code&gt;color_pick_text&lt;/code&gt;, &lt;code&gt;color_pick_destroy&lt;/code&gt;; &lt;code&gt;color_picker_width&lt;/code&gt;): a saturation / value square, a hue bar and an opacity bar beside the colour it was opened with (a click takes it back) and the new one, a switch of the text's format (hex, rgb, hsl, oklch) and the colour as text, applied as it is typed. Every part is a Tab stop, moved by the arrows (Shift: a tenth; the hue by degrees), and screen readers see sliders, a radio group and a field. No eyedropper: the platform layer reads no pixel of the screen.&lt;/li&gt;&lt;li&gt;&lt;code&gt;ui.color_parse&lt;/code&gt; / &lt;code&gt;ui.color_text&lt;/code&gt;: hex, &lt;code&gt;rgb()&lt;/code&gt; / &lt;code&gt;rgba()&lt;/code&gt;, &lt;code&gt;hsl()&lt;/code&gt; / &lt;code&gt;hsla()&lt;/code&gt; and &lt;code&gt;oklch()&lt;/code&gt; read and written, in the style they were written in (&lt;code&gt;Color_Style&lt;/code&gt;: the format, the legacy comma syntax or the short hex); &lt;code&gt;srgb_to_hsv&lt;/code&gt;, &lt;code&gt;hsv_to_srgb&lt;/code&gt;, &lt;code&gt;srgb_to_hsl&lt;/code&gt;, &lt;code&gt;hsl_to_srgb&lt;/code&gt;, &lt;code&gt;srgb_to_oklch&lt;/code&gt;, &lt;code&gt;oklch_to_srgb&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;&lt;code&gt;ui.alpha_picker&lt;/code&gt;, &lt;code&gt;ui.checker_draw&lt;/code&gt;; &lt;code&gt;hue_picker&lt;/code&gt; takes &lt;code&gt;horizontal&lt;/code&gt;; &lt;code&gt;sat_val_picker&lt;/code&gt;, &lt;code&gt;hue_picker&lt;/code&gt; and &lt;code&gt;alpha_picker&lt;/code&gt; take the keyboard and tell screen readers their values.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.77.0</id>
    <title>gui_toolkit 0.77.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.77.0"/>
    <updated>2026-11-04T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Fixed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;A folded pane's strip in the theme, a fold button on the stacks that fold, tooltips the size of their text&lt;/strong&gt;: the strip of a folded side (&lt;code&gt;pane_split&lt;/code&gt;, a dock's folded split) painted nothing at rest and the palette's raw hover colour (opaque white on a dark theme) under the pointer; it now has the theme's &lt;code&gt;pane_strip background&lt;/code&gt; (by default the bars' surface) and the theme's &lt;code&gt;hover_fill&lt;/code&gt; over it, and its chevron is larger (&lt;code&gt;PANE_CHEVRON_EM&lt;/code&gt; 1.4, also &lt;code&gt;pane_toggle&lt;/code&gt;'s). A dock's stacks on a side that folds have a chevron button at the end of their strip, as large as the menu's button (&lt;code&gt;pane_toggle&lt;/code&gt;, which now takes the size &lt;code&gt;next&lt;/code&gt; gives it; a Tab stop, Enter folds); a strip's tabs are in the room its end's buttons leave, so tabs too many for a narrow stack are cut and the fold and menu buttons stay in view (they were pushed out of the strip). A tooltip's content inherited the app's style, so under a style that fills it was as large as the window; a size relative to the window is now the content's own in it, &lt;code&gt;ui.tooltip_text(text)&lt;/code&gt; is as wide as its text up to &lt;code&gt;TOOLTIP_MAX_WIDTH_EM&lt;/code&gt; and wraps past it, and &lt;code&gt;tooltip&lt;/code&gt; goes above the pointer when it does not fit below (&lt;code&gt;TOOLTIP_ABOVE_EM&lt;/code&gt;); its first frame measures it unseen and asks for the next one, which places it (it was placed by the size of 10 x 3 em it was taken to have, and stayed past the window's edge when nothing else made a frame). Tests &lt;code&gt;docking a_folded_strip_takes_the_theme_colours&lt;/code&gt;, &lt;code&gt;the_fold_button_folds_and_the_strip_brings_it_back&lt;/code&gt;, &lt;code&gt;the_end_buttons_stay_in_view_past_too_many_tabs&lt;/code&gt;, &lt;code&gt;a_tooltip_over_a_tall_strip_fits_its_text&lt;/code&gt;; &lt;code&gt;ui_robust tooltip_places&lt;/code&gt; (above the pointer at the bottom).&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.76.0</id>
    <title>gui_toolkit 0.76.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.76.0"/>
    <updated>2026-11-04T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.menu_at(p)&lt;/code&gt; and &lt;code&gt;ui.wheel_consumed()&lt;/code&gt;: the wheel over an open menu is the menu's&lt;/strong&gt;: &lt;code&gt;menu_at&lt;/code&gt; says whether a point is on a level of the open menu (a submenu, a nested menu, a drop-down's list) as the last build laid it out, so an app that routes the wheel to its own content before it builds the interface (a browser's page) gives it nothing there; &lt;code&gt;wheel_consumed&lt;/code&gt; says whether this build's wheel went to the interface (a box that scrolls under the pointer, or a menu's level, one that fits included). A menu taller than the window scrolls under the wheel, one that fits takes it and does not move, down and across; the scroller under either gets nothing (test &lt;code&gt;keyboard menu_takes_the_wheel_over_it&lt;/code&gt;).&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.75.0</id>
    <title>gui_toolkit 0.75.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.75.0"/>
    <updated>2026-11-04T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Changed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Slug glyph data built in half the time&lt;/strong&gt;: &lt;code&gt;slug_build&lt;/code&gt; sorts the curves of an axis once (one &lt;code&gt;u64&lt;/code&gt; key each) and puts each curve in the bands it spans, found from its bounds against the bands' own; it sorted the curves of every band and tested every curve against every band of each of the ten band counts it tries. The same data (test &lt;code&gt;slug bands_are_their_definition&lt;/code&gt;); 400 glyphs of a face, best of 5: Segoe UI 5.5 -&amp;gt; 2.8 ms, Times New Roman 8.3 -&amp;gt; 3.9 ms, Nirmala UI 10.0 -&amp;gt; 4.6 ms.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.74.0</id>
    <title>gui_toolkit 0.74.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.74.0"/>
    <updated>2026-11-04T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Changed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;font.color_prepare&lt;/code&gt;, textures zeroed on the GPU&lt;/strong&gt;: &lt;code&gt;font.color_prepare&lt;/code&gt; makes what color glyphs are drawn with (Direct2D on a WARP device, about 20 ms) for an application to call on a thread of its own while it starts; the first color glyph a frame looked up made it on the drawing thread. Textures are made render targets too and zeroed by a clear on the GPU (&lt;code&gt;ClearRenderTargetView&lt;/code&gt;) where they were zeroed by uploads of zeros: a 2048 x 2048 glyph atlas page 6 ms (R8) and 3.5 ms (RGBA) of the CPU before, its first frame's.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.73.0</id>
    <title>gui_toolkit 0.73.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.73.0"/>
    <updated>2026-11-03T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Fixed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;The ASCII case helpers are package &lt;code&gt;ascii&lt;/code&gt;&lt;/strong&gt; (&lt;code&gt;ascii/ascii.odin&lt;/code&gt;: &lt;code&gt;ascii.lower&lt;/code&gt;, &lt;code&gt;upper&lt;/code&gt;, &lt;code&gt;lower_byte&lt;/code&gt; / &lt;code&gt;upper_byte&lt;/code&gt;, &lt;code&gt;equal_fold&lt;/code&gt;, &lt;code&gt;has_prefix_fold&lt;/code&gt;, &lt;code&gt;contains_fold&lt;/code&gt;), no longer &lt;code&gt;base&lt;/code&gt;'s &lt;code&gt;ascii_*&lt;/code&gt;: a package named &lt;code&gt;base&lt;/code&gt;, which &lt;code&gt;font&lt;/code&gt;, &lt;code&gt;devtools&lt;/code&gt;, &lt;code&gt;platform&lt;/code&gt; and &lt;code&gt;config&lt;/code&gt; now import, clashed with an app's own package of that name (Odin wants one name per package in a program).&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.72.0</id>
    <title>gui_toolkit 0.72.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.72.0"/>
    <updated>2026-11-03T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Fixed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;ASCII case for names and protocols&lt;/strong&gt;: &lt;code&gt;strings.to_lower&lt;/code&gt;, &lt;code&gt;to_upper&lt;/code&gt; and &lt;code&gt;equal_fold&lt;/code&gt; of Odin dev-2026-11 fold by Unicode (the Kelvin sign U+212A is &lt;code&gt;k&lt;/code&gt; to them, the long s U+017F &lt;code&gt;s&lt;/code&gt;), where names and protocols want ASCII. New in &lt;code&gt;base&lt;/code&gt; (&lt;code&gt;base/text.odin&lt;/code&gt;): &lt;code&gt;ascii_lower&lt;/code&gt;, &lt;code&gt;ascii_upper&lt;/code&gt;, &lt;code&gt;ascii_lower_byte&lt;/code&gt; / &lt;code&gt;ascii_upper_byte&lt;/code&gt;, &lt;code&gt;ascii_equal_fold&lt;/code&gt;, &lt;code&gt;ascii_has_prefix_fold&lt;/code&gt;, &lt;code&gt;ascii_contains_fold&lt;/code&gt;. Switched to them: the DevTools server's header names and Host (&lt;code&gt;Ho\u017Ft:&lt;/code&gt; is no Host, &lt;code&gt;localho\u017Ft&lt;/code&gt; no localhost), CSS colour keywords, &lt;code&gt;nodeName&lt;/code&gt;, the accessibility roles and actions; font family names as cache keys (Windows, Linux, macOS) and fontconfig's / Core Text's answer checked against the family asked for (&lt;code&gt;DejaVu San\u017F&lt;/code&gt; no longer loads DejaVu Sans); preference booleans; the GTK theme name, file extensions for MIME types on Linux; the changelog tool's type and slugs, &lt;code&gt;tk&lt;/code&gt;'s checksums and emoji version line, &lt;code&gt;run_tests&lt;/code&gt;' groups, the examples' option names. Unicode stays for user text (find in page, fuzzy matching, type-ahead, the settings' and DevTools' searches, the test session's text lookups), display text and Windows paths. Lint &lt;code&gt;tests/unicode_case&lt;/code&gt; (a step of &lt;code&gt;run_tests&lt;/code&gt;): a call of &lt;code&gt;strings.to_lower&lt;/code&gt; / &lt;code&gt;to_upper&lt;/code&gt; / &lt;code&gt;equal_fold&lt;/code&gt; or &lt;code&gt;unicode.to_lower&lt;/code&gt; / &lt;code&gt;to_upper&lt;/code&gt; in the toolkit's sources fails unless &lt;code&gt;tools/unicode_case_allowed.txt&lt;/code&gt; lists its line with why; an entry that matches no line fails too.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.71.0</id>
    <title>gui_toolkit 0.71.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.71.0"/>
    <updated>2026-11-03T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Docking&lt;/strong&gt; (&lt;code&gt;ui/dock_model.odin&lt;/code&gt;, &lt;code&gt;ui/docking.odin&lt;/code&gt;, &lt;code&gt;docs/docking.md&lt;/code&gt;): the app's panels in stacks of tabs the user rearranges. The layout is the app's &lt;code&gt;ui.Dock&lt;/code&gt;, flat data: a tree of nodes in one &lt;code&gt;#soa&lt;/code&gt; array (leaves: a stack of panels and the one shown; splits: an axis, a ratio, the second side folded), floating roots at a place of their own, the panels (the app's &lt;code&gt;u32&lt;/code&gt; ids) in tab order; &lt;code&gt;dock_add&lt;/code&gt;, &lt;code&gt;dock_move&lt;/code&gt; (into a stack at a tab, at a side of one, at an edge of the space, floating), &lt;code&gt;dock_move_node&lt;/code&gt;, &lt;code&gt;dock_redock&lt;/code&gt;, &lt;code&gt;dock_close&lt;/code&gt;, &lt;code&gt;dock_activate&lt;/code&gt;, &lt;code&gt;dock_set_split&lt;/code&gt;, &lt;code&gt;dock_layout&lt;/code&gt;, &lt;code&gt;dock_target_at&lt;/code&gt;; one line of text (&lt;code&gt;dock_format&lt;/code&gt; / &lt;code&gt;dock_parse&lt;/code&gt;: unknown names dropped with the stacks they leave empty, the panels it does not name placed by the app, any other text refused with the dock left as it was). &lt;code&gt;dock_begin&lt;/code&gt; / &lt;code&gt;dock_panel&lt;/code&gt; / &lt;code&gt;dock_end&lt;/code&gt; build it: a tab dragged out shows the drop targets (five squares over the stack under the pointer, four at the edges of the space, the strips between their tabs) and a translucent preview of where it lands; let go elsewhere it floats (an overlay of the window with a frame and a shadow, moved by its strip with the drop targets, resized by its corner, docked back by a double click); Escape cancels; the handles are &lt;code&gt;pane_split&lt;/code&gt;'s (minimum sizes, fold); close buttons, a middle click; the stack's menu reaches every drop target from the keyboard; the arrows along a strip, Ctrl+Shift+arrows move a tab, Ctrl+Tab goes through a stack; roles tab list, tab (controls its panel), tab panel, separator. Theme entries &lt;code&gt;dock_preview&lt;/code&gt; and &lt;code&gt;dock_marker&lt;/code&gt;. Example &lt;code&gt;examples/docking&lt;/code&gt;; tests &lt;code&gt;tests/docking&lt;/code&gt; (the model and the text; the drags, the keyboard and the menu through the test session).&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.70.0</id>
    <title>gui_toolkit 0.70.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.70.0"/>
    <updated>2026-11-03T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Changed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.build_events&lt;/code&gt;&lt;/strong&gt;: a copy of the last build's input, kept by the state until the next build (it was the caller's slice, valid until its next poll).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Built with Odin dev-2026-11&lt;/strong&gt; (pinned by SHA-256 in the CI, &lt;code&gt;docs/getting-started.md&lt;/code&gt;): &lt;code&gt;core:image&lt;/code&gt;'s pixels are a &lt;code&gt;[dynamic]u8&lt;/code&gt;, nothing keeps a reference to a stack past its procedure (the compiler's new escape analysis: the tests' globals are cleared, &lt;code&gt;ui.use&lt;/code&gt; keeps the caller's state on purpose), &lt;code&gt;core:compress/deflate&lt;/code&gt; checks &lt;code&gt;flate&lt;/code&gt;'s streams in the tests and &lt;code&gt;docs/flate.md&lt;/code&gt; compares both (&lt;code&gt;flate&lt;/code&gt; stays for streams and &lt;code&gt;deflate_runs&lt;/code&gt;). wgpu-native stays 29.0.1.1.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.69.0</id>
    <title>gui_toolkit 0.69.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.69.0"/>
    <updated>2026-11-03T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Menus taller than the window scroll&lt;/strong&gt;: a level (menu, submenu, nested menu, dropdown list) whose content is taller than the window is as tall as the window, placed again at each frame (a window made shorter while it is open), and scrolls: the wheel, its scroll bar (a press on it is not a press outside; the rows leave it room), the keyboard's selection brought into view (Up / Down / Home / End / Page Up / Page Down, type-ahead to a hidden row, a dropdown's current value from &lt;code&gt;menu_select&lt;/code&gt;). A menu that fits is placed as before (flipped to the other side of its anchor, else shifted to stay whole). &lt;code&gt;ui.menu_item_rect(depth, idx)&lt;/code&gt;: where an item was laid out. Tests &lt;code&gt;menu_taller_than_the_window_scrolls&lt;/code&gt;, &lt;code&gt;menu_near_the_bottom_flips_or_shifts&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Changed&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Menus are dense&lt;/strong&gt;: &lt;code&gt;MENU_ITEM_EM&lt;/code&gt; is 1.9 (was 2.2): rows of 29 px for 15 px text, as Windows 11's and Chrome's menus (times the density: 22 px at &lt;code&gt;DENSITY_COMPACT&lt;/code&gt;, 34 px at &lt;code&gt;DENSITY_MAX&lt;/code&gt;); the padding above the first item and below the last is 0.25 em (was 0.3), a separator's gaps 0.2 em (were 0.25); the icon cell is as tall as the row. Test &lt;code&gt;menu_rows_follow_the_density&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.68.0</id>
    <title>gui_toolkit 0.68.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.68.0"/>
    <updated>2026-11-03T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.pane_split&lt;/code&gt;, &lt;code&gt;ui.pane_toggle&lt;/code&gt;, &lt;code&gt;ui.Pane&lt;/code&gt;&lt;/strong&gt;: panes the user resizes from a few em (&lt;code&gt;PANE_MIN_EM&lt;/code&gt;) to all the room but a few em for the other side, folds (a drag under half the minimum, a double click, Enter, a chevron button) to a strip that brings them back (a click, Enter, a pull), and places at the side or below (&lt;code&gt;pane_axis&lt;/code&gt;, &lt;code&gt;pane_place_menu&lt;/code&gt;); the app owns a &lt;code&gt;Pane&lt;/code&gt; per split (sizes per orientation, folded, place) and saves it through &lt;code&gt;Pane_Options.on_save&lt;/code&gt;; &lt;code&gt;pane_format&lt;/code&gt; / &lt;code&gt;pane_parse&lt;/code&gt; make it a line of text; &lt;code&gt;menu_move_to&lt;/code&gt; lists &amp;quot;Move to&amp;quot; items for a tab that may go to another strip. Keyboard (arrows, Home, End, Enter) and accessible (a separator with its value, &lt;code&gt;expanded&lt;/code&gt;). &lt;code&gt;examples/panes&lt;/code&gt; uses them. Tests &lt;code&gt;tests/panes/pane_split_test.odin&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.67.0</id>
    <title>gui_toolkit 0.67.0</title>
    <link rel="alternate" type="text/html" href="https://sachahjkl.github.io/gui_toolkit/changelog.html#v0.67.0"/>
    <updated>2026-11-03T00:00:00Z</updated>
    <content type="html">&lt;h3&gt;Added&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;code&gt;ui.set_scrollbar_arrows&lt;/code&gt;&lt;/strong&gt;: classic arrow buttons at both ends of the scroll bars of scroll boxes, off by default (the bars stay as they were): each as long as the bar is broad, taken from the track; a press scrolls a step (3 em, eased like the wheel), held it repeats after 250 ms every 50 ms while the pointer stays on it. &lt;code&gt;ui.scrollbar_arrow_rects&lt;/code&gt; gives where they are; &lt;strong&gt;&lt;code&gt;draw.triangle&lt;/code&gt;&lt;/strong&gt; fills a triangle in one-pixel rows (the arrows' glyph). Test arrow_buttons_step_and_repeat&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
</feed>
