Skip to content
This repository was archived by the owner on Jul 3, 2020. It is now read-only.

jar_libs_path and KeyEventKeyCode #106

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
target/
.vscode
.DS_Store
13 changes: 10 additions & 3 deletions cargo-apk/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

114 changes: 38 additions & 76 deletions cargo-apk/injected-glue/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,23 @@ pub unsafe extern fn cargo_apk_injected_glue_load_asset(ptr: *const (), len: usi
Box::into_raw(Box::new(data)) as *mut _
}

use ffi::{JNIEnv, ANativeActivity, _JavaVM, JavaVM, JNIInvokeInterface};
use std::mem::transmute;

#[no_mangle]
pub unsafe extern fn cargo_apk_injected_glue_attach_jvm() {
let mut env: *mut JNIEnv = unsafe {std::mem::uninitialized()};

let a: &ANativeActivity = unsafe {transmute(get_app().activity)};
let vm: &mut _JavaVM = unsafe {transmute(a.vm)};
let it: &JNIInvokeInterface = unsafe {transmute(vm.functions)};

let f = it.AttachCurrentThread;
let ret = f(vm as *mut JavaVM, &mut env as *mut *mut JNIEnv, 0 as *mut c_void);

write_log(format!("attach vm result: {}", ret).as_str());
}

/// This static variable will store the android_app* on creation, and set it back to 0 at
/// destruction.
/// Apart from this, the static is never written, so there is no risk of race condition.
Expand All @@ -86,12 +103,20 @@ struct Context {
primary_pointer_id: Cell<i32>,
}

pub mod touch_event;
pub use touch_event::{TouchEvent, TouchEventType, Pointer, PointerState};

#[derive(Clone, Copy, Debug)]
pub enum KeyEventAction {
Up,
Down,
}

/// An event triggered by the Android environment.
#[derive(Clone, Copy, Debug)]
pub enum Event {
EventMotion(Motion),
EventKeyUp,
EventKeyDown,
Touch(TouchEvent),
KeyEvent(KeyEventAction, i32),
InitWindow,
SaveState,
TermWindow,
Expand All @@ -110,24 +135,6 @@ pub enum Event {
Destroy,
}

/// 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,
}

#[cfg(not(target_os = "android"))]
use this_platform_is_not_supported;

