From 76daaff0239ddf07731530cbed4e3c18a67f3e0d Mon Sep 17 00:00:00 2001 From: stjet <49297268+stjet@users.noreply.github.com> Date: Sat, 8 Feb 2025 07:13:24 +0000 Subject: [PATCH] too funny not to preserve --- src/bin/main.rs | 1 + src/components/press_button.rs | 8 ++- src/essential/onscreen_keyboard.rs | 95 +++++++++++++++++++++++++----- src/framebuffer.rs | 20 ++++++- src/messages.rs | 1 + src/window_manager.rs | 36 +++++++++-- 6 files changed, 135 insertions(+), 26 deletions(-) diff --git a/src/bin/main.rs b/src/bin/main.rs index 6fa77c6..67942ea 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -12,6 +12,7 @@ fn main() { height: fb.var_screen_info.yres_virtual as usize, bytes_per_pixel, stride: fb.fix_screen_info.line_length as usize / bytes_per_pixel, + old_stride: None, }; init(fb, fb_info); diff --git a/src/components/press_button.rs b/src/components/press_button.rs index 04b5324..c7d1e37 100644 --- a/src/components/press_button.rs +++ b/src/components/press_button.rs @@ -10,8 +10,8 @@ use crate::window_manager::{ DrawInstructions }; const MONO_WIDTH: u8 = 10; pub struct PressButton { - top_left: Point, - size: Dimensions, + pub top_left: Point, + pub size: Dimensions, text: String, press_return: T, } @@ -20,7 +20,9 @@ impl Component for PressButton { // fn handle_message(&mut self, message: WindowMessage) -> Option { match message { - WindowMessage::Touch(x, y) => { + WindowMessage::Touch(_, _) => { + //assume that the parent window-like passed it to us intentionally and checked already + //we can check again, but why? Some(self.press_return.clone()) }, _ => None, diff --git a/src/essential/onscreen_keyboard.rs b/src/essential/onscreen_keyboard.rs index 38b6c5d..fdc51b8 100644 --- a/src/essential/onscreen_keyboard.rs +++ b/src/essential/onscreen_keyboard.rs @@ -3,19 +3,20 @@ use std::vec::Vec; use std::collections::HashMap; use crate::window_manager::{ DrawInstructions, WindowLike, WindowLikeType, KeyChar }; -use crate::messages::{ WindowMessage, WindowMessageResponse }; +use crate::messages::{ WindowMessage, WindowMessageResponse, WindowManagerRequest }; use crate::framebuffer::Dimensions; use crate::themes::ThemeInfo; use crate::components::Component; use crate::components::press_button::PressButton; +use crate::utils::point_inside; -const padding_y: usize = 15; -const padding_x: usize = 15; +const PADDING_Y: usize = 15; +const PADDING_X: usize = 15; //padding in between keys in the x direction -const key_padding_x: usize = 5; -const key_padding_y: usize = 5; +const KEY_PADDING_X: usize = 5; +const KEY_PADDING_Y: usize = 5; -#[derive(Default, Eq, PartialEq, Hash)] +#[derive(Clone, Default, Eq, PartialEq, Hash)] enum Board { #[default] Regular, @@ -24,6 +25,17 @@ enum Board { SymbolsShift, } +impl Board { + fn inc(&mut self) -> Self { + match self { + Board::Regular => Board::Shift, + Board::Shift => Board::Symbols, + Board::Symbols => Board::SymbolsShift, + Board::SymbolsShift => Board::Regular, + } + } +} + #[derive(Clone)] enum KeyResponse { Key(char), @@ -32,11 +44,15 @@ enum KeyResponse { SwitchBoard, } +//if alt is true and ctrl is true, only alt will be sent. +//because I don't care about ctrl+alt stuff, and won't use it. +//(and probably not supported by this with a real keyboard anyways) #[derive(Default)] pub struct OnscreenKeyboard { dimensions: Dimensions, components: Vec>>, alt: bool, + ctrl: bool, board: Board, } @@ -48,7 +64,39 @@ impl WindowLike for OnscreenKeyboard { self.set_key_components(); WindowMessageResponse::JustRedraw }, - // + WindowMessage::Touch(x, y) => { + for c in &mut self.components { + if point_inside([x, y], c.top_left, c.size) { + let returned = c.handle_message(WindowMessage::Touch(x, y)); + if let Some(returned) = returned { + return match returned { + KeyResponse::Key(ch) => { + WindowMessageResponse::Request(WindowManagerRequest::DoKeyChar(if self.alt { + KeyChar::Alt(ch) + } else if self.ctrl { + KeyChar::Ctrl(ch) + } else { + KeyChar::Press(ch) + })) + }, + KeyResponse::Alt => { + self.alt = !self.alt; + WindowMessageResponse::DoNothing + }, + KeyResponse::Ctrl => { + self.ctrl = !self.ctrl; + WindowMessageResponse::DoNothing + }, + KeyResponse::SwitchBoard => { + self.board = self.board.inc(); + WindowMessageResponse::DoNothing + }, + }; + } + } + } + WindowMessageResponse::DoNothing + }, _ => WindowMessageResponse::DoNothing, } } @@ -60,7 +108,7 @@ impl WindowLike for OnscreenKeyboard { } instructions } - // + fn subtype(&self) -> WindowLikeType { WindowLikeType::OnscreenKeyboard } @@ -93,7 +141,7 @@ impl OnscreenKeyboard { HashMap::from([ (Board::Regular, vec!['𐘃', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '𐘁']), //escape and backspace (Board::Shift, vec!['𐘃', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '𐘁']), //escape and backspace - (Board::Symbols, vec!['~', '*', '"', '\'', ':', ';', '!', '?', '𐘁']), //basckspace + (Board::Symbols, vec!['~', '*', '"', '\'', ':', ';', '!', '?', '𐘁']), //backspace (Board::SymbolsShift, vec!['[', ']', '{', '}', '𐘁']), //backspace ]), HashMap::from([ @@ -101,16 +149,17 @@ impl OnscreenKeyboard { (Board::Shift, vec!['𐘧', '𐘎', ' ', '𐘂']), //switch board (special case, not a real key), alt (special case, not a real key), enter (Board::Symbols, vec!['𐘧', '𐘎', ',', '_', ' ', '/', '.', '𐘂']), //switch board (special case, not a real key), alt (special case, not a real key), enter (Board::SymbolsShift, vec!['𐘧', '𐘎', '\\', '<', ' ', '>', '𐘾', '𐘂']), //switch board (special case, not a real key), alt (special case, not a real key), ctrl (special case, not a real key), enter + //ctrl = shimazu ]), ]; //hardcoded for now - let mut y = padding_y; - let key_height = (self.dimensions[1] - padding_y * 2 - key_padding_y * (rows.len() - 1)) / rows.len(); - let reg_key_width = (self.dimensions[0] - padding_x * 2 - key_padding_x * (10 - 1)) / 10; + let mut y = PADDING_Y; + let key_height = (self.dimensions[1] - PADDING_Y * 2 - KEY_PADDING_Y * (rows.len() - 1)) / rows.len(); + let reg_key_width = (self.dimensions[0] - PADDING_X * 2 - KEY_PADDING_X * (10 - 1)) / 10; for row in rows { let row_keys = &row[&self.board]; //centre - let mut x = padding_x + (10 - row_keys.len()) * (reg_key_width + key_padding_x) / 2; + let mut x = PADDING_X + (10 - row_keys.len()) * (reg_key_width + KEY_PADDING_X) / 2; for key in row_keys { let press_return = if key == &'𐘧' { KeyResponse::SwitchBoard @@ -121,10 +170,24 @@ impl OnscreenKeyboard { } else { KeyResponse::Key(*key) }; - self.components.push(Box::new(PressButton::new([x, y], [reg_key_width, key_height], key.to_string(), press_return))); - x += reg_key_width + key_padding_x; + let mut text = key.to_string(); + if text == "𐘧" { + text = "Switch".to_string(); + } else if text == "𐘎" { + text = "Alt".to_string(); + } else if text == "𐘂" { + text = "Enter".to_string(); + } else if text == "𐘁" { + text = "Back".to_string(); + } else if text == "𐘃" { + text = "Esc".to_string(); + } else if text == "𐘾" { + text = "Ctrl".to_string(); + } + self.components.push(Box::new(PressButton::new([x, y], [reg_key_width, key_height], text, press_return))); + x += reg_key_width + KEY_PADDING_X; } - y += key_height + key_padding_y; + y += key_height + KEY_PADDING_Y; } } } diff --git a/src/framebuffer.rs b/src/framebuffer.rs index 15d5ea2..449cca6 100644 --- a/src/framebuffer.rs +++ b/src/framebuffer.rs @@ -38,6 +38,7 @@ pub struct FramebufferInfo { pub height: usize, pub bytes_per_pixel: usize, pub stride: usize, + pub old_stride: Option, //used/set only when rotate is true } //currently doesn't check if writing onto next line accidentally @@ -45,6 +46,7 @@ pub struct FramebufferWriter { info: FramebufferInfo, buffer: Vec, saved_buffer: Option>, + rotate_buffer: Option>, } impl FramebufferWriter { @@ -57,10 +59,25 @@ impl FramebufferWriter { self.info.clone() } - pub fn get_buffer(&self) -> &[u8] { + pub fn get_buffer(&mut self) -> &[u8] { &self.buffer } + pub fn get_transposed_buffer(&mut self) -> &[u8] { + let mut output_array = vec![255; self.info.byte_len]; + let row_bytes_len = self.info.stride * self.info.bytes_per_pixel; + let row_bytes_len_transposed = self.info.old_stride.unwrap_or(self.info.height) * self.info.bytes_per_pixel; + for y in 0..self.info.height { + for x in 0..self.info.width { + for i in 0..self.info.bytes_per_pixel { + output_array[x * row_bytes_len_transposed + y * self.info.bytes_per_pixel + i] = self.buffer[y * row_bytes_len + x * self.info.bytes_per_pixel + i]; + } + } + } + self.rotate_buffer = Some(output_array); + &self.rotate_buffer.as_ref().unwrap() + } + pub fn save_buffer(&mut self) { self.saved_buffer = Some(self.buffer.clone()); } @@ -237,6 +254,7 @@ impl Default for FramebufferWriter { info: Default::default(), buffer: Vec::new(), saved_buffer: None, + rotate_buffer: None, } } } diff --git a/src/messages.rs b/src/messages.rs index 924f06c..a86279d 100644 --- a/src/messages.rs +++ b/src/messages.rs @@ -31,6 +31,7 @@ pub enum WindowManagerRequest { CloseStartMenu, Unlock, Lock, + DoKeyChar(KeyChar), // } diff --git a/src/window_manager.rs b/src/window_manager.rs index c0db4d6..42ff4f7 100644 --- a/src/window_manager.rs +++ b/src/window_manager.rs @@ -39,7 +39,7 @@ pub const TASKBAR_HEIGHT: usize = 38; pub const INDICATOR_HEIGHT: usize = 20; const WINDOW_TOP_HEIGHT: usize = 26; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub enum KeyChar { Press(char), Alt(char), @@ -53,6 +53,23 @@ enum ThreadMessage { } pub fn init(framebuffer: Framebuffer, framebuffer_info: FramebufferInfo) { + let args: Vec<_> = env::args().collect(); + + let rotate = args.contains(&"rotate".to_string()); + + let framebuffer_info = if rotate { + FramebufferInfo { + byte_len: framebuffer_info.byte_len, + width: framebuffer_info.height, + height: framebuffer_info.width, + bytes_per_pixel: framebuffer_info.bytes_per_pixel, + stride: framebuffer_info.height, + old_stride: Some(framebuffer_info.stride), + } + } else { + framebuffer_info + }; + let dimensions = [framebuffer_info.width, framebuffer_info.height]; println!("bg: {}x{}", dimensions[0], dimensions[1] - TASKBAR_HEIGHT - INDICATOR_HEIGHT); @@ -61,7 +78,7 @@ pub fn init(framebuffer: Framebuffer, framebuffer_info: FramebufferInfo) { writer.init(framebuffer_info.clone()); - let mut wm: WindowManager = WindowManager::new(writer, framebuffer, dimensions); + let mut wm: WindowManager = WindowManager::new(writer, framebuffer, dimensions, rotate); wm.draw(None, false); @@ -91,7 +108,6 @@ pub fn init(framebuffer: Framebuffer, framebuffer_info: FramebufferInfo) { } }); - let args: Vec<_> = env::args().collect(); let touch = args.contains(&"touch".to_string()); //read touchscreen presses (hopefully) @@ -204,6 +220,7 @@ impl fmt::Debug for WindowLikeInfo { pub struct WindowManager { writer: RefCell, + rotate: bool, id_count: usize, window_infos: Vec, osk: Option, @@ -219,9 +236,10 @@ pub struct WindowManager { //1 is up, 2 is down impl WindowManager { - pub fn new(writer: FramebufferWriter, framebuffer: Framebuffer, dimensions: Dimensions) -> Self { + pub fn new(writer: FramebufferWriter, framebuffer: Framebuffer, dimensions: Dimensions, rotate: bool) -> Self { let mut wm = WindowManager { writer: RefCell::new(writer), + rotate, id_count: 0, window_infos: Vec::new(), osk: None, @@ -612,7 +630,7 @@ impl WindowManager { } else { //see if in onscreen keyboard, if so send to it after offsetting coords if self.osk.is_some() { - let mut osk = self.osk.as_mut().unwrap(); + let osk = self.osk.as_mut().unwrap(); if point_inside([x, y], osk.top_left, osk.dimensions) { osk.window_like.handle_message(WindowMessage::Touch(x - osk.top_left[0], y - osk.top_left[1])) } else { @@ -692,6 +710,9 @@ impl WindowManager { WindowManagerRequest::ClipboardCopy(content) => { self.clipboard = Some(content); }, + WindowManagerRequest::DoKeyChar(kc) => { + self.handle_message(WindowManagerMessage::KeyChar(kc)); + }, }; } @@ -804,6 +825,9 @@ impl WindowManager { self.writer.borrow_mut().draw_buffer(window_info.top_left, window_dimensions[1], window_dimensions[0] * bytes_per_pixel, &window_writer.get_buffer()); w_index += 1; } - self.framebuffer.write_frame(self.writer.borrow().get_buffer()); + //could probably figure out a way to do borrow() when self.rotate is false but does it matter? + let mut writer_borrow = self.writer.borrow_mut(); + let frame = if self.rotate { writer_borrow.get_transposed_buffer() } else { writer_borrow.get_buffer() }; + self.framebuffer.write_frame(frame); } }