Kernel: Move cursor handling from TTY -> TerminalDriver
This commit is contained in:
parent
c0942d78cb
commit
40d1d20cd6
|
@ -11,29 +11,38 @@ namespace Kernel
|
|||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<FramebufferTerminalDriver>> create(BAN::RefPtr<FramebufferDevice>);
|
||||
|
||||
virtual uint32_t width() const override { return m_framebuffer_device->width() / m_font.width(); }
|
||||
virtual uint32_t height() const override { return m_framebuffer_device->height() / m_font.height(); }
|
||||
uint32_t width() const override { return m_framebuffer_device->width() / m_font.width(); }
|
||||
uint32_t height() const override { return m_framebuffer_device->height() / m_font.height(); }
|
||||
|
||||
virtual void putchar_at(uint16_t, uint32_t, uint32_t, Color, Color) override;
|
||||
virtual bool scroll(Color) override;
|
||||
virtual void clear(Color) override;
|
||||
void putchar_at(uint16_t, uint32_t, uint32_t, Color, Color) override;
|
||||
bool scroll(Color) override;
|
||||
void clear(Color) override;
|
||||
|
||||
virtual void set_cursor_position(uint32_t, uint32_t) override;
|
||||
void set_cursor_shown(bool) override;
|
||||
void set_cursor_position(uint32_t, uint32_t) override;
|
||||
|
||||
virtual bool has_font() const override { return true; }
|
||||
bool has_font() const override { return true; }
|
||||
|
||||
virtual void set_font(LibFont::Font&& font) override { m_font = BAN::move(font); };
|
||||
virtual const LibFont::Font& font() const override { return m_font; };
|
||||
BAN::ErrorOr<void> set_font(LibFont::Font&& font) override;
|
||||
const LibFont::Font& font() const override { return m_font; };
|
||||
|
||||
private:
|
||||
FramebufferTerminalDriver(BAN::RefPtr<FramebufferDevice> framebuffer_device)
|
||||
: m_framebuffer_device(framebuffer_device)
|
||||
{ }
|
||||
|
||||
void read_cursor();
|
||||
void show_cursor(bool use_data);
|
||||
|
||||
private:
|
||||
BAN::RefPtr<FramebufferDevice> m_framebuffer_device;
|
||||
LibFont::Font m_font;
|
||||
static constexpr Color s_cursor_color = TerminalColor::BRIGHT_WHITE;
|
||||
|
||||
uint32_t m_cursor_x { 0 };
|
||||
uint32_t m_cursor_y { 0 };
|
||||
bool m_cursor_shown { true };
|
||||
BAN::Vector<uint32_t> m_cursor_data;
|
||||
static constexpr Color m_cursor_color = TerminalColor::BRIGHT_WHITE;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace Kernel
|
|||
virtual bool scroll(Color) { return false; }
|
||||
virtual void clear(Color) = 0;
|
||||
|
||||
virtual void set_cursor_shown(bool) = 0;
|
||||
virtual void set_cursor_position(uint32_t, uint32_t) = 0;
|
||||
|
||||
virtual bool has_font() const { return false; }
|
||||
|
|
|
@ -34,7 +34,6 @@ namespace Kernel
|
|||
void putcodepoint(uint32_t codepoint);
|
||||
void putchar_at(uint32_t codepoint, uint32_t x, uint32_t y);
|
||||
void render_from_buffer(uint32_t x, uint32_t y);
|
||||
void set_cursor_position(uint32_t x, uint32_t y);
|
||||
|
||||
private:
|
||||
enum class State
|
||||
|
@ -82,7 +81,6 @@ namespace Kernel
|
|||
uint32_t m_row { 0 };
|
||||
uint32_t m_column { 0 };
|
||||
Cell* m_buffer { nullptr };
|
||||
bool m_show_cursor { true };
|
||||
|
||||
BAN::RefPtr<TerminalDriver> m_terminal_driver;
|
||||
};
|
||||
|
|
|
@ -5,15 +5,14 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<BAN::RefPtr<FramebufferTerminalDriver>> FramebufferTerminalDriver::create(BAN::RefPtr<FramebufferDevice> framebuffer_device)
|
||||
{
|
||||
auto font = TRY(LibFont::Font::prefs());;
|
||||
|
||||
auto* driver = new FramebufferTerminalDriver(framebuffer_device);
|
||||
if (driver == nullptr)
|
||||
auto* driver_ptr = new FramebufferTerminalDriver(framebuffer_device);
|
||||
if (driver_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
driver->m_font = BAN::move(font);
|
||||
auto driver = BAN::RefPtr<FramebufferTerminalDriver>::adopt(driver_ptr);
|
||||
TRY(driver->set_font(BAN::move(TRY(LibFont::Font::prefs()))));
|
||||
driver->set_cursor_position(0, 0);
|
||||
driver->clear(TerminalColor::BLACK);
|
||||
return BAN::RefPtr<FramebufferTerminalDriver>::adopt(driver);
|
||||
return driver;
|
||||
}
|
||||
|
||||
void FramebufferTerminalDriver::putchar_at(uint16_t ch, uint32_t x, uint32_t y, Color fg, Color bg)
|
||||
|
@ -34,6 +33,12 @@ namespace Kernel
|
|||
}
|
||||
|
||||
m_framebuffer_device->sync_pixels_rectangle(x, y, m_font.width(), m_font.height());
|
||||
|
||||
if (x == m_cursor_x && y == m_cursor_y)
|
||||
{
|
||||
read_cursor();
|
||||
show_cursor(false);
|
||||
}
|
||||
}
|
||||
|
||||
bool FramebufferTerminalDriver::scroll(Color color)
|
||||
|
@ -45,24 +50,96 @@ namespace Kernel
|
|||
|
||||
void FramebufferTerminalDriver::clear(Color color)
|
||||
{
|
||||
for (auto& pixel : m_cursor_data)
|
||||
pixel = color.rgb;
|
||||
|
||||
for (uint32_t y = 0; y < m_framebuffer_device->height(); y++)
|
||||
for (uint32_t x = 0; x < m_framebuffer_device->width(); x++)
|
||||
m_framebuffer_device->set_pixel(x, y, color.rgb);
|
||||
m_framebuffer_device->sync_pixels_full();
|
||||
}
|
||||
|
||||
void FramebufferTerminalDriver::set_cursor_position(uint32_t x, uint32_t y)
|
||||
void FramebufferTerminalDriver::read_cursor()
|
||||
{
|
||||
const uint32_t cursor_h = m_font.height() / 8;
|
||||
const uint32_t cursor_top = m_font.height() * 13 / 16;
|
||||
|
||||
x *= m_font.width();
|
||||
y *= m_font.height();
|
||||
const uint32_t x = m_cursor_x * m_font.width();
|
||||
const uint32_t y = m_cursor_y * m_font.height();
|
||||
|
||||
for (uint32_t dy = 0; dy < cursor_h; dy++)
|
||||
for (uint32_t dx = 0; dx < m_font.width(); dx++)
|
||||
m_framebuffer_device->set_pixel(x + dx, y + cursor_top + dy, s_cursor_color.rgb);
|
||||
m_framebuffer_device->sync_pixels_rectangle(x, y + cursor_top, m_font.width(), cursor_h);
|
||||
m_cursor_data[dy * m_font.width() + dx] = m_framebuffer_device->get_pixel(x + dx, y + cursor_top + dy);
|
||||
}
|
||||
|
||||
void FramebufferTerminalDriver::show_cursor(bool use_data)
|
||||
{
|
||||
const auto get_color =
|
||||
[this, use_data](uint32_t x, uint32_t y) -> uint32_t
|
||||
{
|
||||
if (!use_data)
|
||||
return m_cursor_color.rgb;
|
||||
return m_cursor_data[y * m_font.width() + x];
|
||||
};
|
||||
|
||||
const uint32_t cursor_h = m_font.height() / 8;
|
||||
const uint32_t cursor_w = m_font.width();
|
||||
const uint32_t cursor_top = m_font.height() * 13 / 16;
|
||||
|
||||
const uint32_t x = m_cursor_x * m_font.width();
|
||||
const uint32_t y = m_cursor_y * m_font.height();
|
||||
|
||||
for (uint32_t dy = 0; dy < cursor_h; dy++)
|
||||
for (uint32_t dx = 0; dx < cursor_w; dx++)
|
||||
m_framebuffer_device->set_pixel(x + dx, y + cursor_top + dy, get_color(dx, dy));
|
||||
m_framebuffer_device->sync_pixels_rectangle(x, y + cursor_top, cursor_w, cursor_h);
|
||||
}
|
||||
|
||||
void FramebufferTerminalDriver::set_cursor_shown(bool shown)
|
||||
{
|
||||
if (m_cursor_shown == shown)
|
||||
return;
|
||||
m_cursor_shown = shown;
|
||||
|
||||
if (m_cursor_shown)
|
||||
{
|
||||
read_cursor();
|
||||
show_cursor(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
show_cursor(true);
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferTerminalDriver::set_cursor_position(uint32_t x, uint32_t y)
|
||||
{
|
||||
if (!m_cursor_shown)
|
||||
{
|
||||
m_cursor_x = x;
|
||||
m_cursor_y = y;
|
||||
return;
|
||||
}
|
||||
|
||||
show_cursor(true);
|
||||
m_cursor_x = x;
|
||||
m_cursor_y = y;
|
||||
read_cursor();
|
||||
show_cursor(false);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> FramebufferTerminalDriver::set_font(LibFont::Font&& font)
|
||||
{
|
||||
const uint32_t cursor_h = font.height() / 8;
|
||||
const uint32_t cursor_w = font.width();
|
||||
TRY(m_cursor_data.resize(cursor_h * cursor_w));
|
||||
for (auto& val : m_cursor_data)
|
||||
val = TerminalColor::BLACK.rgb;
|
||||
|
||||
m_font = BAN::move(font);
|
||||
m_cursor_x = BAN::Math::clamp<uint32_t>(m_cursor_x, 0, width() - 1);
|
||||
m_cursor_y = BAN::Math::clamp<uint32_t>(m_cursor_y, 0, height() - 1);
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -92,19 +92,6 @@ namespace Kernel
|
|||
return {};
|
||||
}
|
||||
|
||||
void VirtualTTY::set_cursor_position(uint32_t x, uint32_t y)
|
||||
{
|
||||
ASSERT(m_write_lock.current_processor_has_lock());
|
||||
static uint32_t last_x = -1;
|
||||
static uint32_t last_y = -1;
|
||||
if (last_x != uint32_t(-1) && last_y != uint32_t(-1))
|
||||
render_from_buffer(last_x, last_y);
|
||||
if (m_show_cursor)
|
||||
m_terminal_driver->set_cursor_position(x, y);
|
||||
last_x = x;
|
||||
last_y = y;
|
||||
}
|
||||
|
||||
void VirtualTTY::reset_ansi()
|
||||
{
|
||||
ASSERT(m_write_lock.current_processor_has_lock());
|
||||
|
@ -370,7 +357,7 @@ namespace Kernel
|
|||
case 'l':
|
||||
if (m_ansi_state.question && m_ansi_state.nums[0] == 25)
|
||||
{
|
||||
m_show_cursor = (ch == 'h');
|
||||
m_terminal_driver->set_cursor_shown(ch == 'h');
|
||||
return reset_ansi();
|
||||
}
|
||||
reset_ansi();
|
||||
|
@ -511,7 +498,6 @@ namespace Kernel
|
|||
return;
|
||||
case State::WaitingAnsiCSI:
|
||||
handle_ansi_csi(ch);
|
||||
set_cursor_position(m_column, m_row);
|
||||
return;
|
||||
case State::WaitingUTF8:
|
||||
if ((ch & 0xC0) != 0x80)
|
||||
|
@ -531,14 +517,9 @@ namespace Kernel
|
|||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
bool old_show_cursor = m_show_cursor;
|
||||
m_show_cursor = false;
|
||||
set_cursor_position(m_column, m_row);
|
||||
|
||||
putcodepoint(codepoint);
|
||||
|
||||
m_show_cursor = old_show_cursor;
|
||||
set_cursor_position(m_column, m_row);
|
||||
m_terminal_driver->set_cursor_position(m_column, m_row);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue