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