Expand Down Expand Up @@ -382,64 +389,19 @@ pub extern fn inputs_callback(_: *mut ffi::android_app, event: *const ffi::AInpu
let action_code = action & ffi::AMOTION_EVENT_ACTION_MASK;

match etype {
ffi::AINPUT_EVENT_TYPE_KEY => match action_code {
ffi::AKEY_EVENT_ACTION_DOWN => { send_event(Event::EventKeyDown); },
ffi::AKEY_EVENT_ACTION_UP => send_event(Event::EventKeyUp),
_ => write_log(&format!("unknown input-event-type:{} action_code:{}", etype, action_code)),
ffi::AINPUT_EVENT_TYPE_KEY => {
let key_code = unsafe { ffi::AKeyEvent_getKeyCode(event) };
match action_code {
ffi::AKEY_EVENT_ACTION_DOWN => send_event(Event::KeyEvent(KeyEventAction::Down, key_code)),
ffi::AKEY_EVENT_ACTION_UP => send_event(Event::KeyEvent(KeyEventAction::Up, key_code)),
_ => write_log(&format!("unknown input-event-type:{} action_code:{}", etype, action_code)),
}
},

ffi::AINPUT_EVENT_TYPE_MOTION => {
let motion_action = match action_code {
ffi::AMOTION_EVENT_ACTION_DOWN |
ffi::AMOTION_EVENT_ACTION_POINTER_DOWN => MotionAction::Down,
ffi::AMOTION_EVENT_ACTION_UP |
ffi::AMOTION_EVENT_ACTION_POINTER_UP => MotionAction::Up,
ffi::AMOTION_EVENT_ACTION_MOVE => MotionAction::Move,
ffi::AMOTION_EVENT_ACTION_CANCEL => MotionAction::Cancel,
_ => {
write_log(&format!("unknown action_code:{}", action_code));
return 0
}
};
let context = get_context();
let idx = ((action & ffi::AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
>> ffi::AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT)
as usize;

let pointer_id = unsafe { ffi::AMotionEvent_getPointerId(event, idx) };
if action_code == ffi::AMOTION_EVENT_ACTION_DOWN {
context.primary_pointer_id.set(pointer_id);
}
let primary_pointer_id = context.primary_pointer_id.get();
let multitouch = context.multitouch.get();

match motion_action {
MotionAction::Down | MotionAction::Up | MotionAction::Cancel => {
if multitouch || pointer_id == primary_pointer_id {
send_event(Event::EventMotion(Motion {
action: motion_action,
pointer_id: pointer_id,
x: unsafe { ffi::AMotionEvent_getX(event, idx) },
y: unsafe { ffi::AMotionEvent_getY(event, idx) },
}));
}
}
MotionAction::Move => {
// A move event may have multiple changed pointers. Send an event for each.
let pointer_count = unsafe { ffi::AMotionEvent_getPointerCount(event) };
for idx in 0..pointer_count {
let pointer_id = unsafe { ffi::AMotionEvent_getPointerId(event, idx) };
if multitouch || pointer_id == primary_pointer_id {
send_event(Event::EventMotion(Motion {
action: motion_action,
pointer_id: pointer_id,
x: unsafe { ffi::AMotionEvent_getX(event, idx) },
y: unsafe { ffi::AMotionEvent_getY(event, idx) },
}));
}
}
}
}
send_event(Event::Touch(TouchEvent::from_input_event(event)))
},

_ => write_log(&format!("unknown input-event-type:{} action_code:{}", etype, action_code)),
}
0
Expand Down
151 changes: 151 additions & 0 deletions cargo-apk/injected-glue/touch_event.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
use ffi;

#[derive(Clone, Copy, Debug)]
pub enum TouchEventType{
Down,
PointerDown,
Move,
PointerUp,
Up,
Cancel,
}

impl TouchEventType{
fn from_input_event(event: *const ffi::AInputEvent) -> TouchEventType{

// let action = unsafe {ffi::AMotionEvent_getAction(event)} & ffi::AMOTION_EVENT_ACTION_MASK;

match unsafe {ffi::AMotionEvent_getAction(event)} & ffi::AMOTION_EVENT_ACTION_MASK {
// match action {
ffi::AMOTION_EVENT_ACTION_DOWN => //| ffi::AMOTION_EVENT_ACTION_POINTER_DOWN =>
TouchEventType::Down,
ffi::AMOTION_EVENT_ACTION_MOVE =>
TouchEventType::Move,
ffi::AMOTION_EVENT_ACTION_POINTER_DOWN =>
TouchEventType::PointerDown,
ffi::AMOTION_EVENT_ACTION_POINTER_UP =>
TouchEventType::PointerUp,
ffi::AMOTION_EVENT_ACTION_UP => //| ffi::AMOTION_EVENT_ACTION_POINTER_UP =>
TouchEventType::Up,
_ => TouchEventType::Cancel
}

// if action == ffi::AMOTION_EVENT_ACTION_DOWN {
// TouchEventType::Down
// } else if action == ffi::AMOTION_EVENT_ACTION_POINTER_DOWN {
// TouchEventType::PointerDown
// } else if action == ffi::AMOTION_EVENT_ACTION_UP {
// TouchEventType::Up
// } else if action == ffi::AMOTION_EVENT_ACTION_POINTER_UP {
// TouchEventType::PointerUp
// } else if action == ffi::AMOTION_EVENT_ACTION_MOVE{
// TouchEventType::Move
// } else{
// TouchEventType::Cancel
// }
}
}

#[derive(Clone, Copy, Debug)]
pub struct TouchEvent {
pub event_type: TouchEventType,
pub timestamp: i64,
pub num_pointers: u8,
pub p0: Pointer,
pub p1: Option<Pointer>,
pub p2: Option<Pointer>,
pub p3: Option<Pointer>,
pub flag: i32,
}

impl TouchEvent {

pub fn from_input_event(event: *const ffi::AInputEvent) -> TouchEvent {

let n = unsafe {ffi::AMotionEvent_getPointerCount(event)};

TouchEvent {
timestamp: unsafe {ffi::AMotionEvent_getEventTime(event)},
p0: Pointer::from_input_event(event, 0),
num_pointers: n as u8,
p1: if n > 1 {Some(Pointer::from_input_event(event, 1))} else {None},
p2: if n > 2 {Some(Pointer::from_input_event(event, 2))} else {None},
p3: if n > 3 {Some(Pointer::from_input_event(event, 3))} else {None},
event_type: TouchEventType::from_input_event(event),
flag: 0,
}
}
}


#[derive(Clone, Copy, Debug)]
pub enum PointerState{
Released,
Pressed,
Moved,
Stationary,
Cancelled,
}

impl PointerState {
fn from_input_event(event: *const ffi::AInputEvent, pointer_idx: usize) -> PointerState {
let action = unsafe {ffi::AMotionEvent_getAction(event)};

// primary pointer;
if action == ffi::AMOTION_EVENT_ACTION_DOWN {
return PointerState::Pressed;
}else if action == ffi::AMOTION_EVENT_ACTION_UP {
return PointerState::Released;
}

// actions regardless of pointer index;
if action == ffi::AMOTION_EVENT_ACTION_MOVE {
return PointerState::Moved;
}else if action == ffi::AMOTION_EVENT_ACTION_CANCEL {
return PointerState::Cancelled;
}

// index where the action occured;
let action_idx = (action & ffi::AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> ffi::AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
if (pointer_idx as i32) != action_idx {
return PointerState::Stationary;
}

let action_masked = action & ffi::AMOTION_EVENT_ACTION_MASK;

if action_masked == ffi::AMOTION_EVENT_ACTION_POINTER_DOWN {
return PointerState::Pressed;
}else if action_masked == ffi::AMOTION_EVENT_ACTION_POINTER_UP {
return PointerState::Released;
}

PointerState::Stationary
}
}

#[derive(Clone, Copy, Debug)]
pub struct Pointer {
pub state: PointerState,
pub x: f32,
pub y: f32,
pub id: i32,
pub pressure: f32,
pub vertical_radius: f32,
pub horizontal_radius: f32,
pub rotation_angle: f32,
}

impl Pointer {
fn from_input_event(event: *const ffi::AInputEvent, idx:usize) -> Pointer {
Pointer {
state: PointerState::from_input_event(event, idx),
id: unsafe {ffi::AMotionEvent_getPointerId(event, idx)},
x: unsafe {ffi::AMotionEvent_getX(event, idx)},
y: unsafe {ffi::AMotionEvent_getY(event, idx)},
vertical_radius: unsafe {ffi::AMotionEvent_getTouchMajor(event, idx)} / 2.0,
horizontal_radius: unsafe {ffi::AMotionEvent_getTouchMinor(event, idx)} / 2.0,
pressure: 0.0,
rotation_angle:0.0,
}
}
}
21 changes: 21 additions & 0 deletions cargo-apk/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,21 @@ pub fn build(manifest_path: &Path, config: &Config) -> BuildResult {
shared_objects_to_load
};

// copy external java jars to android-artifacts/build/libs;
if let Some(ref src) = config.jar_libs_path {
if !fs::metadata(src).is_err() {
if let Ok(paths) = fs::read_dir(src) {
let dst = android_artifacts_dir.join("build/libs");
for f in paths {
if let Ok(f) = f {
let d = dst.join(f.file_name());
fs::copy(f.path(), d).unwrap();
}
}
}
}
}

// Write the Java source
// FIXME: duh, the file will be replaced every time, so this only works with one target
build_java_src(&android_artifacts_dir, &config,
Expand Down Expand Up @@ -281,6 +296,9 @@ fn build_android_artifacts_dir(path: &Path, config: &Config) {

let mut ffi = File::create(path.join("injected-glue/ffi.rs")).unwrap();
ffi.write_all(&include_bytes!("../injected-glue/ffi.rs")[..]).unwrap();

let mut touch = File::create(path.join("injected-glue/touch_event.rs")).unwrap();
touch.write_all(&include_bytes!("../injected-glue/touch_event.rs")[..]).unwrap();
}

build_linker(path);
Expand Down Expand Up @@ -327,6 +345,8 @@ fn build_java_src<'a, I>(path: &Path, config: &Config, libs: I)
let mut file = File::create(&file).unwrap();

let mut libs_string = String::new();
libs_string.push_str("System.loadLibrary(\"main\");\n");

for name in libs {
// Strip off the 'lib' prefix and ".so" suffix.
let line = format!(" System.loadLibrary(\"{}\");\n",
Expand Down Expand Up @@ -445,6 +465,7 @@ fn build_build_xml(path: &Path, config: &Config) {
write!(file, r#"<?xml version="1.0" encoding="UTF-8"?>
<project name="{project_name}" default="help">
<property file="local.properties" />
<property environment="env" />
<loadproperties srcFile="project.properties" />
<import file="custom_rules.xml" optional="true" />
<import file="${{sdk.dir}}/tools/ant/build.xml" />
Expand Down
Loading