Kernel: Fix text mode cursor

Apparently text mode renders cursor in the *foreground* color. My
current clear function used the same color for foreground and background
making the cursor effectively invisible.

Also cursor hiding is now done by moving the cursor off bounds (0, height)
some website I read said this to be valid even on VGA compatible cards
without disable bit.

http://www.osdever.net/FreeVGA/vga/textcur.htm
This commit is contained in:
Bananymous 2025-04-25 02:31:33 +03:00
parent 9f3f8f950a
commit 9ff9d679e9
2 changed files with 35 additions and 23 deletions

View File

@ -30,6 +30,7 @@ namespace Kernel
{}
BAN::ErrorOr<void> initialize();
void move_cursor_impl(uint32_t x, uint32_t y);
private:
const paddr_t m_paddr;
@ -37,6 +38,10 @@ namespace Kernel
const uint32_t m_height;
const uint32_t m_pitch;
vaddr_t m_vaddr { 0 };
uint32_t m_cursor_x { 0 };
uint32_t m_cursor_y { 0 };
bool m_cursor_shown { true };
static constexpr Color s_cursor_color = TerminalColor::WHITE;
};

View File

@ -122,32 +122,11 @@ namespace Kernel
{
for (uint32_t y = 0; y < m_height; y++)
for (uint32_t x = 0; x < m_width; x++)
putchar_at(' ', x, y, color, color);
putchar_at(' ', x, y, TerminalColor::WHITE, color);
}
void TextModeTerminalDriver::set_cursor_shown(bool shown)
void TextModeTerminalDriver::move_cursor_impl(uint32_t x, uint32_t y)
{
if (shown)
{
IO::outb(0x3D4, 0x0A);
IO::outb(0x3D5, (IO::inb(0x3D5) & 0xC0) | 14);
IO::outb(0x3D4, 0x0B);
IO::outb(0x3D5, (IO::inb(0x3D5) & 0xE0) | 15);
}
else
{
IO::outb(0x3D4, 0x0A);
IO::outb(0x3D5, 0x20);
}
}
void TextModeTerminalDriver::set_cursor_position(uint32_t x, uint32_t y)
{
// NOTE: cursor is allowed to be on width as scrolling only
// happens after character gets printed to next line
if (x == m_width)
return;
const uint16_t pos = y * m_width + x;
IO::outb(0x3D4, 0x0F);
IO::outb(0x3D5, pos & 0xFF);
@ -155,4 +134,32 @@ namespace Kernel
IO::outb(0x3D5, pos >> 8);
}
void TextModeTerminalDriver::set_cursor_shown(bool shown)
{
if (m_cursor_shown == shown)
return;
m_cursor_shown = shown;
if (shown)
move_cursor_impl(m_cursor_x, m_cursor_y);
else
move_cursor_impl(0, m_height);
}
void TextModeTerminalDriver::set_cursor_position(uint32_t x, uint32_t y)
{
ASSERT(x <= m_width);
ASSERT(y < m_height);
m_cursor_x = x;
m_cursor_y = y;
if (!m_cursor_shown)
return;
if (x == m_width)
move_cursor_impl(0, m_height);
else
move_cursor_impl(x, y);
}
}