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 /// TODO 37 // window_async: bool, 38 /// 窗口是否大小可变 39 resizable: bool, 40 /// 窗口的渲染模式 41 mode: Cell<RenderMode>, 42 // TODO 43 // file_opt: Option<File>, 44 // TODO: 改定长数组 45 // data_opt: Option<& 'static mut [Color]>, 46 /// 窗口的渲染数据 47 data_opt: Option<Box<[Color]>>, 48 /// 帧缓冲文件 49 fb_file: File, 50 } 51 52 impl Renderer for Window { 53 fn width(&self) -> u32 { 54 self.w 55 } 56 57 fn height(&self) -> u32 { 58 self.h 59 } 60 61 fn data(&self) -> &[Color] { 62 self.data_opt.as_ref().unwrap() 63 } 64 65 fn data_mut(&mut self) -> &mut [Color] { 66 self.data_opt.as_mut().unwrap() 67 } 68 69 fn sync(&mut self) -> bool { 70 // 处理窗口大小超限的情况 71 let width = min(self.width() as i32, SCREEN_WIDTH as i32 - self.x); 72 let height = min(self.height() as i32, SCREEN_HEIGHT as i32 - self.y); 73 74 for y in 0..height as i32 { 75 for x in 0..width as i32 { 76 let pixel = self.get_pixel(x, y); 77 let offset = (((y + self.y()) * SCREEN_WIDTH as i32) + x + self.x()) * 4; 78 // 写缓冲区 79 self.fb_file 80 .seek(SeekFrom::Start(offset as u64)) 81 .expect("Unable to seek framebuffer"); 82 self.fb_file 83 .write_all(&pixel.to_bgra_bytes()) 84 .expect("Unable to write framebuffer"); 85 } 86 } 87 true 88 } 89 90 fn mode(&self) -> &Cell<RenderMode> { 91 &self.mode 92 } 93 } 94 95 #[allow(dead_code)] 96 impl Window { 97 /// TODO: 接收flags 98 pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str, color: Color) -> Self { 99 Window { 100 x: x, 101 y: y, 102 w: w, 103 h: h, 104 title: title.to_string(), 105 // window_async: false, 106 resizable: false, 107 mode: Cell::new(RenderMode::Blend), 108 // file_opt: None, 109 data_opt: Some(vec![color; (w * h) as usize].into_boxed_slice()), 110 fb_file: File::open(FB_FILE_PATH).expect("[Error] Window failed to open fb file"), 111 } 112 113 // TODO: 与服务器通信 114 } 115 116 /// 返回窗口x坐标 117 pub fn x(&self) -> i32 { 118 self.x 119 } 120 121 /// 返回窗口y坐标 122 pub fn y(&self) -> i32 { 123 self.y 124 } 125 126 /// 返回窗口标题 127 pub fn title(&self) -> String { 128 self.title.clone() 129 } 130 131 /// 改变窗口的位置 132 pub fn set_pos(&mut self, x: i32, y: i32) { 133 self.x = x; 134 self.y = y; 135 } 136 137 /// 改变窗口的大小 138 pub fn set_size(&mut self, width: u32, height: u32) { 139 self.w = width; 140 self.h = height; 141 } 142 143 /// 改变窗口标题 144 pub fn set_title(&mut self, title: &str) { 145 self.title = title.to_string(); 146 } 147 } 148