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