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