flowchart LR
subgraph JS["JavaScript Runtime"]
JSAPI["window.lepusBridge / window.lepusApi"]
end
subgraph MB["MoonBit Runtime"]
WV["WebView"]
PL["PluginHost + CommandRouter"]
WM["WindowManager (IPC)"]
APP["Managed App (parent/child)"]
end
subgraph NATIVE["Native Layer"]
STUB["stub.c + binding.mbt"]
LIB["webview C library"]
end
JSAPI <-->|"Command request/response"| PL
PL <-->|"Cross-process command/event"| WM
APP --> WM
PL --> WV
WV --> STUB --> LIB.titlebar {
-webkit-app-region: drag;
}
.titlebar button {
-webkit-app-region: no-drag;
}moon build --target native example
moon run --target native example///|
fn main {
let win = @webview.Window(title="Lepus WebView", width=960, height=640)
win.set_html("<html><body><h1>Hello from MoonBit</h1></body></html>")
win.run()
}moon check
moon test --target native
moon build --target native#external
pub type BindingHandletype CommandBridge[X]pub struct IpcMessage {
source_window_id : Int
target_window_id : Int
message_type : IpcMessageType
message_id : Int
subtype : String
data : String
}pub struct Plugin {
name : String
install_scripts : Array[String]
parent_installers : Array[(ProcessPluginRouter) -> Unit]
child_installers : Array[(PluginContext[Unit], ProcessCommandProxy) -> Unit]
direct_installers : Array[(PluginContext[Unit]) -> Unit]
}pub fn plugin() -> @webview.Plugin {
@webview.Plugin("math", fn(plugin) {
plugin.command("sum", fn(payload : SumPayload) {
SumReply{ total: payload.left + payload.right }
})
})
}#alias(new, deprecated="Use `Plugin()` instead")
fn Plugin::Plugin(name : String, register : (PluginBuilder) -> Unit) -> Pluginpub struct PluginBuilder {
plugin_name : String
install_scripts : Array[String]
parent_installers : Array[(ProcessPluginRouter) -> Unit]
child_installers : Array[(PluginContext[Unit], ProcessCommandProxy) -> Unit]
direct_installers : Array[(PluginContext[Unit]) -> Unit]
}fn[Payload : FromJson + ToJson, Reply : FromJson + ToJson] PluginBuilder::command(self : PluginBuilder, api_name : String, callback : async (Payload) -> Reply) -> Unitfn[Payload : FromJson + ToJson, Reply : FromJson + ToJson] PluginBuilder::command_result_async(self : PluginBuilder, api_name : String, callback : async (Payload) -> Reply) -> Unitfn[Payload : FromJson + ToJson, Reply : FromJson + ToJson] PluginBuilder::command_sync(self : PluginBuilder, api_name : String, callback : (Payload) -> Reply) -> Unittype PluginContext[X]fn[X, Payload : FromJson, Reply : ToJson] PluginContext::command_async(self : PluginContext[X], api_name : String, callback : async (Payload) -> Reply) -> Unitfn[X, Payload : FromJson, Reply : ToJson] PluginContext::command_result_async(self : PluginContext[X], api_name : String, callback : async (Payload) -> Reply) -> Unitfn[X, Payload : FromJson, Reply : ToJson] PluginContext::command_result_bg(self : PluginContext[X], api_name : String, callback : (Payload) -> Reply raise) -> Unitfn[X, Payload : FromJson, Reply : ToJson] PluginContext::command_sync(self : PluginContext[X], api_name : String, callback : (Payload) -> Reply) -> Unitfn[X] PluginContext::install_command_api(self : PluginContext[X], api_name : String, register : (String) -> Unit) -> Unittype PluginHost[X]#alias(new, deprecated="Use `PluginHost()` instead")
fn[X] PluginHost::PluginHost(webview : WebView[X], global_name? : String) -> PluginHost[X]fn PluginHost::install(self : PluginHost[Unit], plugin : Plugin, proxy? : ProcessCommandProxy?) -> Unitfn[Payload : ToJson, Reply : FromJson] ProcessCommandProxy::call(self : ProcessCommandProxy, name : String, payload : Payload, target_window_id? : Int, timeout_ms? : Int) -> Reply raise ProcessCommandErrorfn[Payload : ToJson, Reply : FromJson] ProcessCommandProxy::call_plugin(self : ProcessCommandProxy, plugin_name : String, api_name : String, payload : Payload, target_window_id? : Int, timeout_ms? : Int) -> Reply raise ProcessCommandErrorfn ProcessCommandProxy::new(wm : WindowManager, source_window_id : Int, subtype? : String) -> ProcessCommandProxyfn[Payload : ToJson, Reply : FromJson] ProcessCommandProxy::plugin_handler(self : ProcessCommandProxy, plugin_name : String, api_name : String, target_window_id? : Int, timeout_ms? : Int) -> ((Payload) -> Reply raise)fn ProcessCommandReplyForTest::from_json(Json, JsonPath) -> ProcessCommandReplyForTest raise JsonDecodeErrorfn[Payload : ToJson] ProcessCommandRequest::new(name : String, payload : Payload) -> ProcessCommandRequestfn[Reply : FromJson] ProcessCommandResponse::decode_reply(self : ProcessCommandResponse) -> Reply raise ProcessCommandErrorfn ProcessCommandResponse::from_json(Json, JsonPath) -> ProcessCommandResponse raise JsonDecodeErrorasync fn ProcessCommandRouter::dispatch(self : ProcessCommandRouter, request : ProcessCommandRequest) -> ProcessCommandResponsefn[Payload : FromJson, Reply : ToJson] ProcessCommandRouter::handle(self : ProcessCommandRouter, name : String, callback : (Payload) -> Reply) -> Unitfn[Payload : FromJson, Reply : ToJson] ProcessCommandRouter::handle_async(self : ProcessCommandRouter, name : String, callback : async (Payload) -> Reply) -> Unitfn[Payload : FromJson, Reply : ToJson] ProcessCommandRouter::handle_result(self : ProcessCommandRouter, name : String, callback : (Payload) -> Reply raise) -> Unitfn[Payload : FromJson, Reply : ToJson] ProcessCommandRouter::handle_result_async(self : ProcessCommandRouter, name : String, callback : async (Payload) -> Reply) -> Unitfn ProcessCommandRouter::plugin(self : ProcessCommandRouter, plugin_name : String, register : (ProcessPluginRouter) -> Unit) -> Unitasync fn ProcessCommandRouter::serve(self : ProcessCommandRouter, wm : WindowManager, child_pid : Int, subtype? : String) -> Unitfn[Payload : FromJson, Reply : ToJson] ProcessPluginRouter::command(self : ProcessPluginRouter, api_name : String, callback : (Payload) -> Reply) -> Unitfn[Payload : FromJson, Reply : ToJson] ProcessPluginRouter::command_async(self : ProcessPluginRouter, api_name : String, callback : async (Payload) -> Reply) -> Unitfn[Payload : FromJson, Reply : ToJson] ProcessPluginRouter::command_result(self : ProcessPluginRouter, api_name : String, callback : (Payload) -> Reply raise) -> Unitfn[Payload : FromJson, Reply : ToJson] ProcessPluginRouter::command_result_async(self : ProcessPluginRouter, api_name : String, callback : async (Payload) -> Reply) -> Unittype WebView[X]let webview = @webview.WebView::new_managed(task_group)
webview.set_title("My WebView")
webview.set_size(800, 600, @webview.SizeHint::None)
webview.set_html("<html><body><h1>Hello, World!</h1></body></html>")
webview.terminate()let webview = @webview.WebView::new_managed(task_group)
webview.navigate("https://www.example.com")
webview.navigate("data:text/html,<h1>Hello</h1>")
webview.terminate()let webview = @webview.WebView::new_managed(task_group)
webview.set_html("<html><body><h1>Hello, World!</h1></body></html>")
webview.terminate()fn[X] WebView::set_window_customization(self : WebView[X], frameless : Bool, resizable : Bool, closeable : Bool, always_on_top : Bool, transparent : Bool, title_bar_style : TitleBarStyle, title_bar_overlay : Bool) -> Unit#external
pub type WebView_tpub struct Window {
title : String
width : Int
height : Int
size_hint : SizeHint
debug : Int
devtools : Bool
child_arg : String
frameless : Bool
resizable : Bool
closeable : Bool
always_on_top : Bool
transparent : Bool
title_bar_style : TitleBarStyle
title_bar_overlay : Bool
traffic_light_position : (Int, Int)
enable_window_controls_plugin : Bool
url : String
html : String
pending_custom_protocols : Array[(String, String)]
runtime_window_id : Int
plugins : Array[Plugin]
}#alias(new, deprecated="Use `Window()` instead")
fn Window::Window(title? : String, url? : String, width? : Int, height? : Int, size_hint? : SizeHint, debug? : Int, devtools? : Bool, child_arg? : String, frameless? : Bool, resizable? : Bool, closeable? : Bool, always_on_top? : Bool, transparent? : Bool, title_bar_style? : TitleBarStyle, title_bar_overlay? : Bool, traffic_light_position? : (Int, Int), enable_window_controls_plugin? : Bool) -> Windowfn Window::set_window_customization(self : Window, frameless : Bool, resizable : Bool, closeable : Bool, always_on_top : Bool, transparent : Bool, title_bar_style : TitleBarStyle, title_bar_overlay : Bool) -> Unitfn WindowManager::broadcast(self : WindowManager, source_window_id : Int, subtype : String, data : String) -> Intfn WindowManager::create_child_window(_self : WindowManager, title : String, url : String, width? : Int, height? : Int, parent_id? : Int) -> Intfn WindowManager::create_window(self : WindowManager, title : String, url : String, width? : Int, height? : Int) -> Intfn WindowManager::request(_self : WindowManager, source_window_id : Int, target_window_id : Int, subtype : String, data : String, timeout_ms? : Int) -> Stringfn WindowManager::respond(_self : WindowManager, source_window_id : Int, target_window_id : Int, request_id : Int, data : String) -> Intfn WindowManager::send_message(_self : WindowManager, source_window_id : Int, target_window_id : Int, message_type : IpcMessageType, subtype : String, data : String) -> Intasync fn WindowManager::serve_process_commands(self : WindowManager, child_pid : Int, handler : async (ProcessCommandRequest) -> ProcessCommandResponse, subtype? : String) -> Unitfn WindowManager::set_fullscreen_window(_self : WindowManager, window_id : Int, fullscreen : Bool) -> Intfn WindowManager::set_traffic_light_position(_self : WindowManager, window_id : Int, x : Int, y : Int) -> Intfn WindowManager::set_window_customization(_self : WindowManager, window_id : Int, frameless : Bool, resizable : Bool, closeable : Bool, always_on_top : Bool, transparent : Bool, title_bar_style : TitleBarStyle, title_bar_overlay : Bool) -> Intfn[Reply : FromJson] decode_process_command_response(raw : String) -> Reply raise ProcessCommandErrorfn wm_connect_child_process() -> Intfn wm_create_child_window(title : Bytes, url : Bytes, width : Int, height : Int, parent_window_id : Int) -> Intfn wm_create_window(title : Bytes, url : Bytes, width : Int, height : Int, x : Int, y : Int, has_x : Int, has_y : Int, parent_window_id : Int) -> Intfn wm_fork_process() -> Intfn wm_ipc_pop_message_wire(window_id : Int) -> Bytesfn wm_ipc_request_bytes(source_window_id : Int, target_window_id : Int, subtype : Bytes, data : Bytes, timeout_ms : Int) -> Bytesfn wm_ipc_respond(source_window_id : Int, target_window_id : Int, request_id : Int, data : Bytes) -> Intfn wm_ipc_send(source_window_id : Int, target_window_id : Int, message_type : Int, subtype : Bytes, data : Bytes) -> Intfn wm_navigate(window_id : Int, url : Bytes) -> Intfn wm_return_raw(window_id : Int, seq : Bytes, status : Int, result : Bytes) -> Intfn wm_run_window_async(window_id : Int) -> Intfn wm_set_devtools(window_id : Int, enabled : Int) -> Intfn wm_set_fullscreen_window(window_id : Int, fullscreen : Int) -> Intfn wm_set_traffic_light_position(window_id : Int, x : Int, y : Int) -> Intfn wm_set_visibility(window_id : Int, visible : Int) -> Intfn wm_set_window_customization(window_id : Int, frameless : Int, resizable : Int, closeable : Int, always_on_top : Int, transparent : Int, title_bar_style : TitleBarStyle, title_bar_overlay : Int) -> Intfn wm_spawn_process(program : Bytes, arg1 : Bytes) -> Intfn wm_start_drag_window(window_id : Int) -> Intfn wm_toggle_fullscreen_window(window_id : Int) -> Intfn wm_toggle_maximize_window(window_id : Int) -> Intfn wm_unmaximize_window(window_id : Int) -> Intfn wm_wait_child_noblock(pid : Int) -> IntInstall
Download zipA modern desktop application framework based on web technologies.
Dependencies