Research: cosmic-term’s in-window settings drawer — implementation, libcosmic primitives, and fit for DropTerm

Date: 2026-10-03 Question: How does pop-os/cosmic-term implement its in-window settings sidebar, which libcosmic primitives back it, and how would DropTerm’s current separate settings window map onto the same approach?

TL;DR

cosmic-term has no “sidebar” widget and no second window for settings — its settings UI is a libcosmic context drawer: an iced overlay pinned to the right edge of the main window, built almost entirely by the framework. The app’s entire contribution is a ContextPage enum, a context_page field, one message (ToggleContextPage), a context_drawer() trait override returning Option<app::context_drawer::ContextDrawer> (title + content + on_close), and a core.window.show_context flip; libcosmic’s view_main does the composition, clamps the drawer to 344–480px, wraps it in a scrollable, styles it Layer::Primary / Container::ContextDrawer, and gives it a Close button. The settings content is one scrolling column of widget::settings sections — no page list, no nav bar. Every control applies instantly: a config_set! macro writes through cosmic_config-generated set_<field> methods, then update_config() re-pushes the config into every live terminal. There is no animation, no Apply/OK/Cancel, no extra window::Id; the terminal underneath is disabled and unfocused (not resized — the drawer overlays it), and Escape closes it (after one unfocus pass). Crucially, cosmic-term @ master pins the exact libcosmic rev DropTerm pins (08a09e3), so every API cited below already exists in DropTerm’s dependency tree; cosmic::widget::sidebar does not exist at that rev (or anywhere in libcosmic).

Findings

All cosmic-term citations are from a clone of pop-os/cosmic-term @ master (default branch, confirmed via git remote show origin), HEAD 3ef31d750d3b09a73f266923b0d64c5df038cf9f (2026-10-01). Its Cargo.lock pins libcosmic git+https://github.com/pop-os/libcosmic.git#08a09e3dfa1f729d52585fcedd6e731130235363 — byte-identical to DropTerm’s pinned rev (DropTerm Cargo.toml:30-33), so all libcosmic citations are from the local cargo checkout of that rev and apply verbatim to DropTerm.

1. Overall structure (Q1): ContextPage + ToggleContextPage + framework drawer

There is no src/settings.rs or src/sidebar.rs in cosmic-term, and grep -ri sidebar src/ returns zero hits. The settings UI lives in src/main.rs:

2. The widget itself (Q2): framework widget::ContextDrawer, an iced overlay — not widget::sidebar

3. Layout integration (Q3): the terminal does NOT shrink — the drawer overlays a disabled terminal

4. Navigation / sections (Q4): one scrolling column of widget::settings sections — no page list

5. Apply semantics (Q5): instant apply, per-control config_set!, then re-config every terminal

6. Animation / transition (Q6): none

7. libcosmic primitives @ 08a09e3 (Q7): the exact contract DropTerm would code against

From the local checkout of pop-os/libcosmic @ 08a09e3 (the rev both DropTerm and cosmic-term pin):

8. Window-level concerns (Q8): one window, disabled terminals, Escape closes

9. The same pattern in other first-party COSMIC apps

Fit for DropTerm

DropTerm today (verified in this repo): settings is a second window — open_settings opens a 700×760 normal window with exit_on_close_request: false, one per process (src/app.rs:1229-1246), tracked by settings_window: Option<window::Id> (src/app.rs:398); because a normal window can never stack above the layer surface, opening it hides the drop-down (“the settings window is a normal window and can never stack above the terminal’s layer surface, so opening it hides the drop-down first” — src/app.rs:1247-1253), and a close-first rule closes it whenever terminal actions re-show the surface (close_settings_if_open, src/app.rs:1194-1206). Content is settings::view(&self.config, &self.settings_buffer) (src/app.rs:2920; src/settings.rs:708), a scrollable column of per-Section cards (Section = Appearance, Geometry, Behavior, Terminal, Advanced — src/settings.rs:41-48, ALL at :54-60, keys() at :62+), instant-apply with a SettingsBuffer for in-flight drafts (src/app.rs:402; slider release vs move at src/settings.rs:793-794). Trigger is Ctrl+Shift+I (src/keybinds.rs:54-61) plus the planned context-menu item (settings-trigger.md).

What transfers directly (most of it):

What the sidebar approach deletes or changes:

Open risks: