diff --git a/README.md b/README.md index 73d55d4..5c4b845 100644 --- a/README.md +++ b/README.md @@ -33,32 +33,48 @@ chmod +x local-install sudo ./local-install ``` +## Running + +``` +ming +``` + +Type in the password to unlock. Open the start menu by doing `Alt+s`, and use the `j` and `k` keys to move up and down (like Vim), and press the `Enter` key to select a category / open a window. + ## Running on Mobile Linux Running with an onscreen keyboard. The framebuffer may not be redrawn to the screen without a (real) key press. The volume down button seems to work. -`evtest` needs to be installed. +`evtest` needs to be installed. Currently, the input device is assumed to be at `/dev/first-touchscreen`. ``` -cargo build --release -./target/release/ming touch +ming touch ``` Optionally, in landscape mode: ``` -cargo build --release -./target/release/ming touch rotate +ming touch rotate ``` -After testing, the install scripts in the previous section can be used. - mobile example ## Philosophy See [/docs/philosophy.md](/docs/philosophy.md) for some hopefully interesting ramblings. +## Documentation + +### Developing Windows + +[section incomplete] + +Windows (may be called apps in other window managers) can be developed in any language, though it is easiest to do so in Rust because the `ming-wm-lib` crate can be used. + +### Window Usage + +Usage for most of the included windows and window-likes are included in `docs/window-likes`, which can also be accessed from the "Help" entry in the start menu. + ## Security Make sure the permissions of `password.env` are so other users cannot read or write to it. If there is no plan to recompile, just delete it. diff --git a/install b/install index 9750f60..36339d0 100755 --- a/install +++ b/install @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh cp -r ./target/release/bmps /usr/local/bin/bmps cp ./target/release/ming /usr/local/bin/ming cp ./target/release/mingUtils_Terminal /usr/local/bin/mingUtils_Terminal diff --git a/local-install b/local-install index 3ef92eb..f44b77e 100755 --- a/local-install +++ b/local-install @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh cp -r ./target/release/bmps ~/.local/bin/bmps cp ./target/release/ming ~/.local/bin/ming cp ./target/release/mingUtils_Terminal ~/.local/bin/mingUtils_Terminal diff --git a/ming-wm-lib/Cargo.toml b/ming-wm-lib/Cargo.toml index 2e6d3ae..e74b738 100644 --- a/ming-wm-lib/Cargo.toml +++ b/ming-wm-lib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ming-wm-lib" -version = "0.1.2" +version = "0.1.3" repository = "https://github.com/stjet/ming-wm" description = "library for building windows for ming-wm in rust" license = "GPL-3.0-or-later" diff --git a/ming-wm-lib/src/ipc.rs b/ming-wm-lib/src/ipc.rs index e2376ed..2a09348 100644 --- a/ming-wm-lib/src/ipc.rs +++ b/ming-wm-lib/src/ipc.rs @@ -60,7 +60,7 @@ pub fn listen(mut window_like: impl WindowLike) { format!("{}", &window_like.handle_message(WindowMessage::deserialize(arg).unwrap()).serialize()) }, "draw" => { - format!("{}", &window_like.draw(&ThemeInfo::deserialize(arg).unwrap()).serialize()) + format!("{}", &window_like.draw(&ThemeInfo::deserialize(arg).unwrap()).serialize().replace("\n", "")) }, "title" => { format!("{}", window_like.title()) diff --git a/ming-wm-lib/src/messages.rs b/ming-wm-lib/src/messages.rs index 90a9e5b..d2664a5 100644 --- a/ming-wm-lib/src/messages.rs +++ b/ming-wm-lib/src/messages.rs @@ -85,6 +85,7 @@ pub enum ShortcutType { pub type WindowsVec = Vec<(usize, String)>; +#[non_exhaustive] pub enum InfoType { //let taskbar know what the current windows in the workspace are WindowsInWorkspace(WindowsVec, usize), //Vec<(id, name)>, focused id diff --git a/src/bin/malvim.rs b/src/bin/malvim.rs index 542f93d..a108a21 100644 --- a/src/bin/malvim.rs +++ b/src/bin/malvim.rs @@ -104,17 +104,19 @@ impl WindowLike for Malvim { } else if (key_press.key == 'i' || key_press.key == 'A') && self.mode == Mode::Normal && self.state == State::None && self.files.len() > 0 { if key_press.key == 'A' { let current_file = &mut self.files[self.current_file_index]; - current_file.cursor_pos = current_file.content[current_file.line_pos].len(); + current_file.cursor_pos = current_file.content[current_file.line_pos].chars().count(); } self.mode = Mode::Insert; changed = false; } else if self.mode == Mode::Insert { let current_file = &mut self.files[self.current_file_index]; - let current_length = current_file.content[current_file.line_pos].len(); + let current_length = current_file.content[current_file.line_pos].chars().count(); let line = ¤t_file.content[current_file.line_pos]; if key_press.key == '𐘂' { //the enter key - let mut line = line.clone(); + let mut line: Vec = line.chars().collect(); let (left, right) = line.split_at_mut(current_file.cursor_pos); + let left = left.into_iter().map(|c| c.to_string()).collect::>().join(""); + let right = right.into_iter().map(|c| c.to_string()).collect::>().join(""); current_file.content[current_file.line_pos] = left.to_string(); let spaces = if self.autoindent { //find out how many spaces the line starts with, copy that to the new line @@ -130,7 +132,7 @@ impl WindowLike for Malvim { } else { 0 }; - current_file.content.insert(current_file.line_pos + 1, " ".repeat(spaces) + right); + current_file.content.insert(current_file.line_pos + 1, " ".repeat(spaces) + &right); current_file.line_pos += 1; current_file.cursor_pos = spaces; } else if key_press.key == '𐘁' { //backspace @@ -140,7 +142,7 @@ impl WindowLike for Malvim { } else { if current_file.line_pos > 0 { //merge the prev line and this line - let old_previous_line_length = current_file.content[current_file.line_pos - 1].len(); + let old_previous_line_length = current_file.content[current_file.line_pos - 1].chars().count(); let removed = current_file.content.remove(current_file.line_pos); current_file.content[current_file.line_pos - 1] += &removed; current_file.line_pos -= 1; @@ -148,18 +150,18 @@ impl WindowLike for Malvim { } } } else { - current_file.content[current_file.line_pos] = line.substring(0, current_file.cursor_pos).to_string() + &key_press.key.to_string() + line.substring(current_file.cursor_pos, line.len()); + current_file.content[current_file.line_pos] = line.substring(0, current_file.cursor_pos).to_string() + &key_press.key.to_string() + line.substring(current_file.cursor_pos, line.chars().count()); current_file.cursor_pos += 1; } } else if self.mode == Mode::Normal && self.files.len() > 0 { let current_file = &mut self.files[self.current_file_index]; - let current_length = current_file.content[current_file.line_pos].len(); + let current_length = current_file.content[current_file.line_pos].chars().count(); let mut numbered = false; // if self.state == State::Replace { if current_length > 0 && current_file.cursor_pos < current_length { let line = ¤t_file.content[current_file.line_pos]; - current_file.content[current_file.line_pos] = line.substring(0, current_file.cursor_pos).to_string() + &key_press.key.to_string() + line.substring(current_file.cursor_pos + 1, line.len()); + current_file.content[current_file.line_pos] = line.substring(0, current_file.cursor_pos).to_string() + &key_press.key.to_string() + line.substring(current_file.cursor_pos + 1, line.chars().count()); } self.state = State::None; } else if self.state == State::MaybeDelete { @@ -170,7 +172,7 @@ impl WindowLike for Malvim { } else if current_file.line_pos == current_file.content.len() { current_file.line_pos = current_file.content.len() - 1; } - let new_length = current_file.content[current_file.line_pos].len(); + let new_length = current_file.content[current_file.line_pos].chars().count(); current_file.cursor_pos = calc_new_cursor_pos(current_file.cursor_pos, new_length); } else if key_press.key == 'w' { //todo: currently doesn't work on a single space? @@ -179,7 +181,7 @@ impl WindowLike for Malvim { //offset until space or eol let offset = line.chars().skip(current_file.cursor_pos).position(|c| c == ' ').unwrap_or(line.chars().count() - current_file.cursor_pos); current_file.content[current_file.line_pos] = line.remove(current_file.cursor_pos, offset); - let new_length = current_file.content[current_file.line_pos].len(); + let new_length = current_file.content[current_file.line_pos].chars().count(); current_file.cursor_pos = calc_new_cursor_pos(current_file.cursor_pos, new_length); } } @@ -190,7 +192,7 @@ impl WindowLike for Malvim { if current_file.line_pos >= current_file.content.len() { current_file.line_pos = current_file.content.len() - 1; } - let new_length = current_file.content[current_file.line_pos].len(); + let new_length = current_file.content[current_file.line_pos].chars().count(); current_file.cursor_pos = calc_new_cursor_pos(current_file.cursor_pos, new_length); } changed = false; @@ -198,15 +200,25 @@ impl WindowLike for Malvim { } else if self.state == State::Find || self.state == State::BackFind { let old_pos = current_file.cursor_pos; let find_pos = if self.state == State::Find { - if old_pos < current_file.content[current_file.line_pos].len() { - old_pos + current_file.content[current_file.line_pos].chars().skip(old_pos + 1).position(|c| c == key_press.key).unwrap_or(0) + 1 + if old_pos < current_file.content[current_file.line_pos].chars().count() { + let found_index = current_file.content[current_file.line_pos].chars().skip(old_pos + 1).position(|c| c == key_press.key); + if let Some(found_index) = found_index { + old_pos + found_index + 1 + } else { + old_pos + } } else { old_pos } } else { //how does this work again? no idea if old_pos != 0 { - old_pos - current_file.content[current_file.line_pos].chars().rev().skip(current_length - old_pos + 1).position(|c| c == key_press.key).unwrap_or(0) - 2 + let found_index = current_file.content[current_file.line_pos].chars().rev().skip(current_length - old_pos + 1).position(|c| c == key_press.key); + if let Some(found_index) = found_index { + old_pos - found_index - 2 + } else { + old_pos + } } else { old_pos //0 } @@ -234,14 +246,15 @@ impl WindowLike for Malvim { } else { current_file.line_pos = current_file.line_pos.checked_sub(1).unwrap_or(0); } - let new_length = current_file.content[current_file.line_pos].len(); + let new_length = current_file.content[current_file.line_pos].chars().count(); current_file.cursor_pos = calc_new_cursor_pos(current_file.cursor_pos, new_length); changed = false; } else if key_press.key == 'l' { if current_length > 0 { current_file.cursor_pos += 1; - if current_file.cursor_pos > current_file.content[current_file.line_pos].len() { - current_file.cursor_pos = current_file.content[current_file.line_pos].len(); + let line_len = current_file.content[current_file.line_pos].chars().count(); + if current_file.cursor_pos > line_len { + current_file.cursor_pos = line_len; } } changed = false; @@ -250,7 +263,7 @@ impl WindowLike for Malvim { changed = false; } else if key_press.key == '$' { //yeah, no `- 1`, that's right - current_file.cursor_pos = current_file.content[current_file.line_pos].len(); + current_file.cursor_pos = current_file.content[current_file.line_pos].chars().count(); changed = false; } else if key_press.key == '^' { current_file.cursor_pos = current_file.content[current_file.line_pos].chars().position(|c| c != ' ').unwrap_or(0); @@ -266,7 +279,7 @@ impl WindowLike for Malvim { changed = false; } else if key_press.key == 'G' { current_file.line_pos = current_file.content.len() - 1; - let new_length = current_file.content[current_file.line_pos].len(); + let new_length = current_file.content[current_file.line_pos].chars().count(); current_file.cursor_pos = calc_new_cursor_pos(current_file.cursor_pos, new_length); changed = false; } else if key_press.key == 'f' { @@ -279,6 +292,8 @@ impl WindowLike for Malvim { self.maybe_num = Some(self.maybe_num.unwrap_or(0) * 10 + key_press.key.to_digit(10).unwrap() as usize); numbered = true; changed = false; + } else { + changed = false; } if !numbered && self.state != State::Maybeg { self.maybe_num = None; @@ -313,6 +328,7 @@ impl WindowLike for Malvim { }, WindowMessage::ChangeDimensions(dimensions) => { self.dimensions = dimensions; + self.calc_current(); WindowMessageResponse::JustRedraw }, WindowMessage::Shortcut(shortcut) => { @@ -329,7 +345,7 @@ impl WindowLike for Malvim { if self.mode == Mode::Insert { let current_file = &mut self.files[self.current_file_index]; let line = ¤t_file.content[current_file.line_pos]; - current_file.content[current_file.line_pos] = line.substring(0, current_file.cursor_pos).to_string() + ©_string + line.substring(current_file.cursor_pos, line.len()); + current_file.content[current_file.line_pos] = line.substring(0, current_file.cursor_pos).to_string() + ©_string + line.substring(current_file.cursor_pos, line.chars().count()); current_file.cursor_pos += copy_string.len(); self.calc_top_line_pos(); self.calc_current(); //too over zealous but whatever diff --git a/src/bin/terminal.rs b/src/bin/terminal.rs index b9b16bb..1ae0f83 100644 --- a/src/bin/terminal.rs +++ b/src/bin/terminal.rs @@ -98,6 +98,7 @@ impl WindowLike for Terminal { }, WindowMessage::ChangeDimensions(dimensions) => { self.dimensions = dimensions; + self.calc_actual_lines(); WindowMessageResponse::JustRedraw }, WindowMessage::KeyPress(key_press) => { @@ -135,6 +136,7 @@ impl WindowLike for Terminal { let running_process = self.running_process.as_mut().unwrap(); if let Some(_status) = running_process.try_wait().unwrap() { //process exited + self.pty_outerr_rx = None; self.mode = Mode::Input; changed = true; } else { @@ -285,7 +287,13 @@ impl Terminal { thread::spawn(move || { let reader = BufReader::new(pty); for line in reader.lines() { - tx1.send(line.unwrap().to_string()).unwrap(); + //panics too much + if let Ok(line) = line { + tx1.send(line.to_string()).unwrap(); + } else { + //the process has exited. dead process = dead pty = os input/output error + break; + } } }); let mut stdin = self.running_process.as_mut().unwrap().stdin.take().unwrap(); diff --git a/src/essential/onscreen_keyboard.rs b/src/essential/onscreen_keyboard.rs index a8b6742..3284677 100644 --- a/src/essential/onscreen_keyboard.rs +++ b/src/essential/onscreen_keyboard.rs @@ -121,7 +121,7 @@ impl WindowLike for OnscreenKeyboard { } fn ideal_dimensions(&self, dimensions: Dimensions) -> Dimensions { - [dimensions[0] - 175, 250] + [dimensions[0] - 180, 250] } } diff --git a/src/essential/start_menu.rs b/src/essential/start_menu.rs index 8554da5..2dc0923 100644 --- a/src/essential/start_menu.rs +++ b/src/essential/start_menu.rs @@ -125,7 +125,7 @@ impl WindowLike for StartMenu { } fn ideal_dimensions(&self, _dimensions: Dimensions) -> Dimensions { - [175, 250] + [180, 250] } } diff --git a/src/framebuffer.rs b/src/framebuffer.rs index 58830ad..48e2c29 100644 --- a/src/framebuffer.rs +++ b/src/framebuffer.rs @@ -134,7 +134,7 @@ impl FramebufferWriter { start_pos = ((top_left[1] + row + char_info.2 as usize) * self.info.stride + top_left[0]) * self.info.bytes_per_pixel; for col in &char_info.1[row] { if col > &0 { - if start_pos < self.info.byte_len { + if start_pos + 3 < self.info.byte_len { self._draw_pixel(start_pos, color_with_alpha(color, bg_color, *col)); } } diff --git a/src/window_manager.rs b/src/window_manager.rs index e498acb..3af9717 100644 --- a/src/window_manager.rs +++ b/src/window_manager.rs @@ -323,7 +323,7 @@ impl WindowManager { let focused_info = &self.window_infos[focused_index]; if focused_info.window_like.subtype() == WindowLikeType::Window && focused_info.window_like.resizable() && !focused_info.fullscreen { //mostly arbitrary - let min_window_size = [100, WINDOW_TOP_HEIGHT + 5]; + let min_window_size = [100, WINDOW_TOP_HEIGHT + 100]; let mut changed = false; let delta = 15; let window = &mut self.window_infos[focused_index]; @@ -734,6 +734,7 @@ impl WindowManager { window_writer.draw_circle(centre, radius, color); }, DrawInstructions::Text(top_left, fonts, text, color, bg_color, horiz_spacing, mono_width) => { + //if overflow, won't draw, I think window_writer.draw_text(top_left, fonts, &text, color, bg_color, horiz_spacing.unwrap_or(1), mono_width); }, DrawInstructions::Bmp(top_left, path, reverse) => {