Selaa lähdekoodia

实现基本的C/S框架 (#1)

R0ronoa 1 vuosi sitten
vanhempi
commit
bee61dca28

+ 6 - 0
.vscode/settings.json

@@ -0,0 +1,6 @@
+{
+    "rust-analyzer.linkedProjects": [
+        "./starry_client/Cargo.toml",
+        "./starry_server/Cargo.toml",
+    ],
+}

+ 2 - 0
starry_client/.cargo/config.toml

@@ -0,0 +1,2 @@
+[build]
+target = "x86_64-unknown-linux-musl"

+ 10 - 0
starry_client/Cargo.toml

@@ -0,0 +1,10 @@
+[package]
+name = "starry_client"
+version = "0.1.0"
+edition = "2021"
+description = "The client of Starry Engine"
+authors = [ "2447742618 <2447742618@qq.com>" ]
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]

+ 41 - 0
starry_client/Makefile

@@ -0,0 +1,41 @@
+# The toolchain we use.
+# You can get it by running DragonOS' `tools/bootstrap.sh`
+TOOLCHAIN="+nightly-2023-08-15-x86_64-unknown-linux_dragonos-gnu"
+RUSTFLAGS+="-C target-feature=+crt-static -C link-arg=-no-pie"
+
+# 如果是在dadk中编译,那么安装到dadk的安装目录中
+INSTALL_DIR?=$(DADK_CURRENT_BUILD_DIR)
+# 如果是在本地编译,那么安装到当前目录下的install目录中
+INSTALL_DIR?=./install
+
+
+run:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run
+
+build:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build
+
+clean:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean
+
+test:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test
+
+doc:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) doc
+
+run-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --release
+
+build-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --release
+
+clean-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --release
+
+test-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --release
+
+.PHONY: install
+install: 
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --path . --no-track --root $(INSTALL_DIR) --force

+ 82 - 0
starry_client/src/base/color.rs

@@ -0,0 +1,82 @@
+use core::fmt;
+
+/// 一个像素的颜色值
+#[derive(Clone, Copy)]
+pub struct Color {
+    /// ARGB
+    pub data: u32,
+}
+
+#[allow(dead_code)]
+impl Color {
+    /// 通过RGB值创建颜色(不透明)
+    pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
+        Color {
+            data: 0xFF000000 | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32),
+        }
+    }
+
+    /// 通过RGBA值创建颜色
+    pub const fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
+        Color {
+            data : ((a as u32) << 24) | ((r as u32) << 16) | (g as u32) << 8 | (b as u32),
+        }
+    }
+
+    /// 获取R值
+    pub fn r(&self) -> u8 {
+        ((self.data & 0x00FF0000) >> 16) as u8
+    }
+
+    /// 获取G值
+    pub fn g(&self) -> u8 {
+        ((self.data & 0x0000FF00) >> 8) as u8
+    }
+
+    /// 获取B值
+    pub fn b(&self) -> u8 {
+        (self.data & 0x000000FF) as u8
+    }
+
+    /// 获取A值
+    pub fn a(&self) -> u8 {
+        ((self.data & 0xFF000000) >> 24) as u8
+    }
+
+    /// 颜色插值
+    pub fn interpolate(from_color: Color, to_color: Color, scale: f64) -> Color {
+        let r = Color::value_interpolate(from_color.r(), to_color.r(), scale);
+        let g = Color::value_interpolate(from_color.r(), to_color.r(), scale);
+        let b = Color::value_interpolate(from_color.r(), to_color.r(), scale);
+        let a = Color::value_interpolate(from_color.r(), to_color.r(), scale);
+        Color::rgba(r, g, b, a)
+    }
+
+    /// 颜色值插值
+    fn value_interpolate(from_value: u8, to_value: u8, scale: f64) -> u8 {
+        ((to_value as f64 - from_value as f64) * scale + from_value as f64) as u8
+    }
+
+    /// 转化为RGBA字节形式
+    pub fn to_rgba_bytes(&self) -> [u8; 4] {
+        [self.r(), self.g(), self.b(), self.a()]
+    }
+
+    /// 转化为BGRA字节形式(DragonOS帧缓冲数据格式)
+    pub fn to_bgra_bytes(&self) -> [u8; 4] {
+        [self.b(), self.g(), self.r(), self.a()]
+    }
+}
+
+/// 比较两个颜色值(不考虑透明度)
+impl PartialEq for Color {
+    fn eq(&self, other: &Self) -> bool {
+        self.r() == other.r() && self.g() == other.g() && self.b() == other.b()
+    }
+}
+
+impl fmt::Debug for Color {
+    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+        write!(f, "{:#010X}", { self.data })
+    }
+}

+ 174 - 0
starry_client/src/base/event.rs

@@ -0,0 +1,174 @@
+#[derive(Copy, Clone, Debug)]
+pub enum EventOption {
+    /// 按键事件
+    Key(KeyEvent),
+    /// 鼠标相对移动事件
+    MouseRelative(MouseRelativeEvent),
+    /// 鼠标按键事件
+    Button(ButtonEvent),
+    /// 空事件
+    None,
+    /// 未知事件
+    Unknown,    
+}
+
+/// TODO: 整理
+pub const EVENT_NONE: i64 = 0;
+pub const EVENT_KEY: i64 = 1;
+pub const EVENT_MOUSE_RELATIVE: i64 = 2;
+pub const EVENT_BUTTON: i64 = 3;
+pub const EVENT_MOUSE_UPDATE: i64 = 4;
+
+/// 通用事件
+#[derive(Copy, Clone, Debug)]
+pub struct Event {
+    pub code: i64,
+    pub a: i64,
+    pub b: i64,
+}
+
+impl Event {
+    pub fn new() -> Event {
+        Event {
+            code: 0,
+            a: 0,
+            b: 0,
+        }
+    }
+
+    pub fn to_option(self) -> EventOption {
+        match self.code {
+            EVENT_NONE => EventOption::None,
+            EVENT_KEY => EventOption::Key(KeyEvent::from_event(self)),
+            EVENT_MOUSE_RELATIVE => EventOption::MouseRelative(MouseRelativeEvent::from_event(self)),
+            EVENT_BUTTON => EventOption::Button(ButtonEvent::from_event(self)),
+            _ => EventOption::Unknown,
+        }
+    }
+}
+
+/// 键盘按键事件
+#[derive(Copy, Clone, Debug)]
+pub struct KeyEvent {
+    /// 按键字符
+    pub character: char,
+    /// 按键扫描码
+    pub scancode: u8,
+    /// 是否按下
+    pub pressed: bool,
+}
+
+impl KeyEvent {
+    /// 转换为Event
+    pub fn to_event(&self) -> Event {
+        Event {
+            code: EVENT_KEY,
+            a: self.character as i64,
+            b: self.scancode as i64 | (self.pressed as i64) << 8,
+        }
+    }
+
+    /// 从Event转换为KeyEvent
+    pub fn from_event(event: Event) -> KeyEvent {
+        KeyEvent {
+            character: char::from_u32(event.a as u32).unwrap_or('\0'),
+            scancode: event.b as u8,
+            pressed: event.b & (1 << 8) == (1 << 8),
+        }
+    }
+}
+
+/// 鼠标相对移动事件
+#[derive(Copy, Clone, Debug)]
+pub struct MouseRelativeEvent {
+    /// x轴向上的相对运动
+    pub dx: i32,
+    /// y轴向上的相对运动
+    pub dy: i32,
+}
+
+impl MouseRelativeEvent {
+    /// 转换为Event
+    pub fn to_event(&self) -> Event {
+        Event {
+            code: EVENT_MOUSE_RELATIVE,
+            a: self.dx as i64,
+            b: self.dy as i64,
+        }
+    }
+
+    /// 从Event转换为MouseRelativeEvent
+    pub fn from_event(event: Event) -> MouseRelativeEvent {
+        MouseRelativeEvent {
+            dx: event.a as i32,
+            dy: event.b as i32,
+        }
+    }
+}
+
+/// TODO: 按键松开事件
+/// 鼠标按键事件
+#[derive(Clone, Copy, Debug)]
+pub struct ButtonEvent {
+    /// 左键是否按下
+    pub left: bool,
+    /// 右键是否按下
+    pub right: bool,
+    /// 中键是否按下
+    pub middle: bool,
+}
+
+impl ButtonEvent {
+    pub fn new(byte: u8) -> Self {
+        ButtonEvent {
+            left: byte & (1 << 0) == 1,
+            middle: byte & (1 << 1) == 1,
+            right: byte & (1 << 2) == 1,
+        }
+    }
+
+    /// 转换为Event
+    pub fn to_event(&self) -> Event {
+        Event {
+            code: EVENT_BUTTON,
+            a: self.left as i64 | (self.middle as i64) << 1 | (self.right as i64) << 2,
+            b: 0    
+        }
+    }
+
+    /// 从Event转换为ButtonEvent
+    pub fn from_event(event: Event) -> ButtonEvent {
+        ButtonEvent {
+            left: event.a & (1 << 0)  == 1,
+            middle: event.a & (1 << 1) == 1,
+            right: event.a & (1 << 2) == 1
+        }
+    }
+}
+
+/// 鼠标位置更新事件
+pub struct MouseUpdateEvent {
+    /// 更新后鼠标位置x坐标
+    pub x: i32,
+    /// 更新后鼠标位置y坐标
+    pub y: i32,
+}
+
+impl MouseUpdateEvent {
+    /// 转换为Event
+    pub fn to_event(&self) -> Event {
+        Event {
+            code: EVENT_MOUSE_UPDATE,
+            a: self.x as i64,
+            b: self.y as i64,
+        }
+    }
+
+    /// 从Event转换为MouseUpdateEvent
+    pub fn from_event(event: Event) -> MouseUpdateEvent {
+        MouseUpdateEvent {
+            x: event.a as i32,
+            y: event.b as i32,
+        }
+    }
+}

