·
1 commit
to master
since this release
A lot has happened since our last release, and that was already too long ago. So now, it is finally time to tag a release, with an already way too long list of great improvements as well as fixes.
Contour 0.7.0 makes the window a workspace: native GUI tabs in the title bar, split panes, saved layouts, and an optional terminal-styled UI that draws the application's own chrome on the character grid. It adds an experimental daemon mode for sessions that outlive the window showing them, accessibility support across the terminal and its chrome, the kitty graphics, text-sizing and clipboard protocols, ReGIS vector graphics, and a large round of VT conformance work.
Tabs, splits and layouts
- Adds first-class GUI tabs presented in a custom window title bar, replacing the status-line tab list (the {Tabs} status-line directive remains supported for existing configs)
- Adds split panes — split the active pane vertically (Ctrl+Shift+E) or horizontally (Ctrl+Shift+O), close a pane (Ctrl+Shift+X), and move pane focus with Alt+Shift+Arrow
- Adds pane management actions: swap the active pane with a neighbor (Ctrl+Alt+Arrow), resize it (Ctrl+Shift+Alt+Arrow), flip a split's orientation (Ctrl+Shift+Backslash), and move a pane to a new position in the split tree (unbound by default)
- Adds pane zoom (TogglePaneZoom, Ctrl+Shift+Z): gives the active pane the whole tab area, hiding its siblings, and toggles back to the tiled layout. Moving pane focus while zoomed keeps the zoom and shows the newly focused pane; splitting, closing or rearranging panes returns to the tiled view. A zoomed tab is titled after the pane on screen and wears a Z badge
- Adds dragging tabs: reorder a tab within its strip, drag it into another window, or tear it out into a new window, with a live drop-position indicator showing where it will land; the running terminal survives the move (within the same process)
- Adds renaming a tab by double-clicking it, and a color-swatch picker in its context menu. The picker is keyboard-driven — the cursor keys and the vim motions h/j/k/l walk the swatches, Enter or Space picks the highlighted one, Escape dismisses — and opens on the color the tab already wears
- Adds the actions SetTabColor and ResetTabColor, so coloring a tab is no longer mouse-only: both appear in the command palette, and either can be bound in input_mapping. SetTabColor opens the tab's color picker, or applies a color outright when given one (for example
{ mods: [Shift,Control], key: 'R', action: SetTabColor, color: '#ff0000' }) - Adds configurable layouts: named sets of tabs with per-tab command, working directory, name, color, profile, and split panes; open at startup via default_layout, via
--layout NAME, or the LaunchLayout action. SaveLayout writes the current window's tabs back into layouts.yml, prompting for a name when none was given — and is reachable from the command palette, so saving a layout needs no keybinding - Adds the dim_unfocused profile option: dims a pane while it is not the focused one (an inactive pane of a split, or any pane of an unfocused window) by blending it toward its background color; 0.0 (default) disables dimming
- Adds the top-level options tab_bar_position (Top/Bottom) and tab_bar_visibility (Always/Never/Multiple), to place the GUI tab bar at the top or bottom of the window and to hide it entirely or show it only when more than one tab is open
- BREAKING: tab_bar_position and tab_bar_visibility belong to the top level of contour.yml, not to a profile — a window shows one tab bar whichever profiles its tabs run. If you tried them in a 0.7.0 prerelease, move these two keys out of your
profiles:block; a profile-scoped copy is no longer read - Adds Ctrl+Tab / Ctrl+Shift+Tab and Ctrl+PageDown / Ctrl+PageUp as tab-switching shortcuts. They reach existing configurations too, and binding them yourself still wins. Note that Ctrl+Tab is now taken from applications that request it through the Kitty keyboard protocol
- Adds switching tabs with a horizontal mouse wheel tilt or a two-finger trackpad swipe, over the tab strip or the terminal, configurable via the new global tab_switch_on_horizontal_wheel option (default on); an application that requested mouse reporting keeps the horizontal wheel, and the bypass modifier (Shift) switches tabs even then. Also fixes a sideways swipe over the tab bar doing nothing at all on a trackpad
- Fixes the tab bar placement and visibility settings appearing to do nothing until Contour was restarted
Window and desktop integration
- Changes the window to use a custom client-side-decorated title bar (tab strip plus window controls) by default on all platforms; set show_title_bar: true to use the native server-side window decoration instead, in which case the tab strip is kept but its window controls defer to the OS frame
- Adds window_control_style, deciding how the window's minimize/maximize/close buttons are drawn and which side of the tab bar they sit on — until now always Windows-shaped and always on the right, which on macOS is the wrong corner. The default
autofollows the host: macOS gets real traffic lights on the left, KDE Plasma gets Breeze's circular hover fills, everything else keeps today's buttons. Setwindows,macosorplasmato pin one. Changing it from the settings page applies to every open window at once, without a restart - Fixes the window losing its drop shadow on KDE Plasma. Contour's window is frameless by default so its own tab bar can be the title bar, and a frameless window gets no decoration from the system — which is what draws the shadow. The window now publishes a shadow of its own to KWin, on both X11 and Wayland, sized and shaped like Breeze's so it matches the rest of the desktop;
window_shadowsets it toNone,Small,Medium,LargeorVeryLarge. Only KWin can act on this, so on other compositors and window managers it has no effect - Fixes the same loss on Windows and macOS, where it also cost the window its rounded corners. Neither goes frameless any more: on Windows the frame is kept and made invisible, so the system draws the shadow and the rounded corners while the tab bar still covers the whole window; on macOS the window stays a normal one whose content simply extends into the title bar, so the shadow, the rounded corners, full-screen, window tabbing and double-click-to-zoom all keep working. On macOS the system's own traffic lights are now used instead of Contour's drawn copies
- Fixes background blur never turning off again on X11 once it had been switched on, and fixes the window border being drawn dark on Windows regardless of the
themesetting - Fixes multi-monitor handling: the window no longer re-pins itself to the widest screen on every frame, refresh-rate/DPI tracking follows the window's actual screen after a monitor move, and new windows open on the spawning window's screen
- Changes a display-scale change (moving to a monitor with a different scale, a late Wayland fractional-scale arrival) to preserve the terminal's columns and lines with a single corrective window resize
- Changes font zoom to keep the window and pane size fixed and adjust the terminal's columns and lines (and the child PTY size) instead of resizing the window
- Fixes window resize oscillation/flicker: the terminal no longer fights the window manager by resizing its own window from resize events; the grid floors to the given size (sub-cell remainder renders as padding) while X11/macOS keep WM-side cell snapping via size hints
- Fixes window spawn flicker: the window is sized from the real font metrics before it is first shown and opens directly in the profile's window state, instead of appearing at a default size and jumping
- Fixes window sizing on tiling Wayland compositors: a freshly-spawned terminal was mis-sized until a manual resize (#1955), and the window snapped back to the configured terminal_size after a screen or scale change (#1941)
- Fixes programmatic window resizes (CSI 8 t) shrinking the window by the title-bar height on every call, and CSI 4 t resizing the grid without the window; in split windows both now solve the pane layout so the requesting pane receives its exact grid
- Fixes the KDE forced-font-DPI override being read from the X11 key in Wayland sessions (now honors forceFontDPIWayland) and no longer re-reads the setting file on every frame
- Fixes the window padding being computed against the wrong scale when a forced font DPI is configured (KDE's "Force font DPI"), which fitted the grid to a width the window did not have and left the terminal's own idea of where the grid starts disagreeing with where it was drawn
Command palette, settings and menus
- Adds a command palette (Ctrl+Shift+P): a searchable popup listing every command with its documentation and key binding, making actions that have no binding reachable at all. Recently used commands are pinned on top and remembered across restarts; command_palette_recent_count sets how many (0 disables)
- Adds a GUI settings page for changing the configuration. Settings are grouped into collapsible sections with a search box over them, and the indicator status line is built visually — a preview of the finished line, one chip per placeholder, and a style sheet exposing every attribute a template can carry, with the raw template still editable as text
- Adds a right-click context menu to the terminal: copy, paste, select all, the hyperlink under the cursor, opening the current folder, splitting and closing panes, switching profile, and a soft or hard terminal reset. It opens exactly when a selection drag would have worked, so an application that asked for the mouse (vim, tmux) still receives its right-click; hold Shift to open the menu anyway. Bind OpenContextMenu in input_mapping to move it to another button
- Adds a window menu on right-clicking the empty part of the title bar or tab bar: open a tab (optionally under a named profile), close the current tab or all of them, and switch the tab bar between always visible, auto-hide and hidden
- Adds
ui_style: terminal, which draws the application's own chrome — the tab bar and title bar, and the controls within menus, popups and the settings page — as fixed-size character cells in the terminal font, with square corners and box-drawing separators, so the window reads as one continuous TUI. Tabs keep every affordance they have today: drag to reorder, tear off into a new window, rename, close, context menu and color picker. It is the recommended way to get the terminal look now that a window can hold split panes, where the indicator status line's {Tabs} item draws one tab list per pane instead of one per window. Colors keep following the OS palette and thethemesetting; optionally setui_font_familyandui_font_size, or leave them unset to inherit the default profile's font. Takes effect on the next start - Adds a drop shadow to menus, context menus and popups, so they read as floating above the terminal rather than pasted onto it. Under
ui_style: terminalit is a hard-edged offset shadow that stays on the character grid
Hyperlinks, file paths and hint mode
- Adds a tooltip naming an OSC 8 hyperlink's target when it is hovered, so it can be read before it is followed. A local file:// target is shown as a plain path. Turn it off with
hyperlink_hover_tooltip: false - Adds Ctrl-click support for opening detected local filesystem paths under the mouse cursor (#1947)
- Fixes an OSC 8
file://hyperlink failing to open when the application spelled the host name in full: programs build such a link fromgethostname(2), which reports the fully-qualified name on some machines and the short one on others, and Contour accepted only the short form — every other spelling was taken for another machine's file and handed to the desktop as a network location. The short name, the fully-qualified name,localhostand no host at all are now all recognized as this machine, whatever their case, and the host is stripped before the file is opened. A link to a file that carries no host now opens in your$EDITORlike any other, instead of being sent to the desktop - Adds a scope parameter to the HintMode action: scope: Scrollback scans the scrollback history as well as the visible page, capped by the new hint_scrollback_lines profile option (default 1000). Its labels are assigned once and stay put, so you can activate hint mode, scroll to older output, and then type the label you see; scope: Visible remains the default
- Fixes hint mode missing any URL or path that the terminal broke across two rows because the window was too narrow: patterns are now matched against the whole logical line, so such a match is one hint whose highlight follows it across the line break and which yields the complete text rather than the fragment on one row
Accessibility
- Adds accessibility support: the terminal caret is reported to the operating system, so screen magnifiers (Windows Magnifier, KDE Plasma zoom) and screen readers can follow it; with OSC 133 shell integration the live shell prompt is additionally exposed as its own focusable region
- Adds a description of the window chrome for screen readers: the tab bar reads as a tab list whose tabs announce themselves as they are switched, the window and tab buttons say what they do instead of naming their glyph, and every settings field carries its own label
- Adds screen-reader announcements for the bell, desktop notifications and read-only mode, which have no other way to be noticed. Turn them off with
accessibility_announcements: false - Adds reading the selected text aloud through the operating system's speech synthesizer, from the context menu or with Ctrl+Shift+S. Needs Qt's TextToSpeech module and an installed voice; where either is missing the feature is simply not offered
Daemon mode and remote sessions
- EXPERIMENTAL: Contour gains a daemon mode.
contour daemonhosts shell sessions in a background process so they survive the window showing them, andcontour clientconnects to it as a full Contour window whose tabs mirror the daemon's sessions live — images, hyperlinks and sized text included — starting a daemon on demand if none is running. The daemon speaks tmux's control-mode protocol in both directions, so tmux-aware tooling and the stock tmux binary can attach to it, andcontour client --tmuxattaches Contour to a real tmux server. A daemon can also be reached over the network with--listen-tcp HOST:PORT, always TLS-encrypted and requiring a preshared token. Works on Linux, macOS and Windows (10 1803+). Built in by default, but experimental: its command-line flags and wire protocol may still change between releases
Keyboard and mouse input
- Adds Win32 Input Mode (DEC private mode 9001) for native ConPTY keyboard input encoding, fixing keyboard input for applications that request this mode on Windows
- Adds
WheelLeftandWheelRightas bindable mouse buttons ininput_mapping - Smooths mouse-wheel scrolling: a wheel notch now glides to rest with inertia instead of jumping whole lines, giving the mouse wheel the same smooth feel as a touchpad. Active whenever smooth_scrolling is enabled
- Fixes mouse-wheel scrolling in alternate-screen pagers such as less, most and man: a wheel notch now scrolls them out of the box (via alternate-scroll, emitting cursor-key presses) even when the pager has not enabled a mouse protocol, matching the behavior of other terminals; DECSET ?1007 works accordingly (#1951)
- Fixes
input_mappingrejectingCtrlas a modifier name — the very spelling Contour shows in its own menus and command palette — so a binding written with it was silently discarded;ControlandCtrlare now interchangeable,Hyperis bindable at last, and the same names work inbypass_mouse_protocol_modifierandmouse_block_selection_modifier - Fixes a single-character key binding only firing when its letter was written in the same case the keyboard happened to report, which left
key: 'q'parsing cleanly and then never firing; on macOS this also revived five built-inCtrl+Altshortcuts that were dead unless CapsLock was on - Fixes an
input_mappingentry that fails to parse vanishing without a word — Contour now reports which entry was dropped and which of its fields was at fault - Fixes cursor, navigation and function keys sending a bogus modifier parameter while CapsLock or NumLock is active (for example UpArrow emitting ESC[1;65A instead of ESC[A), which broke arrow keys and F-keys in most applications, and fixes XTerm modifyOtherKeys mode 2 reporting plain keys as modified in the same situation, so applications enabling that mode (such as vim) received ESC[27;65;97~ instead of a plain a (#1954)
- Fixes Vi mode being unusable while CapsLock or NumLock is active: arrows, Home, End, PageUp and PageDown now move the cursor, the search prompt accepts typed characters again, Escape leaves visual mode, and a [count] prefix is parsed. Also fixes DECUDK user-defined keys being suppressed, hint-mode label characters leaking into the running application, and numpad digits never working as a Vi [count] prefix (#1954)
- Fixes macOS reporting where a key sits on the keyboard where the Kitty keyboard protocol asks which character that key types, so fifteen keys reached the application as an entirely different key — in any program speaking that protocol, fish among them. Ctrl+U arrived as Ctrl+Space, which fish does not bind, so it inserted a space instead of clearing the line; Ctrl+I, Ctrl+P, Ctrl+L, Ctrl+J, Ctrl+K, Ctrl+N, Ctrl+M and the bracket, semicolon, backslash, comma, period, slash and backtick keys were mistranslated the same way. The character is now taken from the keyboard layout that is actually active, so it is also right on a layout other than US ANSI
- Fixes xterm's
CSI > Pp ; Pv m(XTMODKEYS) being read with its resource number in place of its value, so an application asking formodifyOtherKeyslevel 2 selected level 4 and got nothing. Adds the matchingCSI > Ps nfor turning a resource back off - Fixes the Vi search prompt treating a Meta-modified key as if it were unmodified, so that for example Meta+Backspace deleted a character instead of being ignored
- Fixes leaving Vi visual mode with Escape also sending that Escape on to the running application
- Fixes the input-method (IME) candidate window opening at the wrong position: the reported cursor rectangle now honors the configured window margin and the pane's position inside a split, and widens over double-width (CJK) characters
Rendering, fonts and Unicode
- Improves Unicode width measurement: a grapheme cluster is measured as a whole, so ZWJ sequences, skin-tone modifiers and Indic conjuncts occupy the columns they actually need instead of being sized from their first codepoint. Following terminal-unicode-core, VS16 promotes a cluster to the emoji presentation and may widen it to two columns, while VS15 selects the text presentation without changing the width — a cluster already on screen is never narrowed. Cluster measurement is on by default and can be turned off with DEC mode 2027, which returns width measurement to the classic per-codepoint wcwidth() model
- Improves font fallback: a character no font in the chain covers is now resolved by asking which installed font actually covers it, rather than giving up at the end of the chain
- Prefers a monospaced font when falling back, rather than taking whichever font in the chain happens to come first; a proportional font is still used where no monospaced one has the character, so nothing that renders today stops rendering. The strict_spacing setting now genuinely refuses non-monospaced fallbacks, which it previously did not (#1939)
- Fixes text falling back to the wrong font, and being drawn a cell too far to the left, whenever a run contained a single character the primary font was missing. A prompt such as Claude Code's, where an ornament and a non-breaking space precede the first word, had that whole first word re-shaped in a fallback font. Only the characters the primary font genuinely lacks now fall back, and a glyph can no longer advance the cursor by zero cells (#1939)
- Fixes a font's
weight:andslant:being silently ignored unless spelled exactly one way. The names are now matched without regard to case or separator, sobold,Bold,extra_bold,extra boldandExtraBoldall work — including the CamelCase spellings thatcontour generate configitself writes, which previously did not load back. The alternate names each weight is also known by (regular,ultralight,semilight,semibold,ultrabold,ultrablack) are accepted too, and a value that still cannot be read is now reported instead of quietly leaving the default in place - Deprecates
slant: thin. It never named a slant — it reached the table as a copy of the weight list — and continues to meannormal, now with a warning - Fixes the terminal reporting a bold-italic font to the application (OSC 50) as merely italic, dropping the weight from the pattern
- Fixes curly underlines being drawn almost as tall as a lowercase letter and running into the text above them on fonts that declare line spacing, such as the default "monospace" on many Linux systems (#1754), and fixes the other underline styles sitting one row too high, on the baseline itself — the upper stroke of a double underline could be drawn inside the letters, a dotted underline came out as dashes or vanished entirely, and a double underline's strokes were a pixel too thin at even thicknesses
- Fixes combining marks vanishing from uniformly styled lines: a character written in decomposed form, such as a Greek or Cyrillic letter followed by a combining accent, was drawn as its base letter alone, because the batched rendering path those lines take can only carry one codepoint per column
- Fixes selecting text changing how wide a glyph is drawn, so that emoji and other multi-codepoint characters no longer gain padding and push the rest of the line to the right when highlighted (#1752)
- Fixes a tall glyph — a Nerd Font icon, a powerline separator — overwriting a neighbouring glyph in the texture atlas, and no longer shifts such a glyph sideways off its own bearing
- Fixes characters rendering as other characters, or shrunken and unreadable, on a pane whose size has changed a lot: the glyph cache was built once for the original size, so a window maximized from small, or a pane given most of the tab, could need more slots than it held and glyphs began overwriting each other mid-frame. The cache is now resized along with the page, and splitting no longer builds each pane's cache at the wrong size only to rebuild it immediately (#2040)
- Fixes a pane rendering blank or partially after a font, font-size or DPI change that reached it while it was not on screen — minimized, occluded, or on another tab. The pane kept shaping text with fonts it had already discarded, and the frame was dropped instead of drawn
- Fixes the status line and non-displayed pages being drawn against whichever screen was current rather than the one being rendered, which took the cursor row and the cursor colour from the wrong page
- Fixes searching for text outside Latin-1: a needle such as "Привет" or an emoji drove the case handling through functions that are undefined for those codepoints, which could silently mismatch or abort the terminal. Case is now folded per the Unicode character database, so "smart case" and case-insensitive search work for non-Latin scripts as well
- Fixes Unicode characters sometimes being wrongly decoded during high-bandwidth output
Images and graphics
- Adds the kitty graphics protocol (APC G): transmitting, displaying, placing and deleting images, in PNG or raw RGB/RGBA, including chunked transmission
- Adds the iTerm2 OSC 1337 extensions: the capabilities report and inline images
- Adds ReGIS vector graphics (DCS p), DEC's VT330/VT340 graphics language: lines, circles, arcs, interpolated curves, filled polygons, shading, text, colour registers with HLS/RGB specs, position reports, the interactive locator, and macrographs. ReGIS is now advertised in the primary Device Attributes (feature 3) and answered by XTSMGRAPHICS
- EXPERIMENTAL: Adds the Good Image Protocol (GIP) — a DCS-based protocol for displaying raster images with named image pools, LRU eviction, three compositing layers (below/replace/above), configurable resize and alignment policies, Auto/PNG/RGB/RGBA format support with automatic format detection, and DA1 capability advertisement via code 90. The new
contour catcommand displays an image file through it from the shell (#100) - Fixes Contour crashing on a sixel image whose raster attribute declares an extreme pixel aspect ratio — a 30-byte escape sequence in any file, log or command output was enough to take the terminal down, because the ratio was taken straight off the wire and made the guard against writing outside the image wrap around (#2049)
- Fixes a crash in the sixel parser caused by aspect ratio miscalculation (#1945)
- Fixes sixel images being squashed vertically on displays taller than about 1530 pixels, which is every 4K panel: an aspect ratio the screen could show perfectly well was capped to a fixed limit. The limit now follows the image canvas, so a larger screen makes full use of the range it can display, and a stated image height can no longer overshoot that canvas
Shell integration
- Adds OSC 133 prompt marks (A, C and D) to the bundled shell integration, so Contour can tell a prompt apart from a command's output. This is what makes "copy last command output" work; previously those marks were only recorded while the opt-in semantic-block protocol (DEC mode 2034) was enabled, which no shell turns on
- Adds the actions SelectAll, SoftReset (DECSTR), CopyHyperlink, and CopyLastCommandPrompt, CopyLastCommandOutput and CopyLastCommandBlock for copying the most recently finished command straight from the scrollback
- Fixes the tcsh shell integration emitting its escape sequences as literal text (tcsh's echo does not understand \e), so working-directory reporting and prompt marks never reached the terminal at all
- Fixes prompt marks being duplicated when the window is widened and dropped when it is narrowed: a marked line long enough to wrap had its mark copied onto every line the wrap produced, so jump-to-previous-mark and CopyPreviousMarkRange landed on the wrong line after a resize
New VT sequences and protocols
- Adds the kitty text sizing protocol (OSC 66): text drawn several cells tall and wide, with fractional scales and alignment within the block
- Adds the kitty pointer shape protocol (OSC 22), so an application can set, push and pop the mouse cursor shape
- Adds the kitty clipboard protocol (OSC 5522)
- Adds the ConEmu-style progress indicator (
OSC 9;4), already emitted by package managers, build tools and installers and supported by Windows Terminal, iTerm2 and Ghostty. A long-running command's progress now shows as a bar along the bottom of its tab, as the{Progress}status-line placeholder, and on the OS taskbar where there is one; error, paused and indeterminate states are distinguished. It works in daemon mode too, so a client attaching mid-operation adopts the bar already in flight. The indicator persists until the application clears it, as the sequence specifies; setprogress_timeoutto a number of milliseconds to have Contour withdraw one that stops being updated. Also fixes a bareOSC 9;4raising a desktop notification whose text was the literal "4" - Adds in-band window resize notifications (DEC mode 2048)
- Adds TERM_PROGRAM and TERM_PROGRAM_VERSION to the environment, so applications can identify the terminal without querying it
- Adds OSC 52 clipboard read, gated by an opt-in policy
- Adds the special colors (OSC 5 and OSC 105), makes the highlight colors settable, answers every color query, and parses the whole X11 colour specification grammar
- Adds the VT525 color-assignment sequences DECAC (Assign Color), DECATC (Alternate Text Color) and DECSTGLT (Select Color Look-Up Table): applications can color the GUI tab from the shell (DECAC item 2, as Windows Terminal does), set the default text colors (DECAC item 1), and — in DECSTGLT alternate-color mode — assign colors to text-attribute combinations such as bold or underline (DECATC) (#1975)
- Adds xterm's title modes (XTSMTITLE/XTRMTITLE), an icon title, a title stack, and the remaining XTWINOPS window operations
- Adds 8-bit C1 control support: S7C1T/S8C1T, 8-bit replies under S8C1T, the GR invocation register, and the GL/GR locking shifts
- Adds KAM, LNM, SRM, VPR, DECBI, DECID, DECTST, DECREQTPARM, XTCHECKSUM, and DECSET 41 (MoreFix), which makes a tab honour a pending wrap
- Adds DECSCL (Set Conformance Level, CSI Ps1;Ps2"p) — applications can change the terminal's conformance level at runtime, with C1 transmission mode (7-bit/8-bit) support
- Adds text macros (DECDMAC/DECINVM) — define macros via DCS and invoke them via CSI, with hex encoding support, delete-all, recursion guard, and deferred execution
- Adds User-Defined Keys (DECUDK) — reprogram function keys F6-F20 with custom strings via DCS, with clear/keep semantics and lock mechanism
- Adds DRCS (DECDLD) — dynamically redefinable character sets with sixel-like bitmap glyph definitions (backend storage; frontend rendering is pending)
- Adds the User-Preferred Supplemental Set: DECAUPSS assigns it, DECRQUPSS reports it back, and the SCS designator "<" designates it into a G-set
- Wires up all NRCS (National Replacement Character Sets) in SCS dispatch: British, Dutch, Finnish, French, FrenchCanadian, German, NorwegianDanish, Spanish, Swedish, Swiss across G0-G3
- Adds DEC Technical Character Set with full 94-position Unicode mapping (Greek letters, math symbols, bracket pieces, arrows)
- Adds DEC Locator mouse protocol (DECELR/DECLRP/DECSLE/DECRQLP) — the DEC alternative to xterm mouse tracking, with one-shot mode and configurable event filtering
- Closes VT level 5 conformance gap (#100): DA1 now honestly reports all implemented extensions
VT conformance and correctness fixes
- Fixes a numeric parameter of an escape sequence overflowing when the connected program sent more digits than the value could hold; such a parameter is now rejected rather than wrapping to an unrelated number
- Fixes the left and right margins (DECSLRM) being ignored by carriage return, NEL, CNL, CPL, backspace, autowrap, REP, CBT and vertical scrolling; and fixes scroll-down inside a left/right margin dropping the lines in the middle of the region
- Fixes the six rectangular-area sequences (DECCRA, DECFRA, DECERA, DECSERA, DECRQCRA, DECSACE) disagreeing on how to read their coordinates: an omitted one-based parameter was stored as zero and then decremented, addressing outside the grid
- Fixes DECRQCRA (CSI Ps * y) answering the wrong final byte and the wrong checksum, and ignoring origin mode (DECOM)
- Fixes DECCRA dropping a copy entirely when the request ended in a trailing semicolon, and running past the target page's edge
- Fixes DECALN (ESC # 8) writing outside the grid once the screen had scrolled
- Fixes a line feed below the scrolling region walking the cursor off the page, and DECSNLS (CSI Ps * |) resizing the columns instead of the lines
- Fixes REP (CSI Ps b) dropping a request that omitted its parameter
- Fixes the cursor not carrying across the alternate-screen switches DECSET 47 and 1047, and maps the 1047 alternate buffer
- Fixes a 132-column DECCOLM switch surviving a hard reset (RIS), and DECSTR (soft reset) leaving left/right margin mode (DECLRMM) set
- Fixes VT and FF not honouring linefeed mode (LNM) as LF does, DCH honouring the top/bottom margin, and ED 2 honouring the scroll region
- Fixes passive mouse tracking (DEC mode 2029) surviving a terminal reset: after RIS the mode read as off while mouse reports still carried its extra parameter, which applications cannot parse, and wheel scrolling on the alternate screen emitted nothing
- Fixes scrollback preservation for top anchored full width scroll regions
- Fixes a DCS sequence carrying intermediate bytes after its parameters being misparsed, because the parser dropped those bytes on the way out of the parameter state
- Fixes numeric capability reporting by XTGETTCAP
- Improves DECRQM, which now answers for the modes it knows but cannot change, and DECRQSS, which now reports the scroll-region margins one-based, reports DECSACE, and omits default colours from its SGR report
- Changes DECSCL to erase the screen as a real terminal does, and gates DECRQM and DECSLRM by the conformance level it selects
Stability, performance and startup
- Fixes Contour taking minutes to open on a desktop whose notification daemon is installed but not running — the case when dunst is disabled, for instance. Each terminal session asked the desktop about notifications synchronously as it was created, and with nothing there to answer, every one of them waited out D-Bus's 25-second reply timeout before any window could appear; a window with several tabs paid it once per tab. Desktop notifications are now sent without ever waiting for a reply, so an absent or wedged notification daemon costs nothing at startup, and can no longer freeze the terminal for the same 25 seconds when a program raises a notification or rings the bell. A notification daemon that starts after Contour did is now picked up too
- Fixes multi-second shell startup stall when the shell (e.g. fish) queries terminal capabilities before the display is attached — queued replies are now flushed on display attach instead of waiting for the next focus/input event
- Fixes a hang and a crash on startup when probing the audio device, for profiles that cannot ring an audible bell
- Improves PTY throughput performance determinism by rewriting the internal grid cell storage
- Fixes crashes and heap corruption when rapidly changing the font or window size, caused by data races between the UI thread and the Qt Scene Graph render thread; geometry/font changes are now deferred and applied on the render thread (#1922, probably #1712, #408)
- Fixes Contour aborting when a pane was closed or a tab switched while a frame was being drawn: closing a split pane could take the whole window down, because the drawing thread was reading the session the closing pane had just given up. A tab switch could likewise draw one frame out of two different terminals
- Fixes a crash when closing a tab, window or split pane, in the moment between the shell exiting and the session being destroyed: the thread watching for that exit was asked to stop but never waited for, and destroying it while it still ran aborted the application
- Fixes a crash on Windows when opening a new tab, window or split pane while the shell could not be started there — most visibly from a WSL or SSH session, or with a shell such as nushell. Such a spawn now retries in Contour's own directory before falling back to the login shell, and if it still cannot start, the reason is shown in the pane and the pane closes on a key press, rather than taking the whole application down
- Fixes a crash on Windows when opening a new tab or split from a pane that had reported its working directory over OSC 7 — a remote directory from an SSH session that does not exist locally, or the raw
file://URL handed to CreateProcess() instead of the extracted path. A working directory is now only inherited when it exists on the local machine - Fixes a crash, and a possible window freeze, under heavy output on Wayland: the input method's cursor-position queries were answered from the render thread without locking the grid, racing a concurrent resize or reflow
- Fixes a crash when entering Vi normal mode (Ctrl+Shift+Space) while an application was producing output, most reliably a remote tmux session over SSH. Showing the indicator status line resizes the page, and that reflowed the grid without locking it against the thread writing into it. The same lock was missing from the scroll, selection, search and paste actions
- Fixes Contour aborting when an application's font request (OSC 50) was approved after the pane it came from had gone away, or after the window had briefly lost its drawing surface — leaving the dialog open across a pane close, a tab switch or a screen change was enough. The approved font is now remembered as that session's own, so it also survives a configuration reload or a tab rebind instead of silently reverting to the profile's font
- Fixes the built-in SSH client corrupting its own connection when a key was pressed or the window resized during heavy output, which ended the session with "Decrypt failed" or "Out of boundary" and then filled the log with write errors. The connection is no longer driven from two threads at once, and a failed write ends the session instead of being retried forever. Opening two SSH sessions at the same moment also no longer races the SSH library's one-time initialization
- Fixes an error being logged on every normal shell exit: a pseudo-terminal master reports its last slave closing as EIO, which is end-of-file rather than a failure
Configuration, packaging and build
- Fixes profile settings that only took effect after a restart: changing background_image, its blur or opacity, the background color, or the scrollbar position now applies as soon as the config is reloaded or the profile is switched
- Fixes loading of optional fields in the config file (#1940)
- Fixes CMAKE_BUILD_TYPE=None builds no longer having NDEBUG force-defined, so distribution packagers get a neutral build that keeps assertions and debug symbols intact; the expensive internal terminal-state invariant checks are now gated behind the new CONTOUR_VERIFY_STATE option instead of NDEBUG (#1956)
- Fixes the statically linked Linux binary failing to build since the RHI-rendered display landed: the static Qt image now ships Qt 6.11.1, as the Qt6GuiPrivate CMake package needed for the RHI headers only exists since Qt 6.9 (#1983)
- Fixes std::simd feature test for GCC 16 compiler