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