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