Files
ming-wm/docs/system/writing_windows.md
stjet fa4627316d v1.0.2: arrow keys, start menu paging support
key press convenience methods, fix logo, docs, add more chars
2025-03-23 21:41:59 +00:00

4.4 KiB

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. 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:

[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:

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:

cargo build --release
mv target/release/mingMisc_Example /usr/bin/mingMisc_Example #or whatever directory the ming binary is in

The example Hello World window!

Now what?

Handle various inputs in handle_message, and have it mutate the state. Draw the relevant state in draw. Not too hard, eh?

Besides looking at the examples (Koxinga, src/bin), read the ming-wm-lib docs!

Also, docs/system/keys.md may be useful.

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.
  • Window panics will be logged to ~/.local/share/ming-wm/logs.txt.