|
|
@@ -37,6 +37,12 @@ private:
|
|
|
std::string message_line_;
|
|
|
int height_ = 0, width_ = 0;
|
|
|
|
|
|
+ // For cursor blinking logic
|
|
|
+ bool cursor_visible_ = true;
|
|
|
+ std::chrono::steady_clock::time_point last_cursor_move_time_ = std::chrono::steady_clock::now();
|
|
|
+ static constexpr std::chrono::milliseconds BLINK_INTERVAL = std::chrono::milliseconds(500);
|
|
|
+ static constexpr std::chrono::milliseconds BLINK_STATIONARY_THRESHOLD = std::chrono::milliseconds(1000); // 1 second
|
|
|
+
|
|
|
// Private helper method declarations
|
|
|
std::string resolve_key(int ch);
|
|
|
bool handle_input(int ch);
|
|
|
@@ -91,6 +97,8 @@ void TuiEditor::run() {
|
|
|
// Initial render
|
|
|
render();
|
|
|
|
|
|
+ std::chrono::steady_clock::time_point last_blink_toggle_time = std::chrono::steady_clock::now();
|
|
|
+
|
|
|
while (!should_quit_) {
|
|
|
// Handle screen resize
|
|
|
int new_height, new_width;
|
|
|
@@ -106,6 +114,9 @@ void TuiEditor::run() {
|
|
|
core_->set_viewport_size(content_width, content_height);
|
|
|
debug_log << "Screen resized to: " << width_ << "x" << height_ << std::endl;
|
|
|
debug_log << "Content area: " << content_width << "x" << content_height << std::endl;
|
|
|
+ // Force cursor to be visible after resize, as it implies movement.
|
|
|
+ last_cursor_move_time_ = std::chrono::steady_clock::now();
|
|
|
+ cursor_visible_ = true;
|
|
|
render(); // Re-render after resize
|
|
|
}
|
|
|
|
|
|
@@ -114,8 +125,29 @@ void TuiEditor::run() {
|
|
|
|
|
|
// Only process input and render if we got actual input (not timeout)
|
|
|
if (ch != ERR) {
|
|
|
+ last_cursor_move_time_ = std::chrono::steady_clock::now();
|
|
|
+ cursor_visible_ = true; // Ensure cursor is visible on input
|
|
|
handle_input(ch);
|
|
|
render();
|
|
|
+ last_blink_toggle_time = std::chrono::steady_clock::now(); // Reset blink timer after input
|
|
|
+ } else { // No input (timeout occurred)
|
|
|
+ auto now = std::chrono::steady_clock::now();
|
|
|
+ if (now - last_cursor_move_time_ > BLINK_STATIONARY_THRESHOLD) {
|
|
|
+ // If stationary for long enough, start/continue blinking
|
|
|
+ if (now - last_blink_toggle_time > BLINK_INTERVAL) {
|
|
|
+ cursor_visible_ = !cursor_visible_;
|
|
|
+ core_->check_and_clear_message(); // Check and clear messages (like for GtkEditor's blink)
|
|
|
+ render(); // Re-render to show/hide cursor
|
|
|
+ last_blink_toggle_time = now;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // Still "moving" recently, keep cursor visible.
|
|
|
+ // If it was just hidden by a blink, make it visible again.
|
|
|
+ if (!cursor_visible_) {
|
|
|
+ cursor_visible_ = true;
|
|
|
+ render(); // Make sure it's visible
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -125,6 +157,13 @@ void TuiEditor::handle_editor_event(EditorEvent event) {
|
|
|
should_quit_ = true;
|
|
|
} else if (event == EditorEvent::Message) {
|
|
|
message_line_ = core_->last_message(); // Still update local message_line_ for rendering
|
|
|
+ } else if (event == EditorEvent::CursorMoved) {
|
|
|
+ last_cursor_move_time_ = std::chrono::steady_clock::now();
|
|
|
+ cursor_visible_ = true;
|
|
|
+ render(); // Ensure immediate redraw to show cursor at new position
|
|
|
+ } else if (event == EditorEvent::TransientMessageCleared) {
|
|
|
+ // Redraw to clear the message from the screen
|
|
|
+ render();
|
|
|
} else if (event == EditorEvent::CommandMode) {
|
|
|
core_->minibuffer_manager().activate_minibuffer(
|
|
|
MinibufferMode::Command, ":",
|
|
|
@@ -135,7 +174,7 @@ void TuiEditor::handle_editor_event(EditorEvent event) {
|
|
|
auto result = core_->minibuffer_manager().parse_and_execute_command_string(input);
|
|
|
core_->set_message(result.message);
|
|
|
}
|
|
|
- },
|
|
|
+ }, // Added comma here
|
|
|
[this]() { core_->set_message("Cancelled"); }
|
|
|
);
|
|
|
} else if (event == EditorEvent::BufferSwitchMode) {
|
|
|
@@ -189,7 +228,7 @@ void TuiEditor::handle_editor_event(EditorEvent event) {
|
|
|
} else {
|
|
|
core_->set_message("Theme not found: " + input);
|
|
|
}
|
|
|
- },
|
|
|
+ }, // Added comma here
|
|
|
[this]() { core_->set_message("Cancelled"); }
|
|
|
);
|
|
|
} else if (event == EditorEvent::ISearchMode) {
|
|
|
@@ -513,7 +552,7 @@ void TuiEditor::render_window(std::shared_ptr<Window> window, int x, int y, int
|
|
|
}
|
|
|
|
|
|
// Show cursor if this is the cursor line and this is the active window
|
|
|
- if (buffer_line_idx == cursor.line && is_active) {
|
|
|
+ if (buffer_line_idx == cursor.line && is_active && cursor_visible_) {
|
|
|
int cursor_screen_x = x + line_number_width + cursor.column;
|
|
|
if (cursor_screen_x < x + width) {
|
|
|
char cursor_char = ' ';
|