add gui in os
This commit is contained in:
parent
10e1c57b7d
commit
07029a2e5f
20 changed files with 649 additions and 4 deletions
|
@ -2,7 +2,7 @@
|
||||||
name = "os"
|
name = "os"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Yifan Wu <shinbokuow@163.com>"]
|
authors = ["Yifan Wu <shinbokuow@163.com>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
@ -18,6 +18,9 @@ k210-pac = { git = "https://github.com/wyfcyx/k210-pac" }
|
||||||
k210-hal = { git = "https://github.com/wyfcyx/k210-hal" }
|
k210-hal = { git = "https://github.com/wyfcyx/k210-hal" }
|
||||||
k210-soc = { git = "https://github.com/wyfcyx/k210-soc" }
|
k210-soc = { git = "https://github.com/wyfcyx/k210-soc" }
|
||||||
easy-fs = { path = "../easy-fs" }
|
easy-fs = { path = "../easy-fs" }
|
||||||
|
virtio-input-decoder = "0.1.4"
|
||||||
|
embedded-graphics = "0.7.1"
|
||||||
|
tinybmp = "0.3.1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
board_qemu = []
|
board_qemu = []
|
||||||
|
|
BIN
os/src/assert/desktop.bmp
Normal file
BIN
os/src/assert/desktop.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 MiB |
BIN
os/src/assert/file.bmp
Normal file
BIN
os/src/assert/file.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
os/src/assert/folder.bmp
Normal file
BIN
os/src/assert/folder.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
os/src/assert/mouse.bmp
Normal file
BIN
os/src/assert/mouse.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
69
os/src/drivers/gpu/mod.rs
Normal file
69
os/src/drivers/gpu/mod.rs
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
use crate::sync::UPIntrFreeCell;
|
||||||
|
use alloc::{sync::Arc, vec::Vec};
|
||||||
|
use core::any::Any;
|
||||||
|
use embedded_graphics::pixelcolor::Rgb888;
|
||||||
|
use tinybmp::Bmp;
|
||||||
|
use virtio_drivers::{VirtIOGpu, VirtIOHeader};
|
||||||
|
const VIRTIO7: usize = 0x10007000;
|
||||||
|
pub trait GPUDevice: Send + Sync + Any {
|
||||||
|
fn update_cursor(&self);
|
||||||
|
fn getfreambuffer(&self) -> &mut [u8];
|
||||||
|
fn flush(&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static::lazy_static!(
|
||||||
|
pub static ref GPU_DEVICE: Arc<dyn GPUDevice> = Arc::new(VirtIOGPU::new());
|
||||||
|
);
|
||||||
|
|
||||||
|
pub struct VirtIOGPU {
|
||||||
|
gpu: UPIntrFreeCell<VirtIOGpu<'static>>,
|
||||||
|
fb: &'static [u8],
|
||||||
|
}
|
||||||
|
static BMP_DATA: &[u8] = include_bytes!("../../assert/mouse.bmp");
|
||||||
|
impl VirtIOGPU {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
unsafe {
|
||||||
|
let mut virtio = VirtIOGpu::new(&mut *(VIRTIO7 as *mut VirtIOHeader)).unwrap();
|
||||||
|
|
||||||
|
let fbuffer = virtio.setup_framebuffer().unwrap();
|
||||||
|
let len = fbuffer.len();
|
||||||
|
let ptr = fbuffer.as_mut_ptr();
|
||||||
|
let fb = core::slice::from_raw_parts_mut(ptr, len);
|
||||||
|
|
||||||
|
let bmp = Bmp::<Rgb888>::from_slice(BMP_DATA).unwrap();
|
||||||
|
let raw = bmp.as_raw();
|
||||||
|
let mut b = Vec::new();
|
||||||
|
for i in raw.image_data().chunks(3) {
|
||||||
|
let mut v = i.to_vec();
|
||||||
|
b.append(&mut v);
|
||||||
|
if i == [255, 255, 255] {
|
||||||
|
b.push(0x0)
|
||||||
|
} else {
|
||||||
|
b.push(0xff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtio.setup_cursor(b.as_slice(), 50, 50, 50, 50).unwrap();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
gpu: UPIntrFreeCell::new(virtio),
|
||||||
|
fb,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GPUDevice for VirtIOGPU {
|
||||||
|
fn flush(&self) {
|
||||||
|
self.gpu.exclusive_access().flush().unwrap();
|
||||||
|
}
|
||||||
|
fn getfreambuffer(&self) -> &mut [u8] {
|
||||||
|
unsafe {
|
||||||
|
let ptr = self.fb.as_ptr() as *const _ as *mut u8;
|
||||||
|
core::slice::from_raw_parts_mut(ptr, self.fb.len())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn update_cursor(&self) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
68
os/src/drivers/input/mod.rs
Normal file
68
os/src/drivers/input/mod.rs
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
use core::any::Any;
|
||||||
|
use alloc::{sync::Arc, string::ToString};
|
||||||
|
use embedded_graphics::{text::Text, prelude::{Size, Point}};
|
||||||
|
use k210_hal::cache::Uncache;
|
||||||
|
use virtio_drivers::{VirtIOHeader, VirtIOInput};
|
||||||
|
use virtio_input_decoder::{Decoder, Key, KeyType};
|
||||||
|
use crate::{gui::{Button, Component}, sync::UPIntrFreeCell, syscall::PAD};
|
||||||
|
|
||||||
|
use super::GPU_DEVICE;
|
||||||
|
|
||||||
|
const VIRTIO5: usize = 0x10005000;
|
||||||
|
const VIRTIO6: usize = 0x10006000;
|
||||||
|
|
||||||
|
struct VirtIOINPUT(UPIntrFreeCell<VirtIOInput<'static>>);
|
||||||
|
|
||||||
|
pub trait INPUTDevice: Send + Sync + Any {
|
||||||
|
fn handler_interrupt(&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static::lazy_static!(
|
||||||
|
pub static ref KEYBOARD_DEVICE: Arc<dyn INPUTDevice> = Arc::new(VirtIOINPUT::new(VIRTIO5));
|
||||||
|
pub static ref MOUSE_DEVICE: Arc<dyn INPUTDevice> = Arc::new(VirtIOINPUT::new(VIRTIO6));
|
||||||
|
);
|
||||||
|
|
||||||
|
impl VirtIOINPUT {
|
||||||
|
pub fn new(addr: usize) -> Self {
|
||||||
|
Self(unsafe {
|
||||||
|
UPIntrFreeCell::new(VirtIOInput::new(&mut *(addr as *mut VirtIOHeader)).unwrap())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl INPUTDevice for VirtIOINPUT {
|
||||||
|
fn handler_interrupt(&self) {
|
||||||
|
let mut input = self.0.exclusive_access();
|
||||||
|
input.ack_interrupt();
|
||||||
|
let event = input.pop_pending_event().unwrap();
|
||||||
|
let dtype = match Decoder::decode(
|
||||||
|
event.event_type as usize,
|
||||||
|
event.code as usize,
|
||||||
|
event.value as usize,
|
||||||
|
) {
|
||||||
|
Ok(dtype) => dtype,
|
||||||
|
Err(_) => return,
|
||||||
|
};
|
||||||
|
match dtype {
|
||||||
|
virtio_input_decoder::DecodeType::Key(key, r#type) => {
|
||||||
|
println!("{:?} {:?}", key, r#type);
|
||||||
|
if r#type == KeyType::Press {
|
||||||
|
let mut inner = PAD.exclusive_access();
|
||||||
|
let a = inner.as_ref().unwrap();
|
||||||
|
match key.to_char() {
|
||||||
|
Ok(mut k) => {
|
||||||
|
if k == '\r' {
|
||||||
|
a.repaint(k.to_string() + "\n")
|
||||||
|
} else {
|
||||||
|
a.repaint(k.to_string())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_) => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtio_input_decoder::DecodeType::Mouse(mouse) => println!("{:?}", mouse),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,9 @@
|
||||||
pub mod block;
|
pub mod block;
|
||||||
pub mod chardev;
|
pub mod chardev;
|
||||||
pub mod plic;
|
pub mod plic;
|
||||||
|
pub mod gpu;
|
||||||
|
pub mod input;
|
||||||
pub use block::BLOCK_DEVICE;
|
pub use block::BLOCK_DEVICE;
|
||||||
pub use chardev::UART;
|
pub use chardev::UART;
|
||||||
|
pub use gpu::*;
|
||||||
|
pub use input::*;
|
|
@ -11,6 +11,6 @@ pub trait File: Send + Sync {
|
||||||
fn write(&self, buf: UserBuffer) -> usize;
|
fn write(&self, buf: UserBuffer) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use inode::{list_apps, open_file, OSInode, OpenFlags};
|
pub use inode::{list_apps, open_file, OSInode, OpenFlags,ROOT_INODE};
|
||||||
pub use pipe::{make_pipe, Pipe};
|
pub use pipe::{make_pipe, Pipe};
|
||||||
pub use stdio::{Stdin, Stdout};
|
pub use stdio::{Stdin, Stdout};
|
||||||
|
|
61
os/src/gui/button.rs
Normal file
61
os/src/gui/button.rs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
use alloc::{sync::Arc, string::String};
|
||||||
|
use embedded_graphics::{prelude::{Size, Point, Primitive, RgbColor, Dimensions}, primitives::{Rectangle, PrimitiveStyle}, pixelcolor::Rgb888, Drawable, text::{Text, Alignment}, mono_font::{ascii::{FONT_6X10, FONT_10X20}, MonoTextStyle}};
|
||||||
|
|
||||||
|
use crate::{sync::UPIntrFreeCell, drivers::GPU_DEVICE};
|
||||||
|
|
||||||
|
use super::{Component, Graphics};
|
||||||
|
|
||||||
|
pub struct Button {
|
||||||
|
inner: UPIntrFreeCell<ButtonInner>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ButtonInner {
|
||||||
|
graphic: Graphics,
|
||||||
|
text: String,
|
||||||
|
parent: Option<Arc<dyn Component>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Button {
|
||||||
|
pub fn new(size: Size, point: Point, parent: Option<Arc<dyn Component>>,text:String) -> Self {
|
||||||
|
let point = match &parent {
|
||||||
|
Some(p) => {
|
||||||
|
let (_, p) = p.bound();
|
||||||
|
Point::new(p.x + point.x,p.y + point.y)
|
||||||
|
},
|
||||||
|
None => point,
|
||||||
|
};
|
||||||
|
Self {
|
||||||
|
inner: unsafe {
|
||||||
|
UPIntrFreeCell::new(
|
||||||
|
ButtonInner {
|
||||||
|
graphic: Graphics { size, point, drv:GPU_DEVICE.clone() },
|
||||||
|
text,
|
||||||
|
parent,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for Button {
|
||||||
|
fn paint(&self) {
|
||||||
|
let mut inner = self.inner.exclusive_access();
|
||||||
|
let text = inner.text.clone();
|
||||||
|
Text::with_alignment(
|
||||||
|
text.as_str(),
|
||||||
|
inner.graphic.bounding_box().center(),
|
||||||
|
MonoTextStyle::new(&FONT_10X20, Rgb888::BLACK),
|
||||||
|
Alignment::Center
|
||||||
|
).draw(&mut inner.graphic);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add(&self, comp: alloc::sync::Arc<dyn Component>) {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bound(&self) -> (embedded_graphics::prelude::Size, embedded_graphics::prelude::Point) {
|
||||||
|
let inner = self.inner.exclusive_access();
|
||||||
|
(inner.graphic.size, inner.graphic.point)
|
||||||
|
}
|
||||||
|
}
|
56
os/src/gui/graphic.rs
Normal file
56
os/src/gui/graphic.rs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
use alloc::sync::Arc;
|
||||||
|
use embedded_graphics::{
|
||||||
|
draw_target::DrawTarget,
|
||||||
|
pixelcolor::Rgb888,
|
||||||
|
prelude::{OriginDimensions, Point, RgbColor, Size},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::drivers::{GPUDevice, GPU_DEVICE};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Graphics {
|
||||||
|
pub size: Size,
|
||||||
|
pub point: Point,
|
||||||
|
pub drv: Arc<dyn GPUDevice>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Graphics {
|
||||||
|
pub fn new(size: Size, point: Point) -> Self {
|
||||||
|
Self {
|
||||||
|
size,
|
||||||
|
point,
|
||||||
|
drv: GPU_DEVICE.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OriginDimensions for Graphics {
|
||||||
|
fn size(&self) -> Size {
|
||||||
|
self.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DrawTarget for Graphics {
|
||||||
|
type Color = Rgb888;
|
||||||
|
|
||||||
|
type Error = core::convert::Infallible;
|
||||||
|
|
||||||
|
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = embedded_graphics::Pixel<Self::Color>>,
|
||||||
|
{
|
||||||
|
let fb = self.drv.getfreambuffer();
|
||||||
|
|
||||||
|
pixels.into_iter().for_each(|px| {
|
||||||
|
let idx = ((self.point.y + px.0.y) * 1024 + self.point.x + px.0.x) as usize * 4;
|
||||||
|
if idx + 2 >= fb.len() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fb[idx] = px.1.b();
|
||||||
|
fb[idx + 1] = px.1.g();
|
||||||
|
fb[idx + 2] = px.1.r();
|
||||||
|
});
|
||||||
|
self.drv.flush();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
78
os/src/gui/icon.rs
Normal file
78
os/src/gui/icon.rs
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
|
||||||
|
|
||||||
|
use alloc::{vec::Vec, string::String, sync::Arc};
|
||||||
|
use embedded_graphics::{prelude::{Size, Point, RgbColor}, image::Image, text::Text, mono_font::{MonoTextStyle, iso_8859_13::FONT_6X12, ascii::FONT_10X20}, pixelcolor::Rgb888, Drawable};
|
||||||
|
use tinybmp::Bmp;
|
||||||
|
|
||||||
|
use crate::{sync::UPIntrFreeCell, drivers::GPU_DEVICE};
|
||||||
|
|
||||||
|
use super::{Graphics, Component, ImageComp};
|
||||||
|
|
||||||
|
static FILEICON: &[u8] = include_bytes!("../assert/file.bmp");
|
||||||
|
|
||||||
|
pub struct IconController {
|
||||||
|
inner: UPIntrFreeCell<IconControllerInner>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IconControllerInner {
|
||||||
|
files: Vec<String>,
|
||||||
|
graphic: Graphics,
|
||||||
|
parent: Option<Arc<dyn Component>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IconController {
|
||||||
|
pub fn new(files: Vec<String>,parent: Option<Arc<dyn Component>>) -> Self {
|
||||||
|
IconController {
|
||||||
|
inner: unsafe {
|
||||||
|
UPIntrFreeCell::new(
|
||||||
|
IconControllerInner {
|
||||||
|
files,
|
||||||
|
graphic: Graphics {
|
||||||
|
size: Size::new(1024, 768),
|
||||||
|
point: Point::new(0, 0),
|
||||||
|
drv: GPU_DEVICE.clone()
|
||||||
|
},
|
||||||
|
parent,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for IconController {
|
||||||
|
fn paint(&self) {
|
||||||
|
println!("demo");
|
||||||
|
let mut inner = self.inner.exclusive_access();
|
||||||
|
let mut x = 10;
|
||||||
|
let mut y = 10;
|
||||||
|
let v = inner.files.clone();
|
||||||
|
for file in v {
|
||||||
|
println!("file");
|
||||||
|
let bmp = Bmp::<Rgb888>::from_slice(FILEICON).unwrap();
|
||||||
|
Image::new(&bmp, Point::new(x, y),).draw(&mut inner.graphic);
|
||||||
|
let text = Text::new(
|
||||||
|
file.as_str(),
|
||||||
|
Point::new(x + 20, y + 80),
|
||||||
|
MonoTextStyle::new(&FONT_10X20,Rgb888::BLACK)
|
||||||
|
);
|
||||||
|
text.draw(&mut inner.graphic);
|
||||||
|
if y >= 600 {
|
||||||
|
x = x + 70;
|
||||||
|
y = 10;
|
||||||
|
} else {
|
||||||
|
y = y + 90;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add(&self, comp: Arc<dyn Component>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bound(&self) -> (Size, Point) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
72
os/src/gui/image.rs
Normal file
72
os/src/gui/image.rs
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
use alloc::{vec::Vec, sync::Arc};
|
||||||
|
use embedded_graphics::{
|
||||||
|
image::Image,
|
||||||
|
prelude::{Point, Size}, pixelcolor::Rgb888, Drawable,
|
||||||
|
};
|
||||||
|
use tinybmp::Bmp;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
drivers::{BLOCK_DEVICE, GPU_DEVICE},
|
||||||
|
sync::UPIntrFreeCell,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{Graphics, Component};
|
||||||
|
|
||||||
|
pub struct ImageComp {
|
||||||
|
|
||||||
|
inner: UPIntrFreeCell<ImageInner>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ImageInner {
|
||||||
|
image: &'static [u8],
|
||||||
|
graphic: Graphics,
|
||||||
|
parent: Option<Arc<dyn Component>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ImageComp {
|
||||||
|
pub fn new(size: Size, point: Point, v: &'static [u8],parent: Option<Arc<dyn Component>>) -> Self {
|
||||||
|
unsafe {
|
||||||
|
ImageComp {
|
||||||
|
inner: UPIntrFreeCell::new(ImageInner {
|
||||||
|
parent,
|
||||||
|
image: v,
|
||||||
|
graphic: Graphics {
|
||||||
|
size,
|
||||||
|
point,
|
||||||
|
drv: GPU_DEVICE.clone(),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for ImageComp {
|
||||||
|
fn paint(&self) {
|
||||||
|
let mut inner = self.inner.exclusive_access();
|
||||||
|
let b = unsafe {
|
||||||
|
let len = inner.image.len();
|
||||||
|
let ptr = inner.image
|
||||||
|
.as_ptr() as *const u8;
|
||||||
|
core::slice::from_raw_parts(ptr, len)
|
||||||
|
};
|
||||||
|
let bmp = Bmp::<Rgb888>::from_slice(b).unwrap();
|
||||||
|
let point = match &inner.parent {
|
||||||
|
Some(parent) => {
|
||||||
|
let (_, point) = parent.bound();
|
||||||
|
Point::new(point.x + inner.graphic.point.x, point.y + inner.graphic.point.y)
|
||||||
|
}
|
||||||
|
None => inner.graphic.point,
|
||||||
|
};
|
||||||
|
Image::new(&bmp, point,).draw(&mut inner.graphic);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add(&self, comp: alloc::sync::Arc<dyn Component>) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bound(&self) -> (Size, Point) {
|
||||||
|
let inner = self.inner.exclusive_access();
|
||||||
|
(inner.graphic.size, inner.graphic.point)
|
||||||
|
}
|
||||||
|
}
|
21
os/src/gui/mod.rs
Normal file
21
os/src/gui/mod.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
mod graphic;
|
||||||
|
mod image;
|
||||||
|
mod panel;
|
||||||
|
mod icon;
|
||||||
|
mod button;
|
||||||
|
mod terminal;
|
||||||
|
use alloc::sync::Arc;
|
||||||
|
use embedded_graphics::prelude::{Size, Point};
|
||||||
|
use core::any::Any;
|
||||||
|
pub use graphic::*;
|
||||||
|
pub use panel::*;
|
||||||
|
pub use image::*;
|
||||||
|
pub use icon::*;
|
||||||
|
pub use terminal::*;
|
||||||
|
pub use button::*;
|
||||||
|
|
||||||
|
pub trait Component: Send + Sync + Any {
|
||||||
|
fn paint(&self);
|
||||||
|
fn add(&self, comp: Arc<dyn Component>);
|
||||||
|
fn bound(&self) -> (Size, Point);
|
||||||
|
}
|
66
os/src/gui/panel.rs
Normal file
66
os/src/gui/panel.rs
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
use alloc::{collections::VecDeque, sync::Arc, rc::Weak};
|
||||||
|
use embedded_graphics::{
|
||||||
|
pixelcolor::Rgb888,
|
||||||
|
prelude::{Point, Primitive, RgbColor, Size},
|
||||||
|
primitives::{PrimitiveStyle, Rectangle},
|
||||||
|
Drawable,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{drivers::GPU_DEVICE, sync::UPIntrFreeCell};
|
||||||
|
|
||||||
|
use super::{Component, Graphics};
|
||||||
|
|
||||||
|
pub struct Panel {
|
||||||
|
inner: UPIntrFreeCell<PanelInner>,
|
||||||
|
}
|
||||||
|
struct PanelInner {
|
||||||
|
graphic: Graphics,
|
||||||
|
comps: VecDeque<Arc<dyn Component>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Panel {
|
||||||
|
pub fn new(size: Size, point: Point) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: unsafe {
|
||||||
|
UPIntrFreeCell::new(PanelInner {
|
||||||
|
graphic: Graphics {
|
||||||
|
size,
|
||||||
|
point,
|
||||||
|
drv: GPU_DEVICE.clone(),
|
||||||
|
},
|
||||||
|
comps: VecDeque::new(),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for Panel {
|
||||||
|
fn paint(&self) {
|
||||||
|
let mut inner = self.inner.exclusive_access();
|
||||||
|
|
||||||
|
Rectangle::new(Point::new(0, 0), inner.graphic.size)
|
||||||
|
.into_styled(PrimitiveStyle::with_fill(Rgb888::WHITE))
|
||||||
|
.draw(&mut inner.graphic)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let len = inner.comps.len();
|
||||||
|
drop(inner);
|
||||||
|
for i in 0..len {
|
||||||
|
let mut inner = self.inner.exclusive_access();
|
||||||
|
let comp = Arc::downgrade(&inner.comps[i]);
|
||||||
|
drop(inner);
|
||||||
|
comp.upgrade().unwrap().paint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add(&self, comp: alloc::sync::Arc<dyn Component>) {
|
||||||
|
let mut inner = self.inner.exclusive_access();
|
||||||
|
inner.comps.push_back(comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bound(&self) -> (Size, Point) {
|
||||||
|
let inner = self.inner.exclusive_access();
|
||||||
|
(inner.graphic.size, inner.graphic.point)
|
||||||
|
}
|
||||||
|
}
|
89
os/src/gui/terminal.rs
Normal file
89
os/src/gui/terminal.rs
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
use alloc::{collections::VecDeque, sync::Arc, string::{String, ToString}};
|
||||||
|
use embedded_graphics::{prelude::{Size, Point, RgbColor, Primitive, Dimensions}, text::{Text, Alignment}, mono_font::{MonoTextStyle, ascii::FONT_10X20}, pixelcolor::Rgb888, Drawable, primitives::{Rectangle, PrimitiveStyle}};
|
||||||
|
|
||||||
|
use crate::{sync::UPIntrFreeCell, drivers::GPU_DEVICE};
|
||||||
|
|
||||||
|
use super::{Graphics, Component, Panel, button::Button};
|
||||||
|
|
||||||
|
pub struct Terminal {
|
||||||
|
inner: UPIntrFreeCell<TerminalInner>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TerminalInner {
|
||||||
|
pub text: String,
|
||||||
|
titel:Option<String>,
|
||||||
|
graphic: Graphics,
|
||||||
|
comps: VecDeque<Arc<dyn Component>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Terminal {
|
||||||
|
pub fn new(size: Size, point: Point, parent: Option<Arc<dyn Component>>,titel: Option<String>,text:String) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: unsafe {
|
||||||
|
UPIntrFreeCell::new(
|
||||||
|
TerminalInner {
|
||||||
|
text,
|
||||||
|
titel,
|
||||||
|
graphic: Graphics {
|
||||||
|
size,
|
||||||
|
point,
|
||||||
|
drv: GPU_DEVICE.clone(),
|
||||||
|
},
|
||||||
|
comps: VecDeque::new(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn repaint(&self, text:String){
|
||||||
|
let mut inner = self.inner.exclusive_access();
|
||||||
|
inner.text += text.as_str();
|
||||||
|
Text::with_alignment(
|
||||||
|
inner.text.clone().as_str(),
|
||||||
|
Point::new( 20, 50),
|
||||||
|
MonoTextStyle::new(&FONT_10X20, Rgb888::BLACK),
|
||||||
|
Alignment::Left
|
||||||
|
).draw(&mut inner.graphic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for Terminal {
|
||||||
|
fn paint(&self) {
|
||||||
|
let mut inner = self.inner.exclusive_access();
|
||||||
|
let len = inner.comps.len();
|
||||||
|
drop(inner);
|
||||||
|
for i in 0..len {
|
||||||
|
let mut inner = self.inner.exclusive_access();
|
||||||
|
let comp = Arc::downgrade(&inner.comps[i]);
|
||||||
|
drop(inner);
|
||||||
|
comp.upgrade().unwrap().paint();
|
||||||
|
}
|
||||||
|
let mut inner = self.inner.exclusive_access();
|
||||||
|
let titel = inner.titel.get_or_insert("No Titel".to_string()).clone();
|
||||||
|
let text = Text::new(
|
||||||
|
titel.as_str(),
|
||||||
|
Point::new(20, 20),
|
||||||
|
MonoTextStyle::new(&FONT_10X20,Rgb888::BLACK)
|
||||||
|
);
|
||||||
|
text.draw(&mut inner.graphic);
|
||||||
|
|
||||||
|
Text::with_alignment(
|
||||||
|
inner.text.clone().as_str(),
|
||||||
|
Point::new( 20, 50),
|
||||||
|
MonoTextStyle::new(&FONT_10X20, Rgb888::BLACK),
|
||||||
|
Alignment::Left
|
||||||
|
).draw(&mut inner.graphic);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add(&self, comp: Arc<dyn Component>) {
|
||||||
|
let mut inner = self.inner.exclusive_access();
|
||||||
|
inner.comps.push_back(comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bound(&self) -> (Size, Point) {
|
||||||
|
let inner = self.inner.exclusive_access();
|
||||||
|
(inner.graphic.size, inner.graphic.point)
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,8 @@
|
||||||
#![feature(panic_info_message)]
|
#![feature(panic_info_message)]
|
||||||
#![feature(alloc_error_handler)]
|
#![feature(alloc_error_handler)]
|
||||||
|
|
||||||
|
use crate::drivers::{GPU_DEVICE, KEYBOARD_DEVICE, MOUSE_DEVICE};
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -28,6 +30,7 @@ mod syscall;
|
||||||
mod task;
|
mod task;
|
||||||
mod timer;
|
mod timer;
|
||||||
mod trap;
|
mod trap;
|
||||||
|
mod gui;
|
||||||
|
|
||||||
core::arch::global_asm!(include_str!("entry.asm"));
|
core::arch::global_asm!(include_str!("entry.asm"));
|
||||||
|
|
||||||
|
@ -54,6 +57,9 @@ lazy_static! {
|
||||||
pub fn rust_main() -> ! {
|
pub fn rust_main() -> ! {
|
||||||
clear_bss();
|
clear_bss();
|
||||||
mm::init();
|
mm::init();
|
||||||
|
GPU_DEVICE.clone();
|
||||||
|
KEYBOARD_DEVICE.clone();
|
||||||
|
MOUSE_DEVICE.clone();
|
||||||
trap::init();
|
trap::init();
|
||||||
trap::enable_timer_interrupt();
|
trap::enable_timer_interrupt();
|
||||||
timer::set_next_trigger();
|
timer::set_next_trigger();
|
||||||
|
|
51
os/src/syscall/gui.rs
Normal file
51
os/src/syscall/gui.rs
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
use alloc::{sync::Arc, vec::{Vec, }, string::ToString};
|
||||||
|
use embedded_graphics::{prelude::{Point, Size}, primitives::arc};
|
||||||
|
|
||||||
|
use crate::{gui::{Component, Panel, ImageComp, IconController, Terminal, Button}, fs::ROOT_INODE, sync::UPIntrFreeCell};
|
||||||
|
|
||||||
|
static DT: &[u8] = include_bytes!("../assert/desktop.bmp");
|
||||||
|
|
||||||
|
lazy_static::lazy_static!(
|
||||||
|
pub static ref DESKTOP:UPIntrFreeCell<Arc<dyn Component>> = unsafe {
|
||||||
|
UPIntrFreeCell::new(Arc::new(Panel::new(Size::new(1024, 768), Point::new(0, 0))))
|
||||||
|
};
|
||||||
|
pub static ref PAD:UPIntrFreeCell<Option<Arc<Terminal>>> = unsafe {
|
||||||
|
UPIntrFreeCell::new(None)
|
||||||
|
};
|
||||||
|
);
|
||||||
|
|
||||||
|
pub fn create_desktop() -> isize {
|
||||||
|
let mut p:Arc<dyn Component + 'static> = Arc::new(Panel::new(Size::new(1024, 768), Point::new(0, 0)));
|
||||||
|
let image = ImageComp::new(Size::new(1024, 768),Point::new(0, 0),DT,Some(p.clone()));
|
||||||
|
let icon = IconController::new(ROOT_INODE.ls(), Some(p.clone()));
|
||||||
|
p.add(Arc::new(image));
|
||||||
|
p.add(Arc::new(icon));
|
||||||
|
let mut desktop = DESKTOP.exclusive_access();
|
||||||
|
*desktop = p;
|
||||||
|
desktop.paint();
|
||||||
|
drop(desktop);
|
||||||
|
create_terminal();
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_terminal() {
|
||||||
|
let desktop = DESKTOP.exclusive_access();
|
||||||
|
let arc_t = Arc::new(
|
||||||
|
Terminal::new(
|
||||||
|
Size::new(400, 400),
|
||||||
|
Point::new(200, 100),
|
||||||
|
Some(desktop.clone()),
|
||||||
|
Some("demo.txt".to_string()),
|
||||||
|
"".to_string()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
let text = Panel::new(Size::new(400, 400), Point::new(200, 100));
|
||||||
|
let button = Button::new(Size::new(20, 20), Point::new(370, 10), Some(arc_t.clone()), "X".to_string());
|
||||||
|
arc_t.add(Arc::new(text));
|
||||||
|
arc_t.add(Arc::new(button));
|
||||||
|
arc_t.paint();
|
||||||
|
desktop.add(arc_t.clone());
|
||||||
|
let mut pad = PAD.exclusive_access();
|
||||||
|
*pad = Some(arc_t);
|
||||||
|
}
|
||||||
|
|
|
@ -30,11 +30,13 @@ mod fs;
|
||||||
mod process;
|
mod process;
|
||||||
mod sync;
|
mod sync;
|
||||||
mod thread;
|
mod thread;
|
||||||
|
mod gui;
|
||||||
|
|
||||||
use fs::*;
|
use fs::*;
|
||||||
use process::*;
|
use process::*;
|
||||||
use sync::*;
|
use sync::*;
|
||||||
use thread::*;
|
use thread::*;
|
||||||
|
pub use gui::PAD;
|
||||||
|
|
||||||
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
|
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
|
||||||
match syscall_id {
|
match syscall_id {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue