mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-05-28 15:34:31 +00:00
feat(kernel/tty): implement blinking cursor
This commit is contained in:
parent
bc84c406d9
commit
5293bb2039
@ -20,6 +20,7 @@
|
|||||||
#include <memory.hpp>
|
#include <memory.hpp>
|
||||||
#include <stropts.h>
|
#include <stropts.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <thread>
|
||||||
#include <ini.h>
|
#include <ini.h>
|
||||||
|
|
||||||
#include "../kernel.h"
|
#include "../kernel.h"
|
||||||
@ -112,6 +113,38 @@ namespace KernelConsole
|
|||||||
|
|
||||||
FontRenderer Renderer;
|
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)
|
void paint_callback(TerminalCell *cell, long x, long y)
|
||||||
{
|
{
|
||||||
if (cell->attr.Bright)
|
if (cell->attr.Bright)
|
||||||
@ -123,11 +156,9 @@ namespace KernelConsole
|
|||||||
void cursor_callback(TerminalCursor *cur)
|
void cursor_callback(TerminalCursor *cur)
|
||||||
{
|
{
|
||||||
Renderer.Cursor = {cur->X, cur->Y};
|
Renderer.Cursor = {cur->X, cur->Y};
|
||||||
|
paint_blinker(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualTerminal *Terminals[16] = {nullptr};
|
|
||||||
std::atomic<VirtualTerminal *> CurrentTerminal = nullptr;
|
|
||||||
|
|
||||||
bool SetTheme(std::string Theme)
|
bool SetTheme(std::string Theme)
|
||||||
{
|
{
|
||||||
FileNode *rn = fs->GetByPath("/sys/cfg/term", thisProcess->Info.RootNode);
|
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 Rows = Display->GetWidth / Renderer.CurrentFont->GetInfo().Width;
|
||||||
size_t Cols = Display->GetHeight / Renderer.CurrentFont->GetInfo().Height;
|
size_t Cols = Display->GetHeight / Renderer.CurrentFont->GetInfo().Height;
|
||||||
debug("Terminal size: %ux%u", Rows, Cols);
|
debug("Terminal size: %ux%u", Rows, Cols);
|
||||||
Terminals[0] = new VirtualTerminal(Rows, Cols, Display->GetWidth, Display->GetHeight, paint_callback, cursor_callback);
|
Terminals[0] = new ConsoleTerminal;
|
||||||
Terminals[0]->Clear(0, 0, Rows, Cols - 1);
|
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);
|
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);
|
ini_t *ini = ini_load(Config.c_str(), NULL);
|
||||||
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);
|
|
||||||
int general = ini_find_section(ini, "general", NULL);
|
int general = ini_find_section(ini, "general", NULL);
|
||||||
int cursor = ini_find_section(ini, "cursor", NULL);
|
int cursor = ini_find_section(ini, "cursor", NULL);
|
||||||
assert(general != INI_NOT_FOUND && cursor != INI_NOT_FOUND);
|
assert(general != INI_NOT_FOUND && cursor != INI_NOT_FOUND);
|
||||||
@ -292,16 +314,22 @@ namespace KernelConsole
|
|||||||
int themeIndex = ini_find_property(ini, general, "theme", NULL);
|
int themeIndex = ini_find_property(ini, general, "theme", NULL);
|
||||||
assert(themeIndex != INI_NOT_FOUND);
|
assert(themeIndex != INI_NOT_FOUND);
|
||||||
|
|
||||||
int cursorColor = ini_find_property(ini, cursor, "color", NULL);
|
|
||||||
int cursorBlink = ini_find_property(ini, cursor, "blink", 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 *colorThemeStr = ini_property_value(ini, general, themeIndex);
|
||||||
const char *cursorColorStr = ini_property_value(ini, cursor, cursorColor);
|
const char *cursorColorStr = ini_property_value(ini, cursor, cursorColor);
|
||||||
const char *cursorBlinkStr = ini_property_value(ini, cursor, cursorBlink);
|
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("colorThemeStr=%s", colorThemeStr);
|
||||||
debug("cursorColorStr=%s", cursorColorStr);
|
|
||||||
debug("cursorBlinkStr=%s", cursorBlinkStr);
|
debug("cursorBlinkStr=%s", cursorBlinkStr);
|
||||||
|
debug("cursorColorStr=%s", cursorColorStr);
|
||||||
|
debug("cursorCharStr=%s", cursorCharStr);
|
||||||
|
debug("cursorDelayStr=%s", cursorDelayStr);
|
||||||
|
|
||||||
auto getColorComponent = [](const char *str, int &index) -> int
|
auto getColorComponent = [](const char *str, int &index) -> int
|
||||||
{
|
{
|
||||||
@ -335,11 +363,36 @@ namespace KernelConsole
|
|||||||
uint32_t blinkColor = 0xFFFFFF;
|
uint32_t blinkColor = 0xFFFFFF;
|
||||||
if (cursorColorStr != 0)
|
if (cursorColorStr != 0)
|
||||||
blinkColor = parseColor(cursorColorStr);
|
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);
|
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
|
#ifdef DEBUG
|
||||||
// __test_themes();
|
// __test_themes();
|
||||||
|
@ -84,7 +84,7 @@ void paint_callback(TerminalCell *cell, long x, long y)
|
|||||||
|
|
||||||
nsa void __printfWrapper(char c, void *)
|
nsa void __printfWrapper(char c, void *)
|
||||||
{
|
{
|
||||||
KernelConsole::Terminals[15]->Process(c);
|
KernelConsole::Terminals[15]->Term->Process(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsa void ExPrint(const char *Format, ...)
|
nsa void ExPrint(const char *Format, ...)
|
||||||
@ -162,7 +162,8 @@ nsa void InitFont()
|
|||||||
{
|
{
|
||||||
size_t Cols = Display->GetWidth / CrashFontRenderer.CurrentFont->GetInfo().Width;
|
size_t Cols = Display->GetWidth / CrashFontRenderer.CurrentFont->GetInfo().Width;
|
||||||
size_t Rows = Display->GetHeight / CrashFontRenderer.CurrentFont->GetInfo().Height;
|
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 Cols = Display->GetWidth / CrashFontRenderer.CurrentFont->GetInfo().Width;
|
||||||
size_t Rows = Display->GetHeight / CrashFontRenderer.CurrentFont->GetInfo().Height;
|
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);
|
ExceptionLock.store(true, std::memory_order_release);
|
||||||
|
@ -37,7 +37,7 @@ namespace Driver::TeleTypeDevices
|
|||||||
{
|
{
|
||||||
dev_t min = Node->GetMinor();
|
dev_t min = Node->GetMinor();
|
||||||
if (min == ids.kcon)
|
if (min == ids.kcon)
|
||||||
return KernelConsole::CurrentTerminal.load()->Open(Flags, Mode);
|
return KernelConsole::CurrentTerminal.load()->Term->Open(Flags, Mode);
|
||||||
else if (min == ids.tty)
|
else if (min == ids.tty)
|
||||||
{
|
{
|
||||||
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;
|
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;
|
||||||
@ -55,7 +55,7 @@ namespace Driver::TeleTypeDevices
|
|||||||
{
|
{
|
||||||
dev_t min = Node->GetMinor();
|
dev_t min = Node->GetMinor();
|
||||||
if (min == ids.kcon)
|
if (min == ids.kcon)
|
||||||
return KernelConsole::CurrentTerminal.load()->Close();
|
return KernelConsole::CurrentTerminal.load()->Term->Close();
|
||||||
else if (min == ids.tty)
|
else if (min == ids.tty)
|
||||||
{
|
{
|
||||||
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;
|
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;
|
||||||
@ -73,7 +73,7 @@ namespace Driver::TeleTypeDevices
|
|||||||
{
|
{
|
||||||
dev_t min = Node->GetMinor();
|
dev_t min = Node->GetMinor();
|
||||||
if (min == ids.kcon)
|
if (min == ids.kcon)
|
||||||
return KernelConsole::CurrentTerminal.load()->Ioctl(Request, Argp);
|
return KernelConsole::CurrentTerminal.load()->Term->Ioctl(Request, Argp);
|
||||||
else if (min == ids.tty)
|
else if (min == ids.tty)
|
||||||
{
|
{
|
||||||
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;
|
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;
|
||||||
@ -91,7 +91,7 @@ namespace Driver::TeleTypeDevices
|
|||||||
{
|
{
|
||||||
dev_t min = Node->GetMinor();
|
dev_t min = Node->GetMinor();
|
||||||
if (min == ids.kcon)
|
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)
|
else if (min == ids.tty)
|
||||||
{
|
{
|
||||||
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;
|
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;
|
||||||
@ -109,7 +109,7 @@ namespace Driver::TeleTypeDevices
|
|||||||
{
|
{
|
||||||
dev_t min = Node->GetMinor();
|
dev_t min = Node->GetMinor();
|
||||||
if (min == ids.kcon)
|
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)
|
else if (min == ids.tty)
|
||||||
{
|
{
|
||||||
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;
|
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;
|
||||||
|
@ -170,7 +170,7 @@ namespace Execute
|
|||||||
|
|
||||||
fixme("remove workarounds for stdio and tty");
|
fixme("remove workarounds for stdio and tty");
|
||||||
if (!Parent->tty)
|
if (!Parent->tty)
|
||||||
Process->tty = KernelConsole::CurrentTerminal.load();
|
Process->tty = KernelConsole::CurrentTerminal.load()->Term;
|
||||||
|
|
||||||
if (!ForkStdio(Parent->stdin))
|
if (!ForkStdio(Parent->stdin))
|
||||||
fdt->usr_open("/dev/console", O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
fdt->usr_open("/dev/console", O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||||
|
@ -126,20 +126,34 @@ namespace KernelConsole
|
|||||||
void csi_cha(ANSIArgument *Args, int ArgsCount);
|
void csi_cha(ANSIArgument *Args, int ArgsCount);
|
||||||
void Process(char c);
|
void Process(char c);
|
||||||
|
|
||||||
|
TerminalCell *GetCell(size_t index) { return &Cells[index]; }
|
||||||
|
|
||||||
VirtualTerminal(unsigned short Rows, unsigned short Columns,
|
VirtualTerminal(unsigned short Rows, unsigned short Columns,
|
||||||
unsigned short XPixels, unsigned short YPixels,
|
unsigned short XPixels, unsigned short YPixels,
|
||||||
PaintCallback Paint, CursorCallback Print);
|
PaintCallback Paint, CursorCallback Print);
|
||||||
~VirtualTerminal();
|
~VirtualTerminal();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ConsoleTerminal
|
||||||
|
{
|
||||||
|
VirtualTerminal *Term = nullptr;
|
||||||
|
struct Blinker
|
||||||
|
{
|
||||||
|
bool Enabled = false;
|
||||||
|
uint32_t Color = 0x000000;
|
||||||
|
char Character = '\0';
|
||||||
|
int Delay = 500;
|
||||||
|
} Blink;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 0 - Default
|
* 0 - Default
|
||||||
* 1...11 - User
|
* 1...11 - User
|
||||||
* ...
|
* ...
|
||||||
* 15 - Panic
|
* 15 - Panic
|
||||||
*/
|
*/
|
||||||
extern VirtualTerminal *Terminals[16];
|
extern ConsoleTerminal *Terminals[16];
|
||||||
extern std::atomic<VirtualTerminal *> CurrentTerminal;
|
extern std::atomic<ConsoleTerminal *> CurrentTerminal;
|
||||||
extern int TermColors[];
|
extern int TermColors[];
|
||||||
extern int TermBrightColors[];
|
extern int TermBrightColors[];
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ UART::Driver uart;
|
|||||||
|
|
||||||
EXTERNC void putchar(char c)
|
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)
|
if (vt != nullptr)
|
||||||
vt->Process(c);
|
vt->Process(c);
|
||||||
else
|
else
|
||||||
|
@ -152,8 +152,7 @@ void KernelMainThread()
|
|||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
KPrint("Waiting for \x1b[32m%s\x1b[0m to start...",
|
KPrint("Waiting for init program to start...");
|
||||||
Config.InitPath);
|
|
||||||
thisThread->SetPriority(Tasking::Idle);
|
thisThread->SetPriority(Tasking::Idle);
|
||||||
|
|
||||||
initProc = TaskManager->GetProcessByID(tid);
|
initProc = TaskManager->GetProcessByID(tid);
|
||||||
|
@ -282,7 +282,7 @@ namespace Tasking
|
|||||||
|
|
||||||
/* FIXME: DON'T DELETE THE TTY
|
/* FIXME: DON'T DELETE THE TTY
|
||||||
spawn.cpp is using this as workaround
|
spawn.cpp is using this as workaround
|
||||||
tty == KernelConsole::CurrentTerminal.load();
|
tty == KernelConsole::CurrentTerminal.load()->Term;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* If we own the pointer to the
|
/* If we own the pointer to the
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
theme=vga
|
theme=vga
|
||||||
|
|
||||||
[cursor]
|
[cursor]
|
||||||
color=255,255,255
|
|
||||||
blink=true
|
blink=true
|
||||||
|
color=244,244,244
|
||||||
|
char=_
|
||||||
|
delay=250
|
||||||
|
|
||||||
[vga]
|
[vga]
|
||||||
color0=0,0,0:133,133,133
|
color0=0,0,0:133,133,133
|
||||||
|
Loading…
x
Reference in New Issue
Block a user