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] [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"] }

View File

@@ -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());
}

View File

@@ -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();

View File

@@ -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());
}

View File

@@ -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());
}

View File

@@ -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());
}

View File

@@ -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
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![ 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),
] ]
} }
} }

View File

@@ -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,

View File

@@ -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
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) => { 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)

View File

@@ -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
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::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
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; 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,

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::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);