xref: /StarryEngine/starry_client/src/window.rs (revision 45e1715779ec63c9948d677df0dab834e236e747)
1 use std::{cell::Cell, fs::File, io::{Seek, SeekFrom, Write}};
2 
3 use crate::base::{color::Color, renderer::{RenderMode, Renderer}};
4 
5 // TODO: 读帧缓冲设备属性
6 /// 屏幕宽度
7 const SCREEN_WIDTH: usize = 1440;
8 /// 屏幕高度
9 #[allow(dead_code)]
10 const SCREEN_HEIGHT: usize = 900;
11 
12 /// 客户端的窗口类,与服务端的窗口对象一一对应
13 /// 一般来说客户端应用程序不直接使用该类,而通过Toolkit库间接使用
14 #[allow(dead_code)]
15 pub struct Window {
16     /// 窗口左上角的x坐标
17     x: i32,
18     /// 窗口左上角的y坐标
19     y: i32,
20     /// 窗口的宽度
21     w: u32,
22     /// 窗口的高度
23     h: u32,
24     /// 窗口的标题
25     title: String,
26     /// TODO
27     // window_async: bool,
28     /// 窗口是否大小可变
29     resizable: bool,
30     /// 窗口的渲染模式
31     mode: Cell<RenderMode>,
32     // TODO
33     // file_opt: Option<File>,
34     // TODO: 改定长数组
35     // data_opt: Option<& 'static mut [Color]>,
36     /// 窗口的渲染数据
37     data_opt: Option<Box<[Color]>>,
38 }
39 
40 impl Renderer for Window {
41     fn width(&self) -> u32 {
42         self.w
43     }
44 
45     fn height(&self) -> u32 {
46         self.h
47     }
48 
49     fn data(&self) -> &[Color] {
50         self.data_opt.as_ref().unwrap()
51     }
52 
53     fn data_mut(&mut self) -> &mut [Color]{
54         self.data_opt.as_mut().unwrap()
55     }
56 
57     fn sync(&mut self) -> bool {
58         let mut fb = File::open("/dev/fb0").expect("Unable to open framebuffer");
59 
60         for y in 0..self.height() as i32 {
61             for x in 0..self.width() as i32 {
62                 let pixel = self.get_pixel(x, y);
63                 let offset =  (((y + self.y()) * SCREEN_WIDTH as i32) + x + self.x()) * 4;
64                 // 写缓冲区
65                 fb.seek(SeekFrom::Start(offset as u64)).expect("Unable to seek framebuffer");
66                 fb.write_all(&pixel.to_bgra_bytes()).expect("Unable to write framebuffer");
67             }
68         }
69         true
70     }
71 
72     fn mode(&self) -> &Cell<RenderMode> {
73         &self.mode
74     }
75 }
76 
77 #[allow(dead_code)]
78 impl Window {
79     /// TODO: 接收flags
80     pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str) -> Self {
81         Window {
82             x: x,
83             y: y,
84             w: w,
85             h: h,
86             title: title.to_string(),
87             // window_async: false,
88             resizable: false,
89             mode: Cell::new(RenderMode::Blend),
90             // file_opt: None,
91             data_opt: Some(vec!(Color::rgb(0, 0, 0); (w * h) as usize).into_boxed_slice()),
92         }
93 
94         // TODO: 与服务器通信
95     }
96 
97     /// 返回窗口x坐标
98     pub fn x(&self) -> i32 {
99         self.x
100     }
101 
102     /// 返回窗口y坐标
103     pub fn y(&self) -> i32 {
104         self.y
105     }
106 
107     /// 返回窗口标题
108     pub fn title(&self) -> String {
109         self.title.clone()
110     }
111 
112     /// 改变窗口的位置
113     pub fn set_pos(&mut self, x: i32, y: i32) {
114         self.x = x;
115         self.y = y;
116     }
117 
118     /// 改变窗口的大小
119     pub fn set_size(&mut self, width: u32, height: u32) {
120         self.w = width;
121         self.h = height;
122     }
123 
124     /// 改变窗口标题
125     pub fn set_title(&mut self, title: &str) {
126         self.title = title.to_string();
127     }
128 }