add input methdod framework (add sitelen pona input)
Also change audio player randomness source to /dev/urandom which is way better for the prng we are using
This commit is contained in:
@@ -51,11 +51,11 @@ impl WindowLike for LockScreen {
|
||||
fn draw(&self, _theme_info: &ThemeInfo) -> Vec<DrawInstructions> {
|
||||
vec![
|
||||
DrawInstructions::Rect([0, 0], self.dimensions, [0, 0, 0]),
|
||||
DrawInstructions::Text([4, 4], vec!["nimbus-roman".to_string()], self.lines[0].clone(), [255, 255, 255], [0, 0, 0], None, None),
|
||||
DrawInstructions::Text([4, 4], vec!["nimbus-roman".to_string(), "shippori-mincho".to_string(), "linja-lipamanka".to_string()], self.lines[0].clone(), [255, 255, 255], [0, 0, 0], None, None),
|
||||
//He is my brother.
|
||||
DrawInstructions::Text([4, 4 + 16], vec!["nimbus-roman".to_string()], self.lines[1].clone(), [255, 255, 255], [0, 0, 0], None, None),
|
||||
DrawInstructions::Text([4, 4 + 16], vec!["nimbus-roman".to_string(), "shippori-mincho".to_string(), "linja-lipamanka".to_string()], self.lines[1].clone(), [255, 255, 255], [0, 0, 0], None, None),
|
||||
//But I must kill him and keep strong to do it.
|
||||
DrawInstructions::Text([4, 4 + 16 * 2], vec!["nimbus-roman".to_string()], self.lines[2].clone(), [255, 255, 255], [0, 0, 0], None, None),
|
||||
DrawInstructions::Text([4, 4 + 16 * 2], vec!["nimbus-roman".to_string(), "shippori-mincho".to_string(), "linja-lipamanka".to_string()], self.lines[2].clone(), [255, 255, 255], [0, 0, 0], None, None),
|
||||
DrawInstructions::Text([4, 4 + 16 * 3], vec!["nimbus-roman".to_string()], "Password: ".to_string(), [255, 255, 255], [0, 0, 0], None, None),
|
||||
DrawInstructions::Text([80, 4 + 16 * 3], vec!["nimbus-roman".to_string()], "*".repeat(self.input_password.len()), [255, 255, 255], [0, 0, 0], None, None),
|
||||
]
|
||||
@@ -84,6 +84,16 @@ impl LockScreen {
|
||||
"\"Yellow,\" he thought, and stomped off back to his bedroom to get dressed.".to_string(),
|
||||
"He stared at it.".to_string()
|
||||
],
|
||||
[
|
||||
"\"\"".to_string(),
|
||||
"\"\"".to_string(),
|
||||
"\"\"".to_string()
|
||||
],
|
||||
[
|
||||
"安心".to_string(),
|
||||
"アンコール".to_string(),
|
||||
"ワット".to_string(),
|
||||
],
|
||||
];
|
||||
let rand_index = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as usize % possible_lines.len();
|
||||
Self {
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::vec::Vec;
|
||||
use std::time::{ SystemTime, UNIX_EPOCH };
|
||||
|
||||
use ming_wm_lib::window_manager_types::{ DrawInstructions, WindowLike, WindowLikeType, INDICATOR_HEIGHT };
|
||||
use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse, ShortcutType };
|
||||
use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse, ShortcutType, InfoType };
|
||||
use ming_wm_lib::framebuffer_types::Dimensions;
|
||||
use ming_wm_lib::themes::ThemeInfo;
|
||||
|
||||
@@ -15,6 +15,8 @@ const ONE_DAY: u64 = 24 * ONE_HOUR;
|
||||
pub struct WorkspaceIndicator {
|
||||
dimensions: Dimensions,
|
||||
current_workspace: u8,
|
||||
im_abbr: String,
|
||||
im_buffer: String,
|
||||
}
|
||||
|
||||
impl WindowLike for WorkspaceIndicator {
|
||||
@@ -33,6 +35,15 @@ impl WindowLike for WorkspaceIndicator {
|
||||
_ => WindowMessageResponse::DoNothing,
|
||||
}
|
||||
},
|
||||
WindowMessage::Info(info) => {
|
||||
if let InfoType::InputMethod(im_abbr, im_buffer) = info {
|
||||
self.im_abbr = im_abbr;
|
||||
self.im_buffer = im_buffer;
|
||||
WindowMessageResponse::JustRedraw
|
||||
} else {
|
||||
WindowMessageResponse::DoNothing
|
||||
}
|
||||
},
|
||||
_ => WindowMessageResponse::DoNothing,
|
||||
}
|
||||
}
|
||||
@@ -53,6 +64,14 @@ impl WindowLike for WorkspaceIndicator {
|
||||
instructions.push(DrawInstructions::Text([w * WIDTH + 5, 4], vec!["nimbus-roman".to_string()], (w + 1).to_string(), theme_info.text, theme_info.background, None, None));
|
||||
}
|
||||
}
|
||||
//input method and buffer
|
||||
let im_buffer = if self.im_buffer.len() > 6 {
|
||||
self.im_buffer[0..6].to_string() + "..."
|
||||
} else {
|
||||
self.im_buffer.clone()
|
||||
};
|
||||
let im_info = format!("{}: {}", self.im_abbr, im_buffer);
|
||||
instructions.push(DrawInstructions::Text([self.dimensions[0] - 200, 4], vec!["nimbus-roman".to_string()], im_info, theme_info.text, theme_info.background, None, None));
|
||||
//also add the utc time in the right edge
|
||||
let today_secs = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() % ONE_DAY;
|
||||
let hours = (today_secs / ONE_HOUR).to_string();
|
||||
@@ -73,10 +92,12 @@ impl WindowLike for WorkspaceIndicator {
|
||||
}
|
||||
|
||||
impl WorkspaceIndicator {
|
||||
pub fn new() -> Self {
|
||||
pub fn new(im_abbr: String) -> Self {
|
||||
Self {
|
||||
dimensions: [0, 0],
|
||||
current_workspace: 0,
|
||||
im_abbr,
|
||||
im_buffer: String::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ fn color_with_alpha(color: RGBColor, bg_color: RGBColor, alpha: u8) -> RGBColor
|
||||
//255 * 255 < max(u16)
|
||||
if alpha == 255 {
|
||||
color
|
||||
} else if alpha == 0 {
|
||||
bg_color
|
||||
} else {
|
||||
let alpha = alpha as u16;
|
||||
[
|
||||
@@ -128,7 +130,7 @@ impl FramebufferWriter {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_char(&mut self, top_left: Point, char_info: &FontCharInfo, color: RGBColor, bg_color: RGBColor) {
|
||||
fn _draw_char(&mut self, top_left: Point, char_info: &FontCharInfo, color: RGBColor, bg_color: RGBColor) {
|
||||
let mut start_pos;
|
||||
for row in 0..char_info.height {
|
||||
start_pos = ((top_left[1] + row + char_info.top_offset as usize) * self.info.stride + top_left[0]) * self.info.bytes_per_pixel;
|
||||
@@ -238,7 +240,7 @@ impl FramebufferWriter {
|
||||
} else {
|
||||
add_after = char_width + horiz_spacing;
|
||||
}
|
||||
self.draw_char(top_left, &char_info, color, bg_color);
|
||||
self._draw_char(top_left, &char_info, color, bg_color);
|
||||
top_left[0] += add_after;
|
||||
}
|
||||
}
|
||||
|
||||
19
wm/src/input_method/lat.rs
Normal file
19
wm/src/input_method/lat.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
use ming_wm_lib::window_manager_types::InputMethod;
|
||||
use ming_wm_lib::messages::KeyPress;
|
||||
|
||||
pub struct Lat {}
|
||||
|
||||
impl InputMethod for Lat {
|
||||
fn abbr(&self) -> [char; 3] {
|
||||
['L', 'A', 'T']
|
||||
}
|
||||
|
||||
fn internal_buffer(&self) -> String {
|
||||
String::new()
|
||||
}
|
||||
|
||||
fn add_key_press(&mut self, kp: KeyPress) -> Option<char> {
|
||||
//everything goes
|
||||
Some(kp.key)
|
||||
}
|
||||
}
|
||||
2
wm/src/input_method/mod.rs
Normal file
2
wm/src/input_method/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod lat;
|
||||
pub mod tok;
|
||||
193
wm/src/input_method/tok.rs
Normal file
193
wm/src/input_method/tok.rs
Normal file
@@ -0,0 +1,193 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use ming_wm_lib::window_manager_types::InputMethod;
|
||||
use ming_wm_lib::messages::KeyPress;
|
||||
|
||||
const TOK_CHARSET: [char; 14] = ['m', 'n', 'i', 'u', 'p', 't', 'k', 'e', 'o', 's', 'a', 'w', 'l', 'j'];
|
||||
|
||||
pub struct Tok {
|
||||
mapping: HashMap<String, char>,
|
||||
buffer: String,
|
||||
}
|
||||
|
||||
impl InputMethod for Tok {
|
||||
fn abbr(&self) -> [char; 3] {
|
||||
['T', 'O', 'K']
|
||||
}
|
||||
|
||||
fn internal_buffer(&self) -> String {
|
||||
self.buffer.clone()
|
||||
}
|
||||
|
||||
fn add_key_press(&mut self, kp: KeyPress) -> Option<char> {
|
||||
if kp.is_enter() || kp.is_backspace() {
|
||||
if self.buffer == String::new() {
|
||||
//^if no buffer, enter or backspace key should be passed through
|
||||
Some(kp.key)
|
||||
} else {
|
||||
if kp.is_enter() {
|
||||
if let Some(ret_c) = self.mapping.get(&self.buffer.to_lowercase()) {
|
||||
//^look up in table to see if buffer matches, if so, return
|
||||
self.buffer = String::new();
|
||||
return Some(*ret_c);
|
||||
}
|
||||
}
|
||||
//else, just clear buffer
|
||||
self.buffer = String::new();
|
||||
None
|
||||
}
|
||||
} else if TOK_CHARSET.contains(&kp.key) {
|
||||
self.buffer += &kp.key.to_string();
|
||||
None
|
||||
} else {
|
||||
//pass through stuff not in tp charset
|
||||
Some(kp.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Tok {
|
||||
pub fn new() -> Self {
|
||||
let mapping = HashMap::from([
|
||||
("pali".to_string(), ''),
|
||||
("weka".to_string(), ''),
|
||||
("li".to_string(), ''),
|
||||
("pona".to_string(), ''),
|
||||
("tawa".to_string(), ''),
|
||||
("mi".to_string(), ''),
|
||||
("kulupu".to_string(), ''),
|
||||
("pi".to_string(), ''),
|
||||
("musi".to_string(), ''),
|
||||
("sijelo".to_string(), ''),
|
||||
("ni".to_string(), ''),
|
||||
("palisa".to_string(), ''),
|
||||
("a".to_string(), ''),
|
||||
("akesi".to_string(), ''),
|
||||
("ala".to_string(), ''),
|
||||
("alasa".to_string(), ''),
|
||||
("ali".to_string(), ''),
|
||||
("ale".to_string(), ''),
|
||||
("anpa".to_string(), ''),
|
||||
("ante".to_string(), ''),
|
||||
("anu".to_string(), ''),
|
||||
("awen".to_string(), ''),
|
||||
("e".to_string(), ''),
|
||||
("en".to_string(), ''),
|
||||
("esun".to_string(), ''),
|
||||
("ijo".to_string(), ''),
|
||||
("ike".to_string(), ''),
|
||||
("ilo".to_string(), ''),
|
||||
("insa".to_string(), ''),
|
||||
("jaki".to_string(), ''),
|
||||
("jan".to_string(), ''),
|
||||
("jelo".to_string(), ''),
|
||||
("jo".to_string(), ''),
|
||||
("kala".to_string(), ''),
|
||||
("kalama".to_string(), ''),
|
||||
("kama".to_string(), ''),
|
||||
("kasi".to_string(), ''),
|
||||
("ken".to_string(), ''),
|
||||
("kepeken".to_string(), ''),
|
||||
("kili".to_string(), ''),
|
||||
("kiwen".to_string(), ''),
|
||||
("ko".to_string(), ''),
|
||||
("kon".to_string(), ''),
|
||||
("kule".to_string(), ''),
|
||||
("kute".to_string(), ''),
|
||||
("la".to_string(), ''),
|
||||
("lape".to_string(), ''),
|
||||
("laso".to_string(), ''),
|
||||
("lawa".to_string(), ''),
|
||||
("len".to_string(), ''),
|
||||
("lete".to_string(), ''),
|
||||
("lili".to_string(), ''),
|
||||
("linja".to_string(), ''),
|
||||
("lipu".to_string(), ''),
|
||||
("loje".to_string(), ''),
|
||||
("lon".to_string(), ''),
|
||||
("luka".to_string(), ''),
|
||||
("lukin".to_string(), ''),
|
||||
("lupa".to_string(), ''),
|
||||
("ma".to_string(), ''),
|
||||
("mama".to_string(), ''),
|
||||
("mani".to_string(), ''),
|
||||
("meli".to_string(), ''),
|
||||
("mije".to_string(), ''),
|
||||
("moku".to_string(), ''),
|
||||
("moli".to_string(), ''),
|
||||
("monsi".to_string(), ''),
|
||||
("mu".to_string(), ''),
|
||||
("mun".to_string(), ''),
|
||||
("mute".to_string(), ''),
|
||||
("nanpa".to_string(), ''),
|
||||
("nasa".to_string(), ''),
|
||||
("nasin".to_string(), ''),
|
||||
("nena".to_string(), ''),
|
||||
("ni".to_string(), ''),
|
||||
("nimi".to_string(), ''),
|
||||
("noka".to_string(), ''),
|
||||
("o".to_string(), ''),
|
||||
("olin".to_string(), ''),
|
||||
("ona".to_string(), ''),
|
||||
("open".to_string(), ''),
|
||||
("pakala".to_string(), ''),
|
||||
("pan".to_string(), ''),
|
||||
("pana".to_string(), ''),
|
||||
("pilin".to_string(), ''),
|
||||
("pimeja".to_string(), ''),
|
||||
("pini".to_string(), ''),
|
||||
("pipi".to_string(), ''),
|
||||
("poka".to_string(), ''),
|
||||
("poki".to_string(), ''),
|
||||
("pu".to_string(), ''),
|
||||
("sama".to_string(), ''),
|
||||
("seli".to_string(), ''),
|
||||
("selo".to_string(), ''),
|
||||
("seme".to_string(), ''),
|
||||
("sewi".to_string(), ''),
|
||||
("sike".to_string(), ''),
|
||||
("sin".to_string(), ''),
|
||||
("sina".to_string(), ''),
|
||||
("sinpin".to_string(), ''),
|
||||
("sitelen".to_string(), ''),
|
||||
("sona".to_string(), ''),
|
||||
("soweli".to_string(), ''),
|
||||
("suli".to_string(), ''),
|
||||
("suno".to_string(), ''),
|
||||
("supa".to_string(), ''),
|
||||
("suwi".to_string(), ''),
|
||||
("tan".to_string(), ''),
|
||||
("taso".to_string(), ''),
|
||||
("telo".to_string(), ''),
|
||||
("tenpo".to_string(), ''),
|
||||
("toki".to_string(), ''),
|
||||
("tomo".to_string(), ''),
|
||||
("tu".to_string(), ''),
|
||||
("unpa".to_string(), ''),
|
||||
("uta".to_string(), ''),
|
||||
("utala".to_string(), ''),
|
||||
("walo".to_string(), ''),
|
||||
("wan".to_string(), ''),
|
||||
("waso".to_string(), ''),
|
||||
("wawa".to_string(), ''),
|
||||
("wile".to_string(), ''),
|
||||
("namako".to_string(), ''),
|
||||
("kin".to_string(), ''),
|
||||
("oko".to_string(), ''),
|
||||
("kipisi".to_string(), ''),
|
||||
("leko".to_string(), ''),
|
||||
("monsuta".to_string(), ''),
|
||||
("tonsi".to_string(), ''),
|
||||
("kijetesantakalu".to_string(), ''),
|
||||
("soko".to_string(), ''),
|
||||
("meso".to_string(), ''),
|
||||
("n".to_string(), ''),
|
||||
("misikeke".to_string(), ''),
|
||||
//
|
||||
]);
|
||||
Self {
|
||||
mapping,
|
||||
buffer: String::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,4 +5,5 @@ pub mod window_manager;
|
||||
pub mod fs;
|
||||
mod proxy_window_like;
|
||||
mod essential;
|
||||
mod input_method;
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ use crate::essential::start_menu::StartMenu;
|
||||
use crate::essential::about::About;
|
||||
use crate::essential::help::Help;
|
||||
use crate::essential::onscreen_keyboard::OnscreenKeyboard;
|
||||
use crate::input_method::lat::Lat;
|
||||
use crate::input_method::tok::Tok;
|
||||
|
||||
//todo: a lot of the usize should be changed to u16
|
||||
|
||||
@@ -52,7 +54,6 @@ impl fmt::Debug for WindowLikeInfo {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct WindowManager {
|
||||
writer: RefCell<FramebufferWriter>,
|
||||
rotate: bool,
|
||||
@@ -65,6 +66,8 @@ pub struct WindowManager {
|
||||
focused_id: usize,
|
||||
pub locked: bool,
|
||||
current_workspace: u8,
|
||||
im_list: Vec<Box<dyn InputMethod>>,
|
||||
current_im: usize,
|
||||
framebuffer: Framebuffer,
|
||||
clipboard: Option<String>,
|
||||
version: String,
|
||||
@@ -88,6 +91,8 @@ impl WindowManager {
|
||||
focused_id: 0,
|
||||
locked: false,
|
||||
current_workspace: 0,
|
||||
im_list: vec![Box::new(Lat {}), Box::new(Tok::new())],
|
||||
current_im: 0,
|
||||
framebuffer,
|
||||
clipboard: None,
|
||||
version,
|
||||
@@ -151,7 +156,9 @@ impl WindowManager {
|
||||
self.window_infos = Vec::new();
|
||||
self.add_window_like(Box::new(DesktopBackground::new()), [0, INDICATOR_HEIGHT], None);
|
||||
self.add_window_like(Box::new(Taskbar::new()), [0, self.dimensions[1] - TASKBAR_HEIGHT], None);
|
||||
self.add_window_like(Box::new(WorkspaceIndicator::new()), [0, 0], None);
|
||||
let current_im = &self.im_list[self.current_im];
|
||||
self.add_window_like(Box::new(WorkspaceIndicator::new(current_im.abbr().iter().collect()
|
||||
)), [0, 0], None);
|
||||
}
|
||||
|
||||
fn change_theme(&mut self) {
|
||||
@@ -194,6 +201,24 @@ impl WindowManager {
|
||||
self.window_infos[taskbar_index].window_like.handle_message(message);
|
||||
}
|
||||
|
||||
fn im_update(&mut self, old_buffer: Option<String>) -> bool {
|
||||
let current_im = &self.im_list[self.current_im];
|
||||
let indicator_index = self.window_infos.iter().position(|w| w.window_like.subtype() == WindowLikeType::WorkspaceIndicator);
|
||||
//no window indicator on lockscreen
|
||||
if let Some(indicator_index) = indicator_index {
|
||||
let current_buffer = current_im.internal_buffer();
|
||||
//if old_buffer is None, force sending message
|
||||
if old_buffer.is_none() || current_buffer != old_buffer.unwrap_or_default() {
|
||||
self.window_infos[indicator_index].window_like.handle_message(WindowMessage::Info(InfoType::InputMethod(current_im.abbr().iter().collect(), current_buffer)));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn move_index_to_top(&mut self, index: usize) {
|
||||
let removed = self.window_infos.remove(index);
|
||||
self.window_infos.push(removed);
|
||||
@@ -238,6 +263,8 @@ impl WindowManager {
|
||||
//shrink window size
|
||||
('N', ShortcutType::ChangeWindowSize(Direction::Left)),
|
||||
('M', ShortcutType::ChangeWindowSize(Direction::Up)),
|
||||
//
|
||||
(' ', ShortcutType::NextInputMethod),
|
||||
//no 10th workspace
|
||||
('1', ShortcutType::SwitchWorkspace(0)),
|
||||
('2', ShortcutType::SwitchWorkspace(1)),
|
||||
@@ -383,6 +410,16 @@ impl WindowManager {
|
||||
}
|
||||
}
|
||||
},
|
||||
&ShortcutType::NextInputMethod => {
|
||||
let im_count = self.im_list.len();
|
||||
if self.current_im + 1 == im_count {
|
||||
self.current_im = 0;
|
||||
} else {
|
||||
self.current_im += 1;
|
||||
}
|
||||
self.im_update(None);
|
||||
press_response = WindowMessageResponse::JustRedraw;
|
||||
},
|
||||
&ShortcutType::SwitchWorkspace(workspace) => {
|
||||
if self.current_workspace != workspace {
|
||||
//close start menu if open
|
||||
@@ -527,17 +564,32 @@ impl WindowManager {
|
||||
let mut press_response = WindowMessageResponse::DoNothing;
|
||||
//send to focused window
|
||||
if let Some(focused_index) = self.get_focused_index() {
|
||||
press_response = self.window_infos[focused_index].window_like.handle_message(if key_char == KeyChar::Press(c) {
|
||||
WindowMessage::KeyPress(KeyPress {
|
||||
if key_char == KeyChar::Ctrl(c) {
|
||||
press_response = self.window_infos[focused_index].window_like.handle_message(WindowMessage::CtrlKeyPress(KeyPress {
|
||||
key: c,
|
||||
})
|
||||
}));
|
||||
redraw_ids = Some(vec![self.window_infos[focused_index].id]);
|
||||
} else {
|
||||
WindowMessage::CtrlKeyPress(KeyPress {
|
||||
key: c,
|
||||
})
|
||||
});
|
||||
//at most, only the focused window needs to be redrawed
|
||||
redraw_ids = Some(vec![self.window_infos[focused_index].id]);
|
||||
let old_buffer = self.im_list[self.current_im].internal_buffer().clone();
|
||||
//need to send the key to the input method
|
||||
if let Some(ret_c) = self.im_list[self.current_im].add_key_press(KeyPress { key: c }) {
|
||||
press_response = self.window_infos[focused_index].window_like.handle_message(WindowMessage::KeyPress(KeyPress {
|
||||
key: ret_c,
|
||||
}));
|
||||
}
|
||||
redraw_ids = Some(vec![self.window_infos[focused_index].id]);
|
||||
let wi_updated = self.im_update(Some(old_buffer));
|
||||
if wi_updated {
|
||||
//ideally, make redraw_ids the focused window and the workspace indicator,
|
||||
//but that doesn't work for some reason
|
||||
if press_response == WindowMessageResponse::DoNothing {
|
||||
press_response = WindowMessageResponse::JustRedraw;
|
||||
redraw_ids = None;
|
||||
}
|
||||
} else {
|
||||
redraw_ids = Some(vec![self.window_infos[focused_index].id]);
|
||||
}
|
||||
}
|
||||
//requests can result in window openings and closings, etc
|
||||
if press_response != WindowMessageResponse::JustRedraw {
|
||||
redraw_ids = None;
|
||||
|
||||
Reference in New Issue
Block a user