mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-12-24 12:24:07 +08:00
181 lines
4.4 KiB
Rust
181 lines
4.4 KiB
Rust
|
//! Sciter interop with native code and vice versa.
|
||
|
|
||
|
#![allow(unused_variables)]
|
||
|
#![allow(non_snake_case)]
|
||
|
|
||
|
#[macro_use]
|
||
|
extern crate sciter;
|
||
|
|
||
|
use sciter::{HELEMENT, Element, Value};
|
||
|
|
||
|
struct EventHandler {
|
||
|
root: Option<Element>,
|
||
|
}
|
||
|
|
||
|
impl Drop for EventHandler {
|
||
|
fn drop(&mut self) {
|
||
|
println!("interop::EventHandler: Bye bye, HTML!");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl EventHandler {
|
||
|
|
||
|
fn script_call_test(&self, args: &[Value], root: &Element) -> Option<Value> {
|
||
|
|
||
|
println!("root: {:?}", root);
|
||
|
// return None;
|
||
|
|
||
|
println!("calling 'hello'");
|
||
|
let answer = root.call_function("hello", &make_args!("hello, rust!"));
|
||
|
println!(" answer {:?}", answer);
|
||
|
|
||
|
println!("get and call 'hello'");
|
||
|
let answer = root.eval_script(r"hello");
|
||
|
if answer.is_err() {
|
||
|
return None;
|
||
|
}
|
||
|
let obj = answer.unwrap();
|
||
|
let answer = obj.call(None, &make_args!("argument"), None);
|
||
|
println!(" answer is {:?}", answer);
|
||
|
|
||
|
println!("eval 'hello'");
|
||
|
let answer = root.eval_script(r#"hello("42");"#);
|
||
|
println!(" answer is {:?}", answer);
|
||
|
|
||
|
println!("calling 'raise_error'; the following exceptions are expected then:");
|
||
|
let answer = root.call_function("raise_error", &make_args!(17, "42", false));
|
||
|
println!(" answer is {:?}", answer);
|
||
|
|
||
|
println!("calling inexisting function");
|
||
|
let answer = root.call_function("raise_error2", &[]);
|
||
|
println!(" answer is {:?}", answer);
|
||
|
|
||
|
Some(Value::from(true))
|
||
|
}
|
||
|
|
||
|
fn NativeCall(&mut self, arg: String) -> Value {
|
||
|
Value::from(format!("Rust window ({})", arg))
|
||
|
}
|
||
|
|
||
|
fn GetNativeApi(&mut self) -> Value {
|
||
|
|
||
|
fn on_add(args: &[Value]) -> Value {
|
||
|
let ints = args.iter().map(|x| x.to_int().unwrap());
|
||
|
// let sum: i32 = ints.sum(); // error: issue #27739
|
||
|
let sum: i32 = ints.sum();
|
||
|
Value::from(sum)
|
||
|
}
|
||
|
|
||
|
fn on_sub(args: &[Value]) -> Value {
|
||
|
if args.len() != 2 || args.iter().any(|x| !x.is_int()) {
|
||
|
return Value::error("sub requires 2 integer arguments!");
|
||
|
}
|
||
|
let ints: Vec<_> = args.iter().map(|x| x.to_int().unwrap()).collect();
|
||
|
let (a,b) = (ints[0], ints[1]);
|
||
|
Value::from(a - b)
|
||
|
}
|
||
|
|
||
|
let on_mul = |args: &[Value]| -> Value {
|
||
|
let prod: i32 = args.iter().map(|x| x.to_int().unwrap()).product();
|
||
|
Value::from(prod)
|
||
|
};
|
||
|
|
||
|
let mut api = Value::new();
|
||
|
|
||
|
api.set_item("add", on_add);
|
||
|
api.set_item("sub", on_sub);
|
||
|
api.set_item("mul", on_mul);
|
||
|
|
||
|
println!("returning {:?}", api);
|
||
|
|
||
|
api
|
||
|
}
|
||
|
|
||
|
fn calc_sum(&mut self, a: i32, b: i32) -> i32 {
|
||
|
a + b
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
impl sciter::EventHandler for EventHandler {
|
||
|
|
||
|
fn attached(&mut self, root: HELEMENT) {
|
||
|
self.root = Some(Element::from(root));
|
||
|
}
|
||
|
|
||
|
dispatch_script_call! {
|
||
|
|
||
|
fn NativeCall(String);
|
||
|
|
||
|
fn GetNativeApi();
|
||
|
|
||
|
fn calc_sum(i32, i32);
|
||
|
}
|
||
|
|
||
|
fn on_script_call(&mut self, root: HELEMENT, name: &str, argv: &[Value]) -> Option<Value> {
|
||
|
|
||
|
let args = argv.iter().map(|x| format!("{:?}", &x)).collect::<Vec<String>>().join(", ");
|
||
|
println!("script->native: {}({}), root {:?}", name, args, Element::from(root));
|
||
|
|
||
|
let handled = self.dispatch_script_call(root, name, argv);
|
||
|
if handled.is_some() {
|
||
|
return handled;
|
||
|
}
|
||
|
|
||
|
if name == "ScriptCallTest" {
|
||
|
return self.script_call_test(argv, &Element::from(root));
|
||
|
}
|
||
|
|
||
|
None
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
fn check_options() {
|
||
|
sciter::set_options(sciter::RuntimeOptions::ScriptFeatures(
|
||
|
sciter::SCRIPT_RUNTIME_FEATURES::ALLOW_SYSINFO as u8 // Enables `Sciter.machineName()`
|
||
|
| sciter::SCRIPT_RUNTIME_FEATURES::ALLOW_FILE_IO as u8 // Enables opening file dialog (`view.selectFile()`)
|
||
|
)).ok();
|
||
|
|
||
|
for arg in std::env::args() {
|
||
|
if arg.starts_with("--sciter-gfx=") {
|
||
|
use sciter::GFX_LAYER;
|
||
|
let backend = match arg.split_at("--sciter-gfx=".len()).1.trim() {
|
||
|
"auto" => GFX_LAYER::AUTO,
|
||
|
"cpu" => GFX_LAYER::CPU,
|
||
|
"skia" | "skia-cpu" => GFX_LAYER::SKIA_CPU,
|
||
|
"skia-opengl" => GFX_LAYER::SKIA_OPENGL,
|
||
|
|
||
|
#[cfg(windows)]
|
||
|
"d2d" => GFX_LAYER::D2D,
|
||
|
#[cfg(windows)]
|
||
|
"warp" => GFX_LAYER::WARP,
|
||
|
|
||
|
_ => GFX_LAYER::AUTO,
|
||
|
};
|
||
|
println!("setting {:?} backend", backend);
|
||
|
let ok = sciter::set_options(sciter::RuntimeOptions::GfxLayer(backend));
|
||
|
if let Err(e) = ok {
|
||
|
println!("failed to set backend: {:?}", e);
|
||
|
}
|
||
|
|
||
|
} else if arg.starts_with("--ux-theme") {
|
||
|
#[cfg(windows)]
|
||
|
sciter::set_options(sciter::RuntimeOptions::UxTheming(true)).ok();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn main() {
|
||
|
// interop --sciter-gfx=cpu --ux-theme
|
||
|
check_options();
|
||
|
|
||
|
let html = include_bytes!("interop.htm");
|
||
|
let handler = EventHandler { root: None };
|
||
|
let mut frame = sciter::Window::new();
|
||
|
frame.event_handler(handler);
|
||
|
frame.load_html(html, Some("example://interop.htm"));
|
||
|
frame.run_app();
|
||
|
}
|