+ 120 - 0
starry_client/src/base/graphicspath.rs

@@ -0,0 +1,120 @@
+/// 路径中点的类型
+pub enum PointType {
+    Move,
+    Connect,
+}
+
+/// 表示一条几何路径
+pub struct GraphicsPath {
+    /// 当前点x坐标
+    x: i32,
+    /// 当前点y坐标
+    y: i32,
+    /// 点集合
+    pub points: Vec<(i32, i32, PointType)>,
+}
+
+#[allow(dead_code)]
+impl GraphicsPath {
+    pub fn new() -> GraphicsPath {
+        GraphicsPath {
+            x: 0,
+            y: 0,
+            points: Vec::new(),
+        }
+    }
+
+    /// 移动值指定点
+    pub fn move_to(&mut self, x: i32, y: i32) {
+        self.points.push((x, y, PointType::Move));
+        self.x = x;
+        self.y = y;
+    }
+
+    /// 连线至指定点
+    pub fn line_to(&mut self, x: i32, y: i32) {
+        self.points.push((x, y, PointType::Connect));
+        self.x = x;
+        self.y = y;
+    }
+
+    /// 绘制一条二次贝塞尔曲线
+    pub fn quadratic_bezier_curve_to(&mut self, argx1: i32, argy1: i32, argx2: i32, argy2: i32) {
+        let mut t: f32 = 0.0;
+        let mut u: f32;
+        let mut tt: f32;
+        let mut uu: f32;
+        let mut x: f32;
+        let mut y: f32;
+
+        // 根据二次贝塞尔曲线公式,构造一百个点
+        while t < 1.0 {
+            u = 1.0 - t;
+            uu = u * u;
+            tt = t * t;
+
+            x = (self.x as f32) * uu;
+            y = (self.y as f32) * uu;
+            
+
+            x += 2.0 * u * t * (argx1 as f32);
+            y += 2.0 * u * t * (argy1 as f32);
+
+            x += tt * (argx2 as f32);
+            y += tt * (argy2 as f32);
+
+            t += 0.01;
+            self.points.push((x as i32, y as i32, PointType::Connect));
+        }
+
+        self.x = argx2;
+        self.y = argy2;
+    }
+
+    /// 绘制一条三次贝塞尔曲线
+    pub fn cubic_bezier_curve_to(
+        &mut self,
+        argx1: i32,
+        argy1: i32,
+        argx2: i32,
+        argy2: i32,
+        argx3: i32,
+        argy3: i32,
+    ) {
+        let mut t: f32 = 0.0;
+        let mut u: f32;
+        let mut tt: f32;
+        let mut uu: f32;
+        let mut uuu: f32;
+        let mut ttt: f32;
+        let mut x: f32;
+        let mut y: f32;
+
+        // 根据三次贝塞尔曲线公式,构造一百个点
+        while t < 1.0 {
+            u = 1.0 - t;
+            tt = t * t;
+            uu = u * u;
+            uuu = uu * u;
+            ttt = tt * t;
+
+            x = (self.x as f32) * uuu;
+            y = (self.y as f32) * uuu;
+
+            x += 3.0 * uu * t * (argx1 as f32);
+            y += 3.0 * uu * t * (argy1 as f32);
+
+            x += 3.0 * u * tt * (argx2 as f32);
+            y += 3.0 * u * tt * (argy2 as f32);
+
+            x += ttt * (argx3 as f32);
+            y += ttt * (argy3 as f32);
+
+            t += 0.01;
+            self.points.push((x as i32, y as i32, PointType::Connect));
+        }
+
+        self.x = argx3;
+        self.y = argy3;
+    }
+}

+ 4 - 0
starry_client/src/base/mod.rs

@@ -0,0 +1,4 @@
+pub mod color;
+pub mod graphicspath;
+pub mod renderer;
+pub mod event;

+ 226 - 0
starry_client/src/base/renderer.rs

@@ -0,0 +1,226 @@
+use std::{cell::Cell, cmp};
+
+use super::{
+    color::Color,
+    graphicspath::{GraphicsPath, PointType},
+};
+
+#[derive(Clone, Copy, Debug)]
+pub enum RenderMode {
+    /// 颜色混合
+    Blend,
+    /// 颜色覆盖
+    Overwrite,
+}
+
+/// 用于进行渲染
+pub trait Renderer {
+    /// 获取渲染窗口宽度
+    fn width(&self) -> u32;
+
+    /// 获取渲染窗口高度
+    fn height(&self) -> u32;
+
+    /// 获取帧缓冲数据
+    fn data(&self) -> &[Color];
+
+    /// 获取可变帧缓存数据
+    fn data_mut(&mut self) -> &mut [Color];
+
+    /// 同步数据
+    fn sync(&mut self) -> bool;
+
+    /// 获取/设置渲染模式
+    fn mode(&self) -> &Cell<RenderMode>;
+
+    /// # 函数功能
+    /// 绘制指定位置的像素(左下角为原点)
+    ///
+    /// ## 参数
+    /// - x: 像素x坐标
+    /// - y: 像素y坐标
+    /// - color: 像素颜色值
+    fn pixel(&mut self, x: i32, y: i32, color: Color) {
+        let replace = match self.mode().get() {
+            RenderMode::Blend => false,
+            RenderMode::Overwrite => true,
+        };
+        let w = self.width();
+        let h = self.height();
+        let data = self.data_mut();
+
+        if x >= 0 && y >= 0 && x < w as i32 && y < h as i32 {
+            let new_color = color.data;
+            let alpha = (new_color >> 24) & 0xFF;
+            let old_color = &mut data[y as usize * w as usize + x as usize].data;
+
+            if alpha >= 255 || replace {
+                *old_color = new_color;
+            }
+            // 颜色混合算法(效率更高的实现方法)
+            else if alpha > 0 {
+                let n_alpha = 255 - alpha;
+                let rb = ((n_alpha * (*old_color & 0x00FF00FF))
+                    + (alpha * (new_color & 0x00FF00FF)))
+                    >> 8;
+                let ag = (n_alpha * ((*old_color & 0xFF00FF00) >> 8))
+                    + (alpha * (0x01000000 | ((new_color & 0x0000FF00) >> 8)));
+
+                *old_color = (rb & 0x00FF00FF) | (ag & 0xFF00FF00);
+            }
+        }
+    }
+
+    #[allow(unused_variables)]
+    /// TODO
+    fn arc(&mut self, x0: i32, y0: i32, radius: i32, parts: u8, color: Color) {}
+    #[allow(unused_variables)]
+    /// TODO
+    fn circle(&mut self, x0: i32, y0: i32, radius: i32, color: Color) {}
+    #[allow(unused_variables)]
+    /// TODO
+    fn line4points(&mut self, argx1: i32, argy1: i32, argx2: i32, argy2: i32, color: Color) {}
+    #[allow(unused_variables)]
+    /// TODO
+    /// # 函数功能
+    /// 绘制指定颜色的一条线段
+    /// 
+    /// ## 参数
+    /// - argx1: 起点x坐标
+    /// - argy1: 起点y坐标
+    /// - argx2: 终点x坐标
+    /// - argy2: 终点y坐标
+    /// - color:绘制颜色
+    fn line(&mut self, argx1: i32, argy1: i32, argx2: i32, argy2: i32, color: Color) {}
+
+    /// # 函数功能
+    /// 绘制指定颜色的若干线段(首尾相连)
+    /// 
+    /// ## 参数
+    /// - points: 点集合
+    /// - color: 绘制颜色
+    fn lines(&mut self, points: &[[i32; 2]], color: Color) {
+        if points.is_empty() {
+        } else if points.len() == 1 {
+            self.pixel(points[0][0], points[0][1], color);
+        } else {
+            for i in 0..points.len() - 1 {
+                self.line(
+                    points[i][0],
+                    points[i][1],
+                    points[i + 1][0],
+                    points[i + 1][1],
+                    color,
+                );
+            }
+        }
+    }
+
+    /// # 函数功能
+    /// 绘制一条指定颜色的几何路径
+    ///
+    /// ## 参数
+    /// - graphicspath: 几何路径
+    /// - color: 绘制颜色
+    fn draw_path(&mut self, graphicspath: GraphicsPath, color: Color) {
+        let mut x: i32 = 0;
+        let mut y: i32 = 0;
+
+        for point in graphicspath.points {
+            if let PointType::Connect = point.2 {
+                self.line(x, y, point.0, point.1, color);
+            }
+            x = point.0;
+            y = point.1;
+        }
+    }
+
+    /// # 函数功能
+    /// 绘制单一颜色的矩形
+    ///
+    /// ## 参数
+    /// - x: 起始x坐标
+    /// - y: 起始y坐标
+    /// - w: 矩形宽度
+    /// - h: 矩形高度
+    /// - color: 矩形颜色
+    fn rect(&mut self, x: i32, y: i32, w: u32, h: u32, color: Color) {
+        let replace = match self.mode().get() {
+            RenderMode::Blend => false,
+            RenderMode::Overwrite => true,
+        };
+        let self_w = self.width();
+        let self_h = self.height();
+
+        let start_y = cmp::max(0, cmp::min(self_h as i32 - 1, y));
+        let end_y = cmp::max(start_y, cmp::min(self_h as i32, y + h as i32));
+
+        let start_x = cmp::max(0, cmp::min(self_w as i32 - 1, x));
+        let end_x = cmp::max(start_x, cmp::min(self_w as i32, x + w as i32));
+        let len_x = end_x - start_x;
+
+        let alpha = (color.data >> 24) & 0xFF;
+
+        if alpha >= 255 || replace {
+            let data = self.data_mut();
+            let data_ptr = data.as_mut_ptr();
+            for y in start_y..end_y {
+                let start = (y * self_w as i32 + start_x) as isize;
+                let end = start + len_x as isize;
+                for i in start..end {
+                    unsafe {
+                        *data_ptr.offset(i) = color;
+                    }
+                }
+            }
+        } else {
+            for y in start_y..end_y {
+                for x in start_x..end_x {
+                    self.pixel(x, y, color);
+                }
+            }
+        }
+    }
+
+    /// # 函数功能
+    /// 将整个窗口填充单一颜色
+    ///
+    /// ## 参数
+    /// - color: 窗口颜色
+    fn set(&mut self, color: Color) {
+        let data = self.data_mut();
+        let data_ptr = data.as_mut_ptr();
+        for i in 0..data.len() as isize {
+            unsafe {
+                *data_ptr.offset(i) = color;
+            }
+        }
+    }
+
+    /// # 函数功能
+    /// 将整个窗口置黑
+    fn clear(&mut self) {
+        self.set(Color::rgb(0, 0, 0));
+    }
+
+    /// # 函数功能
+    /// 获取指定坐标的像素颜色
+    ///
+    /// ## 参数
+    /// - x: x坐标
+    /// - y: y坐标
+    ///
+    /// ## 返回值
+    /// 像素颜色
+    fn get_pixel(&self, x: i32, y: i32) -> Color {
+        let p = (self.width() as i32 * y + x) as usize;
+        if p >= self.data().len() {
+            println!("[Error] Client window get pixel overflow!");
+            return Color::rgb(0, 0, 0);
+        }
+        return self.data()[p];
+    }
+    #[allow(unused_variables)]
+    /// TODO
+    fn char(&mut self, x: i32, y: i32, c: char, color: Color) {}
+}

