blob: cdc681514a218d51f4df1edfdcf3d476a02134e6 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/gvr-android-keyboard/src/libraries/headers/vr/gvr/capi/include/gvr_keyboard.h"
#include <android/native_window_jni.h>
#include <dlfcn.h>
#include <jni.h>
#include <cmath>
#include "base/android/jni_android.h"
#include "base/android/scoped_java_ref.h"
#include "base/logging.h"
#include "jni/GvrKeyboardLoaderClient_jni.h"
// Run CALL macro for every function defined in the API.
#define FOR_EACH_API_FN \
CALL(gvr_keyboard_initialize) \
CALL(gvr_keyboard_create) \
CALL(gvr_keyboard_get_input_mode) \
CALL(gvr_keyboard_set_input_mode) \
CALL(gvr_keyboard_get_recommended_world_from_keyboard_matrix) \
CALL(gvr_keyboard_set_world_from_keyboard_matrix) \
CALL(gvr_keyboard_show) \
CALL(gvr_keyboard_update_button_state) \
CALL(gvr_keyboard_update_controller_ray) \
CALL(gvr_keyboard_get_text) \
CALL(gvr_keyboard_set_text) \
CALL(gvr_keyboard_get_selection_indices) \
CALL(gvr_keyboard_set_selection_indices) \
CALL(gvr_keyboard_get_composing_indices) \
CALL(gvr_keyboard_set_composing_indices) \
CALL(gvr_keyboard_set_frame_time) \
CALL(gvr_keyboard_set_eye_from_world_matrix) \
CALL(gvr_keyboard_set_projection_matrix) \
CALL(gvr_keyboard_set_viewport) \
CALL(gvr_keyboard_advance_frame) \
CALL(gvr_keyboard_render) \
CALL(gvr_keyboard_hide) \
CALL(gvr_keyboard_destroy)
namespace {
// Declare implementation function pointers.
#define CALL(fn) decltype(&fn) impl_##fn = nullptr;
FOR_EACH_API_FN
#undef CALL
template <typename Fn>
bool LoadFunction(void* handle, const char* function_name, Fn* fn_out) {
void* fn = dlsym(handle, function_name);
if (!fn) {
LOG(ERROR) << "Failed to load " << function_name
<< " from GVR keyboard library: " << dlerror();
return false;
}
*fn_out = reinterpret_cast<Fn>(fn);
return true;
}
static void* sdk_handle = nullptr;
void CloseSdk() {
if (!sdk_handle)
return;
JNIEnv* env = base::android::AttachCurrentThread();
CHECK(env);
vr_shell::Java_GvrKeyboardLoaderClient_closeKeyboardSDK(
env, reinterpret_cast<jlong>(sdk_handle));
// Null all the function pointers.
#define CALL(fn) impl_##fn = nullptr;
FOR_EACH_API_FN
#undef CALL
sdk_handle = nullptr;
}
bool LoadSdk(void* closure, gvr_keyboard_callback callback) {
if (sdk_handle)
return true;
JNIEnv* env = base::android::AttachCurrentThread();
CHECK(env);
base::android::ScopedJavaLocalRef<jobject> context_wrapper =
vr_shell::Java_GvrKeyboardLoaderClient_getContextWrapper(env);
base::android::ScopedJavaLocalRef<jobject> remote_class_loader =
vr_shell::Java_GvrKeyboardLoaderClient_getRemoteClassLoader(env);
sdk_handle = reinterpret_cast<void*>(
vr_shell::Java_GvrKeyboardLoaderClient_loadKeyboardSDK(env));
if (!sdk_handle) {
LOG(ERROR) << "Failed to load GVR keyboard SDK.";
return false;
}
// Load all function pointers from the SDK.
bool success = true;
#define CALL(fn) success &= LoadFunction(sdk_handle, #fn, &impl_##fn);
FOR_EACH_API_FN
#undef CALL
if (!success) {
CloseSdk();
return false;
}
gvr_keyboard_initialize(env, context_wrapper.obj(),
remote_class_loader.obj());
return success;
}
} // namespace
void gvr_keyboard_initialize(JNIEnv* env,
jobject app_context,
jobject class_loader) {
impl_gvr_keyboard_initialize(env, app_context, class_loader);
}
gvr_keyboard_context* gvr_keyboard_create(void* closure,
gvr_keyboard_callback callback) {
if (!LoadSdk(closure, callback)) {
return nullptr;
}
return impl_gvr_keyboard_create(closure, callback);
}
void gvr_keyboard_destroy(gvr_keyboard_context** context) {
impl_gvr_keyboard_destroy(context);
CloseSdk();
}
int32_t gvr_keyboard_get_input_mode(gvr_keyboard_context* context) {
return impl_gvr_keyboard_get_input_mode(context);
}
void gvr_keyboard_set_input_mode(gvr_keyboard_context* context,
int32_t input_mode) {
impl_gvr_keyboard_set_input_mode(context, input_mode);
}
void gvr_keyboard_get_recommended_world_from_keyboard_matrix(
float distance_from_eye,
gvr_mat4f* matrix) {
impl_gvr_keyboard_get_recommended_world_from_keyboard_matrix(
distance_from_eye, matrix);
}
void gvr_keyboard_set_world_from_keyboard_matrix(gvr_keyboard_context* context,
const gvr_mat4f* matrix) {
impl_gvr_keyboard_set_world_from_keyboard_matrix(context, matrix);
}
void gvr_keyboard_show(gvr_keyboard_context* context) {
impl_gvr_keyboard_show(context);
}
void gvr_keyboard_update_button_state(gvr_keyboard_context* context,
int32_t button_index,
bool pressed) {
impl_gvr_keyboard_update_button_state(context, button_index, pressed);
}
bool gvr_keyboard_update_controller_ray(gvr_keyboard_context* context,
const gvr_vec3f* start,
const gvr_vec3f* end,
gvr_vec3f* hit) {
return impl_gvr_keyboard_update_controller_ray(context, start, end, hit);
}
char* gvr_keyboard_get_text(gvr_keyboard_context* context) {
return impl_gvr_keyboard_get_text(context);
}
void gvr_keyboard_set_text(gvr_keyboard_context* context, const char* text) {
return impl_gvr_keyboard_set_text(context, text);
}
void gvr_keyboard_get_selection_indices(gvr_keyboard_context* context,
size_t* start,
size_t* end) {
impl_gvr_keyboard_get_selection_indices(context, start, end);
}
void gvr_keyboard_set_selection_indices(gvr_keyboard_context* context,
size_t start,
size_t end) {
impl_gvr_keyboard_set_selection_indices(context, start, end);
}
void gvr_keyboard_get_composing_indices(gvr_keyboard_context* context,
size_t* start,
size_t* end) {
impl_gvr_keyboard_get_composing_indices(context, start, end);
}
void gvr_keyboard_set_composing_indices(gvr_keyboard_context* context,
size_t start,
size_t end) {
impl_gvr_keyboard_set_composing_indices(context, start, end);
}
void gvr_keyboard_set_frame_time(gvr_keyboard_context* context,
const gvr_clock_time_point* time) {
impl_gvr_keyboard_set_frame_time(context, time);
}
void gvr_keyboard_set_eye_from_world_matrix(gvr_keyboard_context* context,
int32_t eye_type,
const gvr_mat4f* matrix) {
impl_gvr_keyboard_set_eye_from_world_matrix(context, eye_type, matrix);
}
void gvr_keyboard_set_projection_matrix(gvr_keyboard_context* context,
int32_t eye_type,
const gvr_mat4f* projection) {
impl_gvr_keyboard_set_projection_matrix(context, eye_type, projection);
}
void gvr_keyboard_set_viewport(gvr_keyboard_context* context,
int32_t eye_type,
const gvr_recti* viewport) {
impl_gvr_keyboard_set_viewport(context, eye_type, viewport);
}
void gvr_keyboard_advance_frame(gvr_keyboard_context* context) {
impl_gvr_keyboard_advance_frame(context);
}
void gvr_keyboard_render(gvr_keyboard_context* context, int32_t eye_type) {
impl_gvr_keyboard_render(context, eye_type);
}
void gvr_keyboard_hide(gvr_keyboard_context* context) {
impl_gvr_keyboard_hide(context);
}
#undef FOR_EACH_API_FN