Host settings as a tab and match the Windows Terminal settings UI - #5
Merged
Marc-André Moreau (mamoreau-devolutions) merged 2 commits intoSep 5, 2026
Conversation
Windows Terminal shows its settings as a tab inside the main window, and our settings editor was a separate window with a noticeably different look. Move the editor into a tab and align its visuals with the real thing. Extract the editor into a SettingsView UserControl so it can be hosted anywhere; SettingsWindow now wraps that same view. TerminalTab gains CustomContent (and the IsSettingsTab predicate) so a tab can host non-terminal content, and OpenSettingsTab creates or focuses the single settings tab. The settings tab carries a placeholder pane, so guard the terminal-only paths that would otherwise act on it: ActiveControl returns null there (disabling the control-scope actions), and paste, duplicate, tear-off, restore-last-closed, movePane, layout capture and new-tab sizing all skip it. Without these, tearing off or duplicating the settings tab spawned a bogus PowerShell session, and Ctrl+V was swallowed before reaching the settings text boxes. Visuals are measured against a maximized Windows Terminal capture: page/nav #282828 with #333333 borderless cards, 320px nav, 62px rows with 6px gaps, cards spanning the same x range, a hamburger, profiles listed in the nav, and a footer with Open JSON file on the left plus an accent Save and Discard changes on the right. Enum-ish settings become combo boxes and every toggle row shows its On/Off state through the new SettingsToggle control. AddProfile now commits pending JSON editor buffers first instead of silently discarding unsaved Actions, keybindings and environment edits. The headless UI test application loads FluentTheme so real control templates apply.
An activation that closes the final tab also closes the window, and ActivateAsync then called Show() on it, throwing "Cannot re-show a closed window". Track the closed state and skip the show/activate step. This surfaced on Linux and macOS CI, where the placeholder terminal tab fails to launch, so the settings tab is the only tab and closing it closes the window. Assert the reopen-stack invariant through the tab collection instead of a second activation, and cover the closed-window path with a regression test.
Marc-André Moreau (mamoreau-devolutions)
merged commit Sep 5, 2026
b273dc1
into
master
24 checks passed
Marc-André Moreau (mamoreau-devolutions)
deleted the
copilot/settings-ui-avalonia-devtools-review
branch
September 5, 2026 22:13
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Windows Terminal shows its settings as a tab inside the main window; ours opened a separate window that also looked noticeably different. This moves the editor into a tab and aligns the visuals with the real thing.
Window#0C0C0C(terminal black)#282828#333333with a bright#3D3D3Dborder, 68px tall, 4px gaps#333333, 62px tall, 6px gapsHow it works
SettingsView(newUserControl) holds the whole editor;SettingsWindownow wraps that same view, so the standalone entry point still works.TerminalTabgainsCustomContent(plus anIsSettingsTabpredicate) so a tab can host non-terminal content, andMainWindow.OpenSettingsTab()creates or focuses the single settings tab.Settings-tab guards
The settings tab carries a placeholder pane, so terminal-only paths are guarded. Two of these were user-visible bugs:
Ctrl+Vwas consumed by the window-level key handler and then dropped, so paste was dead in every settings text box.Also guarded: restore-last-closed (the settings tab is no longer remembered),
movePane, layout capture, and new-tab sizing.ActiveControlreturnsnullon the settings tab, which disables the ~30 control-scope actions in one place.Separately,
AddProfilenow commits pending JSON editor buffers first instead of silently discarding unsaved Actions/keybindings/environment edits.Visual parity
Metrics were measured pixel-by-pixel against a maximized Windows Terminal capture (window 1113px wide):
One deliberate difference: WT's capture uses grayscale text antialiasing while we render with subpixel AA, so glyph edges show faint colour fringing. That's a font-rendering mode, invisible at normal viewing distance, so text rendering was left alone.
Testing
dotnet test Devolutions.Terminal.slnx— 13 projects, 825 tests, 0 failuresSettingsTogglestate/binding round-trip, andAddProfilepreserving vs. rejecting JSON editsFluentThemeso real control templates applyCtrl+Vpastes in settings and still pastes in the terminal