+ 2 - 0
starry_client/src/lib.rs

@@ -0,0 +1,2 @@
+pub mod base;
+pub mod window;

+ 14 - 0
starry_client/src/main.rs

@@ -0,0 +1,14 @@
+use starry_client::{base::{color::Color, renderer::Renderer}, window::Window};
+
+
+
+const SCREEN_WIDTH : usize = 1440;
+const SCREEN_HEIGHT : usize = 900;
+
+pub fn main() {
+    let mut window = Window::new((SCREEN_WIDTH / 4) as i32,  (SCREEN_HEIGHT / 4) as i32, (SCREEN_WIDTH / 2) as u32, (SCREEN_HEIGHT / 2) as u32, "First Window");
+
+    window.set(Color::rgb(10, 200, 10));
+
+    window.sync();
+}

+ 114 - 0
starry_client/src/window.rs

@@ -0,0 +1,114 @@
+use std::{cell::Cell, fs::File, io::{Seek, SeekFrom, Write}};
+
+use crate::base::{color::Color, renderer::{RenderMode, Renderer}};
+
+// TODO: 读帧缓冲设备属性
+/// 屏幕宽度
+const SCREEN_WIDTH: usize = 1440;
+/// 屏幕高度
+#[allow(dead_code)]
+const SCREEN_HEIGHT: usize = 900;
+
+#[allow(dead_code)]
+pub struct Window {
+    /// 窗口左上角的x坐标
+    x: i32,
+    /// 窗口左上角的y坐标
+    y: i32,
+    /// 窗口的宽度
+    w: u32,
+    /// 窗口的高度
+    h: u32,
+    /// 窗口的标题
+    t: String,
+    /// TODO
+    // window_async: bool,
+    /// 窗口是否大小可变
+    resizable: bool,
+    /// 窗口的渲染模式
+    mode: Cell<RenderMode>,
+    // TODO
+    // file_opt: Option<File>,
+    // TODO: 改定长数组
+    // data_opt: Option<& 'static mut [Color]>,
+    /// 窗口的渲染数据
+    data_opt: Option<Box<[Color]>>,
+}
+
+impl Renderer for Window {
+    fn width(&self) -> u32 {
+        self.w
+    }
+
+    fn height(&self) -> u32 {
+        self.h
+    }
+
+    fn data(&self) -> &[Color] {
+        self.data_opt.as_ref().unwrap()
+    }
+
+    fn data_mut(&mut self) -> &mut [Color]{
+        self.data_opt.as_mut().unwrap()
+    }
+
+    /// TODO
+    fn sync(&mut self) -> bool {
+        true
+    }
+
+    fn mode(&self) -> &Cell<RenderMode> {
+        &self.mode    
+    }
+}
+
+#[allow(dead_code)]
+impl Window {
+    /// TODO: 接收flags
+    pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str) -> Self {
+        Window {
+            x: x,
+            y: y,
+            w: w,
+            h: h,
+            t: title.to_string(),
+            // window_async: false,
+            resizable: false,
+            mode: Cell::new(RenderMode::Blend),
+            // file_opt: None,
+            data_opt: Some(vec!(Color::rgb(0, 0, 0); (w * h) as usize).into_boxed_slice()),
+        }
+
+        // TODO: 与服务器通信 
+    }
+
+    /// # 函数功能
+    /// 同步数据至系统帧缓冲
+    pub fn sync(&self) {
+        let mut fb = File::open("/dev/fb0").expect("Unable to open framebuffer");
+
+        for y in 0..self.height() as i32 {
+            for x in 0..self.width() as i32 {
+                let pixel = self.get_pixel(x, y);
+                let offset =  (((y + self.y()) * SCREEN_WIDTH as i32) + x + self.x()) * 4;
+                // 写缓冲区
+                fb.seek(SeekFrom::Start(offset as u64)).expect("Unable to seek framebuffer");
+                fb.write_all(&pixel.to_rgba_bytes()).expect("Unable to write framebuffer");
+            }
+        }
+    }
+    
+    pub fn x(&self) -> i32 {
+        self.x
+    }
+
+    pub fn y(&self) -> i32 {
+        self.y
+    }
+
+    pub fn title(&self) -> String {
+        self.t.clone()
+    }
+
+
+}

+ 2 - 0
starry_server/.cargo/config.toml

@@ -0,0 +1,2 @@
+[build]
+target = "x86_64-unknown-linux-musl"

+ 17 - 0
starry_server/Cargo.toml

@@ -0,0 +1,17 @@
+[package]
+name = "starry_server"
+version = "0.1.0"
+edition = "2021"
+description = "The server of Starry Engine"
+authors = [ "2447742618 <2447742618@qq.com>" ]
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+starry_client = {path = "../starry_client" }
+bitflags = "2.4.2"
+serde = "1"
+serde_derive = "1"
+toml = "0.8.1"
+log = "0.4.20"
+image = "0.24.7"

+ 41 - 0
starry_server/Makefile

@@ -0,0 +1,41 @@
+# The toolchain we use.
+# You can get it by running DragonOS' `tools/bootstrap.sh`
+TOOLCHAIN="+nightly-2023-08-15-x86_64-unknown-linux_dragonos-gnu"
+RUSTFLAGS+="-C target-feature=+crt-static -C link-arg=-no-pie"
+
+# 如果是在dadk中编译,那么安装到dadk的安装目录中
+INSTALL_DIR?=$(DADK_CURRENT_BUILD_DIR)
+# 如果是在本地编译,那么安装到当前目录下的install目录中
+INSTALL_DIR?=./install
+
+
+run:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run
+
+build:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build
+
+clean:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean
+
+test:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test
+
+doc:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) doc
+
+run-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --release
+
+build-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --release
+
+clean-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --release
+
+test-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --release
+
+.PHONY: install
+install: 
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --path . --no-track --root $(INSTALL_DIR) --force

+ 71 - 0
starry_server/src/base/display.rs

@@ -0,0 +1,71 @@
+use starry_client::base::{color::Color, renderer::Renderer};
+
+use super::{
+    image::{Image, ImageRoi},
+    rect::Rect,
+};
+
+/// 一个显示窗口
+pub struct Display {
+    /// 左上角x坐标
+    pub x: i32,
+    /// 左上角y坐标
+    pub y: i32,
+    /// 帧缓冲区
+    pub image: Image,
+}
+
+impl Display {
+    /// 创建新窗口
+    pub fn new(x: i32, y: i32, width: i32, height: i32) -> Self {
+        Display {
+            x,
+            y,
+            image: Image::new(width, height),
+        }
+    }
+
+    /// # 函数功能
+    /// 向一个矩形区域内填充单一颜色
+    ///
+    /// ## 参数值
+    /// - rect: 矩形区域(绝对位置)
+    /// - color: 填充的颜色
+    pub fn rect(&mut self, rect: &Rect, color: Color) {
+        self.image.rect(
+            rect.left() - self.x,
+            rect.top() - self.y,
+            rect.width().try_into().unwrap_or(0),
+            rect.height().try_into().unwrap_or(0),
+            color,
+        );
+    }
+
+    /// # 函数功能
+    /// 获得矩形区域相应的Roi
+    ///
+    /// ## 参数值
+    /// - rect: 矩形区域(绝对位置)
+    ///
+    /// ## 返回值
+    /// 矩形区域对应的Roi
+    pub fn roi(&mut self, rect: &Rect) -> ImageRoi {
+        // 得到相对位置的矩形
+        self.image.roi(&Rect::new(
+            rect.left() - self.x,
+            rect.top() - self.y,
+            rect.width(),
+            rect.height(),
+        ))
+    }
+
+    /// 窗口调整大小
+    pub fn resize(&mut self, width: i32, height: i32) {
+        self.image = Image::new(width, height)
+    }
+
+    /// 获得展示窗口矩形
+    pub fn screen_rect(&self) -> Rect {
+        Rect::new(self.x, self.y, self.image.width(), self.image.height())
+    }
+}

+ 392 - 0
starry_server/src/base/image.rs

