extern crate alloc;
extern crate std;
use core::ffi::c_void;
use jni::objects::{Global, JClass, JObject, JValue};
use jni::sys::{jint, jlong, jobject};
use jni::{Env, EnvUnowned, jni_sig, jni_str};
use super::type_id_to_java;
use crate::{IntoFFI, IntoRust, WuiAnyView, WuiTypeId, app::WuiAndroidAppHandles};
unsafe extern "C" {
fn waterui_android_init() -> *mut c_void;
fn waterui_android_app(env: *mut c_void) -> WuiAndroidAppHandles;
}
#[unsafe(no_mangle)]
extern "system" fn Java_dev_waterui_android_ffi_WatcherJni_init<'local>(
_env: EnvUnowned<'local>,
_class: JClass<'local>,
) -> jlong {
unsafe { waterui_android_init() as jlong }
}
#[unsafe(no_mangle)]
extern "system" fn Java_dev_waterui_android_ffi_WatcherJni_app<'local>(
mut env: EnvUnowned<'local>,
_class: JClass<'local>,
env_ptr: jlong,
) -> jobject {
let app = unsafe { waterui_android_app(env_ptr as *mut c_void) };
super::with_env(&mut env, |env| app_to_java(env, app).into_raw())
}
fn app_to_java<'local>(env: &mut Env<'local>, app: WuiAndroidAppHandles) -> JObject<'local> {
let app_struct_class = env
.find_class(jni_str!("dev/waterui/android/runtime/AppStruct"))
.expect("AppStruct class not found");
env.new_object(
&app_struct_class,
jni_sig!("(JJ)V"),
&[
JValue::Long(app.content as jlong),
JValue::Long(app.env as jlong),
],
)
.expect("Failed to create AppStruct")
}
#[unsafe(no_mangle)]
extern "system" fn Java_dev_waterui_android_ffi_WatcherJni_viewId<'local>(
mut env: EnvUnowned<'local>,
_class: JClass<'local>,
view_ptr: jlong,
) -> jobject {
let view = unsafe { &*(view_ptr as *const crate::WuiAnyView) };
let type_id = unsafe { crate::waterui_view_id(view) };
super::with_env(&mut env, |env| type_id_to_java(env, type_id).into_raw())
}
#[unsafe(no_mangle)]
extern "system" fn Java_dev_waterui_android_ffi_WatcherJni_viewBody<'local>(
_env: EnvUnowned<'local>,
_class: JClass<'local>,
view_ptr: jlong,
env_ptr: jlong,
) -> jlong {
let view = view_ptr as *mut crate::WuiAnyView;
let wui_env = env_ptr as *mut crate::WuiEnv;
unsafe { crate::waterui_view_body(view, wui_env) as jlong }
}
#[unsafe(no_mangle)]
extern "system" fn Java_dev_waterui_android_ffi_WatcherJni_viewStretchAxis<'local>(
_env: EnvUnowned<'local>,
_class: JClass<'local>,
view_ptr: jlong,
) -> jint {
let view = view_ptr as *const crate::WuiAnyView;
unsafe { crate::waterui_view_stretch_axis(view) as jint }
}
#[unsafe(no_mangle)]
extern "system" fn Java_dev_waterui_android_ffi_WatcherJni_cloneEnv<'local>(
_env: EnvUnowned<'local>,
_class: JClass<'local>,
env_ptr: jlong,
) -> jlong {
let wui_env = env_ptr as *const crate::WuiEnv;
unsafe { crate::waterui_clone_env(wui_env) as jlong }
}
#[unsafe(no_mangle)]
extern "system" fn Java_dev_waterui_android_ffi_WatcherJni_emptyId<'local>(
mut env: EnvUnowned<'local>,
_class: JClass<'local>,
) -> jobject {
let type_id = WuiTypeId::of::<()>();
super::with_env(&mut env, |env| type_id_to_java(env, type_id).into_raw())
}
#[unsafe(no_mangle)]
extern "system" fn Java_dev_waterui_android_ffi_WatcherJni_spacerId<'local>(
mut env: EnvUnowned<'local>,
_class: JClass<'local>,
) -> jobject {
let type_id = WuiTypeId::of::<waterui_core::Native<waterui::component::spacer::Spacer>>();
super::with_env(&mut env, |env| type_id_to_java(env, type_id).into_raw())
}
#[unsafe(no_mangle)]
extern "system" fn Java_dev_waterui_android_ffi_WatcherJni_appliedFilterId<'local>(
mut env: EnvUnowned<'local>,
_class: JClass<'local>,
) -> jobject {
let type_id = WuiTypeId::of::<waterui_core::Metadata<waterui_graphics::AppliedFilter>>();
super::with_env(&mut env, |env| type_id_to_java(env, type_id).into_raw())
}
#[unsafe(no_mangle)]
extern "system" fn Java_dev_waterui_android_ffi_WatcherJni_viewEffectId<'local>(
mut env: EnvUnowned<'local>,
_class: JClass<'local>,
) -> jobject {
let type_id =
WuiTypeId::of::<waterui_core::Native<waterui_graphics::view_effect::ViewEffectErased>>();
super::with_env(&mut env, |env| type_id_to_java(env, type_id).into_raw())
}
#[unsafe(no_mangle)]
extern "system" fn Java_dev_waterui_android_ffi_WatcherJni_webViewId<'local>(
mut env: EnvUnowned<'local>,
_class: JClass<'local>,
) -> jobject {
let type_id = WuiTypeId::of::<waterui_core::Native<waterui_webview::WebView>>();
super::with_env(&mut env, |env| type_id_to_java(env, type_id).into_raw())
}
#[unsafe(no_mangle)]
unsafe extern "system" fn Java_dev_waterui_android_ffi_WatcherJni_forceAsWebView<'local>(
mut env: EnvUnowned<'local>,
_class: JClass<'local>,
view_ptr: jlong,
) -> jobject {
super::with_env(&mut env, |env| unsafe {
let view_ptr: *mut WuiAnyView = crate::jni::convert::jlong_to_ptr_mut(view_ptr);
let any: waterui::AnyView = view_ptr.into_rust();
let view = *any.downcast_unchecked::<waterui_core::Native<waterui_webview::WebView>>();
let ffi = view.into_inner().into_ffi();
crate::jni::convert::struct_to_java(env, &ffi).into_raw()
})
}
#[unsafe(no_mangle)]
unsafe extern "system" fn Java_dev_waterui_android_ffi_WatcherJni_dropAnyViews<'local>(
_env: EnvUnowned<'local>,
_class: JClass<'local>,
ptr: jlong,
) {
unsafe {
drop(crate::IntoRust::into_rust(
ptr as *mut crate::views::WuiAnyViews,
));
}
}
#[unsafe(no_mangle)]
unsafe extern "system" fn Java_dev_waterui_android_ffi_WatcherJni_dropAnyView<'local>(
_env: EnvUnowned<'local>,
_class: JClass<'local>,
ptr: jlong,
) {
unsafe {
drop(crate::IntoRust::into_rust(ptr as *mut crate::WuiAnyView));
}
}
#[cfg(feature = "gpu")]
struct AndroidGpuRuntimeCompletion {
jvm: jni::JavaVM,
callback: Global<JObject<'static>>,
}
#[cfg(feature = "gpu")]
impl AndroidGpuRuntimeCompletion {
fn complete(self, runtime: waterui_graphics::shared_context::GpuRuntime) {
let runtime = crate::IntoFFI::into_ffi(runtime);
super::with_attached_env(&self.jvm, |env| {
env.call_method(
&self.callback,
jni_str!("onReady"),
jni_sig!("(J)V"),
&[JValue::Long(runtime as jlong)],
)
.expect("GpuRuntimeReadyCallback.onReady failed");
})
.expect("GPU runtime completion failed to attach to JVM");
}
}
#[cfg(feature = "gpu")]
#[unsafe(no_mangle)]
extern "system" fn Java_dev_waterui_android_ffi_WatcherJni_gpuRuntimeCreate<'local>(
mut env: EnvUnowned<'local>,
_class: JClass<'local>,
callback: JObject<'local>,
) {
super::with_env(&mut env, |env| {
let completion = AndroidGpuRuntimeCompletion {
jvm: env
.get_java_vm()
.expect("WatcherJni.gpuRuntimeCreate failed to access JavaVM"),
callback: env
.new_global_ref(callback)
.expect("WatcherJni.gpuRuntimeCreate failed to retain callback"),
};
crate::components::gpu_runtime::create_gpu_runtime(move |runtime| {
completion.complete(runtime);
});
});
}
#[cfg(feature = "gpu")]
#[unsafe(no_mangle)]
extern "system" fn Java_dev_waterui_android_ffi_WatcherJni_envInstallGpuRuntime<'local>(
_env: EnvUnowned<'local>,
_class: JClass<'local>,
env_ptr: jlong,
runtime_ptr: jlong,
) {
let env = unsafe { crate::borrow_ffi_mut(env_ptr as *mut crate::WuiEnv) };
let runtime = unsafe {
crate::IntoRust::into_rust(
runtime_ptr as *mut crate::components::gpu_runtime::WuiGpuRuntime,
)
};
crate::components::gpu_runtime::install_gpu_runtime(&mut env.0, runtime);
}
#[unsafe(no_mangle)]
extern "system" fn Java_dev_waterui_android_ffi_WatcherJni_envInstallWebViewController<'local>(
mut env: EnvUnowned<'local>,
_class: JClass<'local>,
env_ptr: jlong,
factory: JObject<'local>,
) {
super::with_env(&mut env, |env| unsafe {
super::webview_bridge::install_android_webview_controller(
env,
env_ptr as *mut crate::WuiEnv,
factory,
);
});
}