|
35 | 35 | #include <atomic> |
36 | 36 | #include <bitset> |
37 | 37 | #include <chrono> |
| 38 | +#include <cmath> |
38 | 39 | #include <condition_variable> |
39 | 40 | #include <deque> |
40 | 41 | #include <format> |
41 | 42 | #include <functional> |
42 | 43 | #include <memory> |
43 | 44 | #include <mutex> |
| 45 | +#include <numbers> |
44 | 46 | #include <stack> |
45 | 47 | #include <string_view> |
46 | 48 | #include <utility> |
@@ -735,8 +737,11 @@ class Terminal |
735 | 737 | } |
736 | 738 |
|
737 | 739 | bool isHighlighted(CellLocation cell) const noexcept; |
738 | | - bool blinkState() const noexcept { return _slowBlinker.state; } |
739 | | - bool rapidBlinkState() const noexcept { return _rapidBlinker.state; } |
| 740 | + float blinkState() const noexcept { return _slowBlinker.opacity(_currentTime, _settings.blinkStyle); } |
| 741 | + float rapidBlinkState() const noexcept |
| 742 | + { |
| 743 | + return _rapidBlinker.opacity(_currentTime, _settings.blinkStyle); |
| 744 | + } |
740 | 745 |
|
741 | 746 | /// Sets or resets to a new selection. |
742 | 747 | void setSelector(std::unique_ptr<Selection> selector); |
@@ -1047,16 +1052,6 @@ class Terminal |
1047 | 1052 | && _inputHandler.mode() == ViMode::Insert; |
1048 | 1053 | } |
1049 | 1054 |
|
1050 | | - template <typename BlinkerState> |
1051 | | - [[nodiscard]] std::pair<bool, std::chrono::steady_clock::time_point> nextBlinkState( |
1052 | | - BlinkerState blinker, std::chrono::steady_clock::time_point lastBlink) const noexcept |
1053 | | - { |
1054 | | - auto const passed = std::chrono::duration_cast<std::chrono::milliseconds>(_currentTime - lastBlink); |
1055 | | - if (passed < blinker.interval) |
1056 | | - return { blinker.state, lastBlink }; |
1057 | | - return { !blinker.state, _currentTime }; |
1058 | | - } |
1059 | | - |
1060 | 1055 | // Reads from PTY. |
1061 | 1056 | struct PtyReadResult |
1062 | 1057 | { |
@@ -1104,15 +1099,42 @@ class Terminal |
1104 | 1099 | // {{{ blinking state helpers |
1105 | 1100 | mutable std::chrono::steady_clock::time_point _lastCursorBlink; |
1106 | 1101 | mutable unsigned _cursorBlinkState = 1; |
| 1102 | + |
| 1103 | + /// Computes blink opacity based on the configured BlinkStyle. |
1107 | 1104 | struct BlinkerState |
1108 | 1105 | { |
1109 | | - bool state = false; |
1110 | | - std::chrono::milliseconds interval {}; |
| 1106 | + std::chrono::milliseconds period {}; |
| 1107 | + |
| 1108 | + /// Returns opacity in [0, 1] based on the given blink style. |
| 1109 | + [[nodiscard]] float opacity(std::chrono::steady_clock::time_point now, |
| 1110 | + BlinkStyle style) const noexcept |
| 1111 | + { |
| 1112 | + auto const elapsed = std::chrono::duration<float>(now.time_since_epoch()); |
| 1113 | + auto const p = std::chrono::duration<float>(period); |
| 1114 | + auto const smooth = |
| 1115 | + (1.0f + std::cos(2.0f * std::numbers::pi_v<float> * elapsed.count() / p.count())) / 2.0f; |
| 1116 | + switch (style) |
| 1117 | + { |
| 1118 | + case BlinkStyle::Classic: return smooth >= 0.5f ? 1.0f : 0.0f; |
| 1119 | + case BlinkStyle::Smooth: return smooth; |
| 1120 | + case BlinkStyle::Linger: return std::pow(smooth, 1.0f / 3.0f); |
| 1121 | + } |
| 1122 | + return smooth; |
| 1123 | + } |
| 1124 | + |
| 1125 | + /// Returns the time until the next classic toggle transition. |
| 1126 | + [[nodiscard]] std::chrono::milliseconds nextToggleIn( |
| 1127 | + std::chrono::steady_clock::time_point now) const noexcept |
| 1128 | + { |
| 1129 | + using namespace std::chrono; |
| 1130 | + auto const elapsed = duration_cast<milliseconds>(now.time_since_epoch()); |
| 1131 | + auto const halfPeriod = period / 2; |
| 1132 | + auto const inPeriod = elapsed % period; |
| 1133 | + return (inPeriod < halfPeriod) ? (halfPeriod - inPeriod) : (period - inPeriod); |
| 1134 | + } |
1111 | 1135 | }; |
1112 | | - mutable BlinkerState _slowBlinker { .state = false, .interval = std::chrono::milliseconds { 500 } }; |
1113 | | - mutable BlinkerState _rapidBlinker { .state = false, .interval = std::chrono::milliseconds { 300 } }; |
1114 | | - mutable std::chrono::steady_clock::time_point _lastBlink; |
1115 | | - mutable std::chrono::steady_clock::time_point _lastRapidBlink; |
| 1136 | + BlinkerState _slowBlinker { .period = std::chrono::milliseconds { 1000 } }; |
| 1137 | + BlinkerState _rapidBlinker { .period = std::chrono::milliseconds { 600 } }; |
1116 | 1138 | // }}} |
1117 | 1139 |
|
1118 | 1140 | // {{{ Displays this terminal manages |
|
0 commit comments