codemp/src/ffi/java/cursor.rs

81 lines
2.8 KiB
Rust
Raw Normal View History

use jni::{objects::JObject, JNIEnv};
use jni_toolbox::jni;
use crate::{api::{Controller, Cursor}, errors::ControllerError};
use super::null_check;
/// Try to fetch a [Cursor], or returns null if there's nothing.
#[jni(package = "mp.code", class = "CursorController", ptr)]
fn try_recv(controller: &mut crate::cursor::Controller) -> Result<Option<Cursor>, ControllerError> {
super::tokio().block_on(controller.try_recv())
}
/// Block until it receives a [Cursor].
#[jni(package = "mp.code", class = "CursorController", ptr)]
fn recv(controller: &mut crate::cursor::Controller) -> Result<Cursor, ControllerError> {
super::tokio().block_on(controller.recv())
}
/// Receive from Java, converts and sends a [Cursor].
#[jni(package = "mp.code", class = "CursorController")]
fn send(controller: &mut crate::cursor::Controller, cursor: Cursor) -> Result<(), ControllerError> {
super::tokio().block_on(controller.send(cursor))
}
/// Register a callback for cursor changes.
#[jni(package = "mp.code", class = "CursorController")]
fn callback<'local>(env: &mut JNIEnv<'local>, controller: &mut crate::cursor::Controller, cb: JObject<'local>) {
null_check!(env, cb, {});
let Ok(cb_ref) = env.new_global_ref(cb) else {
env.throw_new("mp/code/exceptions/JNIException", "Failed to pin callback reference!")
.expect("Failed to throw exception!");
return;
};
controller.callback(move |controller: crate::cursor::Controller| {
let jvm = super::jvm();
let mut env = jvm.attach_current_thread_permanently()
.expect("failed attaching to main JVM thread");
if let Err(e) = env.with_local_frame(5, |env| {
use jni_toolbox::IntoJavaObject;
let jcontroller = controller.into_java(env)?;
if let Err(e) = env.call_method(
&cb_ref,
"accept",
"(Ljava/lang/Object;)V",
&[jni::objects::JValueGen::Object(&jcontroller)]
) {
tracing::error!("error invoking callback: {e:?}");
};
Ok::<(), jni::errors::Error>(())
}) {
tracing::error!("error invoking callback: {e}");
let _ = env.exception_describe();
}
});
}
/// Clear the callback for cursor changes.
#[jni(package = "mp.code", class = "CursorController")]
fn clear_callback(controller: &mut crate::cursor::Controller) {
controller.clear_callback()
}
/// Block until there is a new value available.
#[jni(package = "mp.code", class = "CursorController")]
fn poll(controller: &mut crate::cursor::Controller) -> Result<(), ControllerError> {
super::tokio().block_on(controller.poll())
}
2024-08-07 01:44:27 +02:00
/// Stop the controller.
#[jni(package = "mp.code", class = "CursorController")]
fn stop(controller: &mut crate::cursor::Controller) -> bool {
controller.stop()
}
2024-08-08 00:29:54 +02:00
/// Called by the Java GC to drop a [crate::cursor::Controller].
#[jni(package = "mp.code", class = "CursorController")]
fn free(input: jni::sys::jlong) {
let _ = unsafe { Box::from_raw(input as *mut crate::cursor::Controller) };
}