1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#![cfg(target_os = "android")]

extern {
    fn cargo_apk_injected_glue_get_native_window() -> *const c_void;
    fn cargo_apk_injected_glue_add_sender(sender: *mut ());
    fn cargo_apk_injected_glue_add_sender_missing(sender: *mut ());
    fn cargo_apk_injected_glue_set_multitouch(multitouch: bool);
    fn cargo_apk_injected_glue_write_log(ptr: *const (), len: usize);
    fn cargo_apk_injected_glue_load_asset(ptr: *const (), len: usize) -> *mut c_void;
    fn cargo_apk_injected_glue_wake_event_loop();
}

use std::mem;
use std::os::raw::c_void;
use std::sync::mpsc::Sender;

/// An event triggered by the Android environment.
#[derive(Clone, Copy, Debug)]
pub enum Event {
    EventMotion(Motion),
    EventKeyUp,
    EventKeyDown,
    InitWindow,
    SaveState,
    TermWindow,
    GainedFocus,
    LostFocus,
    InputChanged,
    WindowResized,
    WindowRedrawNeeded,
    ContentRectChanged,
    ConfigChanged,
    LowMemory,
    Start,
    Resume,
    Pause,
    Stop,
    Destroy,
    Wake
}

/// Data about a motion event.
#[derive(Clone, Copy, Debug)]
pub struct Motion {
    pub action: MotionAction,
    pub pointer_id: i32,
    pub x: f32,
    pub y: f32,
}

/// The type of pointer action in a motion event.
#[derive(Clone, Copy, Debug)]
pub enum MotionAction {
    Down,
    Move,
    Up,
    Cancel,
}

pub enum AssetError {
    AssetMissing,
    EmptyBuffer,
}

/// Adds a sender where events will be sent to.
#[inline]
pub fn add_sender(sender: Sender<Event>) {
    unsafe {
        let sender = Box::into_raw(Box::new(sender)) as *mut _;
        cargo_apk_injected_glue_add_sender(sender);
    }
}

#[inline]
pub fn set_multitouch(multitouch: bool) {
    unsafe {
        cargo_apk_injected_glue_set_multitouch(multitouch);
    }
}

/// Adds a sender where events will be sent to, but also sends
/// any missing events to the sender object.
///
/// The missing events happen when the application starts, but before
/// any senders are registered. Since these might be important to certain
/// applications, this function provides that support.
#[inline]
pub fn add_sender_missing(sender: Sender<Event>) {
    unsafe {
        let sender = Box::into_raw(Box::new(sender)) as *mut _;
        cargo_apk_injected_glue_add_sender_missing(sender);
    }
}

/// Returns a handle to the native window.
#[inline]
pub unsafe fn get_native_window() -> *const c_void {
    cargo_apk_injected_glue_get_native_window()
}

///
#[inline]
pub fn write_log(message: &str) {
    unsafe {
        let (message_ptr, message_len) = mem::transmute(message);
        cargo_apk_injected_glue_write_log(message_ptr, message_len);
    }
}

#[inline]
pub fn load_asset(filename: &str) -> Result<Vec<u8>, AssetError> {
    unsafe {
        let (filename_ptr, filename_len) = mem::transmute(filename);
        let data = cargo_apk_injected_glue_load_asset(filename_ptr, filename_len);
        let data: Box<Result<Vec<u8>, AssetError>> = Box::from_raw(data as *mut _);
        *data
    }
}

// Wakes the event poll asynchronously and sends a Event::Wake event to the senders. 
// This method can be called on any thread. This method returns immediately.
#[inline]
pub fn wake_event_loop() {
    unsafe {
        cargo_apk_injected_glue_wake_event_loop();
    }
}