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:
| | | | |