3.7 KiB
3.7 KiB
Planning: Sing-box Windows Tray Controller in Jai
We will implement a lightweight, headless Windows tray application in the Jai language to control the sing-box core.
1. Core Architecture
The application will run with a hidden/message-only window to remain headless, handling tray interaction, background updates, and process management.
graph TD
A[Main Loop / Hidden Window] --> B[System Tray Icon]
B -->|Right Click| C[Context Menu]
C -->|Set URL| D[Custom Edit Dialog]
C -->|Start/Stop| E[Process Manager: sing-box.exe]
C -->|Update Now| F[Auto-Update Loop: libcurl]
C -->|Exit| G[Shutdown & Cleanup]
F -->|Timer/Thread| F
2. Component Design
A. Headless Window & System Tray Icon
- Win32 Window: We register a window class and create a hidden utility window using
CreateWindowExW. This window serves as the message receiver. - Tray Icon: We register a system tray icon via
Shell_NotifyIconW(usingNOTIFYICONDATAW). - Events: We define a custom window message
WM_TRAY_CALLBACK(WM_USER + 1). When the tray icon receives input (e.g. mouse clicks), Windows sendsWM_TRAY_CALLBACKto our hidden window. - Context Menu: On
WM_RBUTTONUP(right click) orWM_LBUTTONUP(left click) over the tray icon, we load a dynamic popup menu usingCreatePopupMenu,AppendMenuW, andTrackPopupMenu.
B. Custom Modal Dialog (Set URL)
To avoid needing an external resource compiler (.rc) or complex UI libraries, we will implement a clean, lightweight modal window:
- Dialog Window: A popup window using
WS_POPUP | WS_CAPTION | WS_SYSMENUcentered on screen. - Controls:
- A static label: "Enter Sing-box Config URL:"
- An edit control (
EDITwindow class) to input the URL. - An OK button and a Cancel button (
BUTTONwindow class).
- Behavior: Block interactions with other menus, read the edit text on OK, write it to a
url.txtfile, and trigger an immediate config update.
C. Config Downloader (Auto-Update Engine)
- Curl Library: Use the standard
Curlmodule to perform HTTP requests. - Storage: Save the downloaded JSON content to
config.jsonin the same directory as the executable. - Auto-Update Thread: Spawn a background thread (using
Threadmodule) that sleeps for a set interval (e.g., 1 hour), then downloads the URL. If the file content changes, it updatesconfig.jsonand restarts thesing-boxprocess if it was running.
D. Process Management (sing-box.exe)
- Process Spawning: Use the standard
Processmodule'screate_processto run:sing-box.exe run -c config.json - Job Object: Windows processes started via
create_processwill be assigned to a Job Object withJOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE. This ensuressing-box.exeautomatically shuts down when the controller application is closed. - Status Checking: Use
get_process_resultwith 0 timeout to check if sing-box is actively running.
3. Implementation Steps
main.jai: Core application entry point, hidden window loop, tray icon management.dialog.jai: Edit-box dialog for config URL input.updater.jai: Libcurl wrapper and background auto-update thread.build.jai: Jai build script (metaprogram) to compile the app without standard console window popup (using-subsystem windows).
4. Key Questions & Decisions
- Tray Icon: Do we need a default/builtin icon? Yes, we will use a standard Windows system icon (like
IDI_APPLICATIONorIDI_SHIELD) so that the application works out-of-the-box without requiring an external.icoasset. - sing-box Location: We will assume
sing-box.exeis in the same directory as the controller. If not found there, we will search the system PATH.