separate windows out, IPCcargo run --release!
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ming-os-kernel"
|
name = "ming-wm"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
default-run = "main"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# 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"
|
termion = "4.0.3"
|
||||||
rodio = "0.19.0"
|
rodio = "0.19.0"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
ron = "0.8"
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|||||||
@@ -7,12 +7,13 @@ use std::fs::File;
|
|||||||
use rodio::{ Decoder, OutputStream, Sink, Source };
|
use rodio::{ Decoder, OutputStream, Sink, Source };
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
|
|
||||||
use crate::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
|
use ming_wm::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
|
||||||
use crate::messages::{ WindowMessage, WindowMessageResponse };
|
use ming_wm::messages::{ WindowMessage, WindowMessageResponse };
|
||||||
use crate::framebuffer::Dimensions;
|
use ming_wm::framebuffer::Dimensions;
|
||||||
use crate::themes::ThemeInfo;
|
use ming_wm::themes::ThemeInfo;
|
||||||
use crate::utils::{ concat_paths, format_seconds };
|
use ming_wm::utils::{ concat_paths, format_seconds };
|
||||||
use crate::fs::get_all_files;
|
use ming_wm::fs::get_all_files;
|
||||||
|
use ming_wm::ipc::listen;
|
||||||
|
|
||||||
const MONO_WIDTH: u8 = 10;
|
const MONO_WIDTH: u8 = 10;
|
||||||
const LINE_HEIGHT: usize = 18;
|
const LINE_HEIGHT: usize = 18;
|
||||||
@@ -59,13 +60,13 @@ impl WindowLike for AudioPlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn draw(&self, theme_info: &ThemeInfo) -> Vec<DrawInstructions> {
|
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 {
|
if let Some(sink) = &self.sink {
|
||||||
let current = &self.queue[self.queue.len() - sink.len()];
|
let current = &self.queue[self.queue.len() - sink.len()];
|
||||||
let current_name = current.0.file_name().unwrap().to_string_lossy().into_owned();
|
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));
|
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
|
instructions
|
||||||
@@ -73,8 +74,8 @@ impl WindowLike for AudioPlayer {
|
|||||||
|
|
||||||
//properties
|
//properties
|
||||||
|
|
||||||
fn title(&self) -> &'static str {
|
fn title(&self) -> String {
|
||||||
"Audio Player"
|
"Audio Player".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subtype(&self) -> WindowLikeType {
|
fn subtype(&self) -> WindowLikeType {
|
||||||
@@ -98,13 +99,13 @@ impl AudioPlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//t: toggle pause/play
|
//t: toggle pause/play
|
||||||
//h: prev
|
|
||||||
//l: next/skip
|
//l: next/skip
|
||||||
//j: volume down
|
//j: volume down
|
||||||
//k: volume up
|
//k: volume up
|
||||||
//b <dir>: set base directory
|
//b <dir>: set base directory
|
||||||
//p <dir>/<playlist file>: play directory or playlist in random order
|
//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 {
|
fn process_command(&mut self) -> String {
|
||||||
if self.command.len() == 1 {
|
if self.command.len() == 1 {
|
||||||
if let Some(sink) = &mut self.sink {
|
if let Some(sink) = &mut self.sink {
|
||||||
@@ -175,3 +176,7 @@ impl AudioPlayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
listen(AudioPlayer::new());
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,24 +1,7 @@
|
|||||||
use linux_framebuffer::Framebuffer;
|
use linux_framebuffer::Framebuffer;
|
||||||
|
|
||||||
mod framebuffer;
|
use ming_wm::framebuffer::FramebufferInfo;
|
||||||
use framebuffer::FramebufferInfo;
|
use ming_wm::window_manager::init;
|
||||||
|
|
||||||
mod window_manager;
|
|
||||||
use window_manager::init;
|
|
||||||
|
|
||||||
mod window_likes;
|
|
||||||
|
|
||||||
mod components;
|
|
||||||
|
|
||||||
mod themes;
|
|
||||||
|
|
||||||
mod keyboard;
|
|
||||||
|
|
||||||
mod messages;
|
|
||||||
|
|
||||||
mod fs;
|
|
||||||
|
|
||||||
mod utils;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut fb = Framebuffer::new("/dev/fb0").unwrap();
|
let mut fb = Framebuffer::new("/dev/fb0").unwrap();
|
||||||
@@ -4,11 +4,12 @@ use std::fmt;
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::fs::{ read_to_string, write };
|
use std::fs::{ read_to_string, write };
|
||||||
|
|
||||||
use crate::messages::{ WindowMessage, WindowMessageResponse };
|
use ming_wm::messages::{ WindowMessage, WindowMessageResponse };
|
||||||
use crate::themes::ThemeInfo;
|
use ming_wm::themes::ThemeInfo;
|
||||||
use crate::framebuffer::Dimensions;
|
use ming_wm::framebuffer::Dimensions;
|
||||||
use crate::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
|
use ming_wm::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
|
||||||
use crate::utils::{ calc_actual_lines, calc_new_cursor_pos, Substring };
|
use ming_wm::utils::{ calc_actual_lines, calc_new_cursor_pos, Substring };
|
||||||
|
use ming_wm::ipc::listen;
|
||||||
|
|
||||||
const MONO_WIDTH: u8 = 10;
|
const MONO_WIDTH: u8 = 10;
|
||||||
const LINE_HEIGHT: usize = 18;
|
const LINE_HEIGHT: usize = 18;
|
||||||
@@ -302,7 +303,7 @@ impl WindowLike for Malvim {
|
|||||||
};
|
};
|
||||||
instructions.extend(vec![
|
instructions.extend(vec![
|
||||||
DrawInstructions::Rect([used_width, 2], [future_used_width, BAND_HEIGHT - 2], background),
|
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;
|
used_width = future_used_width;
|
||||||
}
|
}
|
||||||
@@ -320,13 +321,13 @@ impl WindowLike for Malvim {
|
|||||||
//write line num text (if start of line)
|
//write line num text (if start of line)
|
||||||
let y0 = BAND_HEIGHT + rel_line_num * LINE_HEIGHT + PADDING;
|
let y0 = BAND_HEIGHT + rel_line_num * LINE_HEIGHT + PADDING;
|
||||||
if line.0 {
|
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;
|
sub_line_num = 0;
|
||||||
}
|
}
|
||||||
let x1 = current.line_num_width + PADDING * 2;
|
let x1 = current.line_num_width + PADDING * 2;
|
||||||
//write actual line
|
//write actual line
|
||||||
//line.2
|
//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;
|
sub_line_num += 1;
|
||||||
let max = sub_line_num * current.max_chars_per_line;
|
let max = sub_line_num * current.max_chars_per_line;
|
||||||
let min = max - 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));
|
instructions.push(DrawInstructions::Rect(top_left, [MONO_WIDTH as usize, LINE_HEIGHT], theme_info.top));
|
||||||
//draw the char over it
|
//draw the char over it
|
||||||
if line.2.len() > 0 {
|
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
|
//bottom blue band stuff
|
||||||
//write mode
|
//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;
|
let file_status;
|
||||||
if self.files.len() > 0 {
|
if self.files.len() > 0 {
|
||||||
file_status = self.files[self.current_file_index].name.clone();
|
file_status = self.files[self.current_file_index].name.clone();
|
||||||
} else {
|
} else {
|
||||||
file_status = "No file open".to_string();
|
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
|
//write command or bottom message
|
||||||
if self.mode == Mode::Command {
|
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() {
|
} 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
|
instructions
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self) -> &'static str {
|
fn title(&self) -> String {
|
||||||
"Malvim"
|
"Malvim".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subtype(&self) -> WindowLikeType {
|
fn subtype(&self) -> WindowLikeType {
|
||||||
@@ -497,3 +498,7 @@ impl Malvim {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
listen(Malvim::new());
|
||||||
|
}
|
||||||
|
|
||||||
@@ -3,10 +3,11 @@ use std::vec;
|
|||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
|
|
||||||
use crate::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
|
use ming_wm::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
|
||||||
use crate::messages::{ WindowMessage, WindowMessageResponse };
|
use ming_wm::messages::{ WindowMessage, WindowMessageResponse };
|
||||||
use crate::framebuffer::Dimensions;
|
use ming_wm::framebuffer::Dimensions;
|
||||||
use crate::themes::ThemeInfo;
|
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'];
|
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> {
|
fn draw(&self, theme_info: &ThemeInfo) -> Vec<DrawInstructions> {
|
||||||
if self.state == State::Seed {
|
if self.state == State::Seed {
|
||||||
vec![
|
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], "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", self.random_chars.clone(), 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 {
|
} else {
|
||||||
let mut instructions = vec![
|
let mut instructions = vec![
|
||||||
@@ -194,7 +195,7 @@ impl WindowLike for Minesweeper {
|
|||||||
let tile = &self.tiles[y][x];
|
let tile = &self.tiles[y][x];
|
||||||
if tile.revealed {
|
if tile.revealed {
|
||||||
if tile.mine {
|
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 {
|
} else {
|
||||||
let color = match tile.touching {
|
let color = match tile.touching {
|
||||||
1 => [0, 0, 255],
|
1 => [0, 0, 255],
|
||||||
@@ -207,7 +208,7 @@ impl WindowLike for Minesweeper {
|
|||||||
//8
|
//8
|
||||||
_ => [128, 128, 128],
|
_ => [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 {
|
} else {
|
||||||
let top_left = [x * tile_size + 6, y * tile_size + 5];
|
let top_left = [x * tile_size + 6, y * tile_size + 5];
|
||||||
@@ -225,15 +226,15 @@ impl WindowLike for Minesweeper {
|
|||||||
//right bottom
|
//right bottom
|
||||||
DrawInstructions::Rect([top_left[0] + tile_size - 4, top_left[1] + 3], [3, tile_size - 4], [128, 128, 128]),
|
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 {
|
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 {
|
} 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
|
instructions
|
||||||
}
|
}
|
||||||
@@ -241,8 +242,8 @@ impl WindowLike for Minesweeper {
|
|||||||
|
|
||||||
//properties
|
//properties
|
||||||
|
|
||||||
fn title(&self) -> &'static str {
|
fn title(&self) -> String {
|
||||||
"Minesweeper"
|
"Minesweeper".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subtype(&self) -> WindowLikeType {
|
fn subtype(&self) -> WindowLikeType {
|
||||||
@@ -349,3 +350,7 @@ impl Minesweeper {
|
|||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
listen(Minesweeper::new());
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,13 +1,18 @@
|
|||||||
|
#![allow(warnings)]
|
||||||
|
|
||||||
use std::vec;
|
use std::vec;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
|
|
||||||
use crate::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
|
use ming_wm::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
|
||||||
use crate::messages::{ WindowMessage, WindowMessageResponse, WindowManagerRequest };
|
use ming_wm::messages::{ WindowMessage, WindowMessageResponse, WindowManagerRequest };
|
||||||
use crate::framebuffer::Dimensions;
|
use ming_wm::framebuffer::Dimensions;
|
||||||
use crate::themes::ThemeInfo;
|
use ming_wm::themes::ThemeInfo;
|
||||||
use crate::components::Component;
|
use ming_wm::components::Component;
|
||||||
use crate::components::highlight_button::HighlightButton;
|
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"];
|
static CATEGORIES: [&'static str; 9] = ["About", "Utils", "Games", "Editing", "Files", "System", "Misc", "Help", "Logout"];
|
||||||
|
|
||||||
@@ -160,7 +165,7 @@ impl StartMenu {
|
|||||||
},
|
},
|
||||||
StartMenuMessage::WindowClick(name) => {
|
StartMenuMessage::WindowClick(name) => {
|
||||||
//open the selected window
|
//open the selected window
|
||||||
WindowMessageResponse::Request(WindowManagerRequest::OpenWindow(name))
|
WindowMessageResponse::Request(WindowManagerRequest::OpenWindow(name.to_string()))
|
||||||
},
|
},
|
||||||
StartMenuMessage::Back => {
|
StartMenuMessage::Back => {
|
||||||
self.add_category_components();
|
self.add_category_components();
|
||||||
@@ -193,3 +198,7 @@ impl StartMenu {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
listen(StartMenu::new());
|
||||||
|
}
|
||||||
|
|
||||||
@@ -4,11 +4,12 @@ use std::process::{ Command, Output };
|
|||||||
use std::str::from_utf8;
|
use std::str::from_utf8;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use crate::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
|
use ming_wm::window_manager::{ DrawInstructions, WindowLike, WindowLikeType };
|
||||||
use crate::messages::{ WindowMessage, WindowMessageResponse };
|
use ming_wm::messages::{ WindowMessage, WindowMessageResponse };
|
||||||
use crate::framebuffer::Dimensions;
|
use ming_wm::framebuffer::Dimensions;
|
||||||
use crate::themes::ThemeInfo;
|
use ming_wm::themes::ThemeInfo;
|
||||||
use crate::utils::concat_paths;
|
use ming_wm::utils::concat_paths;
|
||||||
|
use ming_wm::ipc::listen;
|
||||||
|
|
||||||
const MONO_WIDTH: u8 = 10;
|
const MONO_WIDTH: u8 = 10;
|
||||||
const LINE_HEIGHT: usize = 15;
|
const LINE_HEIGHT: usize = 15;
|
||||||
@@ -92,14 +93,14 @@ impl WindowLike for Terminal {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let line = self.actual_lines[line_num].clone();
|
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;
|
text_y += LINE_HEIGHT;
|
||||||
}
|
}
|
||||||
instructions
|
instructions
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self) -> &'static str {
|
fn title(&self) -> String {
|
||||||
"Terminal"
|
"Terminal".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subtype(&self) -> WindowLikeType {
|
fn subtype(&self) -> WindowLikeType {
|
||||||
@@ -171,3 +172,7 @@ impl Terminal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
listen(Terminal::new());
|
||||||
|
}
|
||||||
|
|
||||||
11
src/bin/test.rs
Normal file
11
src/bin/test.rs
Normal 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);
|
||||||
|
}
|
||||||
@@ -38,12 +38,12 @@ impl<T: Clone> Component<T> for HighlightButton<T> {
|
|||||||
vec![
|
vec![
|
||||||
//highlight background
|
//highlight background
|
||||||
DrawInstructions::Rect(self.top_left, self.size, theme_info.top),
|
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 {
|
} else {
|
||||||
vec![
|
vec![
|
||||||
DrawInstructions::Rect(self.top_left, self.size, theme_info.background),
|
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),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ pub struct ToggleButton<T> {
|
|||||||
name_: String,
|
name_: String,
|
||||||
top_left: Point,
|
top_left: Point,
|
||||||
size: Dimensions,
|
size: Dimensions,
|
||||||
text: &'static str,
|
text: String,
|
||||||
draw_bg: bool,
|
draw_bg: bool,
|
||||||
pub inverted: bool, //whether is it clicked or not
|
pub inverted: bool, //whether is it clicked or not
|
||||||
alignment: ToggleButtonAlignment,
|
alignment: ToggleButtonAlignment,
|
||||||
@@ -54,7 +54,7 @@ impl<T: Clone> Component<T> for ToggleButton<T> {
|
|||||||
//the background if self.draw_bg
|
//the background if self.draw_bg
|
||||||
//DrawInstructions::Rect(),
|
//DrawInstructions::Rect(),
|
||||||
//the text (for now, hardcoded top left)
|
//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> {
|
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 {
|
Self {
|
||||||
name_,
|
name_,
|
||||||
top_left,
|
top_left,
|
||||||
|
|||||||
@@ -50,11 +50,11 @@ impl WindowLike for LockScreen {
|
|||||||
fn draw(&self, _theme_info: &ThemeInfo) -> Vec<DrawInstructions> {
|
fn draw(&self, _theme_info: &ThemeInfo) -> Vec<DrawInstructions> {
|
||||||
vec![
|
vec![
|
||||||
DrawInstructions::Rect([0, 0], self.dimensions, [0, 0, 0]),
|
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], "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", "\"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], "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", "He stared at it.".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", "Password: ".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", "*".repeat(self.input_password.len()), [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
5
src/essential/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
pub mod desktop_background;
|
||||||
|
pub mod taskbar;
|
||||||
|
pub mod lock_screen;
|
||||||
|
pub mod workspace_indicator;
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ impl WindowLike for Taskbar {
|
|||||||
WindowMessage::Init(dimensions) => {
|
WindowMessage::Init(dimensions) => {
|
||||||
self.dimensions = dimensions;
|
self.dimensions = dimensions;
|
||||||
self.components = vec![
|
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
|
WindowMessageResponse::JustRerender
|
||||||
},
|
},
|
||||||
@@ -79,7 +79,8 @@ impl WindowLike for Taskbar {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let info = &self.windows_in_workspace[wi];
|
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;
|
b.inverted = info.0 == self.focused_id;
|
||||||
instructions.extend(b.draw(theme_info));
|
instructions.extend(b.draw(theme_info));
|
||||||
}
|
}
|
||||||
@@ -110,7 +111,7 @@ impl Taskbar {
|
|||||||
if let Some(message) = message {
|
if let Some(message) = message {
|
||||||
match message {
|
match message {
|
||||||
TaskbarMessage::ShowStartMenu => {
|
TaskbarMessage::ShowStartMenu => {
|
||||||
WindowMessageResponse::Request(WindowManagerRequest::OpenWindow("StartMenu"))
|
WindowMessageResponse::Request(WindowManagerRequest::OpenWindow("StartMenu".to_string()))
|
||||||
},
|
},
|
||||||
TaskbarMessage::HideStartMenu => {
|
TaskbarMessage::HideStartMenu => {
|
||||||
WindowMessageResponse::Request(WindowManagerRequest::CloseStartMenu)
|
WindowMessageResponse::Request(WindowManagerRequest::CloseStartMenu)
|
||||||
@@ -44,9 +44,9 @@ impl WindowLike for WorkspaceIndicator {
|
|||||||
for w in 0..9 {
|
for w in 0..9 {
|
||||||
if w == self.current_workspace as usize {
|
if w == self.current_workspace as usize {
|
||||||
instructions.push(DrawInstructions::Rect([w * WIDTH, 0], [WIDTH, self.dimensions[1]], theme_info.top));
|
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 {
|
} 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
|
instructions
|
||||||
51
src/ipc.rs
Normal file
51
src/ipc.rs
Normal 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
12
src/lib.rs
Normal 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;
|
||||||
|
|
||||||
@@ -2,6 +2,8 @@ use std::boxed::Box;
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
|
||||||
|
use serde::{ Deserialize, Serialize };
|
||||||
|
|
||||||
use crate::keyboard::KeyChar;
|
use crate::keyboard::KeyChar;
|
||||||
use crate::framebuffer::Dimensions;
|
use crate::framebuffer::Dimensions;
|
||||||
use crate::window_manager::WindowLike;
|
use crate::window_manager::WindowLike;
|
||||||
@@ -22,9 +24,9 @@ impl PartialEq for WindowBox {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq, Serialize, Deserialize)]
|
||||||
pub enum WindowManagerRequest {
|
pub enum WindowManagerRequest {
|
||||||
OpenWindow(&'static str),
|
OpenWindow(String),
|
||||||
CloseStartMenu,
|
CloseStartMenu,
|
||||||
Unlock,
|
Unlock,
|
||||||
Lock,
|
Lock,
|
||||||
@@ -37,19 +39,20 @@ impl fmt::Debug for WindowManagerRequest{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug, Serialize, Deserialize)]
|
||||||
pub enum WindowMessageResponse {
|
pub enum WindowMessageResponse {
|
||||||
Request(WindowManagerRequest),
|
Request(WindowManagerRequest),
|
||||||
JustRerender,
|
JustRerender,
|
||||||
DoNothing,
|
DoNothing,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct KeyPress {
|
pub struct KeyPress {
|
||||||
pub key: char,
|
pub key: char,
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum Direction {
|
pub enum Direction {
|
||||||
Left,
|
Left,
|
||||||
Down,
|
Down,
|
||||||
@@ -58,7 +61,7 @@ pub enum Direction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//todo, rename to CommandType
|
//todo, rename to CommandType
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq, Serialize, Deserialize)]
|
||||||
pub enum ShortcutType {
|
pub enum ShortcutType {
|
||||||
StartMenu,
|
StartMenu,
|
||||||
SwitchWorkspace(u8),
|
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 {
|
pub enum InfoType {
|
||||||
//let taskbar know what the current windows in the workspace are
|
//let taskbar know what the current windows in the workspace are
|
||||||
WindowsInWorkspace(WindowsVec, usize), //Vec<title, name)>, focused id
|
WindowsInWorkspace(WindowsVec, usize), //Vec<title, name)>, focused id
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
pub enum WindowMessage {
|
pub enum WindowMessage {
|
||||||
Init(Dimensions),
|
Init(Dimensions),
|
||||||
KeyPress(KeyPress),
|
KeyPress(KeyPress),
|
||||||
|
|||||||
79
src/proxy_window_like.rs
Normal file
79
src/proxy_window_like.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use serde::{ Deserialize, Serialize };
|
||||||
|
|
||||||
use crate::framebuffer::RGBColor;
|
use crate::framebuffer::RGBColor;
|
||||||
|
|
||||||
#[derive(PartialEq, Default)]
|
#[derive(PartialEq, Default)]
|
||||||
@@ -7,6 +9,7 @@ pub enum Themes {
|
|||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct ThemeInfo {
|
pub struct ThemeInfo {
|
||||||
pub top: RGBColor,
|
pub top: RGBColor,
|
||||||
pub background: RGBColor,
|
pub background: RGBColor,
|
||||||
|
|||||||
@@ -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;
|
|
||||||
|
|
||||||
@@ -11,21 +11,17 @@ use linux_framebuffer::Framebuffer;
|
|||||||
use termion::input::TermRead;
|
use termion::input::TermRead;
|
||||||
use termion::raw::IntoRawMode;
|
use termion::raw::IntoRawMode;
|
||||||
use termion::cursor;
|
use termion::cursor;
|
||||||
|
use serde::{ Deserialize, Serialize };
|
||||||
|
|
||||||
use crate::framebuffer::{ FramebufferWriter, FramebufferInfo, Point, Dimensions, RGBColor };
|
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::themes::{ ThemeInfo, Themes, get_theme_info };
|
||||||
use crate::keyboard::{ KeyChar, key_to_char };
|
use crate::keyboard::{ KeyChar, key_to_char };
|
||||||
use crate::messages::*;
|
use crate::messages::*;
|
||||||
|
use crate::proxy_window_like::ProxyWindowLike;
|
||||||
use crate::window_likes::start_menu::StartMenu;
|
use crate::essential::desktop_background::DesktopBackground;
|
||||||
use crate::window_likes::minesweeper::Minesweeper;
|
use crate::essential::taskbar::Taskbar;
|
||||||
use crate::window_likes::terminal::Terminal;
|
use crate::essential::lock_screen::LockScreen;
|
||||||
use crate::window_likes::malvim::Malvim;
|
use crate::essential::workspace_indicator::WorkspaceIndicator;
|
||||||
use crate::window_likes::audio_player::AudioPlayer;
|
|
||||||
|
|
||||||
//todo, better error handling for windows
|
//todo, better error handling for windows
|
||||||
|
|
||||||
@@ -71,15 +67,15 @@ pub fn min(one: usize, two: usize) -> usize {
|
|||||||
if one > two { two } else { one }
|
if one > two { two } else { one }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub enum DrawInstructions {
|
pub enum DrawInstructions {
|
||||||
Rect(Point, Dimensions, RGBColor),
|
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),
|
Gradient(Point, Dimensions, RGBColor, RGBColor, usize),
|
||||||
Mingde(Point),
|
Mingde(Point),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum WindowLikeType {
|
pub enum WindowLikeType {
|
||||||
LockScreen,
|
LockScreen,
|
||||||
Window,
|
Window,
|
||||||
@@ -92,15 +88,18 @@ pub enum WindowLikeType {
|
|||||||
pub trait WindowLike {
|
pub trait WindowLike {
|
||||||
fn handle_message(&mut self, message: WindowMessage) -> WindowMessageResponse;
|
fn handle_message(&mut self, message: WindowMessage) -> WindowMessageResponse;
|
||||||
|
|
||||||
|
fn draw(&self, theme_info: &ThemeInfo) -> Vec<DrawInstructions>;
|
||||||
|
|
||||||
//properties
|
//properties
|
||||||
fn title(&self) -> &'static str {
|
fn title(&self) -> String {
|
||||||
""
|
String::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resizable(&self) -> bool {
|
fn resizable(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subtype(&self) -> WindowLikeType;
|
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
|
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) {
|
fn taskbar_update_windows(&mut self) {
|
||||||
let taskbar_index = self.window_infos.iter().position(|w| w.window_like.subtype() == WindowLikeType::Taskbar).unwrap();
|
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
|
relevant.sort_by(|a, b| a.0.cmp(&b.0)); //sort by ids so order is consistent
|
||||||
let message = WindowMessage::Info(InfoType::WindowsInWorkspace(
|
let message = WindowMessage::Info(InfoType::WindowsInWorkspace(
|
||||||
relevant,
|
relevant,
|
||||||
@@ -500,13 +499,13 @@ impl WindowManager {
|
|||||||
if subtype != WindowLikeType::Taskbar && subtype != WindowLikeType::StartMenu {
|
if subtype != WindowLikeType::Taskbar && subtype != WindowLikeType::StartMenu {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let w: WindowBox = match w {
|
let w: WindowBox = match w.as_str() {
|
||||||
"Minesweeper" => Box::new(Minesweeper::new()),
|
"Minesweeper" => Box::new(ProxyWindowLike::new("minesweeper")),
|
||||||
"Malvim" => Box::new(Malvim::new()),
|
"Malvim" => Box::new(ProxyWindowLike::new("malvim")),
|
||||||
"Terminal" => Box::new(Terminal::new()),
|
"Terminal" => Box::new(ProxyWindowLike::new("terminal")),
|
||||||
"Audio Player" => Box::new(AudioPlayer::new()),
|
"Audio Player" => Box::new(ProxyWindowLike::new("audio_player")),
|
||||||
"StartMenu" => Box::new(StartMenu::new()),
|
"StartMenu" => Box::new(ProxyWindowLike::new("start_menu")),
|
||||||
_ => panic!("no such window"),
|
_ => panic!("window not found"), //todo: do not panic
|
||||||
};
|
};
|
||||||
//close start menu if open
|
//close start menu if open
|
||||||
self.toggle_start_menu(true);
|
self.toggle_start_menu(true);
|
||||||
@@ -588,7 +587,7 @@ impl WindowManager {
|
|||||||
instructions = instructions.iter().map(|instruction| {
|
instructions = instructions.iter().map(|instruction| {
|
||||||
match instruction {
|
match instruction {
|
||||||
DrawInstructions::Rect(top_left, dimensions, color) => DrawInstructions::Rect(WindowManager::get_true_top_left(top_left, is_window), *dimensions, *color),
|
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::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),
|
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),
|
DrawInstructions::Rect([0, 0], [1, window_dimensions[1]], theme_info.border_left_top),
|
||||||
//top
|
//top
|
||||||
DrawInstructions::Rect([1, 1], [window_dimensions[0] - 2, WINDOW_TOP_HEIGHT - 3], theme_info.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
|
//top bottom border
|
||||||
DrawInstructions::Rect([1, WINDOW_TOP_HEIGHT - 2], [window_dimensions[0] - 2, 2], theme_info.border_left_top),
|
DrawInstructions::Rect([1, WINDOW_TOP_HEIGHT - 2], [window_dimensions[0] - 2, 2], theme_info.border_left_top),
|
||||||
//right bottom border
|
//right bottom border
|
||||||
@@ -632,7 +631,7 @@ impl WindowManager {
|
|||||||
window_writer.draw_rect(top_left, true_dimensions, color);
|
window_writer.draw_rect(top_left, true_dimensions, color);
|
||||||
},
|
},
|
||||||
DrawInstructions::Text(top_left, font_name, text, color, bg_color, horiz_spacing, mono_width) => {
|
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) => {
|
DrawInstructions::Mingde(top_left) => {
|
||||||
window_writer._draw_mingde(top_left);
|
window_writer._draw_mingde(top_left);
|
||||||
|
|||||||
Reference in New Issue
Block a user