xref: /StarryEngine/starry_client/src/window.rs (revision 731cae0674923fcc85c6e683a2eee596eb642796)
148d97639Syuyi2439 use std::{
248d97639Syuyi2439     cell::Cell,
31bee64b6SR0ronoa     cmp::min,
448d97639Syuyi2439     fs::File,
548d97639Syuyi2439     io::{Seek, SeekFrom, Write},
648d97639Syuyi2439 };
7bee61dcaSR0ronoa 
848d97639Syuyi2439 use crate::base::{
948d97639Syuyi2439     color::Color,
1048d97639Syuyi2439     renderer::{RenderMode, Renderer},
1148d97639Syuyi2439 };
12bee61dcaSR0ronoa 
13bee61dcaSR0ronoa // TODO: 读帧缓冲设备属性
14bee61dcaSR0ronoa /// 屏幕宽度
15bee61dcaSR0ronoa const SCREEN_WIDTH: usize = 1440;
16bee61dcaSR0ronoa /// 屏幕高度
17bee61dcaSR0ronoa #[allow(dead_code)]
18bee61dcaSR0ronoa const SCREEN_HEIGHT: usize = 900;
19bee61dcaSR0ronoa 
202b942a51SR0ronoa const FB_FILE_PATH: &str = "/dev/fb0";
212b942a51SR0ronoa 
2245e17157SR0ronoa /// 客户端的窗口类,与服务端的窗口对象一一对应
2345e17157SR0ronoa /// 一般来说客户端应用程序不直接使用该类,而通过Toolkit库间接使用
24bee61dcaSR0ronoa #[allow(dead_code)]
25bee61dcaSR0ronoa pub struct Window {
26bee61dcaSR0ronoa     /// 窗口左上角的x坐标
27bee61dcaSR0ronoa     x: i32,
28bee61dcaSR0ronoa     /// 窗口左上角的y坐标
29bee61dcaSR0ronoa     y: i32,
30bee61dcaSR0ronoa     /// 窗口的宽度
31bee61dcaSR0ronoa     w: u32,
32bee61dcaSR0ronoa     /// 窗口的高度
33bee61dcaSR0ronoa     h: u32,
34bee61dcaSR0ronoa     /// 窗口的标题
3545e17157SR0ronoa     title: String,
36bee61dcaSR0ronoa     /// 窗口是否大小可变
37bee61dcaSR0ronoa     resizable: bool,
38bee61dcaSR0ronoa     /// 窗口的渲染模式
39bee61dcaSR0ronoa     mode: Cell<RenderMode>,
40*731cae06SR0ronoa     // 命名管道文件
41*731cae06SR0ronoa     file_opt: Option<File>,
42bee61dcaSR0ronoa     // TODO: 改定长数组
43bee61dcaSR0ronoa     // data_opt: Option<& 'static mut [Color]>,
44bee61dcaSR0ronoa     /// 窗口的渲染数据
45bee61dcaSR0ronoa     data_opt: Option<Box<[Color]>>,
462b942a51SR0ronoa     /// 帧缓冲文件
472b942a51SR0ronoa     fb_file: File,
48bee61dcaSR0ronoa }
49bee61dcaSR0ronoa 
50bee61dcaSR0ronoa impl Renderer for Window {
width(&self) -> u3251bee61dcaSR0ronoa     fn width(&self) -> u32 {
52bee61dcaSR0ronoa         self.w
53bee61dcaSR0ronoa     }
54bee61dcaSR0ronoa 
height(&self) -> u3255bee61dcaSR0ronoa     fn height(&self) -> u32 {
56bee61dcaSR0ronoa         self.h
57bee61dcaSR0ronoa     }
58bee61dcaSR0ronoa 
data(&self) -> &[Color]59bee61dcaSR0ronoa     fn data(&self) -> &[Color] {
60bee61dcaSR0ronoa         self.data_opt.as_ref().unwrap()
61bee61dcaSR0ronoa     }
62bee61dcaSR0ronoa 
data_mut(&mut self) -> &mut [Color]63bee61dcaSR0ronoa     fn data_mut(&mut self) -> &mut [Color] {
64bee61dcaSR0ronoa         self.data_opt.as_mut().unwrap()
65bee61dcaSR0ronoa     }
66bee61dcaSR0ronoa 
sync(&mut self) -> bool67bee61dcaSR0ronoa     fn sync(&mut self) -> bool {
681bee64b6SR0ronoa         // 处理窗口大小超限的情况
691bee64b6SR0ronoa         let width = min(self.width() as i32, SCREEN_WIDTH as i32 - self.x);
701bee64b6SR0ronoa         let height = min(self.height() as i32, SCREEN_HEIGHT as i32 - self.y);
711bee64b6SR0ronoa 
721bee64b6SR0ronoa         for y in 0..height as i32 {
731bee64b6SR0ronoa             for x in 0..width as i32 {
7445e17157SR0ronoa                 let pixel = self.get_pixel(x, y);
7545e17157SR0ronoa                 let offset = (((y + self.y()) * SCREEN_WIDTH as i32) + x + self.x()) * 4;
7645e17157SR0ronoa                 // 写缓冲区
772b942a51SR0ronoa                 self.fb_file
782b942a51SR0ronoa                     .seek(SeekFrom::Start(offset as u64))
791c11e7deSyuyi2439                     .expect("Unable to seek framebuffer");
802b942a51SR0ronoa                 self.fb_file
812b942a51SR0ronoa                     .write_all(&pixel.to_bgra_bytes())
821c11e7deSyuyi2439                     .expect("Unable to write framebuffer");
8345e17157SR0ronoa             }
8445e17157SR0ronoa         }
85bee61dcaSR0ronoa         true
86bee61dcaSR0ronoa     }
87bee61dcaSR0ronoa 
mode(&self) -> &Cell<RenderMode>88bee61dcaSR0ronoa     fn mode(&self) -> &Cell<RenderMode> {
89bee61dcaSR0ronoa         &self.mode
90bee61dcaSR0ronoa     }
91bee61dcaSR0ronoa }
92bee61dcaSR0ronoa 
93bee61dcaSR0ronoa #[allow(dead_code)]
94bee61dcaSR0ronoa impl Window {
95bee61dcaSR0ronoa     /// TODO: 接收flags
new(x: i32, y: i32, w: u32, h: u32, title: &str, color: Color) -> Self96b0262857SR0ronoa     pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str, color: Color) -> Self {
97bee61dcaSR0ronoa         Window {
98bee61dcaSR0ronoa             x: x,
99bee61dcaSR0ronoa             y: y,
100bee61dcaSR0ronoa             w: w,
101bee61dcaSR0ronoa             h: h,
10245e17157SR0ronoa             title: title.to_string(),
103bee61dcaSR0ronoa             // window_async: false,
104bee61dcaSR0ronoa             resizable: false,
105bee61dcaSR0ronoa             mode: Cell::new(RenderMode::Blend),
106*731cae06SR0ronoa             file_opt: None,
107b0262857SR0ronoa             data_opt: Some(vec![color; (w * h) as usize].into_boxed_slice()),
1082b942a51SR0ronoa             fb_file: File::open(FB_FILE_PATH).expect("[Error] Window failed to open fb file"),
109bee61dcaSR0ronoa         }
110bee61dcaSR0ronoa 
111bee61dcaSR0ronoa         // TODO: 与服务器通信
112bee61dcaSR0ronoa     }
113bee61dcaSR0ronoa 
11445e17157SR0ronoa     /// 返回窗口x坐标
x(&self) -> i32115bee61dcaSR0ronoa     pub fn x(&self) -> i32 {
116bee61dcaSR0ronoa         self.x
117bee61dcaSR0ronoa     }
118bee61dcaSR0ronoa 
11945e17157SR0ronoa     /// 返回窗口y坐标
y(&self) -> i32120bee61dcaSR0ronoa     pub fn y(&self) -> i32 {
121bee61dcaSR0ronoa         self.y
122bee61dcaSR0ronoa     }
123bee61dcaSR0ronoa 
12445e17157SR0ronoa     /// 返回窗口标题
title(&self) -> String125bee61dcaSR0ronoa     pub fn title(&self) -> String {
12645e17157SR0ronoa         self.title.clone()
1271c11e7deSyuyi2439     }
128bee61dcaSR0ronoa 
12945e17157SR0ronoa     /// 改变窗口的位置
set_pos(&mut self, x: i32, y: i32)13045e17157SR0ronoa     pub fn set_pos(&mut self, x: i32, y: i32) {
13145e17157SR0ronoa         self.x = x;
13245e17157SR0ronoa         self.y = y;
13345e17157SR0ronoa     }
134bee61dcaSR0ronoa 
13545e17157SR0ronoa     /// 改变窗口的大小
set_size(&mut self, width: u32, height: u32)13645e17157SR0ronoa     pub fn set_size(&mut self, width: u32, height: u32) {
13745e17157SR0ronoa         self.w = width;
13845e17157SR0ronoa         self.h = height;
13945e17157SR0ronoa     }
14045e17157SR0ronoa 
14145e17157SR0ronoa     /// 改变窗口标题
set_title(&mut self, title: &str)14245e17157SR0ronoa     pub fn set_title(&mut self, title: &str) {
14345e17157SR0ronoa         self.title = title.to_string();
14445e17157SR0ronoa     }
145bee61dcaSR0ronoa }
146