kernel: Add a blinking cursor to the terminal
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
c5e11bb6cf
commit
27eacac19c
@ -161,7 +161,11 @@ void io_thread()
|
|||||||
static void timer_interrupt(Registers* regs, void*)
|
static void timer_interrupt(Registers* regs, void*)
|
||||||
{
|
{
|
||||||
Timer::tick();
|
Timer::tick();
|
||||||
if (should_invoke_scheduler()) Scheduler::invoke(regs);
|
if (should_invoke_scheduler())
|
||||||
|
{
|
||||||
|
Scheduler::invoke(regs);
|
||||||
|
TextConsole::tick_cursor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyboard_interrupt(Registers*, void*)
|
static void keyboard_interrupt(Registers*, void*)
|
||||||
|
@ -246,6 +246,9 @@ Result<u64> ConsoleDevice::ioctl(int request, void* arg)
|
|||||||
}
|
}
|
||||||
case TTYSETGFX: {
|
case TTYSETGFX: {
|
||||||
s_is_in_graphical_mode = (bool)arg;
|
s_is_in_graphical_mode = (bool)arg;
|
||||||
|
if (!s_is_in_graphical_mode) TextConsole::enable_cursor();
|
||||||
|
else
|
||||||
|
TextConsole::disable_cursor();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
default: return err(EINVAL);
|
default: return err(EINVAL);
|
||||||
|
@ -47,6 +47,11 @@ static bool bold = false;
|
|||||||
static u32 g_x_position = 0;
|
static u32 g_x_position = 0;
|
||||||
static u32 g_y_position = 0;
|
static u32 g_y_position = 0;
|
||||||
|
|
||||||
|
static constexpr int CURSOR_TIMEOUT = 500;
|
||||||
|
static int current_cursor_timeout = CURSOR_TIMEOUT;
|
||||||
|
static bool cursor_activated = true;
|
||||||
|
static bool cursor_enabled = true;
|
||||||
|
|
||||||
static Utf8StateDecoder utf8_decoder;
|
static Utf8StateDecoder utf8_decoder;
|
||||||
|
|
||||||
static Option<EscapeSequenceParser> escape_sequence_parser;
|
static Option<EscapeSequenceParser> escape_sequence_parser;
|
||||||
@ -82,7 +87,7 @@ static void scroll()
|
|||||||
|
|
||||||
static bool should_scroll()
|
static bool should_scroll()
|
||||||
{
|
{
|
||||||
return (g_y_position + FONT_HEIGHT) >= Framebuffer::height();
|
return g_y_position >= Framebuffer::height();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void next_line()
|
static void next_line()
|
||||||
@ -106,6 +111,11 @@ static void erase_current_char()
|
|||||||
Framebuffer::rect(g_x_position, g_y_position, FONT_WIDTH, FONT_HEIGHT, BLACK);
|
Framebuffer::rect(g_x_position, g_y_position, FONT_WIDTH, FONT_HEIGHT, BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void draw_cursor()
|
||||||
|
{
|
||||||
|
Framebuffer::rect(g_x_position, g_y_position, FONT_WIDTH, FONT_HEIGHT, WHITE);
|
||||||
|
}
|
||||||
|
|
||||||
static bool at_end_of_screen()
|
static bool at_end_of_screen()
|
||||||
{
|
{
|
||||||
return (g_x_position + FONT_WIDTH) > Framebuffer::width();
|
return (g_x_position + FONT_WIDTH) > Framebuffer::width();
|
||||||
@ -323,6 +333,11 @@ namespace TextConsole
|
|||||||
if (handle_escape_sequence(c)) return;
|
if (handle_escape_sequence(c)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Erase the current cursor.
|
||||||
|
if (cursor_enabled) erase_current_char();
|
||||||
|
|
||||||
|
bool should_draw_cursor = cursor_enabled;
|
||||||
|
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case L'\n': {
|
case L'\n': {
|
||||||
@ -345,7 +360,10 @@ namespace TextConsole
|
|||||||
case L'\x1b':
|
case L'\x1b':
|
||||||
case L'\x9b':
|
case L'\x9b':
|
||||||
case L'\x90':
|
case L'\x90':
|
||||||
case L'\x9d': escape_sequence_parser = EscapeSequenceParser { (u8)c }; break;
|
case L'\x9d':
|
||||||
|
escape_sequence_parser = EscapeSequenceParser { (u8)c };
|
||||||
|
should_draw_cursor = false;
|
||||||
|
break;
|
||||||
default: {
|
default: {
|
||||||
if (_iscntrl(c)) return;
|
if (_iscntrl(c)) return;
|
||||||
putwchar_at(c, g_x_position, g_y_position);
|
putwchar_at(c, g_x_position, g_y_position);
|
||||||
@ -358,6 +376,42 @@ namespace TextConsole
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (should_draw_cursor)
|
||||||
|
{
|
||||||
|
current_cursor_timeout = CURSOR_TIMEOUT;
|
||||||
|
cursor_activated = true;
|
||||||
|
draw_cursor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tick_cursor()
|
||||||
|
{
|
||||||
|
if (!cursor_enabled) return;
|
||||||
|
|
||||||
|
current_cursor_timeout--;
|
||||||
|
if (current_cursor_timeout == 0)
|
||||||
|
{
|
||||||
|
current_cursor_timeout = CURSOR_TIMEOUT;
|
||||||
|
cursor_activated = !cursor_activated;
|
||||||
|
|
||||||
|
if (cursor_activated) draw_cursor();
|
||||||
|
else
|
||||||
|
erase_current_char();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void disable_cursor()
|
||||||
|
{
|
||||||
|
cursor_enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void enable_cursor()
|
||||||
|
{
|
||||||
|
cursor_enabled = true;
|
||||||
|
cursor_activated = true;
|
||||||
|
current_cursor_timeout = CURSOR_TIMEOUT;
|
||||||
|
draw_cursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> putchar(char c)
|
Result<void> putchar(char c)
|
||||||
|
@ -19,6 +19,9 @@ namespace TextConsole
|
|||||||
Result<void> println(const char* str);
|
Result<void> println(const char* str);
|
||||||
void wprintln(const wchar_t* str);
|
void wprintln(const wchar_t* str);
|
||||||
Result<usize> printf(const char* format, ...) _format(1, 2);
|
Result<usize> printf(const char* format, ...) _format(1, 2);
|
||||||
|
void tick_cursor();
|
||||||
|
void disable_cursor();
|
||||||
|
void enable_cursor();
|
||||||
|
|
||||||
u16 rows();
|
u16 rows();
|
||||||
u16 cols();
|
u16 cols();
|
||||||
|
Loading…
Reference in New Issue
Block a user