feat(kernel/tty): implement blinking cursor

This commit is contained in:
EnderIce2 2025-04-12 10:55:01 +00:00
parent bc84c406d9
commit 5293bb2039
Signed by: enderice2
GPG Key ID: FEB6B8A8507BA62E
9 changed files with 108 additions and 38 deletions

View File

@ -20,6 +20,7 @@
#include <memory.hpp>
#include <stropts.h>
#include <string.h>
#include <thread>
#include <ini.h>
#include "../kernel.h"
@ -112,6 +113,38 @@ namespace KernelConsole
FontRenderer Renderer;
ConsoleTerminal *Terminals[16] = {nullptr};
std::atomic<ConsoleTerminal *> CurrentTerminal = nullptr;
void paint_blinker(bool Enable)
{
if (CurrentTerminal == nullptr)
return;
ConsoleTerminal *term = CurrentTerminal.load();
ConsoleTerminal::Blinker *blinker = &term->Blink;
TerminalCell *cell = term->Term->GetCell(Renderer.Cursor.X + Renderer.Cursor.Y * term->Term->GetWinsize()->ws_row);
uint32_t bgColor = cell->attr.Bright ? TermBrightColors[cell->attr.Background] : TermColors[cell->attr.Background];
Renderer.Paint(Renderer.Cursor.X, Renderer.Cursor.Y,
term->Blink.Character,
Enable ? term->Blink.Color : bgColor,
bgColor);
}
void paint_blinker_thread()
{
bool blink = false;
while (true)
{
paint_blinker(blink);
blink = !blink;
std::this_thread::sleep_for(std::chrono::milliseconds(CurrentTerminal.load()->Blink.Delay));
}
}
void paint_callback(TerminalCell *cell, long x, long y)
{
if (cell->attr.Bright)
@ -123,11 +156,9 @@ namespace KernelConsole
void cursor_callback(TerminalCursor *cur)
{
Renderer.Cursor = {cur->X, cur->Y};
paint_blinker(false);
}
VirtualTerminal *Terminals[16] = {nullptr};
std::atomic<VirtualTerminal *> CurrentTerminal = nullptr;
bool SetTheme(std::string Theme)
{
FileNode *rn = fs->GetByPath("/sys/cfg/term", thisProcess->Info.RootNode);
@ -267,24 +298,15 @@ namespace KernelConsole
size_t Rows = Display->GetWidth / Renderer.CurrentFont->GetInfo().Width;
size_t Cols = Display->GetHeight / Renderer.CurrentFont->GetInfo().Height;
debug("Terminal size: %ux%u", Rows, Cols);
Terminals[0] = new VirtualTerminal(Rows, Cols, Display->GetWidth, Display->GetHeight, paint_callback, cursor_callback);
Terminals[0]->Clear(0, 0, Rows, Cols - 1);
Terminals[0] = new ConsoleTerminal;
Terminals[0]->Term = new VirtualTerminal(Rows, Cols, Display->GetWidth, Display->GetHeight, paint_callback, cursor_callback);
Terminals[0]->Term->Clear(0, 0, Rows, Cols - 1);
CurrentTerminal.store(Terminals[0], std::memory_order_release);
}
void LateInit()
void LoadConsoleConfig(std::string &Config)
{
FileNode *rn = fs->GetByPath("/sys/cfg/term", thisProcess->Info.RootNode);
if (rn == nullptr)
return;
kstat st{};
rn->Stat(&st);
char *sh = new char[st.Size];
rn->Read(sh, st.Size, 0);
ini_t *ini = ini_load(sh, NULL);
ini_t *ini = ini_load(Config.c_str(), NULL);
int general = ini_find_section(ini, "general", NULL);
int cursor = ini_find_section(ini, "cursor", NULL);
assert(general != INI_NOT_FOUND && cursor != INI_NOT_FOUND);
@ -292,16 +314,22 @@ namespace KernelConsole
int themeIndex = ini_find_property(ini, general, "theme", NULL);
assert(themeIndex != INI_NOT_FOUND);
int cursorColor = ini_find_property(ini, cursor, "color", NULL);
int cursorBlink = ini_find_property(ini, cursor, "blink", NULL);
assert(cursorColor != INI_NOT_FOUND && cursorBlink != INI_NOT_FOUND);
int cursorColor = ini_find_property(ini, cursor, "color", NULL);
int cursorChar = ini_find_property(ini, cursor, "char", NULL);
int cursorDelay = ini_find_property(ini, cursor, "delay", NULL);
assert(cursorBlink != INI_NOT_FOUND && cursorColor != INI_NOT_FOUND && cursorChar != INI_NOT_FOUND && cursorDelay != INI_NOT_FOUND);
const char *colorThemeStr = ini_property_value(ini, general, themeIndex);
const char *cursorColorStr = ini_property_value(ini, cursor, cursorColor);
const char *cursorBlinkStr = ini_property_value(ini, cursor, cursorBlink);
const char *cursorCharStr = ini_property_value(ini, cursor, cursorChar);
const char *cursorDelayStr = ini_property_value(ini, cursor, cursorDelay);
debug("colorThemeStr=%s", colorThemeStr);
debug("cursorColorStr=%s", cursorColorStr);
debug("cursorBlinkStr=%s", cursorBlinkStr);
debug("cursorColorStr=%s", cursorColorStr);
debug("cursorCharStr=%s", cursorCharStr);
debug("cursorDelayStr=%s", cursorDelayStr);
auto getColorComponent = [](const char *str, int &index) -> int
{
@ -335,11 +363,36 @@ namespace KernelConsole
uint32_t blinkColor = 0xFFFFFF;
if (cursorColorStr != 0)
blinkColor = parseColor(cursorColorStr);
fixme("cursor blink with colors %X", blinkColor);
debug("cursor blink with colors %X and char '%s' and delay %s", blinkColor, cursorCharStr, cursorDelayStr);
Terminals[0]->Blink.Enabled = true;
Terminals[0]->Blink.Color = blinkColor;
Terminals[0]->Blink.Character = *cursorCharStr;
Terminals[0]->Blink.Delay = atoi(cursorDelayStr);
}
ini_destroy(ini);
delete[] sh;
}
void LateInit()
{
FileNode *rn = fs->GetByPath("/sys/cfg/term", thisProcess->Info.RootNode);
if (rn == nullptr)
return;
{
kstat st;
rn->Stat(&st);
std::string cfg;
cfg.reserve(st.Size);
rn->Read(cfg.data(), st.Size, 0);
LoadConsoleConfig(cfg);
}
if (Terminals[0]->Blink.Enabled)
{
std::thread t = std::thread(paint_blinker_thread);
t.detach();
}
#ifdef DEBUG
// __test_themes();

View File

@ -84,7 +84,7 @@ void paint_callback(TerminalCell *cell, long x, long y)
nsa void __printfWrapper(char c, void *)
{
KernelConsole::Terminals[15]->Process(c);
KernelConsole::Terminals[15]->Term->Process(c);
}
nsa void ExPrint(const char *Format, ...)
@ -162,7 +162,8 @@ nsa void InitFont()
{
size_t Cols = Display->GetWidth / CrashFontRenderer.CurrentFont->GetInfo().Width;
size_t Rows = Display->GetHeight / CrashFontRenderer.CurrentFont->GetInfo().Height;
Terminals[15] = new VirtualTerminal(Cols, Rows, Display->GetWidth, Display->GetHeight, paint_callback, nullptr);
Terminals[15] = new ConsoleTerminal;
Terminals[15]->Term = new VirtualTerminal(Cols, Rows, Display->GetWidth, Display->GetHeight, paint_callback, nullptr);
}
}
@ -372,7 +373,8 @@ nsa void BaseBufferStackError(bool Stack)
{
size_t Cols = Display->GetWidth / CrashFontRenderer.CurrentFont->GetInfo().Width;
size_t Rows = Display->GetHeight / CrashFontRenderer.CurrentFont->GetInfo().Height;
Terminals[15] = new VirtualTerminal(Cols, Rows, Display->GetWidth, Display->GetHeight, paint_callback, nullptr);
Terminals[15] = new ConsoleTerminal;
Terminals[15]->Term = new VirtualTerminal(Cols, Rows, Display->GetWidth, Display->GetHeight, paint_callback, nullptr);
}
ExceptionLock.store(true, std::memory_order_release);

View File

@ -37,7 +37,7 @@ namespace Driver::TeleTypeDevices
{
dev_t min = Node->GetMinor();
if (min == ids.kcon)
return KernelConsole::CurrentTerminal.load()->Open(Flags, Mode);
return KernelConsole::CurrentTerminal.load()->Term->Open(Flags, Mode);
else if (min == ids.tty)
{
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;
@ -55,7 +55,7 @@ namespace Driver::TeleTypeDevices
{
dev_t min = Node->GetMinor();
if (min == ids.kcon)
return KernelConsole::CurrentTerminal.load()->Close();
return KernelConsole::CurrentTerminal.load()->Term->Close();
else if (min == ids.tty)
{
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;
@ -73,7 +73,7 @@ namespace Driver::TeleTypeDevices
{
dev_t min = Node->GetMinor();
if (min == ids.kcon)
return KernelConsole::CurrentTerminal.load()->Ioctl(Request, Argp);
return KernelConsole::CurrentTerminal.load()->Term->Ioctl(Request, Argp);
else if (min == ids.tty)
{
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;
@ -91,7 +91,7 @@ namespace Driver::TeleTypeDevices
{
dev_t min = Node->GetMinor();
if (min == ids.kcon)
return KernelConsole::CurrentTerminal.load()->Read(Buffer, Size, Offset);
return KernelConsole::CurrentTerminal.load()->Term->Read(Buffer, Size, Offset);
else if (min == ids.tty)
{
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;
@ -109,7 +109,7 @@ namespace Driver::TeleTypeDevices
{
dev_t min = Node->GetMinor();
if (min == ids.kcon)
return KernelConsole::CurrentTerminal.load()->Write(Buffer, Size, Offset);
return KernelConsole::CurrentTerminal.load()->Term->Write(Buffer, Size, Offset);
else if (min == ids.tty)
{
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;

View File

@ -170,7 +170,7 @@ namespace Execute
fixme("remove workarounds for stdio and tty");
if (!Parent->tty)
Process->tty = KernelConsole::CurrentTerminal.load();
Process->tty = KernelConsole::CurrentTerminal.load()->Term;
if (!ForkStdio(Parent->stdin))
fdt->usr_open("/dev/console", O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);

View File

@ -126,20 +126,34 @@ namespace KernelConsole
void csi_cha(ANSIArgument *Args, int ArgsCount);
void Process(char c);
TerminalCell *GetCell(size_t index) { return &Cells[index]; }
VirtualTerminal(unsigned short Rows, unsigned short Columns,
unsigned short XPixels, unsigned short YPixels,
PaintCallback Paint, CursorCallback Print);
~VirtualTerminal();
};
struct ConsoleTerminal
{
VirtualTerminal *Term = nullptr;
struct Blinker
{
bool Enabled = false;
uint32_t Color = 0x000000;
char Character = '\0';
int Delay = 500;
} Blink;
};
/**
* 0 - Default
* 1...11 - User
* ...
* 15 - Panic
*/
extern VirtualTerminal *Terminals[16];
extern std::atomic<VirtualTerminal *> CurrentTerminal;
extern ConsoleTerminal *Terminals[16];
extern std::atomic<ConsoleTerminal *> CurrentTerminal;
extern int TermColors[];
extern int TermBrightColors[];

View File

@ -62,7 +62,7 @@ UART::Driver uart;
EXTERNC void putchar(char c)
{
KernelConsole::VirtualTerminal *vt = KernelConsole::CurrentTerminal.load(std::memory_order_acquire);
KernelConsole::VirtualTerminal *vt = KernelConsole::CurrentTerminal.load(std::memory_order_acquire)->Term;
if (vt != nullptr)
vt->Process(c);
else

View File

@ -152,8 +152,7 @@ void KernelMainThread()
goto Exit;
}
KPrint("Waiting for \x1b[32m%s\x1b[0m to start...",
Config.InitPath);
KPrint("Waiting for init program to start...");
thisThread->SetPriority(Tasking::Idle);
initProc = TaskManager->GetProcessByID(tid);

View File

@ -282,7 +282,7 @@ namespace Tasking
/* FIXME: DON'T DELETE THE TTY
spawn.cpp is using this as workaround
tty == KernelConsole::CurrentTerminal.load();
tty == KernelConsole::CurrentTerminal.load()->Term;
*/
/* If we own the pointer to the

View File

@ -2,8 +2,10 @@
theme=vga
[cursor]
color=255,255,255
blink=true
color=244,244,244
char=_
delay=250
[vga]
color0=0,0,0:133,133,133