diff --git a/metainfo.xml b/metainfo.xml index bd46707524..f01ad8133a 100644 --- a/metainfo.xml +++ b/metainfo.xml @@ -129,6 +129,8 @@
  • Removes the ability to inline colorschemes within a configuration profile. Colorschemes must now always be referenced by their name.
  • Adds the ability to chose a color scheme based on the operating systems's dark/light mode setting. This will change live whenever the OS's dark/light mode setting changes as well (#604).
  • Adds VT sequence DECSSCLS (change scroll speed) and properly handle DECSCLM (enable slow scrolling mode) (#1204)
  • +
  • Adds VT sequence parameter ?996 to DSR to report the current color scheme dark/light mode hint.
  • +
  • Adds VT sequence `SM ?2031` and `RM ?2031` to enable/disable unsolicited DSR for color scheme updates by the user or OS.
  • Adds percentage value to Indicator Statusline to indicate scroll offset in scrollback buffer.
  • Adds inheritance of profiles in configuration file based on default profile (#1063).
  • Adds config option `profile.*.bell` to adjust BEL behavior and fixes (#1162) and (#1163).
  • diff --git a/src/vtbackend/Screen.cpp b/src/vtbackend/Screen.cpp index 689e17ea47..7a8d334e14 100644 --- a/src/vtbackend/Screen.cpp +++ b/src/vtbackend/Screen.cpp @@ -78,6 +78,9 @@ using std::vector; namespace vtbackend { +auto constexpr inline ColorPaletteUpdateDsrRequestId = 995; +auto constexpr inline ColorPaletteUpdateDsrReplyId = 996; + auto constexpr inline TabWidth = ColumnCount(8); auto const inline vtCaptureBufferLog = logstore::category("vt.ext.capturebuffer", @@ -92,6 +95,11 @@ auto const inline vtCaptureBufferLog = logstore::category("vt.ext.capturebuffer" namespace // {{{ helper { + constexpr bool isLightColor(RGBColor color) noexcept + { + return ((5 * color.green) + (2 * color.red) + color.blue) > 8 * 128; + } + template inline void sleep_for(std::chrono::duration const& rtime) { @@ -877,6 +885,19 @@ void Screen::reportCursorPosition() _terminal->reply("\033[{};{}R", logicalCursorPosition().line + 1, logicalCursorPosition().column + 1); } +template +CRISPY_REQUIRES(CellConcept) +void Screen::reportColorPaletteUpdate() +{ + auto constexpr DarkModeHint = 1; + auto constexpr LightModeHint = 2; + + auto const modeHint = isLightColor(_state->colorPalette.defaultForeground) ? DarkModeHint : LightModeHint; + + _terminal->reply("\033[?{};{}n", ColorPaletteUpdateDsrReplyId, modeHint); + _terminal->flushInput(); +} + template CRISPY_REQUIRES(CellConcept) void Screen::reportExtendedCursorPosition() @@ -2800,6 +2821,9 @@ namespace impl { switch (seq.param(0)) { + case ColorPaletteUpdateDsrRequestId: + screen.reportColorPaletteUpdate(); + return ApplyResult::Ok; default: return ApplyResult::Unsupported; } } diff --git a/src/vtbackend/Screen.h b/src/vtbackend/Screen.h index 314b499545..0dfd352d9f 100644 --- a/src/vtbackend/Screen.h +++ b/src/vtbackend/Screen.h @@ -50,6 +50,7 @@ class ScreenBase: public SequenceHandler void resetSavedCursorState() { _savedCursor = {}; } virtual void saveCursor() = 0; virtual void restoreCursor() = 0; + virtual void reportColorPaletteUpdate() = 0; [[nodiscard]] virtual Margin margin() const noexcept = 0; [[nodiscard]] virtual Margin& margin() noexcept = 0; @@ -220,6 +221,7 @@ class Screen final: public ScreenBase, public capabilities::StaticDatabase void deviceStatusReport(); // DSR void reportCursorPosition(); // CPR void reportExtendedCursorPosition(); // DECXCPR + void reportColorPaletteUpdate() override; void selectConformanceLevel(VTType level); void requestDynamicColor(DynamicColorName name); void requestCapability(capabilities::Code code); diff --git a/src/vtbackend/Terminal.cpp b/src/vtbackend/Terminal.cpp index 72030d6923..ab2426934c 100644 --- a/src/vtbackend/Terminal.cpp +++ b/src/vtbackend/Terminal.cpp @@ -2195,6 +2195,9 @@ void Terminal::resetColorPalette(ColorPalette const& colors) _state.defaultColorPalette = colors; _settings.colorPalette = colors; _factorySettings.colorPalette = colors; + + if (isModeEnabled(DECMode::ReportColorPaletteUpdated)) + _currentScreen.get().reportColorPaletteUpdate(); } void Terminal::pushColorPalette(size_t slot) diff --git a/src/vtbackend/TerminalState.cpp b/src/vtbackend/TerminalState.cpp index a5c42446c1..1fe54b749e 100644 --- a/src/vtbackend/TerminalState.cpp +++ b/src/vtbackend/TerminalState.cpp @@ -81,6 +81,7 @@ std::string to_string(DECMode mode) case DECMode::Unicode: return "Unicode"; case DECMode::TextReflow: return "TextReflow"; case DECMode::SixelCursorNextToGraphic: return "SixelCursorNextToGraphic"; + case DECMode::ReportColorPaletteUpdated: return "ReportColorPaletteUpdated"; } return fmt::format("({})", static_cast(mode)); } diff --git a/src/vtbackend/primitives.h b/src/vtbackend/primitives.h index 564b00ea3d..5fba012051 100644 --- a/src/vtbackend/primitives.h +++ b/src/vtbackend/primitives.h @@ -686,6 +686,10 @@ enum class DECMode // intersecting with the main page area. ReportGridCellSelection = 2030, + // If enabled, the terminal will report color palette changes to the application, + // if modified by the user or operating system (e.g. dark/light mode adaption). + ReportColorPaletteUpdated = 2031, + // If enabled (default, as per spec), then the cursor is left next to the graphic, // that is, the text cursor is placed at the position of the sixel cursor. // If disabled otherwise, the cursor is placed below the image, as if CR LF was sent, @@ -791,6 +795,7 @@ constexpr unsigned toDECModeNum(DECMode m) case DECMode::MouseAlternateScroll: return 1007; case DECMode::MousePassiveTracking: return 2029; case DECMode::ReportGridCellSelection: return 2030; + case DECMode::ReportColorPaletteUpdated: return 2031; case DECMode::BatchedRendering: return 2026; case DECMode::Unicode: return 2027; case DECMode::TextReflow: return 2028; @@ -837,6 +842,7 @@ constexpr bool isValidDECMode(unsigned int mode) noexcept case DECMode::MouseAlternateScroll: case DECMode::MousePassiveTracking: case DECMode::ReportGridCellSelection: + case DECMode::ReportColorPaletteUpdated: case DECMode::BatchedRendering: case DECMode::Unicode: case DECMode::TextReflow: