terminal: Use os::Timer and EventLoop::register_fd_listener
This commit is contained in:
parent
6bf8225f63
commit
e4c9211edc
@ -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<void> TerminalWidget::init(char* const* args)
|
||||
{
|
||||
m_font = ui::Font::default_font();
|
||||
@ -51,6 +45,8 @@ Result<void> 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<void> 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<void> TerminalWidget::draw(ui::Canvas&)
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<bool> TerminalWidget::process()
|
||||
Result<void> TerminalWidget::process()
|
||||
{
|
||||
char buffer[BUFSIZ];
|
||||
ssize_t nread = read(m_pty, buffer, BUFSIZ);
|
||||
@ -102,8 +105,6 @@ Result<bool> 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<bool> 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_current_cursor_timeout -= (int)diff;
|
||||
if (m_current_cursor_timeout <= 0)
|
||||
{
|
||||
m_current_cursor_timeout = CURSOR_TIMEOUT;
|
||||
m_cursor_timer->restart();
|
||||
m_cursor_activated = !m_cursor_activated;
|
||||
|
||||
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();
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <luna/EscapeSequence.h>
|
||||
#include <luna/Utf8.h>
|
||||
#include <luna/Vector.h>
|
||||
#include <os/Timer.h>
|
||||
#include <stdio.h>
|
||||
#include <termios.h>
|
||||
#include <ui/Font.h>
|
||||
@ -16,8 +17,6 @@ class TerminalWidget : public ui::Widget
|
||||
|
||||
Result<void> draw(ui::Canvas& canvas) override;
|
||||
|
||||
Result<bool> process();
|
||||
|
||||
private:
|
||||
ui::Canvas m_terminal_canvas;
|
||||
Vector<u8> m_line_buffer;
|
||||
@ -29,9 +28,7 @@ class TerminalWidget : public ui::Widget
|
||||
SharedPtr<ui::Font> m_font;
|
||||
SharedPtr<ui::Font> m_bold_font;
|
||||
|
||||
static constexpr int CURSOR_TIMEOUT = 500;
|
||||
|
||||
int m_current_cursor_timeout = CURSOR_TIMEOUT;
|
||||
OwnedPtr<os::Timer> 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<EscapeSequenceParser> m_escape_parser;
|
||||
@ -63,4 +60,5 @@ class TerminalWidget : public ui::Widget
|
||||
bool handle_escape_sequence(wchar_t c);
|
||||
Result<bool> putchar(char c);
|
||||
bool put_code_point(wchar_t c);
|
||||
Result<void> process();
|
||||
};
|
||||
|
@ -20,11 +20,5 @@ Result<int> 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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user