From a2c53aba27bd9615e2d3a739ba126d7cd0afece1 Mon Sep 17 00:00:00 2001 From: stjet <49297268+stjet@users.noreply.github.com> Date: Wed, 5 Feb 2025 08:18:44 +0000 Subject: [PATCH] click test, osk test --- docs/window-likes/audio-player.md | 2 +- docs/window-likes/onscreen-keyboard.md | 1 + src/essential/mod.rs | 1 + src/essential/onscreen_keyboard.rs | 47 ++++++++++++++++ src/keyboard.rs | 22 -------- src/lib.rs | 1 - src/messages.rs | 4 +- src/utils.rs | 21 ++++++++ src/window_manager.rs | 74 ++++++++++++++++++-------- 9 files changed, 126 insertions(+), 47 deletions(-) create mode 100644 docs/window-likes/onscreen-keyboard.md create mode 100644 src/essential/onscreen_keyboard.rs delete mode 100644 src/keyboard.rs diff --git a/docs/window-likes/audio-player.md b/docs/window-likes/audio-player.md index 8e1ea32..0bde4e6 100644 --- a/docs/window-likes/audio-player.md +++ b/docs/window-likes/audio-player.md @@ -1,4 +1,4 @@ -Audio player with playlist and folder support. +Audio player with playlist and folder support. Requires the dev version of `alsa` lib. ## Commands diff --git a/docs/window-likes/onscreen-keyboard.md b/docs/window-likes/onscreen-keyboard.md new file mode 100644 index 0000000..8113684 --- /dev/null +++ b/docs/window-likes/onscreen-keyboard.md @@ -0,0 +1 @@ +This is primarily intended for mobile users. diff --git a/src/essential/mod.rs b/src/essential/mod.rs index 0800750..e594dcb 100644 --- a/src/essential/mod.rs +++ b/src/essential/mod.rs @@ -3,6 +3,7 @@ pub mod taskbar; pub mod lock_screen; pub mod workspace_indicator; pub mod start_menu; +pub mod onscreen_keyboard; pub mod about; pub mod help; diff --git a/src/essential/onscreen_keyboard.rs b/src/essential/onscreen_keyboard.rs new file mode 100644 index 0000000..536a6cc --- /dev/null +++ b/src/essential/onscreen_keyboard.rs @@ -0,0 +1,47 @@ +use std::vec; +use std::vec::Vec; + +use crate::window_manager::{ DrawInstructions, WindowLike, WindowLikeType }; +use crate::messages::{ WindowMessage, WindowMessageResponse }; +use crate::framebuffer::Dimensions; +use crate::themes::ThemeInfo; + +#[derive(Default)] +pub struct OnscreenKeyboard { + dimensions: Dimensions, + // +} + +impl WindowLike for OnscreenKeyboard { + fn handle_message(&mut self, message: WindowMessage) -> WindowMessageResponse { + match message { + WindowMessage::Init(dimensions) => { + self.dimensions = dimensions; + WindowMessageResponse::JustRedraw + }, + // + _ => WindowMessageResponse::DoNothing, + } + } + + fn draw(&self, theme_info: &ThemeInfo) -> Vec { + let mut instructions = vec![DrawInstructions::Rect([0, 0], self.dimensions, theme_info.background)]; + // + instructions + } + // + fn subtype(&self) -> WindowLikeType { + WindowLikeType::OnscreenKeyboard + } + + fn ideal_dimensions(&self, dimensions: Dimensions) -> Dimensions { + [dimensions[0] - 175, 250] + } +} + +impl OnscreenKeyboard { + pub fn new() -> Self { + Self::default() + } +} + diff --git a/src/keyboard.rs b/src/keyboard.rs deleted file mode 100644 index 6834d76..0000000 --- a/src/keyboard.rs +++ /dev/null @@ -1,22 +0,0 @@ -use termion::event::Key; - -#[derive(Clone, Debug, PartialEq)] -pub enum KeyChar { - Press(char), - Alt(char), - Ctrl(char), -} - -//use Linear A for escape, backspace, enter -pub fn key_to_char(key: Key) -> Option { - match key { - Key::Char('\n') => Some(KeyChar::Press('𐘂')), - Key::Char(c) => Some(KeyChar::Press(c)), - Key::Alt(c) => Some(KeyChar::Alt(c)), - Key::Ctrl(c) => Some(KeyChar::Ctrl(c)), - Key::Backspace => Some(KeyChar::Press('𐘁')), - Key::Esc => Some(KeyChar::Press('𐘃')), - _ => None, - } -} - diff --git a/src/lib.rs b/src/lib.rs index 387d654..cb61bd7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,5 @@ pub mod utils; pub mod logging; pub mod ipc; mod proxy_window_like; -mod keyboard; mod essential; diff --git a/src/messages.rs b/src/messages.rs index 132ff80..9baf255 100644 --- a/src/messages.rs +++ b/src/messages.rs @@ -4,12 +4,12 @@ use std::vec::Vec; use serde::{ Deserialize, Serialize }; -use crate::keyboard::KeyChar; use crate::framebuffer::Dimensions; -use crate::window_manager::WindowLike; +use crate::window_manager::{ WindowLike, KeyChar }; pub enum WindowManagerMessage { KeyChar(KeyChar), + Click(u16, u16), // } diff --git a/src/utils.rs b/src/utils.rs index 8e62417..de6e36a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,5 +1,26 @@ use std::path::PathBuf; +use termion::event::Key; + +use crate::window_manager::KeyChar; + +//use Linear A for escape, backspace, enter +pub fn key_to_char(key: Key) -> Option { + match key { + Key::Char('\n') => Some(KeyChar::Press('𐘂')), + Key::Char(c) => Some(KeyChar::Press(c)), + Key::Alt(c) => Some(KeyChar::Alt(c)), + Key::Ctrl(c) => Some(KeyChar::Ctrl(c)), + Key::Backspace => Some(KeyChar::Press('𐘁')), + Key::Esc => Some(KeyChar::Press('𐘃')), + _ => None, + } +} + +pub fn min(one: usize, two: usize) -> usize { + if one > two { two } else { one } +} + pub trait Substring { fn substring(&self, start: usize, end: usize) -> &str; fn remove(&self, index: usize, len: usize) -> String; diff --git a/src/window_manager.rs b/src/window_manager.rs index f4a9d97..231a4ec 100644 --- a/src/window_manager.rs +++ b/src/window_manager.rs @@ -8,14 +8,15 @@ use std::process::exit; use std::cell::RefCell; use linux_framebuffer::Framebuffer; -use termion::input::TermRead; +use termion::input::{ MouseTerminal, TermRead }; use termion::raw::IntoRawMode; use termion::cursor; +use termion::event::{ Event, MouseEvent }; use serde::{ Deserialize, Serialize }; use crate::framebuffer::{ FramebufferWriter, FramebufferInfo, Point, Dimensions, RGBColor }; use crate::themes::{ ThemeInfo, Themes, get_theme_info }; -use crate::keyboard::{ KeyChar, key_to_char }; +use crate::utils::{ min, key_to_char }; use crate::messages::*; use crate::proxy_window_like::ProxyWindowLike; use crate::essential::desktop_background::DesktopBackground; @@ -25,6 +26,7 @@ use crate::essential::workspace_indicator::WorkspaceIndicator; use crate::essential::start_menu::StartMenu; use crate::essential::about::About; use crate::essential::help::Help; +use crate::essential::onscreen_keyboard::OnscreenKeyboard; //use crate::logging::log; pub const TASKBAR_HEIGHT: usize = 38; @@ -45,31 +47,43 @@ pub fn init(framebuffer: Framebuffer, framebuffer_info: FramebufferInfo) { wm.draw(None, false); let stdin = stdin().lock(); - let mut stdout = stdout().into_raw_mode().unwrap(); + let mut stdout = MouseTerminal::from(stdout().into_raw_mode().unwrap()); write!(stdout, "{}", cursor::Hide).unwrap(); stdout.flush().unwrap(); - - for c in stdin.keys() { - if let Some(kc) = key_to_char(c.unwrap()) { - //do not allow exit when locked unless debugging - //if kc == KeyChar::Alt('E') { - if kc == KeyChar::Alt('E') && !wm.locked { - write!(stdout, "{}", cursor::Show).unwrap(); - stdout.suspend_raw_mode().unwrap(); - exit(0); - } else { - wm.handle_message(WindowManagerMessage::KeyChar(kc.clone())); - } - } + for e in stdin.events() { + match e.unwrap() { + Event::Key(c) => { + if let Some(kc) = key_to_char(c) { + //do not allow exit when locked unless debugging + //if kc == KeyChar::Alt('E') { + if kc == KeyChar::Alt('E') && !wm.locked { + write!(stdout, "{}", cursor::Show).unwrap(); + stdout.suspend_raw_mode().unwrap(); + exit(0); + } else { + wm.handle_message(WindowManagerMessage::KeyChar(kc.clone())); + } + } + }, + Event::Mouse(m) => { + if let MouseEvent::Press(_, x, y) = m { + //We don't care what button + //(should also support mobile?) + wm.handle_message(WindowManagerMessage::Click(x, y)); + } + }, + _ => {}, + }; } - - // } -pub fn min(one: usize, two: usize) -> usize { - if one > two { two } else { one } +#[derive(Clone, Debug, PartialEq)] +pub enum KeyChar { + Press(char), + Alt(char), + Ctrl(char), } #[derive(Debug, Serialize, Deserialize)] @@ -89,6 +103,7 @@ pub enum WindowLikeType { Taskbar, StartMenu, WorkspaceIndicator, + OnscreenKeyboard, } pub trait WindowLike { @@ -215,6 +230,7 @@ impl WindowManager { } //if off_only is true, also handle request + //written confusingly but it works I promise fn toggle_start_menu(&mut self, off_only: bool) -> WindowMessageResponse { let start_menu_exists = self.window_infos.iter().find(|w| w.window_like.subtype() == WindowLikeType::StartMenu).is_some(); if (start_menu_exists && off_only) || !off_only { @@ -518,7 +534,23 @@ impl WindowManager { }, } }, - // + WindowManagerMessage::Click(x, y) => { + //println!("{}, {}", x, y); + if x < 10000 && y < 10000 { + //toggle onscreen keyboard if top left keyboard clicked + let osk_index = self.window_infos.iter().position(|w| w.window_like.subtype() == WindowLikeType::OnscreenKeyboard); + if let Some(osk_index) = osk_index { + self.window_infos.remove(osk_index); + } else { + let osk = Box::new(OnscreenKeyboard::new()); + let ideal_dimensions = osk.ideal_dimensions(self.dimensions); + self.add_window_like(osk, [175, self.dimensions[1] - TASKBAR_HEIGHT - 250], Some(ideal_dimensions)); + } + } + //see if in onscreen keyboard, if so send to it after offsetting coords + // + WindowMessageResponse::JustRedraw + }, }; if response != WindowMessageResponse::DoNothing { match response {