Skip to content

Releases

0.22.0

Choose a tag to compare

@github-actions github-actions released this 24 Oct 16:54

New:

  • Clipboard.lastCopy is what was put on the clipboard last, with setText or by selecting text on the screen, so that a program can say that something was copied. Each copy is a value of its own.

Fixed:

  • ProgressBar covers what is below it, also where it has no track color, rather than letting it show through the part still to fill.
  • Keys which arrive at once, like the text an input method commits or a paste in a terminal without bracketed paste, all reach the program. Past 64 keys the earliest were dropped.
  • Shift+Enter, and other keys which otherwise arrive as plain ones, are told apart in iTerm2, xterm, and tmux, which lack the Kitty keyboard protocol, through xterm's modifyOtherKeys. Shift+Enter arrived as Enter, so a TextField with onSubmit submitted instead of breaking the line.

0.21.0

Choose a tag to compare

@github-actions github-actions released this 24 Oct 02:41

New:

  • ProgressBar fills from the left to an eighth of a cell as its progress goes from 0 to 1, in a color of its own over a track color for the part still to fill. It is one row high and DefaultProgressBarWidth cells wide unless its modifier sizes it.
  • Spinner shows the frames of a SpinnerStyle in turn while it is composed, as wide as the widest frame. SpinnerStyle has Dots, Line, and Pulse, and takes frames and an interval of one's own.

Fixed:

  • A program which fails leaves the terminal as one which completes does, with the cursor shown. The terminal was restored before the program's last output, which hid the cursor again.
  • The runMosaic* family of functions closes the TTY only once the terminal stopped reading it. Quitting could fail with IOException: 9 (EBADF) from a read of the closed TTY.
  • On JDK 22 and newer, reads which reach the end of the input return -1, as they do on older JDKs, rather than throwing IndexOutOfBoundsException. This covers Tty, TestTerminal, and StandardStreams.

0.20.0

Choose a tag to compare

@github-actions github-actions released this 22 Oct 14:26

New:

  • LocalTerminalControl hands the terminal over to other programs with released, like an editor or an interactive command, and takes it over again afterwards, drawing everything anew. Meanwhile, nothing is drawn, input is left to those programs, and stdout and stderr are no longer intercepted.
  • Ctrl+Z suspends the program when no key handler consumes it, like it does in a shell, and fg resumes it. TerminalControl.suspendProcess does the same. Neither is supported on Windows.
  • Terminal.released and Terminal.suspendProcess do the same for the terminal alone, without Mosaic, and Tty.suspendProcess stops the process.
  • TextField moves between rows with ↑ and ↓, leaving them to other handlers on the first and last row, for example to recall earlier input. Alt or Ctrl with ← and β†’, and Alt+B and Alt+F, move by words, and Alt+Backspace and Alt+D delete them.
  • TextField selects with Shift and the keys which move the cursor, and by dragging the mouse, which copies the selection to the clipboard. Typing and pasting replace the selection. TextFieldState has selectionStart, selectionEnd, selectedText, select, and selectAll.
  • TextField undoes edits with Ctrl+_ (or Ctrl+/) and redoes them with Ctrl+Shift+Z, grouping typed characters by word. TextFieldState has undo, redo, canUndo, and canRedo.
  • Text deleted with Ctrl+U, Ctrl+K, Ctrl+W, Alt+Backspace, and Alt+D is inserted again with Ctrl+Y, like in a shell.
  • TextField takes minLines.
  • Modifier.onPreviewPasteEvent receives pastes before the focused node, like a text field, so that ancestors can intercept them, for example to insert a placeholder for a large paste.
  • With the mouse enabled, dragging where no pointer handler takes the press selects text, like the terminal does without mouse tracking, and copies it to the clipboard once released. Double clicks select words, and triple clicks rows.

Changed:

  • Ctrl+, Ctrl+], Ctrl+^, and Ctrl+_ are reported as those keys with Ctrl in terminals without the Kitty keyboard protocol, rather than as control characters which were dropped.

0.19.0

Choose a tag to compare

@github-actions github-actions released this 22 Oct 11:34

The first release of the fork, under the org.unitedsoftware.mosaic group and packages.

