Compare commits

..

2 Commits

Author SHA1 Message Date
Bananymous 18e7cf2069 Terminal: Add cursor rendering
Cursor is now shown at the current position. It can be hidden (or shown)
with the ansi `\033[?25h` or `\033[?25l`
2024-08-12 00:50:06 +03:00
Bananymous 60b4d90608 LibGUI: Add Window::get_pixel()
This is fine as its not reading from video memory
2024-08-12 00:49:35 +03:00
3 changed files with 61 additions and 1 deletions

View File

@ -112,6 +112,13 @@ namespace LibGUI
m_framebuffer[y * m_width + x] = color;
}
uint32_t get_pixel(uint32_t x, uint32_t y) const
{
ASSERT(x < m_width);
ASSERT(y < m_height);
return m_framebuffer[y * m_width + x];
}
void fill_rect(int32_t x, int32_t y, uint32_t width, uint32_t height, uint32_t color);
void fill(uint32_t color) { return fill_rect(0, 0, width(), height(), color); }

View File

@ -91,6 +91,9 @@ void Terminal::run()
m_font = MUST(LibFont::Font::load("/usr/share/fonts/lat0-16.psfu"_sv));
MUST(m_cursor_buffer.resize(m_font.width() * m_font.height(), m_bg_color));
show_cursor();
m_window->set_key_event_callback([&](LibGUI::EventPacket::KeyEvent event) { on_key_event(event); });
const int max_fd = BAN::Math::max(m_shell_info.pts_master, m_window->server_fd());
@ -111,9 +114,36 @@ void Terminal::run()
}
}
void Terminal::hide_cursor()
{
const uint32_t cursor_base_x = m_cursor.x * m_font.width();
const uint32_t cursor_base_y = m_cursor.y * m_font.height();
for (uint32_t y = 0; y < m_font.height(); y++)
for (uint32_t x = 0; x < m_font.width(); x++)
m_window->set_pixel(cursor_base_x + x, cursor_base_y + y, m_cursor_buffer[y * m_font.width() + x]);
m_window->invalidate(cursor_base_x, cursor_base_y, m_font.width(), m_font.height());
}
void Terminal::show_cursor()
{
const uint32_t cursor_base_x = m_cursor.x * m_font.width();
const uint32_t cursor_base_y = m_cursor.y * m_font.height();
for (uint32_t y = 0; y < m_font.height(); y++)
for (uint32_t x = 0; x < m_font.width(); x++)
m_cursor_buffer[y * m_font.width() + x] = m_window->get_pixel(cursor_base_x + x, cursor_base_y + y);
if (m_cursor_shown)
{
for (uint32_t y = m_font.height() * 13 / 16; y < m_font.height() - 1; y++)
for (uint32_t x = 0; x < m_font.width(); x++)
m_window->set_pixel(cursor_base_x + x, cursor_base_y + y, 0xFFFFFFFF);
m_window->invalidate(cursor_base_x, cursor_base_y, m_font.width(), m_font.height());
}
}
bool Terminal::read_shell()
{
hide_cursor();
char buffer[128];
ssize_t nread = read(m_shell_info.pts_master, buffer, sizeof(buffer) - 1);
if (nread < 0)
@ -122,6 +152,9 @@ bool Terminal::read_shell()
return false;
for (ssize_t i = 0; i < nread; i++)
putchar(buffer[i]);
show_cursor();
return true;
}
@ -182,7 +215,10 @@ void Terminal::handle_csi(char ch)
}
if (ch == '?')
{
m_csi_info.question = true;
return;
}
if (isdigit(ch))
{
@ -282,6 +318,15 @@ void Terminal::handle_csi(char ch)
case 'u':
m_cursor = m_saved_cursor;
break;
case 'h':
case 'l':
if (!m_csi_info.question || m_csi_info.fields[0] != 25)
{
dprintln("invalid ANSI CSI ?{}{}", m_csi_info.fields[0], (char)ch);
break;
}
m_cursor_shown = (ch == 'h');
break;
default:
dprintln("TODO: CSI {}", ch);
break;
@ -303,6 +348,7 @@ void Terminal::putchar(uint8_t ch)
m_csi_info.index = 0;
m_csi_info.fields[0] = -1;
m_csi_info.fields[1] = -1;
m_csi_info.question = false;
return;
}

View File

@ -18,6 +18,9 @@ private:
void putchar(uint8_t ch);
bool read_shell();
void hide_cursor();
void show_cursor();
void on_key_event(LibGUI::EventPacket::KeyEvent);
void start_shell();
@ -46,16 +49,20 @@ private:
{
int32_t fields[2];
size_t index;
bool question;
};
private:
BAN::UniqPtr<LibGUI::Window> m_window;
LibFont::Font m_font;
Cursor m_cursor { 0, 0 };
ShellInfo m_shell_info;
State m_state { State::Normal };
CSIInfo m_csi_info;
bool m_cursor_shown { true };
Cursor m_cursor { 0, 0 };
BAN::Vector<uint32_t> m_cursor_buffer;
uint8_t m_utf8_index { 0 };
uint8_t m_utf8_bytes[4] { };