separate windows out, IPCcargo run --release!

This commit is contained in:
stjet
2024-10-22 05:28:23 +00:00
parent decf1d3b82
commit cfece80c66
22 changed files with 305 additions and 135 deletions

View File

@@ -1,7 +1,8 @@
[package]
name = "ming-os-kernel"
name = "ming-wm"
version = "0.1.0"
edition = "2018"
default-run = "main"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -12,3 +13,5 @@ bmp-rust = "0.4.1"
termion = "4.0.3"
rodio = "0.19.0"
rand = "0.8.5"
ron = "0.8"
serde = { version = "1", features = ["derive"] }

View File

@@ -7,12 +7,13 @@ use std::fs::File;
use rodio::{ Decoder, OutputStream, Sink, Source };
use rand::prelude::*;
use crate::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
use crate::messages::{ WindowMessage, WindowMessageResponse };
use crate::framebuffer::Dimensions;
use crate::themes::ThemeInfo;
use crate::utils::{ concat_paths, format_seconds };
use crate::fs::get_all_files;
use ming_wm::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
use ming_wm::messages::{ WindowMessage, WindowMessageResponse };
use ming_wm::framebuffer::Dimensions;
use ming_wm::themes::ThemeInfo;
use ming_wm::utils::{ concat_paths, format_seconds };
use ming_wm::fs::get_all_files;
use ming_wm::ipc::listen;
const MONO_WIDTH: u8 = 10;
const LINE_HEIGHT: usize = 18;
@@ -59,13 +60,13 @@ impl WindowLike for AudioPlayer {
}
fn draw(&self, theme_info: &ThemeInfo) -> Vec<DrawInstructions> {
let mut instructions = vec![DrawInstructions::Text([2, self.dimensions[1] - LINE_HEIGHT], "times-new-roman", if self.command.len() > 0 { self.command.clone() } else { self.response.clone() }, theme_info.text, theme_info.background, None, None)];
let mut instructions = vec![DrawInstructions::Text([2, self.dimensions[1] - LINE_HEIGHT], "times-new-roman".to_string(), if self.command.len() > 0 { self.command.clone() } else { self.response.clone() }, theme_info.text, theme_info.background, None, None)];
if let Some(sink) = &self.sink {
let current = &self.queue[self.queue.len() - sink.len()];
let current_name = current.0.file_name().unwrap().to_string_lossy().into_owned();
instructions.push(DrawInstructions::Text([self.dimensions[0] / 2 - current_name.len() * MONO_WIDTH as usize / 2, 2], "times-new-romono", current_name.clone(), theme_info.text, theme_info.background, Some(0), Some(MONO_WIDTH)));
instructions.push(DrawInstructions::Text([self.dimensions[0] / 2 - current_name.len() * MONO_WIDTH as usize / 2, 2], "times-new-romono".to_string(), current_name.clone(), theme_info.text, theme_info.background, Some(0), Some(MONO_WIDTH)));
let time_string = format!("{}/{}", format_seconds(sink.get_pos().as_secs()), format_seconds(current.1));
instructions.push(DrawInstructions::Text([self.dimensions[0] / 2 - time_string.len() * MONO_WIDTH as usize / 2, LINE_HEIGHT + 2], "times-new-romono", time_string, theme_info.text, theme_info.background, Some(0), Some(MONO_WIDTH)));
instructions.push(DrawInstructions::Text([self.dimensions[0] / 2 - time_string.len() * MONO_WIDTH as usize / 2, LINE_HEIGHT + 2], "times-new-romono".to_string(), time_string, theme_info.text, theme_info.background, Some(0), Some(MONO_WIDTH)));
}
//
instructions
@@ -73,8 +74,8 @@ impl WindowLike for AudioPlayer {
//properties
fn title(&self) -> &'static str {
"Audio Player"
fn title(&self) -> String {
"Audio Player".to_string()
}
fn subtype(&self) -> WindowLikeType {
@@ -98,13 +99,13 @@ impl AudioPlayer {
}
//t: toggle pause/play
//h: prev
//l: next/skip
//j: volume down
//k: volume up
//b <dir>: set base directory
//p <dir>/<playlist file>: play directory or playlist in random order
//just hit enter to refresh
//todo: h for help?
//just hit enter or any key to refresh
fn process_command(&mut self) -> String {
if self.command.len() == 1 {
if let Some(sink) = &mut self.sink {
@@ -175,3 +176,7 @@ impl AudioPlayer {
}
}
pub fn main() {
listen(AudioPlayer::new());
}

View File

@@ -1,24 +1,7 @@
use linux_framebuffer::Framebuffer;
mod framebuffer;
use framebuffer::FramebufferInfo;
mod window_manager;
use window_manager::init;
mod window_likes;
mod components;
mod themes;
mod keyboard;
mod messages;
mod fs;
mod utils;
use ming_wm::framebuffer::FramebufferInfo;
use ming_wm::window_manager::init;
fn main() {
let mut fb = Framebuffer::new("/dev/fb0").unwrap();

View File

@@ -4,11 +4,12 @@ use std::fmt;
use std::path::PathBuf;
use std::fs::{ read_to_string, write };
use crate::messages::{ WindowMessage, WindowMessageResponse };
use crate::themes::ThemeInfo;
use crate::framebuffer::Dimensions;
use crate::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
use crate::utils::{ calc_actual_lines, calc_new_cursor_pos, Substring };
use ming_wm::messages::{ WindowMessage, WindowMessageResponse };
use ming_wm::themes::ThemeInfo;
use ming_wm::framebuffer::Dimensions;
use ming_wm::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
use ming_wm::utils::{ calc_actual_lines, calc_new_cursor_pos, Substring };
use ming_wm::ipc::listen;
const MONO_WIDTH: u8 = 10;
const LINE_HEIGHT: usize = 18;
@@ -302,7 +303,7 @@ impl WindowLike for Malvim {
};
instructions.extend(vec![
DrawInstructions::Rect([used_width, 2], [future_used_width, BAND_HEIGHT - 2], background),
DrawInstructions::Text([used_width + 2, 2], "times-new-romono", if file_info.changed { "+ ".to_string() } else { String::new() } + &file_info.name, theme_info.alt_text, background, Some(0), Some(MONO_WIDTH)),
DrawInstructions::Text([used_width + 2, 2], "times-new-romono".to_string(), if file_info.changed { "+ ".to_string() } else { String::new() } + &file_info.name, theme_info.alt_text, background, Some(0), Some(MONO_WIDTH)),
]);
used_width = future_used_width;
}
@@ -320,13 +321,13 @@ impl WindowLike for Malvim {
//write line num text (if start of line)
let y0 = BAND_HEIGHT + rel_line_num * LINE_HEIGHT + PADDING;
if line.0 {
instructions.push(DrawInstructions::Text([PADDING, y0], "times-new-romono", line.1.to_string(), theme_info.alt_secondary, theme_info.alt_background, Some(0), Some(MONO_WIDTH)));
instructions.push(DrawInstructions::Text([PADDING, y0], "times-new-romono".to_string(), line.1.to_string(), theme_info.alt_secondary, theme_info.alt_background, Some(0), Some(MONO_WIDTH)));
sub_line_num = 0;
}
let x1 = current.line_num_width + PADDING * 2;
//write actual line
//line.2
instructions.push(DrawInstructions::Text([x1, y0], "times-new-romono", line.2.clone(), theme_info.alt_text, theme_info.alt_background, Some(0), Some(MONO_WIDTH)));
instructions.push(DrawInstructions::Text([x1, y0], "times-new-romono".to_string(), line.2.clone(), theme_info.alt_text, theme_info.alt_background, Some(0), Some(MONO_WIDTH)));
sub_line_num += 1;
let max = sub_line_num * current.max_chars_per_line;
let min = max - current.max_chars_per_line;
@@ -336,32 +337,32 @@ impl WindowLike for Malvim {
instructions.push(DrawInstructions::Rect(top_left, [MONO_WIDTH as usize, LINE_HEIGHT], theme_info.top));
//draw the char over it
if line.2.len() > 0 {
instructions.push(DrawInstructions::Text(top_left, "times-new-romono", line.2.chars().nth(current_file.cursor_pos - min).unwrap().to_string(), theme_info.top_text, theme_info.top, Some(0), Some(MONO_WIDTH)));
instructions.push(DrawInstructions::Text(top_left, "times-new-romono".to_string(), line.2.chars().nth(current_file.cursor_pos - min).unwrap().to_string(), theme_info.top_text, theme_info.top, Some(0), Some(MONO_WIDTH)));
}
}
}
}
//bottom blue band stuff
//write mode
instructions.push(DrawInstructions::Text([0, self.dimensions[1] - BAND_HEIGHT * 2 + 1], "times-new-romono", self.mode.to_string(), theme_info.top_text, theme_info.top, Some(0), Some(MONO_WIDTH)));
instructions.push(DrawInstructions::Text([0, self.dimensions[1] - BAND_HEIGHT * 2 + 1], "times-new-romono".to_string(), self.mode.to_string(), theme_info.top_text, theme_info.top, Some(0), Some(MONO_WIDTH)));
let file_status;
if self.files.len() > 0 {
file_status = self.files[self.current_file_index].name.clone();
} else {
file_status = "No file open".to_string();
}
instructions.push(DrawInstructions::Text([self.dimensions[0] - file_status.len() * (MONO_WIDTH as usize), self.dimensions[1] - BAND_HEIGHT * 2 + 1], "times-new-romono", file_status, theme_info.top_text, theme_info.top, Some(0), Some(MONO_WIDTH)));
instructions.push(DrawInstructions::Text([self.dimensions[0] - file_status.len() * (MONO_WIDTH as usize), self.dimensions[1] - BAND_HEIGHT * 2 + 1], "times-new-romono".to_string(), file_status, theme_info.top_text, theme_info.top, Some(0), Some(MONO_WIDTH)));
//write command or bottom message
if self.mode == Mode::Command {
instructions.push(DrawInstructions::Text([0, self.dimensions[1] - BAND_HEIGHT], "times-new-romono", ":".to_string() + &self.command.clone().unwrap_or("".to_string()), theme_info.top_text, theme_info.top, Some(0), Some(MONO_WIDTH)));
instructions.push(DrawInstructions::Text([0, self.dimensions[1] - BAND_HEIGHT], "times-new-romono".to_string(), ":".to_string() + &self.command.clone().unwrap_or("".to_string()), theme_info.top_text, theme_info.top, Some(0), Some(MONO_WIDTH)));
} else if self.mode == Mode::Normal && self.bottom_message.is_some() {
instructions.push(DrawInstructions::Text([0, self.dimensions[1] - BAND_HEIGHT], "times-new-romono", self.bottom_message.clone().unwrap(), theme_info.top_text, theme_info.top, Some(0), Some(MONO_WIDTH)));
instructions.push(DrawInstructions::Text([0, self.dimensions[1] - BAND_HEIGHT], "times-new-romono".to_string(), self.bottom_message.clone().unwrap(), theme_info.top_text, theme_info.top, Some(0), Some(MONO_WIDTH)));
}
instructions
}
fn title(&self) -> &'static str {
"Malvim"
fn title(&self) -> String {
"Malvim".to_string()
}
fn subtype(&self) -> WindowLikeType {
@@ -497,3 +498,7 @@ impl Malvim {
}
}
pub fn main() {
listen(Malvim::new());
}

View File

@@ -3,10 +3,11 @@ use std::vec;
use std::collections::VecDeque;
use core::convert::TryFrom;
use crate::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
use crate::messages::{ WindowMessage, WindowMessageResponse };
use crate::framebuffer::Dimensions;
use crate::themes::ThemeInfo;
use ming_wm::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
use ming_wm::messages::{ WindowMessage, WindowMessageResponse };
use ming_wm::framebuffer::Dimensions;
use ming_wm::themes::ThemeInfo;
use ming_wm::ipc::listen;
const HEX_CHARS: [char; 16] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
@@ -156,8 +157,8 @@ impl WindowLike for Minesweeper {
fn draw(&self, theme_info: &ThemeInfo) -> Vec<DrawInstructions> {
if self.state == State::Seed {
vec![
DrawInstructions::Text([4, 4], "times-new-roman", "Type in random characters to initalise the seed".to_string(), theme_info.text, theme_info.background, None, None),
DrawInstructions::Text([4, 4 + 16], "times-new-roman", self.random_chars.clone(), theme_info.text, theme_info.background, None, None),
DrawInstructions::Text([4, 4], "times-new-roman".to_string(), "Type in random characters to initalise the seed".to_string(), theme_info.text, theme_info.background, None, None),
DrawInstructions::Text([4, 4 + 16], "times-new-roman".to_string(), self.random_chars.clone(), theme_info.text, theme_info.background, None, None),
]
} else {
let mut instructions = vec![
@@ -194,7 +195,7 @@ impl WindowLike for Minesweeper {
let tile = &self.tiles[y][x];
if tile.revealed {
if tile.mine {
instructions.push(DrawInstructions::Text([x * tile_size + tile_size / 2 + 2, y * tile_size + tile_size / 2], "times-new-roman", "x".to_string(), [255, 0, 0], theme_info.background, None, None));
instructions.push(DrawInstructions::Text([x * tile_size + tile_size / 2 + 2, y * tile_size + tile_size / 2], "times-new-roman".to_string(), "x".to_string(), [255, 0, 0], theme_info.background, None, None));
} else {
let color = match tile.touching {
1 => [0, 0, 255],
@@ -207,7 +208,7 @@ impl WindowLike for Minesweeper {
//8
_ => [128, 128, 128],
};
instructions.push(DrawInstructions::Text([x * tile_size + tile_size / 2 + 5, y * tile_size + tile_size / 2 + 2], "times-new-roman", tile.touching.to_string(), color, theme_info.background, None, None));
instructions.push(DrawInstructions::Text([x * tile_size + tile_size / 2 + 5, y * tile_size + tile_size / 2 + 2], "times-new-roman".to_string(), tile.touching.to_string(), color, theme_info.background, None, None));
}
} else {
let top_left = [x * tile_size + 6, y * tile_size + 5];
@@ -225,15 +226,15 @@ impl WindowLike for Minesweeper {
//right bottom
DrawInstructions::Rect([top_left[0] + tile_size - 4, top_left[1] + 3], [3, tile_size - 4], [128, 128, 128]),
//
DrawInstructions::Text([x * tile_size + tile_size / 2 - 2, y * tile_size + tile_size / 2], "times-new-roman", u8_to_hex((y * 16 + x) as u8), theme_info.text, theme_info.background, None, None),
DrawInstructions::Text([x * tile_size + tile_size / 2 - 2, y * tile_size + tile_size / 2], "times-new-roman".to_string(), u8_to_hex((y * 16 + x) as u8), theme_info.text, theme_info.background, None, None),
]);
}
}
}
if self.state == State::Lost {
instructions.extend(vec![DrawInstructions::Text([4, 4], "times-new-roman", "You LOST!!! Press a key to play again.".to_string(), theme_info.text, theme_info.background, None, None)]);
instructions.extend(vec![DrawInstructions::Text([4, 4], "times-new-roman".to_string(), "You LOST!!! Press a key to play again.".to_string(), theme_info.text, theme_info.background, None, None)]);
} else if self.state == State::Won {
instructions.extend(vec![DrawInstructions::Text([4, 4], "times-new-roman", "You WON!!! Press a key to play again.".to_string(), theme_info.text, theme_info.background, None, None)]);
instructions.extend(vec![DrawInstructions::Text([4, 4], "times-new-roman".to_string(), "You WON!!! Press a key to play again.".to_string(), theme_info.text, theme_info.background, None, None)]);
}
instructions
}
@@ -241,8 +242,8 @@ impl WindowLike for Minesweeper {
//properties
fn title(&self) -> &'static str {
"Minesweeper"
fn title(&self) -> String {
"Minesweeper".to_string()
}
fn subtype(&self) -> WindowLikeType {
@@ -349,3 +350,7 @@ impl Minesweeper {
//
}
pub fn main() {
listen(Minesweeper::new());
}

View File

@@ -1,13 +1,18 @@
#![allow(warnings)]
use std::vec;
use std::vec::Vec;
use std::boxed::Box;
use crate::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
use crate::messages::{ WindowMessage, WindowMessageResponse, WindowManagerRequest };
use crate::framebuffer::Dimensions;
use crate::themes::ThemeInfo;
use crate::components::Component;
use crate::components::highlight_button::HighlightButton;
use ming_wm::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
use ming_wm::messages::{ WindowMessage, WindowMessageResponse, WindowManagerRequest };
use ming_wm::framebuffer::Dimensions;
use ming_wm::themes::ThemeInfo;
use ming_wm::components::Component;
use ming_wm::components::highlight_button::HighlightButton;
use ming_wm::ipc::listen;
//todo: move to essential
static CATEGORIES: [&'static str; 9] = ["About", "Utils", "Games", "Editing", "Files", "System", "Misc", "Help", "Logout"];
@@ -160,7 +165,7 @@ impl StartMenu {
},
StartMenuMessage::WindowClick(name) => {
//open the selected window
WindowMessageResponse::Request(WindowManagerRequest::OpenWindow(name))
WindowMessageResponse::Request(WindowManagerRequest::OpenWindow(name.to_string()))
},
StartMenuMessage::Back => {
self.add_category_components();
@@ -193,3 +198,7 @@ impl StartMenu {
}
}
pub fn main() {
listen(StartMenu::new());
}

View File

@@ -4,11 +4,12 @@ use std::process::{ Command, Output };
use std::str::from_utf8;
use std::io;
use crate::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
use crate::messages::{ WindowMessage, WindowMessageResponse };
use crate::framebuffer::Dimensions;
use crate::themes::ThemeInfo;
use crate::utils::concat_paths;
use ming_wm::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
use ming_wm::messages::{ WindowMessage, WindowMessageResponse };
use ming_wm::framebuffer::Dimensions;
use ming_wm::themes::ThemeInfo;
use ming_wm::utils::concat_paths;
use ming_wm::ipc::listen;
const MONO_WIDTH: u8 = 10;
const LINE_HEIGHT: usize = 15;
@@ -92,14 +93,14 @@ impl WindowLike for Terminal {
break;
}
let line = self.actual_lines[line_num].clone();
instructions.push(DrawInstructions::Text([PADDING, text_y], "times-new-romono", line, theme_info.alt_text, theme_info.alt_background, Some(0), Some(MONO_WIDTH)));
instructions.push(DrawInstructions::Text([PADDING, text_y], "times-new-romono".to_string(), line, theme_info.alt_text, theme_info.alt_background, Some(0), Some(MONO_WIDTH)));
text_y += LINE_HEIGHT;
}
instructions
}
fn title(&self) -> &'static str {
"Terminal"
fn title(&self) -> String {
"Terminal".to_string()
}
fn subtype(&self) -> WindowLikeType {
@@ -171,3 +172,7 @@ impl Terminal {
}
}
pub fn main() {
listen(Terminal::new());
}

11
src/bin/test.rs Normal file
View File

@@ -0,0 +1,11 @@
use std::process::{ Command, Stdio };
use std::io::{ Read, Write };
fn main() {
println!("a");
let mut a = Command::new("cargo").arg("run").arg("-q").arg("--bin").arg("start_menu").stdout(Stdio::piped()).stdin(Stdio::piped()).stderr(Stdio::null()).spawn().unwrap();
a.stdin.unwrap().write_all("subtype\n".to_string().as_bytes());
let mut output = String::new();
a.stdout.as_mut().unwrap().read_to_string(&mut output);
println!("{}", output);
}

View File

@@ -38,12 +38,12 @@ impl<T: Clone> Component<T> for HighlightButton<T> {
vec![
//highlight background
DrawInstructions::Rect(self.top_left, self.size, theme_info.top),
DrawInstructions::Text([self.top_left[0] + 4, self.top_left[1] + (self.size[1] - font_height) / 2], "times-new-roman", self.text.to_string(), theme_info.top_text, theme_info.top, None, None),
DrawInstructions::Text([self.top_left[0] + 4, self.top_left[1] + (self.size[1] - font_height) / 2], "times-new-roman".to_string(), self.text.to_string(), theme_info.top_text, theme_info.top, None, None),
]
} else {
vec![
DrawInstructions::Rect(self.top_left, self.size, theme_info.background),
DrawInstructions::Text([self.top_left[0] + 4, self.top_left[1] + (self.size[1] - font_height) / 2], "times-new-roman", self.text.to_string(), theme_info.text, theme_info.background, None, None),
DrawInstructions::Text([self.top_left[0] + 4, self.top_left[1] + (self.size[1] - font_height) / 2], "times-new-roman".to_string(), self.text.to_string(), theme_info.text, theme_info.background, None, None),
]
}
}

View File

@@ -17,7 +17,7 @@ pub struct ToggleButton<T> {
name_: String,
top_left: Point,
size: Dimensions,
text: &'static str,
text: String,
draw_bg: bool,
pub inverted: bool, //whether is it clicked or not
alignment: ToggleButtonAlignment,
@@ -54,7 +54,7 @@ impl<T: Clone> Component<T> for ToggleButton<T> {
//the background if self.draw_bg
//DrawInstructions::Rect(),
//the text (for now, hardcoded top left)
DrawInstructions::Text([self.top_left[0] + 4, self.top_left[1] + (self.size[1] - font_height) / 2], "times-new-roman", self.text.to_string(), theme_info.text, theme_info.background, None, None),
DrawInstructions::Text([self.top_left[0] + 4, self.top_left[1] + (self.size[1] - font_height) / 2], "times-new-roman".to_string(), self.text.to_string(), theme_info.text, theme_info.background, None, None),
]
}
@@ -73,7 +73,7 @@ impl<T: Clone> Component<T> for ToggleButton<T> {
}
impl<T> ToggleButton<T> {
pub fn new(name_: String, top_left: Point, size: Dimensions, text: &'static str, click_return: T, unclick_return: T, draw_bg: bool, alignment: Option<ToggleButtonAlignment>) -> Self {
pub fn new(name_: String, top_left: Point, size: Dimensions, text: String, click_return: T, unclick_return: T, draw_bg: bool, alignment: Option<ToggleButtonAlignment>) -> Self {
Self {
name_,
top_left,

View File

@@ -50,11 +50,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], "times-new-roman", "The bulldozer outside the kitchen window was quite a big one.".to_string(), [255, 255, 255], [0, 0, 0], None, None),
DrawInstructions::Text([4, 4 + 16], "times-new-roman", "\"Yellow,\" he thought, and stomped off back to his bedroom to get dressed.".to_string(), [255, 255, 255], [0, 0, 0], None, None),
DrawInstructions::Text([4, 4 + 16 * 2], "times-new-roman", "He stared at it.".to_string(), [255, 255, 255], [0, 0, 0], None, None),
DrawInstructions::Text([4, 4 + 16 * 3], "times-new-roman", "Password: ".to_string(), [255, 255, 255], [0, 0, 0], None, None),
DrawInstructions::Text([77, 4 + 16 * 3], "times-new-roman", "*".repeat(self.input_password.len()), [255, 255, 255], [0, 0, 0], None, None),
DrawInstructions::Text([4, 4], "times-new-roman".to_string(), "The bulldozer outside the kitchen window was quite a big one.".to_string(), [255, 255, 255], [0, 0, 0], None, None),
DrawInstructions::Text([4, 4 + 16], "times-new-roman".to_string(), "\"Yellow,\" he thought, and stomped off back to his bedroom to get dressed.".to_string(), [255, 255, 255], [0, 0, 0], None, None),
DrawInstructions::Text([4, 4 + 16 * 2], "times-new-roman".to_string(), "He stared at it.".to_string(), [255, 255, 255], [0, 0, 0], None, None),
DrawInstructions::Text([4, 4 + 16 * 3], "times-new-roman".to_string(), "Password: ".to_string(), [255, 255, 255], [0, 0, 0], None, None),
DrawInstructions::Text([77, 4 + 16 * 3], "times-new-roman".to_string(), "*".repeat(self.input_password.len()), [255, 255, 255], [0, 0, 0], None, None),
]
}

5
src/essential/mod.rs Normal file
View File

@@ -0,0 +1,5 @@
pub mod desktop_background;
pub mod taskbar;
pub mod lock_screen;
pub mod workspace_indicator;

View File

@@ -33,7 +33,7 @@ impl WindowLike for Taskbar {
WindowMessage::Init(dimensions) => {
self.dimensions = dimensions;
self.components = vec![
Box::new(ToggleButton::new("start-button".to_string(), [PADDING, PADDING], [44, self.dimensions[1] - (PADDING * 2)], "Start", TaskbarMessage::ShowStartMenu, TaskbarMessage::HideStartMenu, false, Some(ToggleButtonAlignment::Left))),
Box::new(ToggleButton::new("start-button".to_string(), [PADDING, PADDING], [44, self.dimensions[1] - (PADDING * 2)], "Start".to_string(), TaskbarMessage::ShowStartMenu, TaskbarMessage::HideStartMenu, false, Some(ToggleButtonAlignment::Left))),
];
WindowMessageResponse::JustRerender
},
@@ -79,7 +79,8 @@ impl WindowLike for Taskbar {
break;
}
let info = &self.windows_in_workspace[wi];
let mut b = ToggleButton::new(info.1.to_string() + "-window", [PADDING * 2 + 44 + (META_WIDTH + PADDING) * wi, PADDING], [META_WIDTH, self.dimensions[1] - (PADDING * 2)], info.1, TaskbarMessage::Nothing, TaskbarMessage::Nothing, false, Some(ToggleButtonAlignment::Left));
let name = &info.1;
let mut b = ToggleButton::new(name.to_string() + "-window", [PADDING * 2 + 44 + (META_WIDTH + PADDING) * wi, PADDING], [META_WIDTH, self.dimensions[1] - (PADDING * 2)], name.to_string(), TaskbarMessage::Nothing, TaskbarMessage::Nothing, false, Some(ToggleButtonAlignment::Left));
b.inverted = info.0 == self.focused_id;
instructions.extend(b.draw(theme_info));
}
@@ -110,7 +111,7 @@ impl Taskbar {
if let Some(message) = message {
match message {
TaskbarMessage::ShowStartMenu => {
WindowMessageResponse::Request(WindowManagerRequest::OpenWindow("StartMenu"))
WindowMessageResponse::Request(WindowManagerRequest::OpenWindow("StartMenu".to_string()))
},
TaskbarMessage::HideStartMenu => {
WindowMessageResponse::Request(WindowManagerRequest::CloseStartMenu)

View File

@@ -44,9 +44,9 @@ impl WindowLike for WorkspaceIndicator {
for w in 0..9 {
if w == self.current_workspace as usize {
instructions.push(DrawInstructions::Rect([w * WIDTH, 0], [WIDTH, self.dimensions[1]], theme_info.top));
instructions.push(DrawInstructions::Text([w * WIDTH + 5, 4], "times-new-roman", (w + 1).to_string(), theme_info.top_text, theme_info.top, None, None));
instructions.push(DrawInstructions::Text([w * WIDTH + 5, 4], "times-new-roman".to_string(), (w + 1).to_string(), theme_info.top_text, theme_info.top, None, None));
} else {
instructions.push(DrawInstructions::Text([w * WIDTH + 5, 4], "times-new-roman", (w + 1).to_string(), theme_info.text, theme_info.background, None, None));
instructions.push(DrawInstructions::Text([w * WIDTH + 5, 4], "times-new-roman".to_string(), (w + 1).to_string(), theme_info.text, theme_info.background, None, None));
}
}
instructions

51
src/ipc.rs Normal file
View File

@@ -0,0 +1,51 @@
use std::io::{ stdin, BufRead };
//use serde::{ Deserialize, Serialize };
use ron;
use crate::window_manager::WindowLike;
/*
pub trait WindowLike {
fn handle_message(&mut self, message: WindowMessage) -> WindowMessageResponse;
fn draw(&self, theme_info: &ThemeInfo) -> Vec<DrawInstructions>;
//properties
fn title(&self) -> &'static str {
""
}
fn resizable(&self) -> bool {
false
}
fn subtype(&self) -> WindowLikeType;
fn ideal_dimensions(&self, dimensions: Dimensions) -> Dimensions; //needs &self or its not object safe or some bullcrap
}
*/
pub fn listen(mut window_like: impl WindowLike) {
let mut stdin = stdin();
for line in stdin.lock().lines() {
let line = line.unwrap().clone();
let mut parts = line.split(" ");
let method = parts.next().unwrap();
let arg = &parts.collect::<Vec<&str>>().join(" ");
if method == "handle_message" {
println!("{}", ron::to_string(&window_like.handle_message(ron::from_str(arg).unwrap())).unwrap());
} else if method == "draw" {
println!("{}", ron::to_string(&window_like.draw(&ron::from_str(arg).unwrap())).unwrap());
} else if method == "title" {
println!("{}", window_like.title());
} else if method == "resizable" {
println!("{}", window_like.resizable());
} else if method == "subtype" {
println!("{}", ron::to_string(&window_like.subtype()).unwrap());
} else if method == "ideal_dimensions" {
println!("{:?}", window_like.ideal_dimensions(ron::from_str(arg).unwrap()));
}
}
}

12
src/lib.rs Normal file
View File

@@ -0,0 +1,12 @@
pub mod framebuffer;
pub mod window_manager;
pub mod components;
pub mod themes;
pub mod messages;
pub mod fs;
pub mod utils;
pub mod ipc;
mod proxy_window_like;
mod keyboard;
mod essential;

View File

@@ -2,6 +2,8 @@ use std::boxed::Box;
use std::fmt;
use std::vec::Vec;
use serde::{ Deserialize, Serialize };
use crate::keyboard::KeyChar;
use crate::framebuffer::Dimensions;
use crate::window_manager::WindowLike;
@@ -22,9 +24,9 @@ impl PartialEq for WindowBox {
}
*/
#[derive(PartialEq)]
#[derive(PartialEq, Serialize, Deserialize)]
pub enum WindowManagerRequest {
OpenWindow(&'static str),
OpenWindow(String),
CloseStartMenu,
Unlock,
Lock,
@@ -37,19 +39,20 @@ impl fmt::Debug for WindowManagerRequest{
}
}
#[derive(PartialEq, Debug)]
#[derive(PartialEq, Debug, Serialize, Deserialize)]
pub enum WindowMessageResponse {
Request(WindowManagerRequest),
JustRerender,
DoNothing,
}
#[derive(Serialize, Deserialize)]
pub struct KeyPress {
pub key: char,
//
}
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Serialize, Deserialize)]
pub enum Direction {
Left,
Down,
@@ -58,7 +61,7 @@ pub enum Direction {
}
//todo, rename to CommandType
#[derive(PartialEq)]
#[derive(PartialEq, Serialize, Deserialize)]
pub enum ShortcutType {
StartMenu,
SwitchWorkspace(u8),
@@ -74,14 +77,16 @@ pub enum ShortcutType {
//
}
pub type WindowsVec = Vec<(usize, &'static str)>;
pub type WindowsVec = Vec<(usize, String)>;
#[derive(Serialize, Deserialize)]
pub enum InfoType {
//let taskbar know what the current windows in the workspace are
WindowsInWorkspace(WindowsVec, usize), //Vec<title, name)>, focused id
//
}
#[derive(Serialize, Deserialize)]
pub enum WindowMessage {
Init(Dimensions),
KeyPress(KeyPress),

79
src/proxy_window_like.rs Normal file
View File

@@ -0,0 +1,79 @@
use std::vec::Vec;
use std::process::{ Command, Child, Stdio };
use std::io::{ BufReader, BufRead, Read, Write };
use std::cell::RefCell;
use ron;
use crate::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
use crate::messages::{ WindowMessage, WindowMessageResponse };
use crate::framebuffer::Dimensions;
use crate::themes::ThemeInfo;
pub struct ProxyWindowLike {
process: RefCell<Child>,
}
impl WindowLike for ProxyWindowLike {
fn handle_message(&mut self, message: WindowMessage) -> WindowMessageResponse {
self.process.borrow_mut().stdin.as_mut().unwrap().write_all(("handle_message ".to_string() + &ron::to_string(&message).unwrap() + "\n").as_bytes());
let output = self.read_line();
ron::from_str(&output).unwrap()
}
fn draw(&self, theme_info: &ThemeInfo) -> Vec<DrawInstructions> {
self.process.borrow_mut().stdin.as_mut().unwrap().write_all(("draw ".to_string() + &ron::to_string(&theme_info).unwrap() + "\n").as_bytes());
let output = self.read_line();
ron::from_str(&output).unwrap()
}
//properties
fn title(&self) -> String {
self.process.borrow_mut().stdin.as_mut().unwrap().write_all("title\n".as_bytes());
self.read_line()
}
fn resizable(&self) -> bool {
self.process.borrow_mut().stdin.as_mut().unwrap().write_all("resizable\n".to_string().as_bytes());
let output = self.read_line();
ron::from_str(&output).unwrap()
}
fn subtype(&self) -> WindowLikeType {
self.process.borrow_mut().stdin.as_mut().unwrap().write_all("subtype\n".to_string().as_bytes());
let output = self.read_line();
ron::from_str(&output).unwrap()
}
fn ideal_dimensions(&self, dimensions: Dimensions) -> Dimensions {
self.process.borrow_mut().stdin.as_mut().unwrap().write_all(("ideal_dimensions".to_string() + &ron::to_string(&dimensions).unwrap() + "\n").as_bytes());
let output = self.read_line();
ron::from_str(&output).unwrap()
}
}
//kill process when this window like dropped
impl Drop for ProxyWindowLike {
fn drop(&mut self) {
self.process.borrow_mut().kill();
}
}
impl ProxyWindowLike {
pub fn new(file: &str) -> Self {
ProxyWindowLike {
//--quiet
process: RefCell::new(Command::new("cargo").arg("run").arg("--quiet").arg("--release").arg("--bin").arg(file).stdout(Stdio::piped()).stdin(Stdio::piped()).stderr(Stdio::null()).spawn().unwrap()),
}
}
fn read_line(&self) -> String {
let mut output = String::new();
let mut buffer = self.process.borrow_mut();
let buffer = buffer.stdout.as_mut().unwrap();
let mut reader = BufReader::new(buffer);
reader.read_line(&mut output).unwrap();
output
}
}

View File

@@ -1,3 +1,5 @@
use serde::{ Deserialize, Serialize };
use crate::framebuffer::RGBColor;
#[derive(PartialEq, Default)]
@@ -7,6 +9,7 @@ pub enum Themes {
//
}
#[derive(Serialize, Deserialize)]
pub struct ThemeInfo {
pub top: RGBColor,
pub background: RGBColor,

View File

@@ -1,11 +0,0 @@
pub mod desktop_background;
pub mod taskbar;
pub mod start_menu;
pub mod lock_screen;
pub mod workspace_indicator;
pub mod minesweeper;
pub mod terminal;
pub mod malvim;
pub mod audio_player;

View File

@@ -11,21 +11,17 @@ use linux_framebuffer::Framebuffer;
use termion::input::TermRead;
use termion::raw::IntoRawMode;
use termion::cursor;
use serde::{ Deserialize, Serialize };
use crate::framebuffer::{ FramebufferWriter, FramebufferInfo, Point, Dimensions, RGBColor };
use crate::window_likes::desktop_background::DesktopBackground;
use crate::window_likes::taskbar::Taskbar;
use crate::window_likes::lock_screen::LockScreen;
use crate::window_likes::workspace_indicator::WorkspaceIndicator;
use crate::themes::{ ThemeInfo, Themes, get_theme_info };
use crate::keyboard::{ KeyChar, key_to_char };
use crate::messages::*;
use crate::window_likes::start_menu::StartMenu;
use crate::window_likes::minesweeper::Minesweeper;
use crate::window_likes::terminal::Terminal;
use crate::window_likes::malvim::Malvim;
use crate::window_likes::audio_player::AudioPlayer;
use crate::proxy_window_like::ProxyWindowLike;
use crate::essential::desktop_background::DesktopBackground;
use crate::essential::taskbar::Taskbar;
use crate::essential::lock_screen::LockScreen;
use crate::essential::workspace_indicator::WorkspaceIndicator;
//todo, better error handling for windows
@@ -71,15 +67,15 @@ pub fn min(one: usize, two: usize) -> usize {
if one > two { two } else { one }
}
#[derive(Debug)]
#[derive(Debug, Serialize, Deserialize)]
pub enum DrawInstructions {
Rect(Point, Dimensions, RGBColor),
Text(Point, &'static str, String, RGBColor, RGBColor, Option<usize>, Option<u8>), //font and text
Text(Point, String, String, RGBColor, RGBColor, Option<usize>, Option<u8>), //font and text
Gradient(Point, Dimensions, RGBColor, RGBColor, usize),
Mingde(Point),
}
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub enum WindowLikeType {
LockScreen,
Window,
@@ -92,15 +88,18 @@ pub enum WindowLikeType {
pub trait WindowLike {
fn handle_message(&mut self, message: WindowMessage) -> WindowMessageResponse;
fn draw(&self, theme_info: &ThemeInfo) -> Vec<DrawInstructions>;
//properties
fn title(&self) -> &'static str {
""
fn title(&self) -> String {
String::new()
}
fn resizable(&self) -> bool {
false
}
fn subtype(&self) -> WindowLikeType;
fn draw(&self, theme_info: &ThemeInfo) -> Vec<DrawInstructions>;
fn ideal_dimensions(&self, dimensions: Dimensions) -> Dimensions; //needs &self or its not object safe or some bullcrap
}
@@ -222,7 +221,7 @@ impl WindowManager {
fn taskbar_update_windows(&mut self) {
let taskbar_index = self.window_infos.iter().position(|w| w.window_like.subtype() == WindowLikeType::Taskbar).unwrap();
let mut relevant: WindowsVec = self.get_windows_in_workspace(false).iter().map(|w| (w.id, w.window_like.title())).collect();
let mut relevant: WindowsVec = self.get_windows_in_workspace(false).iter().map(|w| (w.id, w.window_like.title().to_string())).collect();
relevant.sort_by(|a, b| a.0.cmp(&b.0)); //sort by ids so order is consistent
let message = WindowMessage::Info(InfoType::WindowsInWorkspace(
relevant,
@@ -500,13 +499,13 @@ impl WindowManager {
if subtype != WindowLikeType::Taskbar && subtype != WindowLikeType::StartMenu {
return;
}
let w: WindowBox = match w {
"Minesweeper" => Box::new(Minesweeper::new()),
"Malvim" => Box::new(Malvim::new()),
"Terminal" => Box::new(Terminal::new()),
"Audio Player" => Box::new(AudioPlayer::new()),
"StartMenu" => Box::new(StartMenu::new()),
_ => panic!("no such window"),
let w: WindowBox = match w.as_str() {
"Minesweeper" => Box::new(ProxyWindowLike::new("minesweeper")),
"Malvim" => Box::new(ProxyWindowLike::new("malvim")),
"Terminal" => Box::new(ProxyWindowLike::new("terminal")),
"Audio Player" => Box::new(ProxyWindowLike::new("audio_player")),
"StartMenu" => Box::new(ProxyWindowLike::new("start_menu")),
_ => panic!("window not found"), //todo: do not panic
};
//close start menu if open
self.toggle_start_menu(true);
@@ -588,7 +587,7 @@ impl WindowManager {
instructions = instructions.iter().map(|instruction| {
match instruction {
DrawInstructions::Rect(top_left, dimensions, color) => DrawInstructions::Rect(WindowManager::get_true_top_left(top_left, is_window), *dimensions, *color),
DrawInstructions::Text(top_left, font_name, text, color, bg_color, horiz_spacing, mono_width) => DrawInstructions::Text(WindowManager::get_true_top_left(top_left, is_window), font_name, text.clone(), *color, *bg_color, *horiz_spacing, *mono_width),
DrawInstructions::Text(top_left, font_name, text, color, bg_color, horiz_spacing, mono_width) => DrawInstructions::Text(WindowManager::get_true_top_left(top_left, is_window), font_name.clone(), text.clone(), *color, *bg_color, *horiz_spacing, *mono_width),
DrawInstructions::Mingde(top_left) => DrawInstructions::Mingde(WindowManager::get_true_top_left(top_left, is_window)),
DrawInstructions::Gradient(top_left, dimensions, start_color, end_color, steps) => DrawInstructions::Gradient(WindowManager::get_true_top_left(top_left, is_window), *dimensions, *start_color, *end_color, *steps),
}
@@ -602,7 +601,7 @@ impl WindowManager {
DrawInstructions::Rect([0, 0], [1, window_dimensions[1]], theme_info.border_left_top),
//top
DrawInstructions::Rect([1, 1], [window_dimensions[0] - 2, WINDOW_TOP_HEIGHT - 3], theme_info.top),
DrawInstructions::Text([4, 4], "times-new-roman", window_info.window_like.title().to_string(), theme_info.top_text, theme_info.top, None, None),
DrawInstructions::Text([4, 4], "times-new-roman".to_string(), window_info.window_like.title().to_string(), theme_info.top_text, theme_info.top, None, None),
//top bottom border
DrawInstructions::Rect([1, WINDOW_TOP_HEIGHT - 2], [window_dimensions[0] - 2, 2], theme_info.border_left_top),
//right bottom border
@@ -632,7 +631,7 @@ impl WindowManager {
window_writer.draw_rect(top_left, true_dimensions, color);
},
DrawInstructions::Text(top_left, font_name, text, color, bg_color, horiz_spacing, mono_width) => {
window_writer.draw_text(top_left, font_name, &text, color, bg_color, horiz_spacing.unwrap_or(1), mono_width);
window_writer.draw_text(top_left, &font_name, &text, color, bg_color, horiz_spacing.unwrap_or(1), mono_width);
},
DrawInstructions::Mingde(top_left) => {
window_writer._draw_mingde(top_left);