139 lines
7.5 KiB
Markdown
139 lines
7.5 KiB
Markdown
# mcap
|
|
|
|
A bare [Dear ImGui](https://github.com/ocornut/imgui) (docking branch) desktop application
|
|
written in [Jai](https://jai.community), for Windows, macOS and Linux: the window, the frame loop
|
|
and everything around them, ready for an app to be written into `src/app/app_ui.jai`.
|
|
|
|
## What you get
|
|
|
|
- **Native rendering per platform.** Win32 + Direct3D 11 on Windows; SDL3 + SDL_GPU (Metal on
|
|
macOS, Vulkan on Linux) elsewhere. On Windows the window comes up on a WARP device in a few
|
|
milliseconds while the hardware device is created on a thread, then moves across; a lost
|
|
device is recovered.
|
|
- **Docking and multi-viewport ImGui**, with a default layout (`assets/data/default_imgui.ini`)
|
|
and a Reset Layout hotkey.
|
|
- **One instance.** Launching the app again brings the running one forward, over a shared
|
|
memory channel (a file lock decides the owner on macOS and Linux).
|
|
- **Tray / menu bar.** Closing or minimizing hides the window to the tray; the tray icon brings
|
|
it back or quits.
|
|
- **Hotkeys** from a `[hotkeys]` section of the settings file, and **global hotkeys**
|
|
(`[global_hotkeys]`: Windows and macOS) that work while another app is in front.
|
|
- **A settings file** (`settings.config`) that is written with every key listed, reloaded as
|
|
soon as it is saved, and merged rather than overwritten when the app saves to it.
|
|
- **Themes**: built-ins, 36 shipped `.theme` files, and a theme editor that saves new ones.
|
|
- **Logging** through a multi-producer, single-consumer queue to a per-version log file and an
|
|
in-app Event Log, plus crash reports.
|
|
- **Debug panels**: frame times, memory, renderer, fonts (Ctrl+Shift+D, Ctrl+Shift+1).
|
|
- **DPI awareness**, live resize that keeps drawing, CJK font fallback from the system fonts.
|
|
- **Background shutdown**: closing hands the remaining work to a thread while the window shows
|
|
progress, so it never looks hung.
|
|
- **Asynchronous tests**, compiled into debug builds and run with `run_tests`.
|
|
|
|
## Building
|
|
|
|
Requires the Jai compiler, beta 0.2.030 or later.
|
|
|
|
```
|
|
jai first.jai # debug build
|
|
jai first.jai - release # release build
|
|
jai first.jai - full_release # debug and release
|
|
jai first.jai - release compile_tests # release build with the test suite
|
|
```
|
|
|
|
Binaries are written to `bin/`, with `assets/` copied beside them.
|
|
|
|
| Platform | Output | Notes |
|
|
| --- | --- | --- |
|
|
| Windows | `bin/mcap-debug.exe`, `bin/mcap.exe` | The release build gets the icon and a manifest, and no console. |
|
|
| macOS | `bin/mcap-macos-debug`, `bin/mcap.app` | Apple silicon (arm64) only, with a native `jai`. The release build is an ad hoc signed `.app`. |
|
|
| Linux | `bin/mcap-linux-debug`, `bin/mcap-linux` | Needs SDL3 installed (`libSDL3.so`). |
|
|
|
|
`jai check_targets.jai - linux` type-checks the Linux build from any OS without linking it.
|
|
The macOS check only works on a Mac, since the Objective-C module runs code at compile time.
|
|
|
|
Run any build with `run_tests` to run the test suites (debug builds include them),
|
|
`-allow-multiple-instances` to skip the single-instance check, or `-version`.
|
|
|
|
For unattended runs (scripts, CI, agents), add `-headless`: the app exits once the tests finish,
|
|
with exit code 0 if every suite passed and 1 otherwise, and a failed assertion or runtime check
|
|
is written to stderr, the log and the crash report and exits with 1 instead of opening a message
|
|
box (`runtime_support_headless` in `modules/Runtime_Support.jai`):
|
|
|
|
```
|
|
bin/mcap-debug.exe run_tests -headless -allow-multiple-instances > test-output.txt
|
|
```
|
|
|
|
`jai first.jai - no_crash_dialog [...]` makes builds for automation: `NO_CRASH_DIALOG` makes them
|
|
headless whatever their arguments, and everything they build goes to `bin-headless/` instead of
|
|
`bin/`, so an automated build never writes over the one you run by hand.
|
|
|
|
## Starting a new app
|
|
|
|
```
|
|
jai fork.jai - <output_directory> <app_name> [-folder <name>] [-bundle-id <id>] [-version <x.y.z>] [-git] [-build]
|
|
jai fork.jai - ../my-cool-app "My Cool App" -git -build
|
|
```
|
|
|
|
This copies the template (without `bin/`, `.build/`, `.git/` or `fork.jai`) and sets the names
|
|
below in the copy. The folder name defaults to the app name in lowercase with spaces as `-`
|
|
(`my-cool-app`), the bundle identifier to `com.example.<folder without dashes>`, and the version
|
|
to `0.0.0`. `-git` initializes a repository and commits the copy; `-build` makes a debug build. It also
|
|
writes `<app_name>.focus-config`, a [focus](https://focus-editor.dev) project with the build and
|
|
run commands, which stays out of git since it holds this machine's paths.
|
|
|
|
## Making it your app
|
|
|
|
1. Name it at the top of `first.jai`, or let `fork.jai` do it: `APP_NAME` (window title, tray,
|
|
macOS bundle), `APP_FOLDER_NAME` (executable and data folder; one short lowercase word),
|
|
`APP_BUNDLE_IDENTIFIER` and `VERSION`.
|
|
2. Replace `assets/images/icon.png` (any square size; it becomes the `.exe`, `.app` and window
|
|
icon) and the tray icons `tray_icon.ico` (Windows) and `tray_icon.png`.
|
|
3. Write the app in `src/app/app_ui.jai`: `app_ui_startup` runs once, `app_ui_frame_start` every
|
|
frame before input, `app_main_window_ui` draws, and `app_ui_shutdown` runs on the shutdown
|
|
thread.
|
|
|
|
To add a hotkey, declare a `Hotkey` in `src/ui/imgui_keyboard.jai`, add it to
|
|
`hotkey_actions_build` and `app_check_key_combinations`, bind it in both
|
|
`assets/data/default_hotkeys*.config` files (the build fails if a default leaves an action
|
|
unbound), and raise `APP_USER_SETTINGS_VERSION` in `src/App.jai` so existing settings files get
|
|
the new default.
|
|
|
|
To add a setting, add it to `App_User_Settings`, `Settings_Seen`, `settings_parse` and
|
|
`app_save_user_settings_file` in `src/ui/imgui_theme_registry.jai`.
|
|
|
|
## Layout
|
|
|
|
```
|
|
first.jai build: workspaces, build constants, Windows icon/manifest, macOS .app
|
|
fork.jai copy the template to a new, named project
|
|
check_targets.jai type-check another OS's build
|
|
src/App.jai loads everything; global state (app, platform, perf)
|
|
src/app/ main loop, your UI, background shutdown
|
|
src/base/ logging, fonts, debug panels, platform layers (base/platform/)
|
|
src/ui/ ImGui setup, hotkeys, themes and settings, toasts
|
|
src/graphics/DX11.jai Direct3D 11 device, WARP-first startup, device-loss recovery
|
|
src/backends/ ImGui's SDL_GPU backend; src/freetype/: ImGui's FreeType loader
|
|
assets/ fonts, icons, default hotkeys, default layout, themes
|
|
modules/ Basic (with arenas), Thread, Shared_Memory_Channel, File_Watcher,
|
|
Secure_Memory, XDG, sdl3, imgui-sdl, imgui-dx11-win32, imgui-source
|
|
```
|
|
|
|
## Files at run time
|
|
|
|
| File | Location |
|
|
| --- | --- |
|
|
| `settings.config`, `imgui.ini`, user themes | `%APPDATA%\<APP_FOLDER_NAME>` on Windows, `~/Library/Application Support/<APP_FOLDER_NAME>` on macOS, `~/.local/share/<APP_FOLDER_NAME>` on Linux |
|
|
| Logs | `logs/<version>/` next to the executable (next to the `.app` on macOS) |
|
|
| Shipped themes | `data/themes/` next to the executable |
|
|
|
|
## Platform notes
|
|
|
|
- Global hotkeys are not implemented on Linux (Wayland has no API for them). A desktop
|
|
shortcut that launches the executable has the same effect, since a second launch brings the
|
|
running instance forward.
|
|
- On XFCE the tray icon stays after the window is restored.
|
|
- `Secure_Memory` (used by `Basic`'s arenas to wipe memory) is built without libsodium; see the
|
|
note at the top of `modules/Secure_Memory/module.jai` if your app keeps secrets in memory.
|
|
|
|
Uses https://github.com/overlord-systems/jai-imgui as a template.
|