Repository navigation
Termina 0.17.0
Behavior Changes
- The event loop no longer runs queued work after it stops (#400)
- When the loop stops, it drops all work that is still in the queue. This includes work that
PostorInvokeAsyncqueued before the call toShutdown(). Earlier versions could run that work. - A task that
InvokeAsyncreturned for dropped work ends as canceled withTaskCanceledException. The task ends this way even when the token of the caller is not canceled. InvokeAsynccalled after the loop stopped returns a canceled task.Postcalled after the loop stopped does not run its work.- A queued
CommitAsynccall for inline output ends as canceled in the same way. - Code that must run during shutdown must run before
Shutdown(), not as queued work.
- When the loop stops, it drops all work that is still in the queue. This includes work that
RequestRedrawcan merge with a redraw request that is already queued (#400)- Change the state before you call
RequestRedraw(). A render that runs between the call and the state change can draw the old state. The loop then skips the merged request. - A
RedrawRequested.Instancethat an input source writes to the event channel always renders. Inputsubscribers still see every redraw request asRedrawRequested.
- Change the state before you call
New Features
-
Added an opt-in inline presentation mode (#373, fixes #366 and #370)
TerminalPresentationMode.Inlinekeeps settled output in the primary buffer.IInlineOutputcommits stable layouts above one bounded live region.ScrollInputMode.NativeTerminalleaves selection and scrollback under terminal control.IInlineTerminalControladds relative cursor operations without a change toIAnsiTerminal.AnsiTerminalandVirtualTerminalimplement the new contract.- Full-screen mode remains the default mode.
-
Added semantic clipboard content for copyable text (#374, fixes #367)
WithSemanticContentseparates complete clipboard text from compact display text.TryCopyreports clipboard failure and preserves the current selection.
-
Added a modified Enter key capability result (#375, fixes #240)
- Termina queries active Kitty keyboard flags without a terminal-name guess.
TerminalInputCapabilitiesChangedreports whether modified Enter keys remain distinct.TerminaApplication.InputCapabilitiesexposes the latest result.- Windows console records report native modifier support.
-
Added prompt history cancellation (#376, fixes #368)
CancelHistoryNavigationrestores the draft that existed before history navigation.- The API resets history navigation without a change to current method signatures.
-
Added pointer-aware wheel routing (#376, fixes #240)
MouseScrollEventpreserves zero-based pointer coordinates and keyboard modifiers.- Termina routes wheel input to the measured scroll region under the pointer.
ScrollableContainerNodenow implements the currentIScrollablecontract.
-
Added an optional panel background surface (#379, fixes #378)
PanelNode.WithBackground(Color)sets the surface.PanelNode.Backgroundreads it.- The panel fills its complete bounds, including the border cells.
- A child that resets its colors returns to the surface. A child that selects its own background keeps it.
- A scrollable or streaming node in a surface panel keeps its screen bounds, so the mouse wheel reaches it.
- A panel without a background keeps its current behavior.
Performance
- The event loop renders once for each batch of queued events (#400)
- The loop processes the events that are queued when a batch starts, and then renders once. Events that arrive during the batch go to the next batch.
- Before, the loop rendered the full page after every event. A slow render let the queue grow without limit.
- 20
RequestRedrawcalls in one loop turn now cause 2 to 3 renders. Before, they caused 24 renders. - The cursor blink alone now causes about 1.9 renders each second. Before, it caused about 4.3.
- The final frame is the same as before.
TextAreaNodemeasures a long line cheaply (#400)Measurekeeps the column counts of the text until the text changes. A call with unchanged text takes under 0.01 ms and allocates no memory. Before, it took 43 ms and allocated 16 MB for a line of 600,000 characters.DisplayWidth.GetColumnCountreturns the length of printable ASCII text without an allocation.TextAreaNodekeeps one line wrap for each width. A layout that measures and renders at different widths no longer wraps the line twice for each frame.- One render of an unchanged 600,000-character line takes under 1 ms instead of 69 ms, and allocates 0.27 MB instead of 32 MB.
- Ctrl+Q exits fast with a large transcript or a large paste (#400)
- The loop waits for each batch with
WaitToReadAsyncand stops at a shutdown request. Before, the loop kept running while events kept arriving. - An app with a 1,000,000-character line now exits in about 360 ms. Before, it did not exit within 90 s.
- The loop waits for each batch with
- Wrapping a very long line is now linear in its length (#398, fixes #397, first shipped in 0.16.4)
StyledWordWrapper,WordWrapper, andTextAreaNodeno longer re-measure the rest of a long line for every wrapped row.
- Text writes to the diffing terminal allocate less (#379)
DiffingTerminal.Writeskips the grapheme parse when every char is printable ASCII. All other text uses the old loop.- A full-screen frame of a panel with a background allocates 40 KB instead of 400 KB. It renders in about 0.7 ms instead of 1.5 ms.
- This change applies to every app and every render, not only panels. The output is the same.
Bug Fixes
-
Fixed tail follow after a large content update (#383)
- A
ScrollableContainerNodewithTailWhenAtBottomstopped at the old offset after the content grew by more than 2 rows. This happens often now, because the loop renders once for each batch of events. Measurenow readsIsNearBottombefore it replaces the content height.- When the content shrinks,
Measureclamps the offset to the new range. Before, a shrink could leave a blank pane. - A user who scrolled up stays where the user is.
- A
-
Restored all terminal and input state after a render failure
- Termina now cancels input tasks before it propagates a render exception.
- Termina restores the cursor, mouse modes, keyboard modes, and input mode.
-
Corrected text-area prompt history traversal (#377, fixes #368)
- Up recalls prompt history from the first visual line and saves the current draft.
- Down restores the saved draft from the last visual line.
- Up and Down keep their current visual movement between multiline rows.
-
Made container disposal safe when layout retirement overlaps teardown (#384, first shipped in 0.16.2)
ContainerNode.Dispose()now claims teardown atomically, so concurrent disposal no longer completes the same reactive invalidation subject twice.
-
Added a way to place the cursor in a pre-filled text input (#395, fixes #394, first shipped in 0.16.3)
TextInputBaseNode.CursorPositiongets and sets the cursor as a UTF-16 index into the editable text.TextInputBaseNode.MoveCursorToEnd()moves the cursor to the end of the text.
Compatibility
- Current enum values and public signatures keep their behavior. The release adds no public API change that breaks a caller, apart from the event loop behavior changes above.
- The current
AnsiTerminal(bool)constructor keeps its behavior. - An API approval test prevents accidental contract changes.
Maintenance
- Bumped
Microsoft.SourceLink.GitHubto 10.0.303 (#396) and pinnedSystem.Security.Cryptography.Pkcsto 10.0.13 in the test project (#399) to clear security advisory warnings. - Updated
Microsoft.Extensions.DependencyInjectionandMicrosoft.Extensions.Hostingto 10.0.11 (#380, #389). - Updated
Microsoft.CodeAnalysis.CSharpandMicrosoft.CodeAnalysis.Analyzersto 5.9.0 for the repository (#387). The source generators and analyzers that ship in the package stay on 5.3.0, as in 0.16.4 (#403). Consumers keep the same .NET SDK requirement. - Updated the
incrementalist.cmdtool to 1.2.2 (#385).