Repository navigation
0.19.0
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.onPasteEventreceives pasted text as a singlePasteEventin terminals which support bracketed paste, rather than one key event per character withEnterfor each line break. Unhandled pastes are still delivered as key events.TestMosaic.sendEventsends any terminal event, such as theBracketedPasteEvents around pasted text.DrawScope.drawCursorplaces and shows the terminal's cursor once the frame is rendered, so that input methods show their composition at the caret of text input.TextFieldandTextFieldStatefor editing text. Text wraps to the field's width,maxLineslimits its height, and the terminal's cursor marks the caret. WithonSubmit, 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, andrunMosaicMaintakealternateScreen, which renders full screen on the terminal's alternate screen and restores what it showed before when done. Static output is written once done.WindowTitlesets the title of the terminal window while it is in the composition, restoring the previous title afterwards in terminals which support it.LocalClipboardcopies text to the clipboard with OSC 52, andLocalNotifiershows desktop notifications with the Kitty notification protocol or OSC 9.SpanStyle.linkandwithLinklink text to a URL with OSC 8 hyperlinks.Modifier.clipToBoundskeeps the content of a node, including its children, within its bounds.Modifier.verticalScrollandModifier.horizontalScrollwithScrollStateshow part of content which is larger than the node.ScrollState.scrollToEndkeeps following the end as the content grows.LazyColumnwithLazyListStateonly 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, andscrollToEndscrolls to the latest item.- A focus system:
Modifier.focusable,Modifier.focusRequester,Modifier.onFocusChanged, andLocalFocusManager. 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. Popupshows content on top of everything else, like a completion menu, without taking up space in the layout or being clipped by its ancestors. Itsalignmentlets 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
printlnor a logging library, are intercepted whilerunMosaicruns and shown as static output above the display, rather than corrupting it (JakeWharton#681). TexttakessoftWrap,maxLines, andoverflow.TextOverflow.Ellipsisends text which does not fit with an ellipsis.Imageshows anImageBitmap, 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.sixelGraphicsis true when the terminal reports Sixel support in its primary device attributes.WindowPointerShapesets 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, andonHover. 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 ofTextFields, and the wheel scrollsverticalScroll,horizontalScroll(with Shift), andLazyColumn.runMosaictakesmouse, which is enabled on the alternate screen by default. Inline, the output is located on the screen with cursor position requests. Modifier.borderdraws a box of aBorderStylearound the content, with an optional title.- New
mosaic-markdownlibrary withMarkdown, 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:
TextFieldis focusable and edits while focused, instead of taking afocusedparameter.Textrespects 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 whosekeyis 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.