Skip to content

Commit 91577f7

Browse files
committed
feat(kernel): 实现统一控制台trait并集成anaxa构建系统
1 parent f7f32c3 commit 91577f7

File tree

5 files changed

+270
-34
lines changed

5 files changed

+270
-34
lines changed

.github/workflows/test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ jobs:
2323
with:
2424
targets: x86_64-unknown-none
2525

26+
- name: Setup Anaxa Build System
27+
run: cargo install cargo-anaxa
28+
2629
- name: Cache Rust dependencies
2730
uses: actions/cache@v4
2831
with:

kernel/src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#[macro_use]
2121
extern crate proka_kernel;
2222
extern crate alloc;
23-
use proka_kernel::BASE_REVISION;
23+
use proka_kernel::{output::console::CONSOLE, BASE_REVISION};
2424
/* The Kernel main code */
2525
// The normal one
2626
#[unsafe(no_mangle)]
@@ -71,6 +71,7 @@ pub extern "C" fn kernel_main() -> ! {
7171

7272
let time = proka_kernel::libs::time::time_since_boot();
7373
println!("Time since boot: {time}");
74+
CONSOLE.lock().cursor_show();
7475

7576
loop {
7677
let mut buf = [0u8; 1];

kernel/src/output/console/console_bitfont.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,3 +283,87 @@ impl Write for BitfontConsole {
283283
Ok(())
284284
}
285285
}
286+
287+
// Implement the unified [`Console`] trait
288+
impl crate::output::console::Console for BitfontConsole {
289+
fn clear(&mut self) {
290+
self.position = (0, 0);
291+
unsafe {
292+
core::ptr::write_bytes(self.address, 0, (self.height * self.pitch) as usize);
293+
}
294+
}
295+
296+
fn set_fg_color(&mut self, color: Color) {
297+
self.fg_color = color;
298+
}
299+
300+
fn set_bg_color(&mut self, color: Color) {
301+
self.bg_color = color;
302+
}
303+
304+
fn get_fg_color(&self) -> Color {
305+
self.fg_color
306+
}
307+
308+
fn get_bg_color(&self) -> Color {
309+
self.bg_color
310+
}
311+
312+
fn put_char(&mut self, ch: char) {
313+
// 将 char 转换为 u8,如果是 ASCII 范围内的字符
314+
if ch.is_ascii() {
315+
self.print_char(ch as u8);
316+
} else {
317+
// 对于非 ASCII 字符,打印替换字符 '?'
318+
self.print_char(b'?');
319+
}
320+
}
321+
322+
fn cursor_up(&mut self, _lines: u32) {
323+
// TODO: Implement cursor up
324+
let y = self.position.1.saturating_sub(FONT_H * _lines as u64);
325+
self.position.1 = y;
326+
}
327+
328+
fn cursor_down(&mut self, _lines: u32) {
329+
// TODO: Implement cursor down
330+
let new_y = self.position.1 + FONT_H * _lines as u64;
331+
if new_y + FONT_H <= self.height {
332+
self.position.1 = new_y;
333+
}
334+
}
335+
336+
fn cursor_left(&mut self, _cols: u32) {
337+
// TODO: Implement cursor left
338+
let x = self.position.0.saturating_sub(FONT_W * _cols as u64);
339+
self.position.0 = x;
340+
}
341+
342+
fn cursor_right(&mut self, _cols: u32) {
343+
// TODO: Implement cursor right
344+
let new_x = self.position.0 + FONT_W * _cols as u64;
345+
if new_x + FONT_W <= self.width {
346+
self.position.0 = new_x;
347+
}
348+
}
349+
350+
fn set_cursor_pos(&mut self, x: u32, y: u32) {
351+
self.position.0 = (x as u64 * FONT_W).min(self.width - FONT_W);
352+
self.position.1 = (y as u64 * FONT_H).min(self.height - FONT_H);
353+
}
354+
355+
fn get_cursor_pos(&self) -> (u32, u32) {
356+
(
357+
(self.position.0 / FONT_W) as u32,
358+
(self.position.1 / FONT_H) as u32,
359+
)
360+
}
361+
362+
fn cursor_hide(&mut self) {
363+
// TODO: Implement cursor hide
364+
}
365+
366+
fn cursor_show(&mut self) {
367+
// TODO: Implement cursor show
368+
}
369+
}

kernel/src/output/console/console_ttf.rs

Lines changed: 126 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ impl<'a> TtfConsole<'a> {
155155
font_baseline: 0.0,
156156
cursor_needs_redraw: true,
157157
glyph_cache: GlyphCache::new(GLYPH_CACHE_SIZE),
158-
hidden_cursor: false,
158+
hidden_cursor: true,
159159
ansi_parse_state: AnsiParseState::Normal,
160160
ansi_params: [0; MAX_ANSI_PARAMS],
161161
ansi_param_count: 0,
@@ -377,7 +377,8 @@ impl<'a> TtfConsole<'a> {
377377
}
378378
}
379379

380-
pub fn put_char(&mut self, ch: char) {
380+
/// 将字符写入当前光标位置(不移动光标)
381+
fn put_char_impl(&mut self, ch: char) {
381382
self.ensure_buffer_capacity();
382383

383384
let current_buf_y = (self.cursor_y + self.scroll_offset_y as u32) as usize;
@@ -615,7 +616,7 @@ impl<'a> TtfConsole<'a> {
615616
spaces_to_add = TAB_SPACES as u32;
616617
}
617618
for _ in 0..spaces_to_add {
618-
self.put_char(' ');
619+
self.put_char_impl(' ');
619620
self.cursor_x += 1;
620621
if self.cursor_x >= self.width_chars {
621622
self.cursor_x = 0;
@@ -626,7 +627,7 @@ impl<'a> TtfConsole<'a> {
626627
}
627628
}
628629
_ => {
629-
self.put_char(c);
630+
self.put_char_impl(c);
630631
self.cursor_x += 1;
631632
if self.cursor_x >= self.width_chars {
632633
self.cursor_x = 0;
@@ -780,3 +781,124 @@ impl Write for TtfConsole<'_> {
780781
Ok(())
781782
}
782783
}
784+
785+
// Implement the unified [`Console`] trait
786+
impl<'a> crate::output::console::Console for TtfConsole<'a> {
787+
fn clear(&mut self) {
788+
self.buffer.fill(None);
789+
self.cursor_x = 0;
790+
self.cursor_y = 0;
791+
self.scroll_offset_y = 0;
792+
self.cursor_needs_redraw = true;
793+
self.redraw();
794+
}
795+
796+
fn set_fg_color(&mut self, color: Color) {
797+
if self.current_color != color {
798+
self.current_color = color;
799+
self.cursor_needs_redraw = true;
800+
}
801+
}
802+
803+
fn set_bg_color(&mut self, color: Color) {
804+
if self.current_bg_color != color {
805+
self.current_bg_color = color;
806+
self.renderer.set_clear_color(color);
807+
self.cursor_needs_redraw = true;
808+
self.redraw();
809+
}
810+
}
811+
812+
fn get_fg_color(&self) -> Color {
813+
self.current_color
814+
}
815+
816+
fn get_bg_color(&self) -> Color {
817+
self.current_bg_color
818+
}
819+
820+
fn put_char(&mut self, ch: char) {
821+
// 使用现有的 handle_normal_char 方法处理字符
822+
// 但对于普通字符,直接调用 put_char 并更新位置
823+
match ch {
824+
'\n' => {
825+
self.cursor_x = 0;
826+
self.cursor_y += 1;
827+
self.ensure_buffer_capacity();
828+
}
829+
'\r' => {
830+
self.cursor_x = 0;
831+
}
832+
'\t' => {
833+
let mut spaces_to_add = TAB_SPACES as u32 - (self.cursor_x % TAB_SPACES as u32);
834+
if spaces_to_add == 0 {
835+
spaces_to_add = TAB_SPACES as u32;
836+
}
837+
for _ in 0..spaces_to_add {
838+
self.put_char_impl(' ');
839+
self.cursor_x += 1;
840+
if self.cursor_x >= self.width_chars {
841+
self.cursor_x = 0;
842+
self.cursor_y += 1;
843+
self.ensure_buffer_capacity();
844+
break;
845+
}
846+
}
847+
}
848+
_ => {
849+
self.put_char_impl(ch);
850+
self.cursor_x += 1;
851+
if self.cursor_x >= self.width_chars {
852+
self.cursor_x = 0;
853+
self.cursor_y += 1;
854+
self.ensure_buffer_capacity();
855+
}
856+
}
857+
}
858+
self.cursor_needs_redraw = true;
859+
self.draw_cursor();
860+
self.renderer.present();
861+
}
862+
863+
fn cursor_up(&mut self, lines: u32) {
864+
self.cursor_y = self.cursor_y.saturating_sub(lines);
865+
self.cursor_needs_redraw = true;
866+
}
867+
868+
fn cursor_down(&mut self, lines: u32) {
869+
self.cursor_y = (self.cursor_y + lines).min(self.height_chars - 1);
870+
self.ensure_buffer_capacity();
871+
self.cursor_needs_redraw = true;
872+
}
873+
874+
fn cursor_left(&mut self, cols: u32) {
875+
self.cursor_x = self.cursor_x.saturating_sub(cols);
876+
self.cursor_needs_redraw = true;
877+
}
878+
879+
fn cursor_right(&mut self, cols: u32) {
880+
self.cursor_x = (self.cursor_x + cols).min(self.width_chars - 1);
881+
self.cursor_needs_redraw = true;
882+
}
883+
884+
fn set_cursor_pos(&mut self, x: u32, y: u32) {
885+
self.cursor_x = x.min(self.width_chars - 1);
886+
self.cursor_y = y;
887+
self.ensure_buffer_capacity();
888+
self.cursor_needs_redraw = true;
889+
}
890+
891+
fn get_cursor_pos(&self) -> (u32, u32) {
892+
(self.cursor_x, self.cursor_y)
893+
}
894+
895+
fn cursor_hide(&mut self) {
896+
self.hidden_cursor = true;
897+
self.cursor_needs_redraw = true;
898+
}
899+
900+
fn cursor_show(&mut self) {
901+
self.hidden_cursor = false;
902+
self.cursor_needs_redraw = true;
903+
}
904+
}

kernel/src/output/console/mod.rs

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use core::fmt::{self, Write};
22
use lazy_static::lazy_static;
33
use spin::Mutex;
44

5+
use crate::graphics::Color;
6+
57
#[cfg(ENABLE_BITFONT_CONSOLE)]
68
pub mod console_bitfont;
79
#[cfg(ENABLE_TTF_CONSOLE)]
@@ -12,47 +14,70 @@ pub use console_bitfont::BitfontConsole;
1214
#[cfg(ENABLE_TTF_CONSOLE)]
1315
pub use console_ttf::TtfConsole;
1416

15-
pub enum ConsoleImpl<'a> {
16-
#[cfg(ENABLE_BITFONT_CONSOLE)]
17-
Bitfont(BitfontConsole, core::marker::PhantomData<&'a ()>),
18-
#[cfg(ENABLE_TTF_CONSOLE)]
19-
Ttf(TtfConsole<'a>),
20-
#[cfg(not(any(ENABLE_BITFONT_CONSOLE, ENABLE_TTF_CONSOLE)))]
21-
None(core::marker::PhantomData<&'a ()>),
22-
}
17+
/// 统一的 Console trait,定义所有 console 实现的通用接口
18+
pub trait Console: Write {
19+
/// 清除屏幕
20+
fn clear(&mut self);
2321

24-
impl Write for ConsoleImpl<'_> {
25-
fn write_str(&mut self, s: &str) -> fmt::Result {
26-
match self {
27-
#[cfg(ENABLE_BITFONT_CONSOLE)]
28-
ConsoleImpl::Bitfont(c, _) => c.write_str(s),
29-
#[cfg(ENABLE_TTF_CONSOLE)]
30-
ConsoleImpl::Ttf(c) => c.write_str(s),
31-
#[cfg(not(any(ENABLE_BITFONT_CONSOLE, ENABLE_TTF_CONSOLE)))]
32-
ConsoleImpl::None(_) => Ok(()),
33-
}
34-
}
22+
/// 设置前景色
23+
fn set_fg_color(&mut self, color: Color);
24+
25+
/// 设置背景色
26+
fn set_bg_color(&mut self, color: Color);
27+
28+
/// 获取当前前景色
29+
fn get_fg_color(&self) -> Color;
30+
31+
/// 获取当前背景色
32+
fn get_bg_color(&self) -> Color;
33+
34+
/// 打印单个字符
35+
fn put_char(&mut self, ch: char);
36+
37+
/// 光标上移
38+
fn cursor_up(&mut self, lines: u32);
39+
40+
/// 光标下移
41+
fn cursor_down(&mut self, lines: u32);
42+
43+
/// 光标左移
44+
fn cursor_left(&mut self, cols: u32);
45+
46+
/// 光标右移
47+
fn cursor_right(&mut self, cols: u32);
48+
49+
/// 设置光标位置
50+
fn set_cursor_pos(&mut self, x: u32, y: u32);
51+
52+
/// 获取光标位置
53+
fn get_cursor_pos(&self) -> (u32, u32);
54+
55+
/// 隐藏光标
56+
fn cursor_hide(&mut self);
57+
58+
/// 显示光标
59+
fn cursor_show(&mut self);
3560
}
3661

62+
pub type ConsoleImpl<'a> = alloc::boxed::Box<dyn Console + Send + 'a>;
63+
3764
lazy_static! {
3865
pub static ref CONSOLE: Mutex<ConsoleImpl<'static>> = {
3966
let console_type = crate::config::DEFAULT_CONSOLE_TYPE;
4067
#[cfg(ENABLE_TTF_CONSOLE)]
4168
if console_type == "ttf" {
42-
return Mutex::new(ConsoleImpl::Ttf(TtfConsole::init()));
69+
return Mutex::new(alloc::boxed::Box::new(TtfConsole::init()));
4370
}
4471
#[cfg(ENABLE_BITFONT_CONSOLE)]
4572
if console_type == "bitfont" {
46-
return Mutex::new(ConsoleImpl::Bitfont(BitfontConsole::init(), core::marker::PhantomData));
73+
return Mutex::new(alloc::boxed::Box::new(BitfontConsole::init()));
4774
}
4875

4976
// Fallback
5077
#[cfg(ENABLE_BITFONT_CONSOLE)]
51-
return Mutex::new(ConsoleImpl::Bitfont(BitfontConsole::init(), core::marker::PhantomData));
78+
return Mutex::new(alloc::boxed::Box::new(BitfontConsole::init()));
5279
#[cfg(all(not(ENABLE_BITFONT_CONSOLE), ENABLE_TTF_CONSOLE))]
53-
return Mutex::new(ConsoleImpl::Ttf(TtfConsole::init()));
54-
#[cfg(not(any(ENABLE_BITFONT_CONSOLE, ENABLE_TTF_CONSOLE)))]
55-
return Mutex::new(ConsoleImpl::None(core::marker::PhantomData));
80+
return Mutex::new(alloc::boxed::Box::new(TtfConsole::init()));
5681
};
5782
}
5883

@@ -76,10 +101,11 @@ pub fn select_console(t: ConsoleType) {
76101
let mut console = CONSOLE.lock();
77102
*console = match t {
78103
#[cfg(ENABLE_BITFONT_CONSOLE)]
79-
ConsoleType::Bitfont => {
80-
ConsoleImpl::Bitfont(BitfontConsole::init(), core::marker::PhantomData)
81-
}
104+
ConsoleType::Bitfont => alloc::boxed::Box::new(BitfontConsole::init()),
82105
#[cfg(ENABLE_TTF_CONSOLE)]
83-
ConsoleType::Ttf => ConsoleImpl::Ttf(TtfConsole::init()),
106+
ConsoleType::Ttf => alloc::boxed::Box::new(TtfConsole::init()),
84107
};
85108
}
109+
110+
#[cfg(not(any(ENABLE_BITFONT_CONSOLE, ENABLE_TTF_CONSOLE)))]
111+
compile_error!("At least one console implementation must be enabled");

0 commit comments

Comments
 (0)