winit_surface_window 0.2.0

A helper library to use existing Android Surfaces (like Presentations) as windows within the Rust ecosystem, compatible with raw-window-handle.
Documentation
use crate::error::Result;
use crate::presentation::PresentationWindow;
use jni::objects::{JClass, JObject};
use jni::sys::{jboolean, jint, jintArray, jlong};
use jni::JNIEnv;
use std::ptr;

/// Initialize presentation system from Java/Kotlin code.
/// 
/// # Java Signature
/// ```java
/// public static native boolean initializePresentationSystem(Context context);
/// ```
#[no_mangle]
pub extern "system" fn Java_com_presentation_PresentationHelper_initializePresentationSystem(
    env: JNIEnv,
    _class: JClass,
    context: JObject,
) -> jboolean {
    let result = || -> Result<()> {
        let java_vm = env.get_java_vm()?;
        let vm_ptr = java_vm.get_java_vm_pointer();
        
        unsafe {
            PresentationWindow::initialize(vm_ptr, context)?;
        }
        
        Ok(())
    };
    
    match result() {
        Ok(_) => {
            log::info!("Presentation system initialized successfully");
            1 // true
        }
        Err(e) => {
            log::error!("Failed to initialize presentation system: {}", e);
            0 // false
        }
    }
}

/// Create presentation window on specified display.
/// 
/// # Java Signature
/// ```java
/// public static native long createPresentationOnDisplay(int displayId, long timeoutMs);
/// ```
/// 
/// # Returns
/// A pointer to the PresentationWindow instance, or 0 if creation failed.
#[no_mangle]
pub extern "system" fn Java_com_presentation_PresentationHelper_createPresentationOnDisplay(
    _env: JNIEnv,
    _class: JClass,
    display_id: jint,
    timeout_ms: jlong,
) -> jlong {
    let result = || -> Result<*mut PresentationWindow> {
        let presentation = PresentationWindow::new_on_display(display_id, timeout_ms as u64)?;
        let boxed = Box::new(presentation);
        Ok(Box::into_raw(boxed))
    };
    
    match result() {
        Ok(ptr) => {
            log::info!("Created presentation on display {}", display_id);
            ptr as jlong
        }
        Err(e) => {
            log::error!("Failed to create presentation on display {}: {}", display_id, e);
            0
        }
    }
}

/// Create presentation window on secondary display.
/// 
/// # Java Signature
/// ```java
/// public static native long createPresentationOnSecondaryDisplay(long timeoutMs);
/// ```
/// 
/// # Returns
/// A pointer to the PresentationWindow instance, or 0 if creation failed.
#[no_mangle]
pub extern "system" fn Java_com_presentation_PresentationHelper_createPresentationOnSecondaryDisplay(
    _env: JNIEnv,
    _class: JClass,
    timeout_ms: jlong,
) -> jlong {
    let result = || -> Result<*mut PresentationWindow> {
        let presentation = PresentationWindow::new_on_secondary_display(timeout_ms as u64)?;
        let boxed = Box::new(presentation);
        Ok(Box::into_raw(boxed))
    };
    
    match result() {
        Ok(ptr) => {
            log::info!("Created presentation on secondary display");
            ptr as jlong
        }
        Err(e) => {
            log::error!("Failed to create presentation on secondary display: {}", e);
            0
        }
    }
}

/// Get available display IDs.
/// 
/// # Java Signature
/// ```java
/// public static native int[] getAvailableDisplays();
/// ```
#[no_mangle]
pub extern "system" fn Java_com_presentation_PresentationHelper_getAvailableDisplays(
    env: JNIEnv,
    _class: JClass,
) -> jintArray {
    let result = || -> Result<jintArray> {
        let displays = PresentationWindow::get_available_displays()?;
        let array = env.new_int_array(displays.len() as i32)?;
        env.set_int_array_region(&array, 0, &displays)?;
        Ok(array.into_raw())
    };
    
    match result() {
        Ok(array) => array,
        Err(e) => {
            log::error!("Failed to get available displays: {}", e);
            ptr::null_mut()
        }
    }
}

/// Get presentation window width.
/// 
/// # Java Signature
/// ```java
/// public static native int getPresentationWidth(long presentationPtr);
/// ```
#[no_mangle]
pub extern "system" fn Java_com_presentation_PresentationHelper_getPresentationWidth(
    _env: JNIEnv,
    _class: JClass,
    presentation_ptr: jlong,
) -> jint {
    if presentation_ptr == 0 {
        return 0;
    }
    
    let presentation = unsafe { &*(presentation_ptr as *const PresentationWindow) };
    presentation.width()
}

