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