New:

  • JVM support for RISC-V and s390x!
  • Keys with modifiers which used to be indistinguishable, such as Shift+Enter and Enter, are now reported separately in terminals which support the Kitty keyboard protocol.
  • Modifier.onPasteEvent receives pasted text as a single PasteEvent in terminals which support bracketed paste, rather than one key event per character with Enter for each line break. Unhandled pastes are still delivered as key events.
  • TestMosaic.sendEvent sends any terminal event, such as the BracketedPasteEvents around pasted text.
  • DrawScope.drawCursor places and shows the terminal's cursor once the frame is rendered, so that input methods show their composition at the caret of text input.
  • TextField and TextFieldState for editing text. Text wraps to the field's width, maxLines limits its height, and the terminal's cursor marks the caret. With onSubmit, Enter submits and Shift+Enter or Alt+Enter break lines. Pastes are inserted as a whole, and Ctrl+A, Ctrl+E, Ctrl+U, Ctrl+K, and Ctrl+W work like in a shell.
  • runMosaic, runMosaicBlocking, and runMosaicMain take alternateScreen, which renders full screen on the terminal's alternate screen and restores what it showed before when done. Static output is written once done.
  • WindowTitle sets the title of the terminal window while it is in the composition, restoring the previous title afterwards in terminals which support it.
  • LocalClipboard copies text to the clipboard with OSC 52, and LocalNotifier shows desktop notifications with the Kitty notification protocol or OSC 9.
  • SpanStyle.link and withLink link text to a URL with OSC 8 hyperlinks.
  • Modifier.clipToBounds keeps the content of a node, including its children, within its bounds.
  • Modifier.verticalScroll and Modifier.horizontalScroll with ScrollState show part of content which is larger than the node. ScrollState.scrollToEnd keeps following the end as the content grows.
  • LazyColumn with LazyListState only composes the items which are visible, so it can hold long lists like the messages of a conversation. Keyed items keep their position when items are added before them, and scrollToEnd scrolls to the latest item.
  • A focus system: Modifier.focusable, Modifier.focusRequester, Modifier.onFocusChanged, and LocalFocusManager. Key and paste events go to the focused node and its ancestors first, and to the other nodes only when those do not handle them. Tab and Shift+Tab move the focus, and the first focusable node is focused when nothing else is.
  • Popup shows content on top of everything else, like a completion menu, without taking up space in the layout or being clipped by its ancestors. Its alignment lets it extend up from its position, for example above a text field at the bottom of the screen.
  • Writes to stdout and stderr by other means than Mosaic, like println or a logging library, are intercepted while runMosaic runs and shown as static output above the display, rather than corrupting it (JakeWharton#681).
  • Text takes softWrap, maxLines, and overflow. TextOverflow.Ellipsis ends text which does not fit with an ellipsis.
  • Image shows an ImageBitmap, scaled to fit. kitty and Ghostty show the image itself with the Kitty graphics protocol, using Unicode placeholders so that it moves with the text. iTerm2 and WezTerm use their inline images, which keep transparency, terminals which report Sixel support Sixel graphics, and others half block characters.
  • Terminal.Capabilities.sixelGraphics is true when the terminal reports Sixel support in its primary device attributes.
  • WindowPointerShape sets the shape of the mouse pointer with the Kitty pointer shape protocol while it is in the composition, restoring the previous shape afterwards.
  • Mouse input: Modifier.onPointerEvent, onClick, and onHover. Events go to the innermost node under the pointer first, then to its ancestors, and drags and releases go to the nodes the press went to. Clicks focus focusable nodes and place the cursor of TextFields, and the wheel scrolls verticalScroll, horizontalScroll (with Shift), and LazyColumn. runMosaic takes mouse, which is enabled on the alternate screen by default. Inline, the output is located on the screen with cursor position requests.
  • Modifier.border draws a box of a BorderStyle around the content, with an optional title.
  • New mosaic-markdown library with Markdown, which renders Markdown with syntax highlighted code, diffs, tables, task lists, and OSC 8 links. It handles incomplete input, so responses of language models can be rendered while they stream in.

Changed:

  • TextField is focusable and edits while focused, instead of taking a focused parameter.
  • Text respects the incoming constraints. Lines wider than the maximum width wrap, after the last space which fits where possible, and text is clipped to the bounds of its node. Previously text was always as large as its content and drew over its surroundings.
  • Only rows which changed since the last frame are written to the terminal again.
  • Output taller than the terminal shows its bottom instead of corrupting the screen, since the cursor cannot move above the top of the screen to redraw it.
  • Content is measured with the width of the terminal as its maximum width. With alternateScreen, it is measured to exactly the size of the terminal.
  • Use the AndroidX versions of the Compose runtime and lifecycle dependencies which are now fully multiplatform. Dependency constraints to the corresponding JetBrains artifacts (which are now empty) are present to prevent symbol duplication.
  • Remove support for x86 macOS targets. These have been deprecated for a bit, but support has been removed from the Compose runtime so we have no choice but to match.

Fixed:

  • Clear the set of states which were read during layout and draw passes before each pass. Previously these sets grew infinitely, which was both a memory leak and a performance problem.
  • Close the underlying TTY at the end of the runMosaic* family of functions.
  • Frame times on Linux and Windows no longer jump backwards once per second.
  • Fix arc-based animations on native targets, which built their lookup table incorrectly.
  • Report Shift+Tab as a key event when the terminal sends it as CSI Z.
  • Typing characters outside of ASCII, such as CJK text committed by an input method, no longer crashes. They are delivered as KeyEvents whose key is the character.
  • Wide characters, such as CJK text and most emoji, are measured and drawn as two columns, so they no longer push the rest of the row out of place. Combining marks and emoji joined with zero width joiners stay in the column of the character they modify. Widths follow Unicode 18.
  • Drawing outside of the surface, for example while the terminal is being resized, is clipped instead of crashing.
  • The initial size comes from the TTY in terminals which support in-band resize events but do not report their size when they are enabled, like iTerm2. Previously the size stayed at 80 by 24 until the window was resized.
  • Inline output can be as tall as the terminal. The cursor rests at the end of the last row rather than on a line below the output, which kept the last row of the terminal empty.
  • Resizing terminals which do not report size changes in-band, such as tmux and Terminal.app, no longer crashes the JVM. The resize callback was invoked from the signal handler, on whichever thread received the signal, with the JNI environment of another thread.