From e4c9211edcf0c3fca25690ae5719896f5f8be086 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 8 Jan 2024 19:04:04 +0100 Subject: [PATCH] terminal: Use os::Timer and EventLoop::register_fd_listener --- terminal/TerminalWidget.cpp | 58 ++++++++++++++++--------------------- terminal/TerminalWidget.h | 10 +++---- terminal/main.cpp | 8 +---- 3 files changed, 30 insertions(+), 46 deletions(-) diff --git a/terminal/TerminalWidget.cpp b/terminal/TerminalWidget.cpp index e6a28f26..6058e95f 100644 --- a/terminal/TerminalWidget.cpp +++ b/terminal/TerminalWidget.cpp @@ -29,20 +29,14 @@ static constexpr auto BRIGHT_MAGENTA = ui::Color::from_u32(0xffff00ff); static constexpr auto BRIGHT_CYAN = ui::Color::from_u32(0xff00ffff); static constexpr auto BRIGHT_GRAY = ui::Color::from_u32(0xffffffff); -static long get_time_in_milliseconds() -{ - struct timespec ts; - check(clock_gettime(CLOCK_REALTIME, &ts) == 0); - - return ts.tv_sec * 1000 + ts.tv_nsec / 1000000; -} - static void sigchld_handler(int) { wait(NULL); ui::App::the().set_should_close(true); } +TerminalWidget* s_main = nullptr; + Result TerminalWidget::init(char* const* args) { m_font = ui::Font::default_font(); @@ -51,6 +45,8 @@ Result TerminalWidget::init(char* const* args) m_terminal_canvas = ui::App::the().main_window()->canvas(); m_terminal_canvas.fill(ui::BLACK); + m_cursor_timer = TRY(os::Timer::create_repeating(500, [this]() { this->tick_cursor(); })); + signal(SIGCHLD, sigchld_handler); int master; @@ -64,11 +60,18 @@ Result TerminalWidget::init(char* const* args) m_pty = master; - fcntl(master, F_SETFL, O_NONBLOCK); + fcntl(m_pty, F_SETFL, O_NONBLOCK); + + // FIXME: Find a better solution for this. What if the caller needs several TerminalWidgets in one app? We can't + // just use a singleton, can we? + os::EventLoop::the().register_fd_listener(m_pty, [](int, int) { + check(s_main); + s_main->process(); + }); m_child_pid = child; - m_last_cursor_tick = get_time_in_milliseconds(); + s_main = this; return {}; } @@ -91,7 +94,7 @@ Result TerminalWidget::draw(ui::Canvas&) return {}; } -Result TerminalWidget::process() +Result TerminalWidget::process() { char buffer[BUFSIZ]; ssize_t nread = read(m_pty, buffer, BUFSIZ); @@ -102,8 +105,6 @@ Result TerminalWidget::process() return err(errno); } - bool should_update_cursor = tick_cursor(); - ssize_t drawn = 0; for (ssize_t i = 0; i < nread; i++) @@ -112,32 +113,23 @@ Result TerminalWidget::process() if (did_draw) drawn++; } - if (should_update_cursor || drawn > 0) ui::App::the().main_window()->draw(); + if (drawn > 0) ui::App::the().main_window()->draw(); - return nread == 0; + return {}; } -bool TerminalWidget::tick_cursor() +void TerminalWidget::tick_cursor() { - if (!m_cursor_enabled) return false; + if (!m_cursor_enabled) return; - long now = get_time_in_milliseconds(); - long diff = now - m_last_cursor_tick; - m_last_cursor_tick = now; + m_cursor_timer->restart(); + m_cursor_activated = !m_cursor_activated; - m_current_cursor_timeout -= (int)diff; - if (m_current_cursor_timeout <= 0) - { - m_current_cursor_timeout = CURSOR_TIMEOUT; - m_cursor_activated = !m_cursor_activated; + if (m_cursor_activated) draw_cursor(); + else + erase_current_char(); - if (m_cursor_activated) draw_cursor(); - else - erase_current_char(); - return true; - } - - return false; + ui::App::the().main_window()->draw(); } void TerminalWidget::draw_glyph(wchar_t c, int x, int y) @@ -471,7 +463,7 @@ bool TerminalWidget::put_code_point(wchar_t c) if (should_draw_cursor) { - m_current_cursor_timeout = CURSOR_TIMEOUT; + m_cursor_timer->restart(); m_cursor_activated = true; draw_cursor(); } diff --git a/terminal/TerminalWidget.h b/terminal/TerminalWidget.h index 85a397ef..375fb74e 100644 --- a/terminal/TerminalWidget.h +++ b/terminal/TerminalWidget.h @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -16,8 +17,6 @@ class TerminalWidget : public ui::Widget Result draw(ui::Canvas& canvas) override; - Result process(); - private: ui::Canvas m_terminal_canvas; Vector m_line_buffer; @@ -29,9 +28,7 @@ class TerminalWidget : public ui::Widget SharedPtr m_font; SharedPtr m_bold_font; - static constexpr int CURSOR_TIMEOUT = 500; - - int m_current_cursor_timeout = CURSOR_TIMEOUT; + OwnedPtr m_cursor_timer; bool m_cursor_activated = false; bool m_cursor_enabled = true; @@ -45,7 +42,7 @@ class TerminalWidget : public ui::Widget ui::Color m_foreground_color { ui::WHITE }; ui::Color m_background_color { ui::BLACK }; - bool tick_cursor(); + void tick_cursor(); Utf8StateDecoder m_decoder; Option m_escape_parser; @@ -63,4 +60,5 @@ class TerminalWidget : public ui::Widget bool handle_escape_sequence(wchar_t c); Result putchar(char c); bool put_code_point(wchar_t c); + Result process(); }; diff --git a/terminal/main.cpp b/terminal/main.cpp index fa6043d2..d957565c 100644 --- a/terminal/main.cpp +++ b/terminal/main.cpp @@ -20,11 +20,5 @@ Result luna_main(int argc, char** argv) window->draw(); - while (app.process_events()) - { - bool should_sleep = TRY(terminal.process()); - if (should_sleep) usleep(10000); - } - - return 0; + return app.run(); }