window.rs 3.4 KB

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