beta 1: remove framebuffer crate, replace with own code, small fixes/features added
added some kanji, docs
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ming-wm"
|
name = "ming-wm"
|
||||||
version = "0.1.0"
|
version = "1.0.0-beta.0"
|
||||||
repository = "https://github.com/stjet/ming-wm"
|
repository = "https://github.com/stjet/ming-wm"
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
@@ -9,22 +9,23 @@ default-run = "ming"
|
|||||||
# 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
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
|
members = ["linux"]
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
bmp-rust = "0.4.1"
|
bmp-rust = "0.5.0"
|
||||||
blake2 = { version = "0.10.6", default-features = false }
|
blake2 = { version = "0.10.6", default-features = false }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ming-wm-lib = { path = "ming-wm-lib" }
|
ming-wm-lib = { path = "ming-wm-lib" }
|
||||||
blake2 = { version = "0.10.6", default-features = false }
|
blake2 = { version = "0.10.6", default-features = false }
|
||||||
linux_framebuffer = { package = "framebuffer", version = "0.3.1" }
|
linux = { path = "linux" }
|
||||||
termion = { version = "4.0.3", optional = true }
|
termion = { version = "4.0.3", optional = true }
|
||||||
rodio = { version = "0.19.0", optional = true }
|
rodio = { version = "0.19.0", optional = true }
|
||||||
rand = { version = "0.9.0", default-features = false, features = [ "small_rng" ], optional = true }
|
rand = { version = "0.9.0", default-features = false, features = [ "small_rng" ], optional = true }
|
||||||
id3 = { version = "1.10.0", optional = true }
|
id3 = { version = "1.10.0", optional = true }
|
||||||
mp4ameta = { version = "0.11.0", optional = true }
|
mp4ameta = { version = "0.11.0", optional = true }
|
||||||
metaflac = { version = "0.2.5", optional = true }
|
metaflac = { version = "0.2.5", optional = true }
|
||||||
bmp-rust = "0.4.1"
|
bmp-rust = "0.5.0"
|
||||||
pty-process = { version = "0.5.1", optional = true }
|
pty-process = { version = "0.5.1", optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|||||||
12
README.md
@@ -45,6 +45,8 @@ ming
|
|||||||
|
|
||||||
Type in the password to unlock. Open the start menu by doing `Alt+s`, and use the `j` and `k` keys to move up and down (like Vim), and press the `Enter` key to select a category / open a window.
|
Type in the password to unlock. Open the start menu by doing `Alt+s`, and use the `j` and `k` keys to move up and down (like Vim), and press the `Enter` key to select a category / open a window.
|
||||||
|
|
||||||
|
Usage for most of the included windows and window-likes are included in `docs/window-likes`, which can also be accessed from the "Help" entry in the start menu.
|
||||||
|
|
||||||
## Running on Mobile Linux
|
## Running on Mobile Linux
|
||||||
|
|
||||||
Running with an onscreen keyboard. The framebuffer may not be redrawn to the screen without a (real) key press. The volume down button seems to work.
|
Running with an onscreen keyboard. The framebuffer may not be redrawn to the screen without a (real) key press. The volume down button seems to work.
|
||||||
@@ -67,17 +69,11 @@ ming touch rotate
|
|||||||
|
|
||||||
See [/docs/philosophy.md](/docs/philosophy.md) for some hopefully interesting ramblings.
|
See [/docs/philosophy.md](/docs/philosophy.md) for some hopefully interesting ramblings.
|
||||||
|
|
||||||
## Documentation
|
## Developing Windows
|
||||||
|
|
||||||
### Developing Windows
|
|
||||||
|
|
||||||
[section incomplete]
|
|
||||||
|
|
||||||
Windows (may be called apps in other window managers) can be developed in any language, though it is easiest to do so in Rust because the `ming-wm-lib` crate can be used.
|
Windows (may be called apps in other window managers) can be developed in any language, though it is easiest to do so in Rust because the `ming-wm-lib` crate can be used.
|
||||||
|
|
||||||
### Window Usage
|
See [koxinga](https://github.com/stjet/koxinga) or `src/bin` for examples. The `docs` directory includes a [brief introduction to writing windows](docs/system/writing_windows.md). [incomplete] documentation on the architecture of ming-wm.
|
||||||
|
|
||||||
Usage for most of the included windows and window-likes are included in `docs/window-likes`, which can also be accessed from the "Help" entry in the start menu.
|
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
|
|
||||||
|
|||||||
BIN
bmps/nimbus-roman/é0.bmp
Normal file
|
After Width: | Height: | Size: 390 B |
BIN
bmps/nimbus-romono/é0.bmp
Normal file
|
After Width: | Height: | Size: 390 B |
BIN
bmps/nimbus-romono/𐘁0.bmp
Normal file
|
After Width: | Height: | Size: 438 B |
BIN
bmps/nimbus-romono/𐘂0.bmp
Normal file
|
After Width: | Height: | Size: 438 B |
BIN
bmps/nimbus-romono/𐘃0.bmp
Normal file
|
After Width: | Height: | Size: 438 B |
BIN
bmps/shippori-mincho/一5.bmp
Normal file
|
After Width: | Height: | Size: 142 B |
BIN
bmps/shippori-mincho/上1.bmp
Normal file
|
After Width: | Height: | Size: 582 B |
BIN
bmps/shippori-mincho/下0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/世0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/人0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/僕0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/冬0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/前0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/参0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/君0.bmp
Normal file
|
After Width: | Height: | Size: 582 B |
BIN
bmps/shippori-mincho/夏0.bmp
Normal file
|
After Width: | Height: | Size: 582 B |
BIN
bmps/shippori-mincho/夜0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/夢0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/心1.bmp
Normal file
|
After Width: | Height: | Size: 582 B |
BIN
bmps/shippori-mincho/愛0.bmp
Normal file
|
After Width: | Height: | Size: 582 B |
BIN
bmps/shippori-mincho/日1.bmp
Normal file
|
After Width: | Height: | Size: 406 B |
BIN
bmps/shippori-mincho/明0.bmp
Normal file
|
After Width: | Height: | Size: 582 B |
BIN
bmps/shippori-mincho/星0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/春0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/時0.bmp
Normal file
|
After Width: | Height: | Size: 582 B |
BIN
bmps/shippori-mincho/晴0.bmp
Normal file
|
After Width: | Height: | Size: 582 B |
BIN
bmps/shippori-mincho/月1.bmp
Normal file
|
After Width: | Height: | Size: 494 B |
BIN
bmps/shippori-mincho/未0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/来0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/機0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/水0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/白0.bmp
Normal file
|
After Width: | Height: | Size: 486 B |
BIN
bmps/shippori-mincho/真0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/眠0.bmp
Normal file
|
After Width: | Height: | Size: 582 B |
BIN
bmps/shippori-mincho/神0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/秋0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/線0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/色0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/花0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/行0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/赤0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/間0.bmp
Normal file
|
After Width: | Height: | Size: 582 B |
BIN
bmps/shippori-mincho/雨0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/電0.bmp
Normal file
|
After Width: | Height: | Size: 582 B |
BIN
bmps/shippori-mincho/青0.bmp
Normal file
|
After Width: | Height: | Size: 582 B |
BIN
bmps/shippori-mincho/音0.bmp
Normal file
|
After Width: | Height: | Size: 582 B |
BIN
bmps/shippori-mincho/飛0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
bmps/shippori-mincho/黒0.bmp
Normal file
|
After Width: | Height: | Size: 630 B |
6
build.rs
@@ -18,7 +18,7 @@ fn font_chars_to_alphas(dir: &str) {
|
|||||||
if file_name[1] == "bmp" {
|
if file_name[1] == "bmp" {
|
||||||
if !path.is_dir() {
|
if !path.is_dir() {
|
||||||
let mut ch: Vec<Vec<String>> = Vec::new();
|
let mut ch: Vec<Vec<String>> = Vec::new();
|
||||||
let b = BMP::new_from_file(&path.clone().into_os_string().into_string().unwrap());
|
let b = BMP::new_from_file(&path.clone().into_os_string().into_string().unwrap()).unwrap();
|
||||||
let dib_header = b.get_dib_header().unwrap();
|
let dib_header = b.get_dib_header().unwrap();
|
||||||
let width = dib_header.width as usize;
|
let width = dib_header.width as usize;
|
||||||
let height = dib_header.height as usize;
|
let height = dib_header.height as usize;
|
||||||
@@ -64,5 +64,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
//copy bmp folders to target
|
//copy bmp folders to target
|
||||||
let profile = env::var_os("PROFILE").unwrap().to_string_lossy().to_string();
|
let profile = env::var_os("PROFILE").unwrap().to_string_lossy().to_string();
|
||||||
Command::new("cp").arg("-r").arg("./bmps").arg(format!("./target/{}/bmps", profile)).output().unwrap();
|
Command::new("cp").arg("-r").arg("./bmps").arg(format!("./target/{}/ming_bmps", profile)).output().unwrap();
|
||||||
|
//also copy the docs folder
|
||||||
|
Command::new("cp").arg("-r").arg("./docs").arg(format!("./target/{}/ming_docs", profile)).output().unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
docs/images/window_example.png
Normal file
|
After Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 212 KiB After Width: | Height: | Size: 208 KiB |
|
Before Width: | Height: | Size: 914 KiB After Width: | Height: | Size: 948 KiB |
@@ -1 +0,0 @@
|
|||||||
//
|
|
||||||
108
docs/system/writing_windows.md
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
Though some windows (windows = apps, in ming-wm terminology) are built-in to the ming binary (eg, the help and about windows), most windows are separate binaries. This makes it possible for windows to be written in any language (though it will be far easier to write on in Rust because of the `ming-wm-lib` crate), and ensures that errors / crashes in the windows don't result in the window manager also crashing.
|
||||||
|
|
||||||
|
Some good examples are in `src/bin`. Another good example is the [Koxinga web browser](https://github.com/stjet/koxinga). All of these are written in Rust, though examples of windows written in other languages will be created later.
|
||||||
|
|
||||||
|
## Window Binary Discovery
|
||||||
|
|
||||||
|
The window manager automatically searches for window binaries and adds them to the start menu if:
|
||||||
|
|
||||||
|
- The binary is in the same directory as the ming binary.
|
||||||
|
- The binary file name is in the form `ming<Category>_<App_Name>`. Where `<Category>` is a category name in the start menu. For example, the Terminal binary is named `mingUtils_Terminal`.
|
||||||
|
|
||||||
|
## Inter-Process Communication (IPC)
|
||||||
|
|
||||||
|
Since the windows and the window manager are separate binaries, they need some way to communicate. This is achieved by the window manager spawning the window binary with piped stdout and piped stdin. See `src/proxy_window_like.rs` and `ming-wm-lib/src/ipc.rs` for more information.
|
||||||
|
|
||||||
|
The serialization format is in `ming-wm-lib/src/serialize.rs`. Make sure any newlines (`\n`) in strings are removed before/after serializations. When doing IPC, the window manager assumes the response to a query is one line, so if a newline is present, it will fail to parse the response.
|
||||||
|
|
||||||
|
## Hello, World!
|
||||||
|
|
||||||
|
A minimal example using `ming-wm-lib`.
|
||||||
|
|
||||||
|
`Cargo.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[package]
|
||||||
|
name = "example"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "mingMisc_Example"
|
||||||
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
ming-wm-lib = "0.1.3"
|
||||||
|
```
|
||||||
|
|
||||||
|
`src/main.rs`:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use std::vec::Vec;
|
||||||
|
use std::vec;
|
||||||
|
|
||||||
|
use ming_wm_lib::window_manager_types::{ DrawInstructions, WindowLike, WindowLikeType };
|
||||||
|
use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse };
|
||||||
|
use ming_wm_lib::framebuffer_types::Dimensions;
|
||||||
|
use ming_wm_lib::themes::ThemeInfo;
|
||||||
|
use ming_wm_lib::ipc::listen;
|
||||||
|
|
||||||
|
struct Example {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WindowLike for Example {
|
||||||
|
fn handle_message(&mut self, message: WindowMessage) -> WindowMessageResponse {
|
||||||
|
match message {
|
||||||
|
//placeholder
|
||||||
|
_ => WindowMessageResponse::DoNothing,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(&self, theme_info: &ThemeInfo) -> Vec<DrawInstructions> {
|
||||||
|
vec![DrawInstructions::Text([2, 2], vec!["nimbus-roman".to_string()], "Hello, World!".to_string(), theme_info.text, theme_info.background, None, None)]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn title(&self) -> String {
|
||||||
|
"Example".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subtype(&self) -> WindowLikeType {
|
||||||
|
WindowLikeType::Window
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ideal_dimensions(&self, _dimensions: Dimensions) -> Dimensions {
|
||||||
|
[410, 410]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resizable(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Example {
|
||||||
|
fn new() -> Self {
|
||||||
|
//doesn't do anything atm
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
listen(Example::new());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To install:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo build --release
|
||||||
|
mv target/release/mingMisc_Example /usr/bin/mingMisc_Example #or whatever directory the ming binary is in
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
- For windows that are separate binaries, the Elm Architecture obviously cannot be enforced (unless the window is written in Rust and uses the `ming-wm-lib`. However, the design of the IPC and the nature of the window manager being keyboard-driven makes it so using the Elm Architecture is highly recommended.
|
||||||
|
- Since the window manager currently queries and reads the responses to/from window binaries in the main thread, while the response is being waited for, the window manager is "frozen". Therefore, time-consuming tasks (>1 second) should not be done in the main thread, but rather a separate thread. For example, the ming-wm audio player (`src/bin/audio_player.rs`) does the time-consuming process of reading audio files in a separate thread to not hold up the window manager, and provide quick responses.
|
||||||
|
|
||||||
33
docs/window-likes/malvim.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
A text editor. Specifically, a subset of a vim.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
It is probably best to read a Vim tutorial for the basics. All supportd keystrokes should *mostly* behave the same as in Vim.
|
||||||
|
|
||||||
|
### Supported in Command-line Mode
|
||||||
|
|
||||||
|
- `e[dit]`
|
||||||
|
- `t[abe]`, `[tab]n`, `[tab]p`
|
||||||
|
- `q[uit]`
|
||||||
|
- `w[rite]`
|
||||||
|
|
||||||
|
### Supported in Normal Mode
|
||||||
|
|
||||||
|
- `:`
|
||||||
|
- `i`
|
||||||
|
- `A`
|
||||||
|
- `r`
|
||||||
|
- `dd`
|
||||||
|
- `dw`
|
||||||
|
- `G`
|
||||||
|
- `gg`
|
||||||
|
- `<number>gg`
|
||||||
|
- `f<char>`
|
||||||
|
- `F<char>`
|
||||||
|
- `x`
|
||||||
|
- `h`, `j`, `k`, `l`
|
||||||
|
- `0`, `^`, `$`
|
||||||
|
|
||||||
|
### Malvim Specific
|
||||||
|
|
||||||
|
In Command-line Mode, `autoindent` can be done to toggle auto-indenting (when making new line in Insert Mode [ie, by hitting Enter/Return], space indentation of the new line will be the same as the space indentation of the current line).
|
||||||
9
docs/window-likes/reversi.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
See [Wikipedia](https://en.wikipedia.org/wiki/Reversi) for the rules of the game.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Each square has a two-digit number on it. Type that number to place a piece on that square. If only one digit is typed, the backspace key can be hit to clear that digit. Black goes first.
|
||||||
|
|
||||||
|
Once the game is over, the winner (if it is not a tie) will be announced, and any key can be hit to play again.
|
||||||
|
|
||||||
|
There is currently no computer opponent, so this is a pass-and-play game.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
A basic, line-buffered, modal terminal.
|
A basic, modal terminal.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ In STDIN mode, any keys typed followed by the 'enter' key will send those keys t
|
|||||||
|
|
||||||
### Sudo
|
### Sudo
|
||||||
|
|
||||||
To get sudo to read from stdin, the `-S` option will need to be used (eg, `sudo -S ls`). Also, the password prompt will not show since the terminal is line-buffered. Just switch to STDIN mode, type in the password and hit enter.
|
To get sudo to read from stdin, the `-S` option will need to be used (eg, `sudo -S ls`). Then switch to STDIN mode, type in the password and hit enter.
|
||||||
|
|
||||||
## Copy / Paste
|
## Copy / Paste
|
||||||
|
|
||||||
|
|||||||
5
install
@@ -1,5 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
cp -r ./target/release/bmps /usr/local/bin/bmps
|
rm -rf /usr/local/bin/ming_bmps
|
||||||
|
cp -r ./bmps /usr/local/bin/ming_bmps
|
||||||
|
rm -rf /usr/local/bin/ming_docs
|
||||||
|
cp -r ./docs /usr/local/bin/ming_docs
|
||||||
cp ./target/release/ming /usr/local/bin/ming
|
cp ./target/release/ming /usr/local/bin/ming
|
||||||
cp ./target/release/mingUtils_Terminal /usr/local/bin/mingUtils_Terminal
|
cp ./target/release/mingUtils_Terminal /usr/local/bin/mingUtils_Terminal
|
||||||
cp ./target/release/mingGames_Reversi /usr/local/bin/mingGames_Reversi
|
cp ./target/release/mingGames_Reversi /usr/local/bin/mingGames_Reversi
|
||||||
|
|||||||
8
linux/Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "linux"
|
||||||
|
version = "0.1.0"
|
||||||
|
license = "GPL-3.0-or-later"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libc = "0.2"
|
||||||
146
linux/src/fb.rs
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
use std::fs::{ File, OpenOptions };
|
||||||
|
use std::os::fd::AsRawFd;
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
use libc::{ ioctl, mmap };
|
||||||
|
|
||||||
|
//https://stackoverflow.com/a/75402838
|
||||||
|
|
||||||
|
//https://github.com/torvalds/linux/blob/master/include/uapi/linux/fb.h
|
||||||
|
pub const FBIOGET_VSCREENINFO: u64 = 0x4600;
|
||||||
|
pub const FBIOGET_FSCREENINFO: u64 = 0x4602;
|
||||||
|
|
||||||
|
//https://www.kernel.org/doc/html/latest/fb/api.html
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct FB_BITFIELD {
|
||||||
|
offset: u32,
|
||||||
|
length: u32,
|
||||||
|
msb_right: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct FB_VAR_SCREENINFO {
|
||||||
|
pub xres: u32,
|
||||||
|
pub yres: u32,
|
||||||
|
pub xres_virtual: u32,
|
||||||
|
pub yres_virtual: u32,
|
||||||
|
pub xoffset: u32,
|
||||||
|
pub yoffset: u32,
|
||||||
|
pub bits_per_pixel: u32,
|
||||||
|
pub grayscale: u32,
|
||||||
|
pub red: FB_BITFIELD,
|
||||||
|
pub green: FB_BITFIELD,
|
||||||
|
pub blue: FB_BITFIELD,
|
||||||
|
pub transp: FB_BITFIELD,
|
||||||
|
pub nonstd: u32,
|
||||||
|
pub activate: u32,
|
||||||
|
pub height: u32,
|
||||||
|
pub width: u32,
|
||||||
|
pub accel_flags: u32,
|
||||||
|
pub pixclock: u32,
|
||||||
|
pub left_margin: u32,
|
||||||
|
pub right_margin: u32,
|
||||||
|
pub upper_margin: u32,
|
||||||
|
pub lower_margin: u32,
|
||||||
|
pub hsync_len: u32,
|
||||||
|
pub wsync_len: u32,
|
||||||
|
pub sync: u32,
|
||||||
|
pub vmode: u32,
|
||||||
|
pub rotate: u32,
|
||||||
|
pub colorspace: u32,
|
||||||
|
pub reserved: [u32; 4],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct FB_FIX_SCREENINFO {
|
||||||
|
pub id: [u8; 16],
|
||||||
|
pub smem_start: usize,
|
||||||
|
pub smem_len: u32,
|
||||||
|
pub r#type: u32,
|
||||||
|
pub type_aux: u32,
|
||||||
|
pub visual: u32,
|
||||||
|
pub xpanstep: u16,
|
||||||
|
pub ypanstep: u16,
|
||||||
|
pub ywrapstep: u16,
|
||||||
|
pub line_length: u32,
|
||||||
|
pub mmio_len: u32,
|
||||||
|
pub accel: u32,
|
||||||
|
pub capabilities: u16,
|
||||||
|
pub reserved: [u16; 2],
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Framebuffer {
|
||||||
|
pointer: *mut libc::c_void,
|
||||||
|
pub var_screen_info: FB_VAR_SCREENINFO,
|
||||||
|
pub fix_screen_info: FB_FIX_SCREENINFO,
|
||||||
|
size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Framebuffer {
|
||||||
|
pub fn open(path: &str) -> Result<Self, ()> {
|
||||||
|
let file = Framebuffer::open_file(path)?;
|
||||||
|
let vi = Framebuffer::get_vscreeninfo(file.as_raw_fd())?;
|
||||||
|
let fi = Framebuffer::get_fscreeninfo(file.as_raw_fd())?;
|
||||||
|
//then mmap or something
|
||||||
|
let size = vi.yres_virtual * fi.line_length * (vi.bits_per_pixel / 8);
|
||||||
|
let pointer = unsafe {
|
||||||
|
mmap(ptr::null_mut(), size.try_into().unwrap(), libc::PROT_READ | libc::PROT_WRITE, libc::MAP_SHARED, file.as_raw_fd(), 0)
|
||||||
|
};
|
||||||
|
if pointer == libc::MAP_FAILED {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
Ok(Self {
|
||||||
|
pointer,
|
||||||
|
var_screen_info: vi,
|
||||||
|
fix_screen_info: fi,
|
||||||
|
size: size as usize,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn open_file(path: &str) -> Result<File, ()> {
|
||||||
|
OpenOptions::new().read(true).write(true).open(path).map_err(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_vscreeninfo(raw_fd: i32) -> Result<FB_VAR_SCREENINFO, ()> {
|
||||||
|
let mut vi: FB_VAR_SCREENINFO = Default::default();
|
||||||
|
let result = unsafe {
|
||||||
|
ioctl(raw_fd, FBIOGET_VSCREENINFO, &mut vi)
|
||||||
|
};
|
||||||
|
if result != -1 {
|
||||||
|
Ok(vi)
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_fscreeninfo(raw_fd: i32) -> Result<FB_FIX_SCREENINFO, ()> {
|
||||||
|
let mut fi: FB_FIX_SCREENINFO = Default::default();
|
||||||
|
let result = unsafe {
|
||||||
|
ioctl(raw_fd, FBIOGET_FSCREENINFO, &mut fi)
|
||||||
|
};
|
||||||
|
if result != -1 {
|
||||||
|
Ok(fi)
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_frame(&mut self, frame: &[u8]) {
|
||||||
|
unsafe {
|
||||||
|
ptr::copy_nonoverlapping(frame.as_ptr(), self.pointer as *mut u8, frame.len());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Framebuffer {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
libc::munmap(self.pointer, self.size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
2
linux/src/lib.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod fb;
|
||||||
|
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
cp -r ./target/release/bmps ~/.local/bin/bmps
|
rm -rf ~/.local/bin/ming_bmps
|
||||||
|
cp -r ./bmps ~/.local/bin/ming_bmps
|
||||||
|
rm -rf ~/.local/bin/ming_docs
|
||||||
|
cp -r ./docs ~/.local/bin/ming_docs
|
||||||
cp ./target/release/ming ~/.local/bin/ming
|
cp ./target/release/ming ~/.local/bin/ming
|
||||||
cp ./target/release/mingUtils_Terminal ~/.local/bin/mingUtils_Terminal
|
cp ./target/release/mingUtils_Terminal ~/.local/bin/mingUtils_Terminal
|
||||||
cp ./target/release/mingGames_Reversi ~/.local/bin/mingGames_Reversi
|
cp ./target/release/mingGames_Reversi ~/.local/bin/mingGames_Reversi
|
||||||
|
|||||||
@@ -215,6 +215,8 @@ impl AudioPlayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
queue
|
queue
|
||||||
|
} else if parts[1].ends_with(".mp3") {
|
||||||
|
vec![concat_paths(&self.base_directory, parts[1]).unwrap()]
|
||||||
} else {
|
} else {
|
||||||
get_all_files(PathBuf::from(new_path))
|
get_all_files(PathBuf::from(new_path))
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -138,6 +138,10 @@ impl WindowLike for FileExplorer {
|
|||||||
let bytes_len = metadata.len();
|
let bytes_len = metadata.len();
|
||||||
instructions.push(DrawInstructions::Text([5, start_y], vec!["nimbus-roman".to_string()], format!("Size: {} mb ({} b)", bytes_len / (1024_u64).pow(2), bytes_len), theme_info.text, theme_info.background, None, None));
|
instructions.push(DrawInstructions::Text([5, start_y], vec!["nimbus-roman".to_string()], format!("Size: {} mb ({} b)", bytes_len / (1024_u64).pow(2), bytes_len), theme_info.text, theme_info.background, None, None));
|
||||||
start_y += HEIGHT;
|
start_y += HEIGHT;
|
||||||
|
if let Ok(elapsed) = metadata.modified().unwrap().elapsed() {
|
||||||
|
//properly format months, days, hours, minutes, secs instead
|
||||||
|
instructions.push(DrawInstructions::Text([5, start_y], vec!["nimbus-roman".to_string()], format!("Last Modified: {} minutes ago", elapsed.as_secs() / 60), theme_info.text, theme_info.background, None, None));
|
||||||
|
}
|
||||||
//todo: other stuff
|
//todo: other stuff
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use std::io::{ stdin, stdout, BufReader, BufRead, Write };
|
|||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
use linux_framebuffer::Framebuffer;
|
use linux::fb::Framebuffer;
|
||||||
use termion::input::TermRead;
|
use termion::input::TermRead;
|
||||||
use termion::raw::IntoRawMode;
|
use termion::raw::IntoRawMode;
|
||||||
use termion::{ clear, cursor };
|
use termion::{ clear, cursor };
|
||||||
@@ -162,7 +162,7 @@ fn init(framebuffer: Framebuffer, framebuffer_info: FramebufferInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let fb = Framebuffer::new("/dev/fb0").unwrap();
|
let fb = Framebuffer::open("/dev/fb0").unwrap();
|
||||||
let bytes_per_pixel = (fb.var_screen_info.bits_per_pixel as usize) / 8;
|
let bytes_per_pixel = (fb.var_screen_info.bits_per_pixel as usize) / 8;
|
||||||
let fb_info = FramebufferInfo {
|
let fb_info = FramebufferInfo {
|
||||||
byte_len: (fb.var_screen_info.yres_virtual * fb.fix_screen_info.line_length) as usize,
|
byte_len: (fb.var_screen_info.yres_virtual * fb.fix_screen_info.line_length) as usize,
|
||||||
|
|||||||
@@ -213,9 +213,9 @@ impl WindowLike for Malvim {
|
|||||||
} else {
|
} else {
|
||||||
//how does this work again? no idea
|
//how does this work again? no idea
|
||||||
if old_pos != 0 {
|
if old_pos != 0 {
|
||||||
let found_index = current_file.content[current_file.line_pos].chars().rev().skip(current_length - old_pos + 1).position(|c| c == key_press.key);
|
let found_index = current_file.content[current_file.line_pos].chars().rev().skip(current_length - old_pos).position(|c| c == key_press.key);
|
||||||
if let Some(found_index) = found_index {
|
if let Some(found_index) = found_index {
|
||||||
old_pos - found_index - 2
|
old_pos - found_index - 1
|
||||||
} else {
|
} else {
|
||||||
old_pos
|
old_pos
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::vec;
|
|||||||
use std::sync::mpsc::{ channel, Receiver, Sender };
|
use std::sync::mpsc::{ channel, Receiver, Sender };
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::process::{ Child, Stdio };
|
use std::process::{ Child, Stdio };
|
||||||
use std::io::{ BufReader, BufRead, Write };
|
use std::io::{ Read, Write };
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@@ -79,7 +79,8 @@ pub struct Terminal {
|
|||||||
current_stdin_input: String,
|
current_stdin_input: String,
|
||||||
current_path: String,
|
current_path: String,
|
||||||
running_process: Option<Child>,
|
running_process: Option<Child>,
|
||||||
pty_outerr_rx: Option<Receiver<String>>,
|
process_current_line: Vec<u8>, //bytes of line
|
||||||
|
pty_outerr_rx: Option<Receiver<u8>>,
|
||||||
pty_in_tx: Option<Sender<String>>,
|
pty_in_tx: Option<Sender<String>>,
|
||||||
last_command: Option<String>,
|
last_command: Option<String>,
|
||||||
}
|
}
|
||||||
@@ -126,8 +127,17 @@ impl WindowLike for Terminal {
|
|||||||
//update
|
//update
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
loop {
|
loop {
|
||||||
if let Ok(line) = self.pty_outerr_rx.as_mut().unwrap().recv_timeout(Duration::from_millis(5)) {
|
if let Ok(ci) = self.pty_outerr_rx.as_mut().unwrap().recv_timeout(Duration::from_millis(5)) {
|
||||||
self.lines.push(strip_ansi_escape_codes(line));
|
if char::from(ci) == '\n' {
|
||||||
|
let pcl_len = self.process_current_line.len();
|
||||||
|
self.lines.push(strip_ansi_escape_codes(String::from_utf8(self.process_current_line.clone()).unwrap_or("?".repeat(pcl_len))));
|
||||||
|
self.process_current_line = Vec::new();
|
||||||
|
} else if char::from(ci) == '\r' {
|
||||||
|
//for now, ignore
|
||||||
|
//
|
||||||
|
} else {
|
||||||
|
self.process_current_line.push(ci);
|
||||||
|
}
|
||||||
changed = true;
|
changed = true;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@@ -138,6 +148,7 @@ impl WindowLike for Terminal {
|
|||||||
//process exited
|
//process exited
|
||||||
self.pty_outerr_rx = None;
|
self.pty_outerr_rx = None;
|
||||||
self.mode = Mode::Input;
|
self.mode = Mode::Input;
|
||||||
|
self.process_current_line = Vec::new();
|
||||||
changed = true;
|
changed = true;
|
||||||
} else {
|
} else {
|
||||||
if key_press.key == 'i' {
|
if key_press.key == 'i' {
|
||||||
@@ -160,7 +171,10 @@ impl WindowLike for Terminal {
|
|||||||
//enter
|
//enter
|
||||||
let _ = self.pty_in_tx.as_mut().unwrap().send(self.current_stdin_input.clone());
|
let _ = self.pty_in_tx.as_mut().unwrap().send(self.current_stdin_input.clone());
|
||||||
self.mode = Mode::Running;
|
self.mode = Mode::Running;
|
||||||
|
let pcl_len = self.process_current_line.len();
|
||||||
|
self.lines.push(strip_ansi_escape_codes(String::from_utf8(self.process_current_line.clone()).unwrap_or("?".repeat(pcl_len))) + &self.current_stdin_input);
|
||||||
self.current_stdin_input = String::new();
|
self.current_stdin_input = String::new();
|
||||||
|
self.process_current_line = Vec::new();
|
||||||
} else if key_press.key == '𐘁' {
|
} else if key_press.key == '𐘁' {
|
||||||
//backspace
|
//backspace
|
||||||
if self.current_stdin_input.len() > 0 {
|
if self.current_stdin_input.len() > 0 {
|
||||||
@@ -285,11 +299,9 @@ impl Terminal {
|
|||||||
self.running_process = Some(blocking::Command::new("sh").arg("-c").arg(&self.current_input).current_dir(&self.current_path).stdin(Stdio::piped()).spawn(pts).unwrap());
|
self.running_process = Some(blocking::Command::new("sh").arg("-c").arg(&self.current_input).current_dir(&self.current_path).stdin(Stdio::piped()).spawn(pts).unwrap());
|
||||||
let (tx1, rx1) = channel();
|
let (tx1, rx1) = channel();
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let reader = BufReader::new(pty);
|
for ci in pty.bytes() {
|
||||||
for line in reader.lines() {
|
if let Ok(ci) = ci {
|
||||||
//panics too much
|
tx1.send(ci).unwrap();
|
||||||
if let Ok(line) = line {
|
|
||||||
tx1.send(line.to_string()).unwrap();
|
|
||||||
} else {
|
} else {
|
||||||
//the process has exited. dead process = dead pty = os input/output error
|
//the process has exited. dead process = dead pty = os input/output error
|
||||||
break;
|
break;
|
||||||
@@ -310,6 +322,7 @@ impl Terminal {
|
|||||||
});
|
});
|
||||||
self.pty_outerr_rx = Some(rx1);
|
self.pty_outerr_rx = Some(rx1);
|
||||||
self.pty_in_tx = Some(tx2);
|
self.pty_in_tx = Some(tx2);
|
||||||
|
self.process_current_line = Vec::new();
|
||||||
Mode::Running
|
Mode::Running
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -317,18 +330,20 @@ impl Terminal {
|
|||||||
fn calc_actual_lines(&mut self) {
|
fn calc_actual_lines(&mut self) {
|
||||||
self.actual_lines = Vec::new();
|
self.actual_lines = Vec::new();
|
||||||
let max_chars_per_line = (self.dimensions[0] - PADDING * 2) / MONO_WIDTH as usize;
|
let max_chars_per_line = (self.dimensions[0] - PADDING * 2) / MONO_WIDTH as usize;
|
||||||
let end = if self.mode != Mode::Running {
|
let lines_len = self.lines.len();
|
||||||
self.lines.len()
|
let end = if self.mode != Mode::Running || self.process_current_line.len() > 0 {
|
||||||
|
lines_len
|
||||||
} else {
|
} else {
|
||||||
self.lines.len() - 1
|
lines_len - 1
|
||||||
};
|
};
|
||||||
for line_num in 0..=end {
|
for line_num in 0..=end {
|
||||||
let mut working_line = if line_num == self.lines.len() {
|
let mut working_line = if line_num >= lines_len {
|
||||||
if self.mode == Mode::Input {
|
if self.mode == Mode::Input {
|
||||||
|
//must_add_current_line will be false
|
||||||
"$ ".to_string() + &self.current_input + "█"
|
"$ ".to_string() + &self.current_input + "█"
|
||||||
} else {
|
} else {
|
||||||
//Mode::Stdin
|
let pcl_len = self.process_current_line.len();
|
||||||
self.current_stdin_input.clone() + "█"
|
strip_ansi_escape_codes(String::from_utf8(self.process_current_line.clone()).unwrap_or("?".repeat(pcl_len))) + &self.current_stdin_input.clone() + "█"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.lines[line_num].clone()
|
self.lines[line_num].clone()
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use ming_wm_lib::window_manager_types::{ DrawInstructions, WindowLike, WindowLik
|
|||||||
use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse };
|
use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse };
|
||||||
use ming_wm_lib::framebuffer_types::Dimensions;
|
use ming_wm_lib::framebuffer_types::Dimensions;
|
||||||
use ming_wm_lib::themes::ThemeInfo;
|
use ming_wm_lib::themes::ThemeInfo;
|
||||||
|
use ming_wm_lib::dirs::exe_dir;
|
||||||
use crate::components::Component;
|
use crate::components::Component;
|
||||||
use crate::components::paragraph::Paragraph;
|
use crate::components::paragraph::Paragraph;
|
||||||
|
|
||||||
@@ -19,7 +20,7 @@ impl WindowLike for About {
|
|||||||
match message {
|
match message {
|
||||||
WindowMessage::Init(dimensions) => {
|
WindowMessage::Init(dimensions) => {
|
||||||
self.dimensions = dimensions;
|
self.dimensions = dimensions;
|
||||||
self.components.push(Box::new(Paragraph::new("help".to_string(), [2, 2], [self.dimensions[0] - 4, self.dimensions[1] - 4], read_to_string("docs/system/README.md").unwrap_or("docs/system/README.md not found".to_string()), ())));
|
self.components.push(Box::new(Paragraph::new("help".to_string(), [2, 2], [self.dimensions[0] - 4, self.dimensions[1] - 4], read_to_string(exe_dir(Some("ming_docs/system/README.md"))).unwrap_or("ming_docs/system/README.md not found".to_string()), ())));
|
||||||
WindowMessageResponse::JustRedraw
|
WindowMessageResponse::JustRedraw
|
||||||
},
|
},
|
||||||
WindowMessage::KeyPress(key_press) => {
|
WindowMessage::KeyPress(key_press) => {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
use ming_wm_lib::window_manager_types::{ DrawInstructions, WindowLike, WindowLikeType };
|
use ming_wm_lib::window_manager_types::{ DrawInstructions, WindowLike, WindowLikeType };
|
||||||
use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse };
|
use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse };
|
||||||
|
use ming_wm_lib::dirs::exe_dir;
|
||||||
use ming_wm_lib::framebuffer_types::Dimensions;
|
use ming_wm_lib::framebuffer_types::Dimensions;
|
||||||
use ming_wm_lib::themes::ThemeInfo;
|
use ming_wm_lib::themes::ThemeInfo;
|
||||||
use crate::components::paragraph::Paragraph;
|
use crate::components::paragraph::Paragraph;
|
||||||
@@ -40,8 +41,12 @@ impl WindowLike for Help {
|
|||||||
self.file_index += 1;
|
self.file_index += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if self.files.len() > 0 {
|
||||||
self.paragraph.as_mut().unwrap().new_text(read_to_string(self.files[self.file_index].clone()).unwrap());
|
self.paragraph.as_mut().unwrap().new_text(read_to_string(self.files[self.file_index].clone()).unwrap());
|
||||||
WindowMessageResponse::JustRedraw
|
WindowMessageResponse::JustRedraw
|
||||||
|
} else {
|
||||||
|
WindowMessageResponse::DoNothing
|
||||||
|
}
|
||||||
} else if self.paragraph.as_mut().unwrap().handle_message(WindowMessage::KeyPress(key_press)).is_some() {
|
} else if self.paragraph.as_mut().unwrap().handle_message(WindowMessage::KeyPress(key_press)).is_some() {
|
||||||
WindowMessageResponse::JustRedraw
|
WindowMessageResponse::JustRedraw
|
||||||
} else {
|
} else {
|
||||||
@@ -53,14 +58,17 @@ impl WindowLike for Help {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn draw(&self, theme_info: &ThemeInfo) -> Vec<DrawInstructions> {
|
fn draw(&self, theme_info: &ThemeInfo) -> Vec<DrawInstructions> {
|
||||||
let mut instructions = vec![DrawInstructions::Text([2, 2], vec!["nimbus-romono".to_string()], self.files[self.file_index].clone().file_name().unwrap().to_string_lossy().to_string(), theme_info.text, theme_info.background, Some(0), None)];
|
let mut instructions = Vec::new();
|
||||||
|
if self.files.len() > 0 {
|
||||||
|
instructions.push(DrawInstructions::Text([2, 2], vec!["nimbus-romono".to_string()], self.files[self.file_index].clone().file_name().unwrap().to_string_lossy().to_string(), theme_info.text, theme_info.background, Some(0), None));
|
||||||
|
}
|
||||||
instructions.extend(self.paragraph.as_ref().unwrap().draw(theme_info));
|
instructions.extend(self.paragraph.as_ref().unwrap().draw(theme_info));
|
||||||
instructions
|
instructions
|
||||||
}
|
}
|
||||||
|
|
||||||
//properties
|
//properties
|
||||||
fn title(&self) -> String {
|
fn title(&self) -> String {
|
||||||
"About".to_string()
|
"Help".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subtype(&self) -> WindowLikeType {
|
fn subtype(&self) -> WindowLikeType {
|
||||||
@@ -74,10 +82,13 @@ impl WindowLike for Help {
|
|||||||
|
|
||||||
impl Help {
|
impl Help {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut files = vec![PathBuf::from("docs/system/shortcuts.md")];
|
let mut files = Vec::new();
|
||||||
for entry in read_dir("docs/window-likes").unwrap() {
|
if let Ok(contents) = read_dir(exe_dir(Some("ming_docs/window-likes"))) {
|
||||||
|
files.push(exe_dir(Some("ming_docs/system/shortcuts.md")));
|
||||||
|
for entry in contents {
|
||||||
files.push(entry.unwrap().path());
|
files.push(entry.unwrap().path());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Self {
|
Self {
|
||||||
dimensions: [0, 0],
|
dimensions: [0, 0],
|
||||||
file_index: 0,
|
file_index: 0,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use crate::fs::{ ExeWindowInfos, get_all_executable_windows };
|
|||||||
use crate::components::Component;
|
use crate::components::Component;
|
||||||
use crate::components::highlight_button::HighlightButton;
|
use crate::components::highlight_button::HighlightButton;
|
||||||
|
|
||||||
static CATEGORIES: [&'static str; 9] = ["About", "Utils", "Games", "Editing", "Files", "Internet", "Misc", "Help", "Logout"];
|
static CATEGORIES: [&'static str; 9] = ["About", "Utils", "Games", "Editing", "Files", "Internet", "Misc", "Help", "Lock"];
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum StartMenuMessage {
|
enum StartMenuMessage {
|
||||||
@@ -109,7 +109,7 @@ impl WindowLike for StartMenu {
|
|||||||
//background
|
//background
|
||||||
DrawInstructions::Rect([0, 1], [self.dimensions[0] - 1, self.dimensions[1] - 1], theme_info.background),
|
DrawInstructions::Rect([0, 1], [self.dimensions[0] - 1, self.dimensions[1] - 1], theme_info.background),
|
||||||
//mingde logo
|
//mingde logo
|
||||||
DrawInstructions::Bmp([2, 2], exe_dir(Some("bmps/mingde.bmp")).to_string_lossy().to_string(), false),
|
DrawInstructions::Bmp([2, 2], exe_dir(Some("ming_bmps/mingde.bmp")).to_string_lossy().to_string(), false),
|
||||||
//I truly don't know why, it should be - 44 but - 30 seems to work better :shrug:
|
//I truly don't know why, it should be - 44 but - 30 seems to work better :shrug:
|
||||||
DrawInstructions::Gradient([2, 42], [40, self.dimensions[1] - 30], [255, 201, 14], [225, 219, 77], 15),
|
DrawInstructions::Gradient([2, 42], [40, self.dimensions[1] - 30], [255, 201, 14], [225, 219, 77], 15),
|
||||||
];
|
];
|
||||||
@@ -138,7 +138,7 @@ impl StartMenu {
|
|||||||
if let Some(message) = message {
|
if let Some(message) = message {
|
||||||
match message {
|
match message {
|
||||||
StartMenuMessage::CategoryClick(name) => {
|
StartMenuMessage::CategoryClick(name) => {
|
||||||
if name == "Logout" {
|
if name == "Lock" {
|
||||||
WindowMessageResponse::Request(WindowManagerRequest::Lock)
|
WindowMessageResponse::Request(WindowManagerRequest::Lock)
|
||||||
} else if name == "About" || name == "Help" {
|
} else if name == "About" || name == "Help" {
|
||||||
//todo above: also do the same for Help
|
//todo above: also do the same for Help
|
||||||
|
|||||||
@@ -249,6 +249,7 @@ impl FramebufferWriter {
|
|||||||
//reverse is workaround for when my bmp lib returns rgba instead of bgra
|
//reverse is workaround for when my bmp lib returns rgba instead of bgra
|
||||||
pub fn draw_bmp(&mut self, top_left: Point, path: String, reverse: bool) {
|
pub fn draw_bmp(&mut self, top_left: Point, path: String, reverse: bool) {
|
||||||
let b = BMP::new_from_file(&path);
|
let b = BMP::new_from_file(&path);
|
||||||
|
if let Ok(b) = b {
|
||||||
let dib_header = b.get_dib_header().unwrap();
|
let dib_header = b.get_dib_header().unwrap();
|
||||||
let pixel_data = b.get_pixel_data().unwrap();
|
let pixel_data = b.get_pixel_data().unwrap();
|
||||||
let height = dib_header.height as usize;
|
let height = dib_header.height as usize;
|
||||||
@@ -263,5 +264,6 @@ impl FramebufferWriter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ fn get_font_char(dir: &str, c: char) -> Option<(char, Vec<Vec<u8>>, u8)> {
|
|||||||
|
|
||||||
pub fn get_font_char_from_fonts(fonts: &[String], c: char) -> (char, Vec<Vec<u8>>, u8) {
|
pub fn get_font_char_from_fonts(fonts: &[String], c: char) -> (char, Vec<Vec<u8>>, u8) {
|
||||||
for font in fonts {
|
for font in fonts {
|
||||||
let p = dirs::exe_dir(Some(&("bmps/".to_string() + &font))).to_string_lossy().to_string();
|
let p = dirs::exe_dir(Some(&("ming_bmps/".to_string() + &font))).to_string_lossy().to_string();
|
||||||
if let Some(font_char) = get_font_char(&p, c) {
|
if let Some(font_char) = get_font_char(&p, c) {
|
||||||
return font_char;
|
return font_char;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let p = dirs::exe_dir(Some(&("bmps/".to_string() + &fonts[0]))).to_string_lossy().to_string();
|
let p = dirs::exe_dir(Some(&("ming_bmps/".to_string() + &fonts[0]))).to_string_lossy().to_string();
|
||||||
//so a ? char must be in every font
|
//so a ? char must be in every font
|
||||||
get_font_char(&p, '?').unwrap()
|
get_font_char(&p, '?').unwrap()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ use std::cell::RefCell;
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
use linux_framebuffer::Framebuffer;
|
use linux::fb::Framebuffer;
|
||||||
|
|
||||||
use ming_wm_lib::framebuffer_types::{ Point, Dimensions };
|
use ming_wm_lib::framebuffer_types::{ Point, Dimensions };
|
||||||
use ming_wm_lib::themes::{ Themes, get_theme_info };
|
use ming_wm_lib::themes::{ Themes, get_theme_info };
|
||||||
use ming_wm_lib::utils::{ min, point_inside };
|
use ming_wm_lib::utils::{ min, point_inside };
|
||||||
|
|||||||