| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172 |
- #pragma once
- #include <chrono>
- namespace lumacs {
- /// @brief Shared cursor blinking logic for both GTK and TUI frontends.
- ///
- /// This utility encapsulates the cursor blinking algorithm:
- /// - Cursor is always visible for a threshold period after movement
- /// - After the threshold, cursor blinks on/off at a fixed interval
- class CursorBlinkController {
- public:
- /// Default blink interval (500ms on, 500ms off)
- static constexpr std::chrono::milliseconds BLINK_INTERVAL{500};
- /// Time cursor stays visible after movement before blinking starts
- static constexpr std::chrono::milliseconds STATIONARY_THRESHOLD{1000};
- CursorBlinkController() = default;
- /// @brief Notify the controller that the cursor has moved.
- /// This resets the blink timer and makes the cursor visible.
- void notify_cursor_moved() {
- last_move_time_ = std::chrono::steady_clock::now();
- visible_ = true;
- }
- /// @brief Update the blink state based on elapsed time.
- /// @return true if the visibility state changed (requires redraw)
- bool update() {
- auto now = std::chrono::steady_clock::now();
- auto since_move = std::chrono::duration_cast<std::chrono::milliseconds>(
- now - last_move_time_);
- // Cursor stays visible during stationary threshold
- if (since_move < STATIONARY_THRESHOLD) {
- if (!visible_) {
- visible_ = true;
- return true; // State changed
- }
- return false;
- }
- // After threshold, blink based on interval
- auto blink_phase = std::chrono::duration_cast<std::chrono::milliseconds>(
- now - last_move_time_ - STATIONARY_THRESHOLD);
- bool should_be_visible = (blink_phase.count() / BLINK_INTERVAL.count()) % 2 == 0;
- if (visible_ != should_be_visible) {
- visible_ = should_be_visible;
- return true; // State changed
- }
- return false;
- }
- /// @brief Check if the cursor should currently be visible.
- [[nodiscard]] bool is_visible() const { return visible_; }
- /// @brief Force cursor to be visible (useful for input events).
- void force_visible() {
- visible_ = true;
- last_move_time_ = std::chrono::steady_clock::now();
- }
- private:
- std::chrono::steady_clock::time_point last_move_time_ = std::chrono::steady_clock::now();
- bool visible_ = true;
- };
- } // namespace lumacs
|