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