@@ -0,0 +1,392 @@
+use std::{
+    cell::Cell,
+    cmp,
+    fs::File,
+    io::{Seek, SeekFrom, Write},
+    mem, ptr,
+};
+
+use image::GenericImageView;
+use starry_client::base::{
+    color::Color,
+    renderer::{RenderMode, Renderer},
+};
+
+use crate::core::{SCREEN_HEIGHT, SCREEN_WIDTH};
+
+use super::rect::Rect;
+
+/// Roi区域中的行数据
+pub struct ImageRoiRows<'a> {
+    /// Roi矩形区域(相对位置)
+    rect: Rect,
+    /// 矩形宽度
+    w: i32,
+    /// 帧缓冲数据
+    data: &'a [Color],
+    /// 当前行号
+    i: i32,
+}
+
+// 实现迭代器
+impl<'a> Iterator for ImageRoiRows<'a> {
+    type Item = &'a [Color];
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.i < self.rect.height() {
+            let start = (self.rect.top() + self.i) * self.w + self.rect.left();
+            let end = start + self.rect.width();
+            self.i += 1;
+            Some(&self.data[start as usize..end as usize])
+        } else {
+            None
+        }
+    }
+}
+
+/// Roi区域中的行数据
+pub struct ImageRoiRowsMut<'a> {
+    /// Roi矩形区域(相对位置)
+    rect: Rect,
+    /// 矩形宽度
+    w: i32,
+    /// 帧缓冲数据
+    data: &'a mut [Color],
+    /// 当前行号
+    i: i32,
+}
+
+// 实现迭代器
+impl<'a> Iterator for ImageRoiRowsMut<'a> {
+    type Item = &'a mut [Color];
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.i < self.rect.height() {
+            let mut data = mem::take(&mut self.data);
+
+            // 剔除掉矩形以上的部分
+            if self.i == 0 {
+                data = data
+                    .split_at_mut(self.rect.top() as usize * self.w as usize)
+                    .1
+            };
+
+            // 分离当前行和剩下的部分
+            let (row, tail) = data.split_at_mut(self.w as usize);
+            self.data = tail;
+            let start = self.rect.left() as usize;
+            let end = self.rect.left() as usize + self.rect.width() as usize;
+            self.i += 1;
+            Some(&mut row[start..end])
+        } else {
+            None
+        }
+    }
+}
+
+/// 图像中的ROI区域
+pub struct ImageRoi<'a> {
+    /// ROI矩形区域(相对位置)
+    rect: Rect,
+    /// 矩形区域宽度
+    w: i32,
+    /// 帧缓冲数据
+    data: &'a mut [Color],
+}
+
+// 实现到迭代器的转换
+impl<'a> IntoIterator for ImageRoi<'a> {
+    type Item = &'a [Color];
+    type IntoIter = ImageRoiRows<'a>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        let Self { rect, w, data } = self;
+        // 两次切片操作
+        let data =
+            &mut data[rect.top() as usize * w as usize..][..rect.height() as usize * w as usize];
+        ImageRoiRows {
+            rect,
+            w,
+            data,
+            i: 0,
+        }
+    }
+}
+
+impl<'a> ImageRoi<'a> {
+    /// 获得Roi相应的行数据
+    pub fn rows(&'a self) -> ImageRoiRows<'a> {
+        ImageRoiRows {
+            rect: self.rect,
+            w: self.w,
+            data: self.data,
+            i: 0,
+        }
+    }
+
+    /// 获得Roi相应的行数据
+    pub fn rows_mut(&'a mut self) -> ImageRoiRowsMut<'a> {
+        ImageRoiRowsMut {
+            rect: self.rect,
+            w: self.w,
+            data: self.data,
+            i: 0,
+        }
+    }
+
+    /// Roi区域颜色混合
+    pub fn blend(&'a mut self, other: &ImageRoi) {
+        for (self_row, other_row) in self.rows_mut().zip(other.rows()) {
+            for (old, new) in self_row.iter_mut().zip(other_row.iter()) {
+                let alpha = (new.data >> 24) & 0xFF;
+                if alpha >= 255 {
+                    old.data = new.data;
+                } else if alpha > 0 {
+                    let n_r = (((new.data >> 16) & 0xFF) * alpha) >> 8;
+                    let n_g = (((new.data >> 8) & 0xFF) * alpha) >> 8;
+                    let n_b = ((new.data & 0xFF) * alpha) >> 8;
+
+                    let n_alpha = 255 - alpha;
+
+                    let o_r = (((old.data >> 16) & 0xFF) * n_alpha) >> 8;
+                    let o_g = (((old.data >> 8) & 0xFF) * n_alpha) >> 8;
+                    let o_b = ((old.data & 0xFF) * n_alpha) >> 8;
+
+                    old.data = ((o_r << 16) | (o_g << 8) | o_b) + ((n_r << 16) | (n_g << 8) | n_b);
+                }
+            }
+        }
+    }
+
+    /// Roi区域颜色覆盖
+    pub fn cover(&'a mut self, other: &ImageRoi) {
+        for (self_row, other_row) in self.rows_mut().zip(other.rows()) {
+            let len = cmp::min(self_row.len(), other_row.len());
+            unsafe {
+                ptr::copy(other_row.as_ptr(), self_row.as_mut_ptr(), len);
+            }
+        }
+    }
+}
+
+/// 包含帧缓冲区的图像
+pub struct ImageRef<'a> {
+    w: i32,
+    h: i32,
+    data: &'a mut [Color],
+    mode: Cell<RenderMode>,
+}
+
+impl<'a> ImageRef<'a> {
+    /// 根据帧缓冲数据创建新图像
+    pub fn from_data(width: i32, height: i32, data: &'a mut [Color]) -> Self {
+        ImageRef {
+            w: width,
+            h: height,
+            data,
+            mode: Cell::new(RenderMode::Blend),
+        }
+    }
+
+    /// 获得图像宽度
+    pub fn width(&self) -> i32 {
+        self.w
+    }
+
+    /// 获得图像高度
+    pub fn height(&self) -> i32 {
+        self.h
+    }
+
+    /// 根据矩形区域返回相应的Roi
+    pub fn roi(&mut self, rect: &Rect) -> ImageRoi {
+        ImageRoi {
+            rect: *rect,
+            w: self.w,
+            data: &mut self.data,
+        }
+    }
+}
+
+impl<'a> Renderer for ImageRef<'a> {
+    fn width(&self) -> u32 {
+        self.w as u32
+    }
+
+    fn height(&self) -> u32 {
+        self.h as u32
+    }
+
+    fn data(&self) -> &[Color] {
+        self.data
+    }
+
+    fn data_mut(&mut self) -> &mut [Color] {
+        self.data
+    }
+
+    fn sync(&mut self) -> bool {
+        true
+    }
+
+    fn mode(&self) -> &Cell<RenderMode> {
+        &self.mode
+    }
+}
+
+/// 包含帧缓冲区的图像
+#[derive(Clone)]
+pub struct Image {
+    /// 宽度
+    w: i32,
+    /// 高度
+    h: i32,
+    /// 像素数据
+    data: Box<[Color]>,
+    /// 渲染模式
+    mode: Cell<RenderMode>,
+}
+
+impl Image {
+    /// 创建默认图像
+    pub fn new(width: i32, height: i32) -> Self {
+        Image::from_color(width, height, Color::rgb(0, 0, 0))
+    }
+
+    /// 创建单一颜色的图像
+    pub fn from_color(width: i32, height: i32, color: Color) -> Self {
+        Image::from_data(
+            width,
+            height,
+            vec![color; (width * height) as usize].into_boxed_slice(),
+        )
+    }
+
+    /// 根据帧缓冲数据创建新图像
+    pub fn from_data(width: i32, height: i32, data: Box<[Color]>) -> Self {
+        Image {
+            w: width,
+            h: height,
+            data,
+            mode: Cell::new(RenderMode::Blend),
+        }
+    }
+
+    pub fn from_path_scale(path: &[u8]) -> Option<Self> {
+        if let Ok(mut img) = image::load_from_memory(path) {
+            // let img = img.resize(20, 20, image::imageops::FilterType::Gaussian);
+
+            let (mut img_width, mut img_heigh) = img.dimensions();
+            if img_width > SCREEN_WIDTH as u32 || img_heigh > SCREEN_HEIGHT as u32 {
+                img = img.resize(
+                    SCREEN_WIDTH as u32,
+                    SCREEN_HEIGHT as u32,
+                    image::imageops::FilterType::Gaussian,
+                );
+                (img_width, img_heigh) = img.dimensions();
+            }
+
+            let mut image = Image::new(img_width as i32, img_heigh as i32);
+            for y in 0..img_heigh {
+                for x in 0..img_width as u32 {
+                    let pixel = img.get_pixel(x, y);
+                    let offset = y * img_width + x;
+                    // println!("Cursor pixel print x:{:?} y:{:?} rgba:{:?} {:?} {:?} {:?}", x, y, pixel[0], pixel[1], pixel[2], pixel[3]);
+                    image.data[offset as usize] =
+                        Color::rgba(pixel[0], pixel[1], pixel[2], pixel[3]);
+                }
+            }
+
+            // println!(
+            //     "[Info] Image created from path successfully,  width: {:?} height: {:?}",
+            //     img_width, img_heigh
+            // );
+
+            return Some(image);
+        } else {
+            println!("[Error] Image created from path failed");
+            return None;
+        }
+    }
+
+    /// 返回图像宽度
+    pub fn width(&self) -> i32 {
+        self.w
+    }
+
+    /// 返回图像高度
+    pub fn height(&self) -> i32 {
+        self.h
+    }
+
+    /// 返回图像宽度和高度
+    pub fn dimensions(&self) -> (i32, i32) {
+        (self.w, self.h)
+    }
+
+    /// # 函数功能
+    /// 根据矩形区域返回相应的Roi
+    ///
+    /// ## 参数值
+    /// - rect: 矩形区域(相对位置)
+    ///
+    /// ## 返回值
+    /// Roi对象
+    pub fn roi(&mut self, rect: &Rect) -> ImageRoi {
+        ImageRoi {
+            rect: *rect,
+            w: self.w,
+            data: &mut self.data,
+        }
+    }
+
+    /// 展示在桌面中央
+    pub fn show_on_desktop(&self) {
+        let xoffset = (SCREEN_WIDTH as i32 - self.width()) / 2;
+        let yoffset = (SCREEN_HEIGHT as i32 - self.height()) / 2;
+        let mut fb = File::open("/dev/fb0").expect("[Error] Unable to open framebuffer");
+        for y in 0..self.height() {
+            for x in 0..self.width() {
+                let index: i32 = y * self.width() + x;
+                let offset = ((y + yoffset) * SCREEN_WIDTH as i32 + x + xoffset) * 4;
+                let color = &self.data[index as usize];
+                println!(
+                    "Image show print x:{:?} y:{:?} rgba:{:?} {:?} {:?} {:?}",
+                    x,
+                    y,
+                    color.r(),
+                    color.g(),
+                    color.b(),
+                    color.a()
+                );
+                fb.seek(SeekFrom::Start(offset as u64)).expect("error");
+                fb.write(&self.data[index as usize].to_bgra_bytes())
+                    .expect("error");
+            }
+        }
+    }
+}
+
+impl Renderer for Image {
+    fn width(&self) -> u32 {
+        self.w as u32
+    }
+
+    fn height(&self) -> u32 {
+        self.h as u32
+    }
+
+    fn data(&self) -> &[Color] {
+        &self.data
+    }
+
+    fn data_mut(&mut self) -> &mut [Color] {
+        &mut self.data
+    }
+
+    fn mode(&self) -> &Cell<RenderMode> {
+        &self.mode
+    }
+
+    fn sync(&mut self) -> bool {
+        true
+    }
+}

+ 4 - 0
starry_server/src/base/mod.rs

@@ -0,0 +1,4 @@
+pub mod display;
+pub mod image;
+pub mod rect;
+pub mod window;

+ 107 - 0
starry_server/src/base/rect.rs

@@ -0,0 +1,107 @@
+use std::cmp::{max, min};
+
+/// 表示一个矩形区域
+#[derive(Clone, Copy, Debug, Default)]
+pub struct Rect {
+    /// 矩形左上角x坐标
+    x: i32,
+    /// 矩形左上角y坐标
+    y: i32,
+    /// 矩形宽度
+    w: i32,
+    /// 矩形高度
+    h: i32,
+}
+
+#[allow(dead_code)]
+impl Rect {
+    /// 创建矩形
+    pub fn new(x: i32, y: i32, w: i32, h: i32) -> Rect {
+        assert!(w >= 0);
+        assert!(h >= 0);
+
+        Rect { x, y, w, h }
+    }
+
+    /// 矩形的面积
+    pub fn area(&self) -> i32 {
+        self.w * self.h
+    }
+
+    /// 矩形的左边界
+    pub fn left(&self) -> i32 {
+        self.x
+    }
+
+    /// 矩形的右边界
+    pub fn right(&self) -> i32 {
+        self.x + self.w
+    }
+
+    /// 矩形的上边界
+    pub fn top(&self) -> i32 {
+        self.y
+    }
+
+    /// 矩形的下边界
+    pub fn bottom(&self) -> i32 {
+        self.y + self.h
+    }
+
+    /// 矩形的宽度
+    pub fn width(&self) -> i32 {
+        self.w
+    }
+
+    /// 矩形的高度
+    pub fn height(&self) -> i32 {
+        self.h
+    }
+
+    /// 求两矩形的并集
+    pub fn container(&self, other: &Rect) -> Rect {
+        let left = min(self.left(), other.left());
+        let right = max(self.right(), other.right());
+        let top = min(self.top(), other.top());
+        let bottom = max(self.bottom(), other.bottom());
+
+        assert!(left <= right);
+        assert!(top <= bottom);
+
+        Rect::new(left, top, right - left, bottom - top)
+    }
+
+    /// 求两矩形的交集
+    pub fn intersection(&self, other: &Rect) -> Rect {
+        let left = max(self.left(), other.left());
+        let right = min(self.right(), other.right());
+        let top = max(self.top(), other.top());
+        let bottom = min(self.bottom(), other.bottom());
+
+        Rect::new(left, top, max(0, right - left), max(0, bottom - top))
+    }
+
+    /// 判断点是否在矩形中
+    pub fn contains(&self, x: i32, y: i32) -> bool {
+        self.left() <= x && self.right() >= x && self.top() <= y && self.bottom() >= y
+    }
+
+    /// 判断矩形是否为空
+    pub fn is_empty(&self) -> bool {
+        self.w == 0 || self.h == 0
+    }
+
+    /// # 函数功能
+    /// 偏移矩形的位置
+    /// 可用于矩形绝对和相对位置的转换
+    ///
+    /// ## 参数
+    /// - x: 向右偏移的量
+    /// - y: 向下偏移的量
+    ///
+    /// ## 返回值
+    /// 偏移得到的矩形
+    pub fn offset(&self, x: i32, y: i32) -> Rect {
+        Rect::new(self.x + x, self.y + y, self.w, self.h)
+    }
+}

+ 111 - 0
starry_server/src/base/window.rs

@@ -0,0 +1,111 @@
+use starry_client::base::event::Event;
+
+use crate::core::SCREEN_HEIGHT;
+
+use super::{display::Display, image::Image, rect::Rect};
+
+/// 窗口按Z值排序的模式
+#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord)]
+pub enum WindowZOrderMode {
+    /// 背景窗口
+    Back,
+    /// 普通窗口
+    Normal,
+    /// 前景窗口
+    Front,
+}
+
+#[allow(dead_code)]
+/// 窗口对象
+pub struct Window {
+    /// 窗口左上角x坐标
+    pub x: i32,
+    /// 窗口左上角y坐标
+    pub y: i32,
+    /// 窗口大小系数
+    pub scale: i32,
+    /// 窗口标题
+    pub title: String,
+    // pub asynchronous: bool,
+    // pub barderless: bool,
+    // pub resizable: bool,
+    /// 是否透明
+    pub transparent: bool,
+    // pub unclosable: bool,
+    /// 排序模式
+    pub zorder: WindowZOrderMode,
+
+    /// 窗体图像
+    pub image: Image,
+    /// 窗口标题图像(聚焦)
+    // pub title_image: Image,
+    /// 窗口标题图像(非聚焦)
+    // pub title_image_unfocused: Image,
+
+    /// 事件数组
+    pub events: Vec<Event>,
+    // TODO 增加所需字段
+}
+
+impl Window {
+    pub fn new(x: i32, y: i32, _w: i32, _h: i32, scale: i32, image_path: &[u8]) -> Window {
+        Window {
+            x: x,
+            y: y,
+            scale: scale,
+            title: String::new(),
+            transparent: false,
+            zorder: WindowZOrderMode::Normal,
+            image: Image::from_path_scale(image_path)
+                .unwrap_or(Image::new(SCREEN_HEIGHT as i32, SCREEN_HEIGHT as i32)),
+            events: Vec::new(),
+        }
+    }
+
+    /// 窗体宽度
+    pub fn width(&self) -> i32 {
+        self.image.width()
+    }
+
+    /// 窗体高度
+    pub fn height(&self) -> i32 {
+        self.image.height()
+    }
+
+    /// 返回窗体对应矩形
+    pub fn rect(&self) -> Rect {
+        Rect::new(self.x, self.y, self.width(), self.height())
+    }
+
+    // TODO
+    // pub fn title_rect(&self) -> Rect {}
+
+    /// # 函数功能
+    /// 渲染窗体到显示窗口中
+    ///
+    /// ## 参数
+    /// - display: 展示窗口
+    /// - rect: 渲染的矩形区域(绝对位置)
+    pub fn draw(&mut self, display: &mut Display, rect: &Rect) {
+        let self_rect = self.rect();
+        let intersect = self_rect.intersection(rect);
+        if !intersect.is_empty() {
+            // (半)透明窗口
+            if self.transparent {
+                display.roi(&intersect).blend(
+                    &self
+                        .image
+                        .roi(&intersect.offset(-self_rect.left(), -self_rect.top())),
+                );
+            }
+            // 不透明窗口
+            else {
+                display.roi(&intersect).cover(
+                    &self
+                        .image
+                        .roi(&intersect.offset(-self_rect.left(), -self_rect.top())),
+                );
+            }
+        }
+    }
+}

+ 88 - 0
starry_server/src/config.rs

@@ -0,0 +1,88 @@
+use std::{fs::File, io::Read};
+
+use log::debug;
+use serde_derive::Deserialize;
+
+/// TODO: 了解serde_derive::Deserialize及依赖
+/// 配置信息
+#[derive(Clone, Deserialize)]
+pub struct Config {
+    // TODO: 补充注释
+    pub normal: String,
+    pub bottom_left_corner: String,
+    pub bottom_right_corner: String,
+    pub bottom_side: String,
+    pub left_side: String,
+    pub right_side: String,
+    pub window_max: String,
+    pub window_max_unfocused: String,
+    pub window_close: String,
+    pub window_close_unfocused: String,
+    // TODO: 实现Color反序列化
+    // #[serde(default = "background_color_default")]
+    // pub background_color: Color,
+    // #[serde(default = "bar_color_default")]
+    // pub bar_color: Color,
+    // #[serde(default = "bar_highlight_color_default")]
+    // pub bar_highlight_color: Color,
+    // #[serde(default = "text_color_default")]
+    // pub text_color: Color,
+    // #[serde(default = "text_highlight_color_default")]
+    // pub text_highlight_color: Color,
+}
+
+// fn background_color_default() -> Color { Color::rgb(0, 0, 0) }
+// fn bar_color_default() -> Color { Color::rgba(47, 52, 63, 224) }
+// fn bar_highlight_color_default() -> Color { Color::rgba(80, 86, 102, 224) }
+// fn text_color_default() -> Color { Color::rgb(204, 210, 224) }
+// fn text_highlight_color_default() -> Color { Color::rgb(204, 210, 224) }
+
+impl Default for Config {
+    fn default() -> Self {
+        Config {
+            normal: String::default(),
+            bottom_left_corner: String::default(),
+            bottom_right_corner: String::default(),
+            bottom_side: String::default(),
+            left_side: String::default(),
+            right_side: String::default(),
+            window_max: String::default(),
+            window_max_unfocused: String::default(),
+            window_close: String::default(),
+            window_close_unfocused: String::default(),
+            // background_color: background_color_default(),
+            // bar_color: bar_color_default(),
+            // bar_highlight_color: bar_highlight_color_default(),
+            // text_color: text_color_default(),
+            // text_highlight_color: text_highlight_color_default(),
+        }
+    }
+}
+
+impl Config {
+    /// 通过字符串解析配置
+    fn config_from_string(config: &str) -> Config {
+        match toml::from_str(config) {
+            Ok(config) => config,
+            Err(err) => {
+                println!("[Error] Config failed to parse config '{}'", err);
+                Config::default()
+            }
+        }
+    }
+
+    /// 通过文件路径解析配置
+    pub fn config_from_path(path: &str) -> Config {
+        let mut string = String::new();
+
+        match File::open(path) {
+            Ok(mut file) => match file.read_to_string(&mut string) {
+                Ok(_) => debug!("[Info] Reading config from path: '{}'", path),
+                Err(err) => debug!("[Error] Config failed to read config '{}': {}", path, err),
+            },
+            Err(err) => debug!("[Error] Config failed to open config '{}': {}", path, err),
+        }
+
+        Self::config_from_string(&string)
+    }
+}

+ 149 - 0
starry_server/src/core/compositor.rs

@@ -0,0 +1,149 @@
+use std::{fs::File, io::{Seek, SeekFrom, Write}, sync::{Arc, RwLock}};
+
+use starry_client::base::renderer::Renderer;
+
+use crate::base::rect::Rect;
+
+use super::{starry_server, window_manager::window_manager, SCREEN_WIDTH};
+
+static mut COMPOSITOR: Option<Arc<Compositor>> = None;
+
+/// 获得合成渲染器实例
+pub fn compositor() -> Option<Arc<Compositor>> {
+    unsafe { COMPOSITOR.clone() }
+}
+
+#[allow(dead_code)]
+/// 合成渲染器
+pub struct Compositor {
+    /// 数据锁
+    data: RwLock<CompositorData>,
+}
+
+pub struct CompositorData {
+    /// 待重绘的窗口
+    redraws: Vec<Rect>,
+
+    fb_file: File,
+}
+
+#[allow(dead_code)]
+impl Compositor {
+    /// 创建合成渲染器
+    pub fn new() {
+        let compositor = Compositor {
+            data: RwLock::new(CompositorData {
+                redraws: Vec::new(),
+                fb_file: File::open("/dev/fb0").expect("[Error] Unable to open framebuffer"),
+            }),
+        };
+
+        unsafe {
+            COMPOSITOR = Some(Arc::new(compositor));
+        }
+
+        // println!("[Init] Compositor created successfully!");
+    }
+
+    /// TODO
+    /// 重绘所有请求的窗口
+    pub fn redraw_all(&self) {
+        // println!("[Info] Compositor begin redraw_all...");
+        let window_manager = window_manager().unwrap();
+        let server = starry_server().unwrap();
+        let cursor_rect = window_manager.cursor_rect();
+        
+        // 对窗口排序
+        window_manager.rezbuffer();
+        
+        let mut window_manager_guard = window_manager.data.write().unwrap();
+        let mut compositor_guard = self.data.write().unwrap();
+        let mut server_guard = server.data.write().unwrap();
+        
+        let mut total_redraw_rect_opt: Option<Rect> = None;
+        for original_rect in compositor_guard.redraws.drain(..) {
+
+            // 更新重绘的总矩形区域
+            if !original_rect.is_empty() {
+                total_redraw_rect_opt = match total_redraw_rect_opt {
+                    Some(total_redraw) => Some(total_redraw.container(&original_rect)),
+                    None => Some(original_rect),
+                }
+            }
+
+            let mut cursors = server_guard.cursors.clone();
+            // 遍历所有显示窗口
+            for display in server_guard.displays.iter_mut() {
+                let rect = original_rect.intersection(&display.screen_rect());
+                if !rect.is_empty() {
+                    // TODO: 填充默认颜色
+
+                    // 倒序渲染所有窗口
+                    let len = window_manager_guard.zbuffer.len();
+                    for index in (0..len).rev() {
+                        let entry = window_manager_guard.zbuffer.get(index).unwrap();
+                        let _id = entry.0;
+                        let index = entry.2;
+                        if let Some(window) = window_manager_guard.windows.get_mut(&index) {
+                            // TODO: 渲染窗口标题
+
+                            // 渲染窗体
+                            window.draw(display, &rect);
+                        }
+                    }
+                }
+
+                let cursor_intersect = rect.intersection(&cursor_rect);
+                if !cursor_intersect.is_empty() {
+                    if let Some(cursor) =
+                        cursors.get_mut(&window_manager_guard.cursor_i)
+                    {
+                        display.roi(&cursor_intersect).blend(&cursor.roi(
+                            &cursor_intersect.offset(-cursor_rect.left(), -cursor_rect.top()),
+                        ));
+                    }
+                }
+            }
+        }
+        
+        // println!("[Info] Compositor calculate total redraw rect done!");
+
+        // TODO 
+        let mut fb = &compositor_guard.fb_file;
+        
+        if let Some(total_redraw_rect) = total_redraw_rect_opt {
+            for display in server_guard.displays.iter_mut() {
+                let display_redraw = total_redraw_rect.intersection(&display.screen_rect());
+                if !display_redraw.is_empty() {
+                    for y in 0..display_redraw.height() {
+                        for x in 0..display_redraw.width() {
+                            let pixel = display.image.get_pixel(x + display_redraw.left() - display.x, y + display_redraw.top() - display.y);
+                            let offset = (((y + display_redraw.top()) * SCREEN_WIDTH as i32) + x + display_redraw.left()) * 4;
+                            fb.seek(SeekFrom::Start(offset as u64)).expect("Unable to seek framebuffer");
+                            fb.write_all(&pixel.to_bgra_bytes()).expect("Unable to write framebuffer");
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /// 窗口请求重绘
+    pub fn request_redraw(&self, rect: Rect) {
+        // println!("[Info] Compositor request redraw rect {:?}", rect);
+        let mut guard = self.data.write().unwrap();
+        let mut push = true;
+
+        for rect in guard.redraws.iter_mut() {
+            let container = rect.container(&rect);
+            if container.area() <= rect.area() + rect.area() {
+                *rect = container;
+                push = false;
+            }
+        }
+
+        if push {
+            guard.redraws.push(rect);
+        }
+    }
+}

+ 128 - 0
starry_server/src/core/input/inputs.rs

@@ -0,0 +1,128 @@
+use super::InputHandler;
+use bitflags::bitflags;
+use starry_client::base::event::{ButtonEvent, Event, MouseRelativeEvent};
+use std::{fs::File, io::Read};
+
+const MOUSE_DEVICE_PATH: &str = "/dev/char/psmouse";
+
+bitflags! {
+    /// 鼠标状态掩码
+    #[derive(Default)]
+    pub struct MouseFlags: u8 {
+        /// 左键是否按下
+        const LEFT_BUTTON = 0b0000_0001;
+
+        /// 右键是否按下
+        const RIGHT_BUTTON = 0b0000_0010;
+
+        /// 滚轮是否按下
+        const MIDDLE_BUTTON = 0b0000_0100;
+
+        /// 鼠标是否启用
+        const ALWAYS_ONE = 0b0000_1000;
+
+        /// x轴移动方向是否为负
+        const X_SIGN = 0b0001_0000;
+
+        /// y轴移动方向是否为负
+        const Y_SIGN = 0b0010_0000;
+
+        /// x方向移动超出范围
+        const X_OVERFLOW = 0b0100_0000;
+
+        /// y方向移动超出范围
+        const Y_OVERFLOW = 0b1000_0000;
+    }
+}
+
+#[allow(dead_code)]
+pub struct MouseInputHandler {
+    /// 读取的文件
+    file: File,
+    /// 当前数据包序号
+    packet_index: u8,
+    /// 鼠标状态
+    flags: MouseFlags,
+    /// x轴相对移动
+    dx: i16,
+    /// y轴相对移动
+    dy: i16,
+    /// 移动系数/灵敏度
+    scale: u8,
+}
+
+impl MouseInputHandler {
+    pub fn new() -> Box<MouseInputHandler> {
+        let file = File::open(MOUSE_DEVICE_PATH).expect("Fail to open mouse device");
+        // println!("[Init] Mouse_Input_Handler created successfully!");
+        Box::new(MouseInputHandler {
+            flags: MouseFlags::empty(),
+            packet_index: 0,
+            file: file,
+            dx: 0,
+            dy: 0,
+            scale: 1,
+        })
+    }
+}
+
+impl InputHandler for MouseInputHandler {
+    fn get_listening_file(&mut self) -> &File {
+        self.file.by_ref()
+    }
+
+    fn set_listening_file(&mut self, file: File) {
+        self.file = file;
+    }
+
+    fn handle(&mut self, packet: u8) -> Vec<Event> {
+        // println!("[Info] Mouse_Input_Handler handle packet {:?}", packet);
+        /// 求补码
+        fn sign_extend(value: u8) -> i16 {
+            ((value as u16) | 0xFF00) as i16
+        }
+
+        let mut events: Vec<Event> = Vec::new();
+        match self.packet_index {
+            0 => {
+                let flags = MouseFlags::from_bits_truncate(packet);
+                if flags.contains(MouseFlags::ALWAYS_ONE) {
+                    self.flags = flags;
+                    events.push(ButtonEvent::new(packet).to_event());
+                }
+            }
+            1 => {
+                // 计算dx
+                if self.flags.contains(MouseFlags::X_OVERFLOW) {
+                    self.dx = 0;
+                } else if self.flags.contains(MouseFlags::X_SIGN) {
+                    self.dx = sign_extend(packet);
+                } else {
+                    self.dx = packet as i16;
+                }
+            }
+            2 => {
+                // 计算dy
+                if self.flags.contains(MouseFlags::Y_OVERFLOW) {
+                    self.dy = 0;
+                } else if self.flags.contains(MouseFlags::Y_SIGN) {
+                    self.dy = sign_extend(packet);
+                } else {
+                    self.dy = packet as i16;
+                }
+
+                // 传入移动事件
+                events.push(
+                    MouseRelativeEvent {
+                        dx: self.dx as i32 * self.scale as i32,
+                        dy: self.dy as i32 * self.scale as i32,
+                    }
+                    .to_event(),
+                );
+            }
+            _ => unreachable!(),
+        }
+        self.packet_index = (self.packet_index + 1) % 3;
+        return events;
+    }
+}

+ 89 - 0
starry_server/src/core/input/mod.rs

@@ -0,0 +1,89 @@
+use std::{
+    fs::File,
+    io::Read,
+    sync::{Arc, RwLock},
+};
+
+use starry_client::base::event::Event;
+
+use self::inputs::MouseInputHandler;
+
+use super::window_manager::window_manager;
+
+pub mod inputs;
+
+static mut INPUT_MANAGER: Option<Arc<InputManager>> = None;
+
+pub fn input_manager() -> Option<Arc<InputManager>> {
+    unsafe { INPUT_MANAGER.clone() }
+}
+
+/// 输入管理器
+#[allow(dead_code)]
+pub struct InputManager {
+    /// 数据锁
+    data: RwLock<InputManagerData>,
+}
+
+pub struct InputManagerData {
+    /// 轮询的文件数组
+    handlers: Vec<Box<dyn InputHandler>>,
+}
+
+impl InputManager {
+    /// 创建输入管理器
+    pub fn new(){
+        let mut input_handlers = Vec::new();
+        // TODO: 通过设备检测添加
+        input_handlers.push(MouseInputHandler::new() as Box<dyn InputHandler>);
+        // TODO: 处理键盘输入
+        let input_manager = InputManager {
+            data: RwLock::new(InputManagerData {
+                handlers: input_handlers,
+            }),
+        };
+
+        unsafe {
+            INPUT_MANAGER = Some(Arc::new(input_manager));
+        }
+
+        // println!("[Init] Input_Manager created successfully!");
+    }
+
+    /// 轮询所有输入设备
+    pub fn polling_all(&self) {
+        // println!("[Info] Input_Manager polling all");
+        let mut guard = self.data.write().unwrap();
+        for handle in guard.handlers.iter_mut() {
+            handle.polling();
+        }
+    }
+}
+
+/// 输入处理器需要实现的特性
+#[allow(dead_code)]
+pub trait InputHandler {
+    /// 获得监听的文件
+    fn get_listening_file(&mut self) -> &File;
+
+    /// 设置监听的文件
+    fn set_listening_file(&mut self, file: File);
+
+    /// 处理字节数据
+    fn handle(&mut self, packet: u8) -> Vec<Event>;
+
+    /// 轮询文件
+    fn polling(&mut self) {
+        let mut buf: [u8; 1024] = [0; 1024];
+        // TODO: 错误信息提示相应文件路径
+        let count = self
+        .get_listening_file()
+        .read(&mut buf)
+            .expect("[Error] Fail to polling file");
+        // println!("[Info] Input_Handler polling read {:?} bytes", count);
+        for i in 0..count {
+            let events = self.handle(buf[i]);
+            window_manager().unwrap().send_events(events);
+        }
+    }
+}

+ 87 - 0
starry_server/src/core/mod.rs

@@ -0,0 +1,87 @@
+use std::{collections::BTreeMap, rc::Rc, sync::{Arc, RwLock}};
+
+use crate::{base::{display::Display, image::Image}, config::Config};
+
+use self::{
+    compositor::{compositor, Compositor},
+    input::{input_manager, InputManager},
+    window_manager::{window_manager, CursorKind, WindowManager},
+};
+
+pub mod compositor;
+pub mod input;
+pub mod window_manager;
+
+/// 屏幕宽度
+pub const SCREEN_WIDTH: usize = 1440;
+/// 屏幕高度
+#[allow(dead_code)]
+pub const SCREEN_HEIGHT: usize = 900;
+
+static DESKTOP_BG: &[u8] = include_bytes!("../desktop_bg.png");
+static CURSOR_NORMAL: &[u8] = include_bytes!("../cursor_normal.png");
+
+static mut STARRY_SERVER: Option<Arc<StarryServer>> = None;
+
+pub fn starry_server() -> Option<Arc<StarryServer>> {
+    unsafe { STARRY_SERVER.clone() }
+}
+
+/// 图形系统服务器
+pub struct StarryServer {
+    /// 数据锁
+    data: RwLock<StarryServerData>,
+}
+
+pub struct StarryServerData {
+    /// 窗口数组
+    pub displays: Vec<Display>,
+    pub config: Rc<Config>,
+    pub cursors: BTreeMap<CursorKind, Image>,
+}
+
+impl StarryServer {
+    /// 创建图形服务器
+    pub fn new(config: Rc<Config>, displays: Vec<Display>){
+        let mut cursors = BTreeMap::new();
+        cursors.insert(CursorKind::None, Image::new(0, 0));
+        cursors.insert(CursorKind::Normal, Image::from_path_scale(CURSOR_NORMAL).unwrap_or(Image::new(10, 10)));        // cursors.insert(CursorKind::BottomLeftCorner, Image::from_path_scale(&config.bottom_left_corner, scale).unwrap_or(Image::new(0, 0)));
+        // cursors.insert(CursorKind::BottomRightCorner, Image::from_path_scale(&config.bottom_right_corner, scale).unwrap_or(Image::new(0, 0)));
+        // cursors.insert(CursorKind::BottomSide, Image::from_path_scale(&config.bottom_side, scale).unwrap_or(Image::new(0, 0)));
+        // cursors.insert(CursorKind::LeftSide, Image::from_path_scale(&config.left_side, scale).unwrap_or(Image::new(0, 0)));
+        // cursors.insert(CursorKind::RightSide, Image::from_path_scale(&config.right_side, scale).unwrap_or(Image::new(0, 0)));
+
+        let server = StarryServer {
+            data: RwLock::new(StarryServerData {
+                displays: displays,
+                config: Rc::clone(&config),
+                cursors: cursors,
+            }),
+        };
+
+
+        unsafe {
+            STARRY_SERVER = Some(Arc::new(server));
+        }
+
+        // println!("[Init] Starry_Server created successfully!");
+    }
+
+    /// 开启主循环
+    pub fn run(&self) {
+        WindowManager::new();
+        Compositor::new();
+        InputManager::new();
+
+        // TODO 临时在此创建桌面窗口
+        window_manager().unwrap().window_new(0, 0, SCREEN_WIDTH as i32, SCREEN_HEIGHT as i32, "", "".to_string(), DESKTOP_BG);
+        
+        // println!("[Init] Starry_Server start main loop!");
+        loop {
+            input_manager().unwrap().polling_all();
+            window_manager().unwrap().handle_all_events();
+            compositor().unwrap().redraw_all();
+            // std::thread::sleep(std::time::Duration::from_millis(1));
+        }
+    }
+}

+ 322 - 0
starry_server/src/core/window_manager.rs

@@ -0,0 +1,322 @@
+use std::{
+    cmp,
+    collections::{BTreeMap, VecDeque},
+    sync::{Arc, RwLock},
+};
+
+use starry_client::base::event::{Event, EventOption, MouseRelativeEvent, MouseUpdateEvent};
+
+use crate::{
+    base::{
+        rect::Rect,
+        window::{Window, WindowZOrderMode},
+    },
+    core::{SCREEN_HEIGHT, SCREEN_WIDTH},
+};
+
+use super::{compositor::compositor, starry_server};
+
+static mut WINDOW_MANAGER: Option<Arc<WindowManager>> = None;
+
+pub fn window_manager() -> Option<Arc<WindowManager>> {
+    unsafe { WINDOW_MANAGER.clone() }
+}
+
+/// 鼠标样式
+#[allow(dead_code)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+pub enum CursorKind {
+    /// 无/不显示
+    None,
+    /// 默认状态
+    Normal,
+    /// 左下角
+    BottomLeftCorner,
+    /// 右下角
+    BottomRightCorner,
+    /// 下边界
+    BottomSide,
+    /// 左边界
+    LeftSide,
+    /// 右边界
+    RightSide,
+}
+
+/// 窗口管理器
+#[allow(dead_code)]
+pub struct WindowManager {
+    /// 数据锁
+    pub data: RwLock<WindowManagerData>,
+}
+
+#[allow(dead_code)]
+pub struct WindowManagerData {
+    /// 下一个窗口的id值
+    next_id: isize,
+    /// TODO
+    _hover: Option<usize>,
+    /// 窗口顺序
+    pub order: VecDeque<usize>,
+    /// 窗口顺序信息(下标index,模式,窗口id)
+    pub zbuffer: Vec<(usize, WindowZOrderMode, usize)>,
+    /// 窗口字典
+    pub windows: BTreeMap<usize, Window>,
+
+    /// 鼠标x坐标
+    pub cursor_x: i32,
+    /// 鼠标y坐标
+    pub cursor_y: i32,
+    /// 鼠标状态
+    pub cursor_i: CursorKind,
+
+    /// 待处理的事件数组
+    events: Vec<Event>,
+}
+
+impl WindowManager {
+    /// 创建窗口管理器
+    pub fn new() {
+        let window_manager = WindowManager {
+            data: RwLock::new(WindowManagerData {
+                next_id: 0,
+                _hover: None,
+                order: VecDeque::new(),
+                zbuffer: Vec::new(),
+                windows: BTreeMap::new(),
+                cursor_x: SCREEN_WIDTH as i32 / 2,
+                cursor_y: SCREEN_HEIGHT as i32 / 2,
+                cursor_i: CursorKind::None,
+                events: Vec::new(),
+            }),
+        };
+
+        unsafe {
+            WINDOW_MANAGER = Some(Arc::new(window_manager));
+        }
+
+        // println!("[Init] Window_Manager created successfully!");
+    }
+
+    /// # 函数功能
+    /// 新建窗口
+    ///
+    /// ## 参数
+    /// - x: 窗口左上角x坐标
+    /// - y: 窗口左上角y坐标
+    /// - width: 窗口宽度
+    /// - height: 窗口高度
+    /// - flags: 窗口属性
+    /// - title: 窗口标题
+    ///
+    /// ## 返回值
+    /// 窗口id
+    pub fn window_new(
+        &self,
+        mut x: i32,
+        mut y: i32,
+        width: i32,
+        height: i32,
+        _flags: &str,
+        _title: String,
+        image_path: &[u8],
+    ){
+        let mouse_update_event: MouseUpdateEvent;
+
+        {
+            let compositor = compositor().unwrap();
+            let mut guard = self.data.write().unwrap();
+
+            let id = guard.next_id as usize; // 新窗口的id
+            guard.next_id += 1;
+
+            if guard.next_id < 0 {
+                guard.next_id = 1;
+            }
+
+            if x < 0 && y < 0 {
+                x = cmp::max(0, (SCREEN_WIDTH as i32 - width) / 2);
+                y = cmp::max(0, (SCREEN_HEIGHT as i32 - height) / 2);
+            }
+
+            // TODO 传入正确的scale
+            // TODO 传入title
+            let window = Window::new(x, y, width, height, 1, image_path);
+
+            // TODO 处理flags
+
+            // TODO 重绘title_rect
+            compositor.request_redraw(window.rect());
+
+            match window.zorder {
+                WindowZOrderMode::Front | WindowZOrderMode::Normal => {
+                    guard.order.push_front(id);
+                }
+                WindowZOrderMode::Back => {
+                    guard.order.push_back(id);
+                }
+            }
+
+            guard.windows.insert(id, window);
+
+            // 确保鼠标正确显示
+            mouse_update_event = MouseUpdateEvent {
+                x: guard.cursor_x,
+                y: guard.cursor_y,
+            };
+        }
+
+        self.handle_mouse_update_event(mouse_update_event);
+    }
+
+    /// 发送事件
+    pub fn send_event(&self, event: Event) {
+        let mut guard = self.data.write().unwrap();
+        guard.events.push(event);
+    }
+
+    /// 发送事件数组
+    pub fn send_events(&self, mut events: Vec<Event>) {
+        let mut guard = self.data.write().unwrap();
+        guard.events.append(&mut events);
+    }
+
+    /// 处理所有事件
+    pub fn handle_all_events(&self) {
+        let mut events: Vec<Event>;
+
+        {
+            let mut guard = self.data.write().unwrap();
+            events = guard.events.clone();
+            guard.events.clear();
+        }
+
+        while let Some(event) = events.pop() {
+            self.handle_event(event);
+        }
+    }
+
+    /// # 函数功能
+    /// 处理事件
+    ///
+    /// ## 参数
+    /// 事件对象
+    pub fn handle_event(&self, event_union: Event) {
+        // println!("[Info] Window_Manager handle event {:?}", event_union.to_option());
+        match event_union.to_option() {
+            EventOption::MouseRelative(event) => self.handle_mouse_relative_event(event),
+            EventOption::Button(_event) => {}
+            unknown => println!("[Error] Unexpected event: {:?}", unknown),
+        }
+    }
+
+    /// 处理鼠标相对移动事件
+    pub fn handle_mouse_relative_event(&self, event: MouseRelativeEvent) {
+        // TODO: 将事件传递给窗口,同时考虑窗口对鼠标位置的影响
+
+        let cursor_x: i32;
+        let cursor_y: i32;
+
+        {
+            let guard = self.data.read().unwrap();
+            cursor_x = guard.cursor_x;
+            cursor_y = guard.cursor_y;
+        }
+
+        let max_x: i32 = SCREEN_WIDTH as i32;
+        let max_y: i32 = SCREEN_HEIGHT as i32;
+        let cursor_rect = self.cursor_rect();
+        
+        //防止鼠标出界
+        let x = cmp::max(0, cmp::min(max_x - cursor_rect.width(), cursor_x + event.dx));
+        let y = cmp::max(0, cmp::min(max_y - cursor_rect.height(), cursor_y - event.dy)); // 原点在左上角,向上为负
+
+        self.handle_mouse_update_event(MouseUpdateEvent { x, y });
+    }
+
+    /// 处理鼠标移动事件
+    pub fn handle_mouse_update_event(&self, event: MouseUpdateEvent) {
+        let /*mut*/ new_cursor = CursorKind::Normal;
+
+        // TODO: 判断新的鼠标状态
+        // TODO: 处理拖拽等事件,传递给相应窗口
+
+        self.update_cursor(event.x, event.y, new_cursor);
+    }
+
+    /// # 函数功能
+    /// 更新鼠标状态
+    ///
+    /// ## 参数
+    /// - x: 鼠标x坐标
+    /// - y: 鼠标y坐标
+    /// - kind: 鼠标状态
+    fn update_cursor(&self, x: i32, y: i32, kind: CursorKind) {
+        // println!("[Info] Mouse_Input_Handler update cursor {:?} {:?} ", x, y);
+
+        let old_cursor_x: i32;
+        let old_cursor_y: i32;
+        let old_cursor_i: CursorKind;
+
+        {
+            let guard = self.data.read().unwrap();
+            old_cursor_x = guard.cursor_x;
+            old_cursor_y = guard.cursor_y;
+            old_cursor_i = guard.cursor_i;
+        }
+
+        if kind != old_cursor_i || x != old_cursor_x || y != old_cursor_y {
+            let cursor_rect = self.cursor_rect();
+            compositor().unwrap().request_redraw(cursor_rect);
+
+            {
+                let mut guard = self.data.write().unwrap();
+                guard.cursor_x = x;
+                guard.cursor_y = y;
+                guard.cursor_i = kind;
+            }
+
+            let cursor_rect = self.cursor_rect();
+            compositor().unwrap().request_redraw(cursor_rect);
+        }
+    }
+
+    /// # 函数功能
+    /// 获得鼠标位置的矩形区域
+    pub fn cursor_rect(&self) -> Rect {
+        let guard = self.data.read().unwrap();
+        let server = starry_server().unwrap();
+        let server_gaurd = server.data.read().unwrap();
+
+        if let Some(image) = server_gaurd.cursors.get(&guard.cursor_i) {
+            return Rect::new(
+                guard.cursor_x,
+                guard.cursor_y,
+                image.width(),
+                image.height(),
+            );
+        }
+
+        return Rect::new(guard.cursor_x, guard.cursor_y, 0, 0);
+    }
+
+    /// 更新zbuffer
+    pub fn rezbuffer(&self) {
+        let mut guard = self.data.write().unwrap();
+
+        guard.zbuffer.clear();
+
+        let len = guard.order.len();
+        for index in 0..len {
+            let id = guard.order[index];
+            let window_z = guard
+                .windows
+                .get(&index)
+                .expect("窗口不存在!")
+                .zorder
+                .clone();
+            guard.zbuffer.push((id, window_z, index));
+        }
+
+        guard.zbuffer.sort_by(|a, b| b.1.cmp(&a.1));
+    }
+}

BIN
starry_server/src/cursor_normal.png


BIN
starry_server/src/desktop_bg.png


+ 5 - 0
starry_server/src/lib.rs

@@ -0,0 +1,5 @@
+pub mod base;
+pub mod core;
+pub mod config;
+
+extern crate bitflags;

+ 19 - 0
starry_server/src/main.rs

@@ -0,0 +1,19 @@
+use std::rc::Rc;
+
+
+use starry_server::{base::display::Display, config::Config, core::{starry_server, StarryServer, SCREEN_HEIGHT, SCREEN_WIDTH}};
+
+
+fn main() {
+    // TODO 考虑多个显示器
+    let mut displays : Vec<Display> = Vec::new();
+    displays.push(Display::new(0, 0, SCREEN_WIDTH as i32, SCREEN_HEIGHT as i32));
+
+    // TODO 暂时不考虑配置文件
+    let config: Rc<Config> = Rc::new(Config::default());
+
+    //开启Starry Server
+    StarryServer::new(config, displays);
+    let server = starry_server().unwrap();
+    server.run();
+}

+ 10 - 0
starry_server/src/starry.toml

@@ -0,0 +1,10 @@
+cursor = "/ui/cursor_normal.png"
+bottom_left_corner = "/ui/cursor_bottom_left_corner.png"
+bottom_right_corner = "/ui/cursor_bottom_right_corner.png"
+bottom_side = "/ui/cursor_bottom_side.png"
+left_side = "/ui/cursor_left_side.png"
+right_side = "/ui/cursor_right_side.png"
+window_max = "/ui/cursor_window_max.png"
+window_max_unfocused = "/ui/cursor_window_max_unfocused.png"
+window_close = "/ui/cursor_window_close.png"
+window_close_unfocused = "/ui/cursor_window_close_unfocused.png"