Skip to content

0.19.0

Choose a tag to compare

@github-actions github-actions released this 22 Oct 11:34
· 34 commits to master since this release

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.