/// Get presentation window height.
/// 
/// # Java Signature
/// ```java
/// public static native int getPresentationHeight(long presentationPtr);
/// ```
#[no_mangle]
pub extern "system" fn Java_com_presentation_PresentationHelper_getPresentationHeight(
    _env: JNIEnv,
    _class: JClass,
    presentation_ptr: jlong,
) -> jint {
    if presentation_ptr == 0 {
        return 0;
    }
    
    let presentation = unsafe { &*(presentation_ptr as *const PresentationWindow) };
    presentation.height()
}

/// Get presentation display ID.
/// 
/// # Java Signature
/// ```java
/// public static native int getPresentationDisplayId(long presentationPtr);
/// ```
/// 
/// # Returns
/// The display ID, or -1 if not available.
#[no_mangle]
pub extern "system" fn Java_com_presentation_PresentationHelper_getPresentationDisplayId(
    _env: JNIEnv,
    _class: JClass,
    presentation_ptr: jlong,
) -> jint {
    if presentation_ptr == 0 {
        return -1;
    }
    
    let presentation = unsafe { &*(presentation_ptr as *const PresentationWindow) };
    presentation.display_id().unwrap_or(-1)
}

/// Check if a presentation window is currently showing.
/// 
/// # Java Signature
/// ```java
/// public static native boolean isPresentationShowing(long presentationPtr);
/// ```
#[no_mangle]
pub extern "system" fn Java_com_presentation_PresentationHelper_isPresentationShowing(
    _env: JNIEnv,
    _class: JClass,
    presentation_ptr: jlong,
) -> jboolean {
    if presentation_ptr == 0 {
        return 0;
    }
    
    let presentation = unsafe { &*(presentation_ptr as *const PresentationWindow) };
    match presentation.is_showing() {
        Ok(showing) => if showing { 1 } else { 0 },
        Err(_) => 0,
    }
}

/// Dismiss a presentation window.
/// 
/// # Java Signature
/// ```java
/// public static native boolean dismissPresentation(long presentationPtr);
/// ```
#[no_mangle]
pub extern "system" fn Java_com_presentation_PresentationHelper_dismissPresentation(
    _env: JNIEnv,
    _class: JClass,
    presentation_ptr: jlong,
) -> jboolean {
    if presentation_ptr == 0 {
        return 0;
    }
    
    let presentation = unsafe { &mut *(presentation_ptr as *mut PresentationWindow) };
    match presentation.dismiss() {
        Ok(_) => {
            log::info!("Presentation dismissed successfully");
            1
        }
        Err(e) => {
            log::error!("Failed to dismiss presentation: {}", e);
            0
        }
    }
}

/// Destroy a presentation window and free its memory.
/// 
/// # Java Signature
/// ```java
/// public static native void destroyPresentation(long presentationPtr);
/// ```
/// 
/// # Safety
/// This function takes ownership of the presentation and frees its memory.
/// The pointer must not be used after calling this function.
#[no_mangle]
pub extern "system" fn Java_com_presentation_PresentationHelper_destroyPresentation(
    _env: JNIEnv,
    _class: JClass,
    presentation_ptr: jlong,
) {
    if presentation_ptr == 0 {
        return;
    }
    
    let presentation = unsafe { Box::from_raw(presentation_ptr as *mut PresentationWindow) };
    drop(presentation);
    log::info!("Presentation destroyed");
}

/// Get the ANativeWindow pointer from a presentation window.
/// This is useful for integration with other native graphics libraries.
/// 
/// # Java Signature
/// ```java
/// public static native long getPresentationNativeWindow(long presentationPtr);
/// ```
/// 
/// # Returns
/// A pointer to the ANativeWindow, or 0 if not available.
/// 
/// # Safety
/// The returned pointer is valid only as long as the PresentationWindow exists.
#[no_mangle]
pub extern "system" fn Java_com_presentation_PresentationHelper_getPresentationNativeWindow(
    _env: JNIEnv,
    _class: JClass,
    presentation_ptr: jlong,
) -> jlong {
    if presentation_ptr == 0 {
        return 0;
    }
    
    let presentation = unsafe { &*(presentation_ptr as *const PresentationWindow) };
    if let Some(surface_window) = presentation.surface_window() {
        unsafe { surface_window.as_ptr() as jlong }
    } else {
        0
    }
}