1307 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			1307 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								#define EGL_NO_PLATFORM_SPECIFIC_TYPES
							 | 
						||
| 
								 | 
							
								#include <EGL/egl.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/error.h>
							 | 
						||
| 
								 | 
							
								// #include <GLContext.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/backend/Android.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/graphics4/graphics.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/input/gamepad.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/input/keyboard.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/input/mouse.h>
							 | 
						||
| 
								 | 
							
								// #include <kinc/input/sensor.h>
							 | 
						||
| 
								 | 
							
								#include <android/sensor.h>
							 | 
						||
| 
								 | 
							
								#include <android/window.h>
							 | 
						||
| 
								 | 
							
								#include <android_native_app_glue.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/input/pen.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/input/surface.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/log.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/system.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/threads/mutex.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/video.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/window.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <unistd.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <stdlib.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void pauseAudio();
							 | 
						||
| 
								 | 
							
								void resumeAudio();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static struct android_app *app = NULL;
							 | 
						||
| 
								 | 
							
								static ANativeActivity *activity = NULL;
							 | 
						||
| 
								 | 
							
								static ASensorManager *sensorManager = NULL;
							 | 
						||
| 
								 | 
							
								static const ASensor *accelerometerSensor = NULL;
							 | 
						||
| 
								 | 
							
								static const ASensor *gyroSensor = NULL;
							 | 
						||
| 
								 | 
							
								static ASensorEventQueue *sensorEventQueue = NULL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static bool started = false;
							 | 
						||
| 
								 | 
							
								static bool paused = true;
							 | 
						||
| 
								 | 
							
								static bool displayIsInitialized = false;
							 | 
						||
| 
								 | 
							
								static bool appIsForeground = false;
							 | 
						||
| 
								 | 
							
								static bool activityJustResized = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <assert.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/log.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef KINC_EGL
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								EGLDisplay kinc_egl_get_display() {
							 | 
						||
| 
								 | 
							
									return eglGetDisplay(EGL_DEFAULT_DISPLAY);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								EGLNativeWindowType kinc_egl_get_native_window(EGLDisplay display, EGLConfig config, int window) {
							 | 
						||
| 
								 | 
							
									kinc_affirm(window == 0);
							 | 
						||
| 
								 | 
							
									EGLint format;
							 | 
						||
| 
								 | 
							
									eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
							 | 
						||
| 
								 | 
							
									int e = ANativeWindow_setBuffersGeometry(app->window, 0, 0, format);
							 | 
						||
| 
								 | 
							
									if (e < 0) {
							 | 
						||
| 
								 | 
							
										kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to set ANativeWindow buffer geometry.");
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return app->window;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef KINC_VULKAN
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <vulkan/vulkan_android.h>
							 | 
						||
| 
								 | 
							
								#include <vulkan/vulkan_core.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								VkResult kinc_vulkan_create_surface(VkInstance instance, int window_index, VkSurfaceKHR *surface) {
							 | 
						||
| 
								 | 
							
									assert(app->window != NULL);
							 | 
						||
| 
								 | 
							
									VkAndroidSurfaceCreateInfoKHR createInfo = {};
							 | 
						||
| 
								 | 
							
									createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
							 | 
						||
| 
								 | 
							
									createInfo.pNext = NULL;
							 | 
						||
| 
								 | 
							
									createInfo.flags = 0;
							 | 
						||
| 
								 | 
							
									createInfo.window = app->window;
							 | 
						||
| 
								 | 
							
									return vkCreateAndroidSurfaceKHR(instance, &createInfo, NULL, surface);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_vulkan_get_instance_extensions(const char **names, int *index, int max) {
							 | 
						||
| 
								 | 
							
									assert(*index + 1 < max);
							 | 
						||
| 
								 | 
							
									names[(*index)++] = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								VkBool32 kinc_vulkan_get_physical_device_presentation_support(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex) {
							 | 
						||
| 
								 | 
							
									// https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_KHR_android_surface.html#_issues
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									// 1) Does Android need a way to query for compatibility between a particular physical device (and queue family?)
							 | 
						||
| 
								 | 
							
									// and a specific Android display?
							 | 
						||
| 
								 | 
							
									// RESOLVED: No. Currently on Android, any physical device is expected to be able to present to the system compositor,
							 | 
						||
| 
								 | 
							
									// and all queue families must support the necessary image layout transitions and synchronization operations.
							 | 
						||
| 
								 | 
							
									return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef KINC_VULKAN
							 | 
						||
| 
								 | 
							
								void kinc_egl_init_window(int window);
							 | 
						||
| 
								 | 
							
								void kinc_egl_destroy_window(int window);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#ifdef KINC_VULKAN
							 | 
						||
| 
								 | 
							
								void kinc_vulkan_init_window(int window);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void initDisplay() {
							 | 
						||
| 
								 | 
							
								#ifndef KINC_VULKAN
							 | 
						||
| 
								 | 
							
									kinc_egl_init_window(0);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#ifdef KINC_VULKAN
							 | 
						||
| 
								 | 
							
									kinc_vulkan_init_window(0);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void termDisplay() {
							 | 
						||
| 
								 | 
							
								#ifndef KINC_VULKAN
							 | 
						||
| 
								 | 
							
									kinc_egl_destroy_window(0);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void updateAppForegroundStatus(bool displayIsInitializedValue, bool appIsForegroundValue) {
							 | 
						||
| 
								 | 
							
									bool oldStatus = displayIsInitialized && appIsForeground;
							 | 
						||
| 
								 | 
							
									displayIsInitialized = displayIsInitializedValue;
							 | 
						||
| 
								 | 
							
									appIsForeground = appIsForegroundValue;
							 | 
						||
| 
								 | 
							
									bool newStatus = displayIsInitialized && appIsForeground;
							 | 
						||
| 
								 | 
							
									if (oldStatus != newStatus) {
							 | 
						||
| 
								 | 
							
										if (newStatus) {
							 | 
						||
| 
								 | 
							
											kinc_internal_foreground_callback();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else {
							 | 
						||
| 
								 | 
							
											kinc_internal_background_callback();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static bool isGamepadEvent(AInputEvent *event) {
							 | 
						||
| 
								 | 
							
									return ((AInputEvent_getSource(event) & AINPUT_SOURCE_GAMEPAD) == AINPUT_SOURCE_GAMEPAD ||
							 | 
						||
| 
								 | 
							
									        (AInputEvent_getSource(event) & AINPUT_SOURCE_JOYSTICK) == AINPUT_SOURCE_JOYSTICK ||
							 | 
						||
| 
								 | 
							
									        (AInputEvent_getSource(event) & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static bool isPenEvent(AInputEvent *event) {
							 | 
						||
| 
								 | 
							
									return (AInputEvent_getSource(event) & AINPUT_SOURCE_STYLUS) == AINPUT_SOURCE_STYLUS;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void touchInput(AInputEvent *event) {
							 | 
						||
| 
								 | 
							
									int action = AMotionEvent_getAction(event);
							 | 
						||
| 
								 | 
							
									int index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
							 | 
						||
| 
								 | 
							
									int id = AMotionEvent_getPointerId(event, index);
							 | 
						||
| 
								 | 
							
									float x = AMotionEvent_getX(event, index);
							 | 
						||
| 
								 | 
							
									float y = AMotionEvent_getY(event, index);
							 | 
						||
| 
								 | 
							
									switch (action & AMOTION_EVENT_ACTION_MASK) {
							 | 
						||
| 
								 | 
							
									case AMOTION_EVENT_ACTION_DOWN:
							 | 
						||
| 
								 | 
							
									case AMOTION_EVENT_ACTION_POINTER_DOWN:
							 | 
						||
| 
								 | 
							
										if (id == 0) {
							 | 
						||
| 
								 | 
							
											kinc_internal_mouse_trigger_press(0, 0, x, y);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										if (isPenEvent(event)) {
							 | 
						||
| 
								 | 
							
											kinc_internal_pen_trigger_press(0, x, y, AMotionEvent_getPressure(event, index));
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										kinc_internal_surface_trigger_touch_start(id, x, y);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case AMOTION_EVENT_ACTION_MOVE:
							 | 
						||
| 
								 | 
							
									case AMOTION_EVENT_ACTION_HOVER_MOVE: {
							 | 
						||
| 
								 | 
							
										size_t count = AMotionEvent_getPointerCount(event);
							 | 
						||
| 
								 | 
							
										for (int i = 0; i < count; ++i) {
							 | 
						||
| 
								 | 
							
											id = AMotionEvent_getPointerId(event, i);
							 | 
						||
| 
								 | 
							
											x = AMotionEvent_getX(event, i);
							 | 
						||
| 
								 | 
							
											y = AMotionEvent_getY(event, i);
							 | 
						||
| 
								 | 
							
											if (id == 0) {
							 | 
						||
| 
								 | 
							
												kinc_internal_mouse_trigger_move(0, x, y);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											if (isPenEvent(event)) {
							 | 
						||
| 
								 | 
							
												kinc_internal_pen_trigger_move(0, x, y, AMotionEvent_getPressure(event, index));
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											kinc_internal_surface_trigger_move(id, x, y);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									} break;
							 | 
						||
| 
								 | 
							
									case AMOTION_EVENT_ACTION_UP:
							 | 
						||
| 
								 | 
							
									case AMOTION_EVENT_ACTION_CANCEL:
							 | 
						||
| 
								 | 
							
									case AMOTION_EVENT_ACTION_POINTER_UP:
							 | 
						||
| 
								 | 
							
										if (id == 0) {
							 | 
						||
| 
								 | 
							
											kinc_internal_mouse_trigger_release(0, 0, x, y);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										if (isPenEvent(event)) {
							 | 
						||
| 
								 | 
							
											kinc_internal_pen_trigger_release(0, x, y, AMotionEvent_getPressure(event, index));
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										kinc_internal_surface_trigger_touch_end(id, x, y);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case AMOTION_EVENT_ACTION_SCROLL:
							 | 
						||
| 
								 | 
							
										if (id == 0) {
							 | 
						||
| 
								 | 
							
											float scroll = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_VSCROLL, 0);
							 | 
						||
| 
								 | 
							
											kinc_internal_mouse_trigger_scroll(0, -(int)scroll);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static float last_x = 0.0f;
							 | 
						||
| 
								 | 
							
								static float last_y = 0.0f;
							 | 
						||
| 
								 | 
							
								static float last_l = 0.0f;
							 | 
						||
| 
								 | 
							
								static float last_r = 0.0f;
							 | 
						||
| 
								 | 
							
								static bool last_hat_left = false;
							 | 
						||
| 
								 | 
							
								static bool last_hat_right = false;
							 | 
						||
| 
								 | 
							
								static bool last_hat_up = false;
							 | 
						||
| 
								 | 
							
								static bool last_hat_down = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int32_t input(struct android_app *app, AInputEvent *event) {
							 | 
						||
| 
								 | 
							
									if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
							 | 
						||
| 
								 | 
							
										int source = AInputEvent_getSource(event);
							 | 
						||
| 
								 | 
							
										if (((source & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) || ((source & AINPUT_SOURCE_MOUSE) == AINPUT_SOURCE_MOUSE)) {
							 | 
						||
| 
								 | 
							
											touchInput(event);
							 | 
						||
| 
								 | 
							
											return 1;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else if ((source & AINPUT_SOURCE_JOYSTICK) == AINPUT_SOURCE_JOYSTICK) {
							 | 
						||
| 
								 | 
							
											// int id = AInputEvent_getDeviceId(event);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											float x = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_X, 0);
							 | 
						||
| 
								 | 
							
											if (x != last_x) {
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_axis(0, 0, x);
							 | 
						||
| 
								 | 
							
												last_x = x;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											float y = -AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_Y, 0);
							 | 
						||
| 
								 | 
							
											if (y != last_y) {
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_axis(0, 1, y);
							 | 
						||
| 
								 | 
							
												last_y = y;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											float l = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_LTRIGGER, 0);
							 | 
						||
| 
								 | 
							
											if (l != last_l) {
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 6, l);
							 | 
						||
| 
								 | 
							
												last_l = l;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											float r = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_RTRIGGER, 0);
							 | 
						||
| 
								 | 
							
											if (r != last_r) {
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 7, r);
							 | 
						||
| 
								 | 
							
												last_r = r;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											float hat_x = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_HAT_X, 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											bool hat_left = false;
							 | 
						||
| 
								 | 
							
											bool hat_right = false;
							 | 
						||
| 
								 | 
							
											if (hat_x < -0.5f) {
							 | 
						||
| 
								 | 
							
												hat_left = true;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else if (hat_x > 0.5f) {
							 | 
						||
| 
								 | 
							
												hat_right = true;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											float hat_y = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_HAT_Y, 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											bool hat_up = false;
							 | 
						||
| 
								 | 
							
											bool hat_down = false;
							 | 
						||
| 
								 | 
							
											if (hat_y < -0.5f) {
							 | 
						||
| 
								 | 
							
												hat_up = true;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else if (hat_y > 0.5f) {
							 | 
						||
| 
								 | 
							
												hat_down = true;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (hat_left != last_hat_left) {
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 14, hat_left ? 1.0f : 0.0f);
							 | 
						||
| 
								 | 
							
												last_hat_left = hat_left;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (hat_right != last_hat_right) {
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 15, hat_right ? 1.0f : 0.0f);
							 | 
						||
| 
								 | 
							
												last_hat_right = hat_right;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (hat_up != last_hat_up) {
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 12, hat_up ? 1.0f : 0.0f);
							 | 
						||
| 
								 | 
							
												last_hat_up = hat_up;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (hat_down != last_hat_down) {
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 13, hat_down ? 1.0f : 0.0f);
							 | 
						||
| 
								 | 
							
												last_hat_down = hat_down;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return 1;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) {
							 | 
						||
| 
								 | 
							
										int32_t code = AKeyEvent_getKeyCode(event);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN) {
							 | 
						||
| 
								 | 
							
											int shift = AKeyEvent_getMetaState(event) & AMETA_SHIFT_ON;
							 | 
						||
| 
								 | 
							
											if (shift) {
							 | 
						||
| 
								 | 
							
												switch (code) {
							 | 
						||
| 
								 | 
							
												case AKEYCODE_1:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_EXCLAMATION);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press('!');
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_4:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_DOLLAR);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press('$');
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_5:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_PERCENT);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press('%');
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_6:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_CIRCUMFLEX);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press('^');
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_7:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_AMPERSAND);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press('&');
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_9:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_OPEN_PAREN);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press('(');
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_0:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_CLOSE_PAREN);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press(')');
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_COMMA:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_LESS_THAN);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press('<');
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_PERIOD:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_GREATER_THAN);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press('>');
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_MINUS:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_UNDERSCORE);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press('_');
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_SLASH:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_QUESTIONMARK);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press('?');
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_BACKSLASH:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_PIPE);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press('|');
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_LEFT_BRACKET:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_OPEN_CURLY_BRACKET);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press('{');
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_RIGHT_BRACKET:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_CLOSE_CURLY_BRACKET);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press('}');
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_SEMICOLON:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_COLON);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press(':');
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_APOSTROPHE:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_DOUBLE_QUOTE);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press('"');
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_GRAVE:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_TILDE);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press('~');
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											switch (code) {
							 | 
						||
| 
								 | 
							
											case AKEYCODE_SHIFT_LEFT:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_SHIFT_RIGHT:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_SHIFT);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_DEL:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_BACKSPACE);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_ENTER:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_ENTER:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_RETURN);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_DPAD_CENTER:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_B:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 1, 1);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BACK:
							 | 
						||
| 
								 | 
							
												if (AKeyEvent_getMetaState(event) & AMETA_ALT_ON) { // Xperia Play
							 | 
						||
| 
								 | 
							
													kinc_internal_gamepad_trigger_button(0, 1, 1);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_BACK);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_A:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 0, 1);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_Y:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 3, 1);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_X:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 2, 1);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_L1:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 4, 1);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_R1:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 5, 1);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_L2:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 6, 1);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_R2:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 7, 1);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_SELECT:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 8, 1);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_START:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 9, 1);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_THUMBL:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 10, 1);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_THUMBR:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 11, 1);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_DPAD_UP:
							 | 
						||
| 
								 | 
							
												if (isGamepadEvent(event))
							 | 
						||
| 
								 | 
							
													kinc_internal_gamepad_trigger_button(0, 12, 1);
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_UP);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_DPAD_DOWN:
							 | 
						||
| 
								 | 
							
												if (isGamepadEvent(event))
							 | 
						||
| 
								 | 
							
													kinc_internal_gamepad_trigger_button(0, 13, 1);
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_DOWN);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_DPAD_LEFT:
							 | 
						||
| 
								 | 
							
												if (isGamepadEvent(event))
							 | 
						||
| 
								 | 
							
													kinc_internal_gamepad_trigger_button(0, 14, 1);
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_LEFT);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_DPAD_RIGHT:
							 | 
						||
| 
								 | 
							
												if (isGamepadEvent(event))
							 | 
						||
| 
								 | 
							
													kinc_internal_gamepad_trigger_button(0, 15, 1);
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(KINC_KEY_RIGHT);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_MODE:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 16, 1);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_STAR:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_MULTIPLY:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_MULTIPLY);
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_press('*');
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_POUND:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_HASH);
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_press('#');
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_COMMA:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_COMMA:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_COMMA);
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_press(',');
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_PERIOD:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_DOT:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_PERIOD);
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_press('.');
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_SPACE:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_SPACE);
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_press(' ');
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_MINUS:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_SUBTRACT:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_HYPHEN_MINUS);
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_press('-');
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_EQUALS:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_EQUALS:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_EQUALS);
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_press('=');
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_LEFT_BRACKET:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_LEFT_PAREN:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_OPEN_BRACKET);
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_press('[');
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_RIGHT_BRACKET:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_RIGHT_PAREN:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_CLOSE_BRACKET);
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_press(']');
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BACKSLASH:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_BACK_SLASH);
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_press('\\');
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_SEMICOLON:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_SEMICOLON);
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_press(';');
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_APOSTROPHE:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_QUOTE);
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_press('\'');
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_GRAVE:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_BACK_QUOTE);
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_press('`');
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_SLASH:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_DIVIDE:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_SLASH);
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_press('/');
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_AT:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_AT);
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_press('@');
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_PLUS:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_ADD:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_down(KINC_KEY_PLUS);
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_press('+');
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											// (DK) Amazon FireTV remote/controller mappings
							 | 
						||
| 
								 | 
							
											// (DK) TODO handle multiple pads (up to 4 possible)
							 | 
						||
| 
								 | 
							
											case AKEYCODE_MENU:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 9, 1);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_MEDIA_REWIND:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 10, 1);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_MEDIA_FAST_FORWARD:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 11, 1);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_MEDIA_PLAY_PAUSE:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 12, 1);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											// (DK) /Amazon FireTV remote/controller mappings
							 | 
						||
| 
								 | 
							
											default:
							 | 
						||
| 
								 | 
							
												if (code >= AKEYCODE_NUMPAD_0 && code <= AKEYCODE_NUMPAD_9) {
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(code + KINC_KEY_NUMPAD_0 - AKEYCODE_NUMPAD_0);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press(code + KINC_KEY_NUMPAD_0 - AKEYCODE_NUMPAD_0);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if (code >= AKEYCODE_0 && code <= AKEYCODE_9) {
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(code + KINC_KEY_0 - AKEYCODE_0);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press(code + KINC_KEY_0 - AKEYCODE_0);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if (code >= AKEYCODE_A && code <= AKEYCODE_Z) {
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_down(code + KINC_KEY_A - AKEYCODE_A);
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_press(code + (shift ? 'A' : 'a') - AKEYCODE_A);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_UP) {
							 | 
						||
| 
								 | 
							
											int shift = AKeyEvent_getMetaState(event) & AMETA_SHIFT_ON;
							 | 
						||
| 
								 | 
							
											if (shift) {
							 | 
						||
| 
								 | 
							
												switch (code) {
							 | 
						||
| 
								 | 
							
												case AKEYCODE_1:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_EXCLAMATION);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_4:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_DOLLAR);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_5:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_PERCENT);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_6:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_CIRCUMFLEX);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_7:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_AMPERSAND);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_9:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_OPEN_PAREN);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_0:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_CLOSE_PAREN);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_COMMA:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_LESS_THAN);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_PERIOD:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_GREATER_THAN);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_MINUS:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_UNDERSCORE);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_SLASH:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_QUESTIONMARK);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_BACKSLASH:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_PIPE);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_LEFT_BRACKET:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_OPEN_CURLY_BRACKET);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_RIGHT_BRACKET:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_CLOSE_CURLY_BRACKET);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_SEMICOLON:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_COLON);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_APOSTROPHE:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_DOUBLE_QUOTE);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												case AKEYCODE_GRAVE:
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_TILDE);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											switch (code) {
							 | 
						||
| 
								 | 
							
											case AKEYCODE_SHIFT_LEFT:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_SHIFT_RIGHT:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_SHIFT);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_DEL:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_BACKSPACE);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_ENTER:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_RETURN);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_DPAD_CENTER:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_B:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 1, 0);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BACK:
							 | 
						||
| 
								 | 
							
												if (AKeyEvent_getMetaState(event) & AMETA_ALT_ON) { // Xperia Play
							 | 
						||
| 
								 | 
							
													kinc_internal_gamepad_trigger_button(0, 1, 0);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else {
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_BACK);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_A:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 0, 0);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_Y:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 3, 0);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_X:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 2, 0);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_L1:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 4, 0);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_R1:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 5, 0);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_L2:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 6, 0);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_R2:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 7, 0);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_SELECT:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 8, 0);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_START:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 9, 0);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_THUMBL:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 10, 0);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_THUMBR:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 11, 0);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_DPAD_UP:
							 | 
						||
| 
								 | 
							
												if (isGamepadEvent(event))
							 | 
						||
| 
								 | 
							
													kinc_internal_gamepad_trigger_button(0, 12, 0);
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_UP);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_DPAD_DOWN:
							 | 
						||
| 
								 | 
							
												if (isGamepadEvent(event))
							 | 
						||
| 
								 | 
							
													kinc_internal_gamepad_trigger_button(0, 13, 0);
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_DOWN);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_DPAD_LEFT:
							 | 
						||
| 
								 | 
							
												if (isGamepadEvent(event))
							 | 
						||
| 
								 | 
							
													kinc_internal_gamepad_trigger_button(0, 14, 0);
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_LEFT);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_DPAD_RIGHT:
							 | 
						||
| 
								 | 
							
												if (isGamepadEvent(event))
							 | 
						||
| 
								 | 
							
													kinc_internal_gamepad_trigger_button(0, 15, 0);
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(KINC_KEY_RIGHT);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BUTTON_MODE:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 16, 0);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_STAR:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_MULTIPLY:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_MULTIPLY);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_POUND:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_HASH);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_COMMA:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_COMMA:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_COMMA);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_PERIOD:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_DOT:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_PERIOD);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_SPACE:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_SPACE);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_MINUS:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_SUBTRACT:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_HYPHEN_MINUS);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_EQUALS:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_EQUALS:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_EQUALS);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_LEFT_BRACKET:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_LEFT_PAREN:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_OPEN_BRACKET);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_RIGHT_BRACKET:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_RIGHT_PAREN:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_CLOSE_BRACKET);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_BACKSLASH:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_BACK_SLASH);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_SEMICOLON:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_SEMICOLON);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_APOSTROPHE:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_QUOTE);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_GRAVE:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_BACK_QUOTE);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_SLASH:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_DIVIDE:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_SLASH);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_AT:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_AT);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_PLUS:
							 | 
						||
| 
								 | 
							
											case AKEYCODE_NUMPAD_ADD:
							 | 
						||
| 
								 | 
							
												kinc_internal_keyboard_trigger_key_up(KINC_KEY_PLUS);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											// (DK) Amazon FireTV remote/controller mappings
							 | 
						||
| 
								 | 
							
											// (DK) TODO handle multiple pads (up to 4 possible)
							 | 
						||
| 
								 | 
							
											case AKEYCODE_MENU:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 9, 0);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_MEDIA_REWIND:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 10, 0);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_MEDIA_FAST_FORWARD:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 11, 0);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											case AKEYCODE_MEDIA_PLAY_PAUSE:
							 | 
						||
| 
								 | 
							
												kinc_internal_gamepad_trigger_button(0, 12, 0);
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											// (DK) /Amazon FireTV remote/controller mappings
							 | 
						||
| 
								 | 
							
											default:
							 | 
						||
| 
								 | 
							
												if (code >= AKEYCODE_NUMPAD_0 && code <= AKEYCODE_NUMPAD_9) {
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(code + KINC_KEY_NUMPAD_0 - AKEYCODE_NUMPAD_0);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if (code >= AKEYCODE_0 && code <= AKEYCODE_9) {
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(code + KINC_KEY_0 - AKEYCODE_0);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else if (code >= AKEYCODE_A && code <= AKEYCODE_Z) {
							 | 
						||
| 
								 | 
							
													kinc_internal_keyboard_trigger_key_up(code + KINC_KEY_A - AKEYCODE_A);
							 | 
						||
| 
								 | 
							
													return 1;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void cmd(struct android_app *app, int32_t cmd) {
							 | 
						||
| 
								 | 
							
									switch (cmd) {
							 | 
						||
| 
								 | 
							
									case APP_CMD_SAVE_STATE:
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case APP_CMD_INIT_WINDOW:
							 | 
						||
| 
								 | 
							
										if (app->window != NULL) {
							 | 
						||
| 
								 | 
							
											if (!started) {
							 | 
						||
| 
								 | 
							
												started = true;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else {
							 | 
						||
| 
								 | 
							
												initDisplay();
							 | 
						||
| 
								 | 
							
												kinc_g4_swap_buffers();
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											updateAppForegroundStatus(true, appIsForeground);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case APP_CMD_TERM_WINDOW:
							 | 
						||
| 
								 | 
							
										termDisplay();
							 | 
						||
| 
								 | 
							
										updateAppForegroundStatus(false, appIsForeground);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case APP_CMD_GAINED_FOCUS:
							 | 
						||
| 
								 | 
							
										if (accelerometerSensor != NULL) {
							 | 
						||
| 
								 | 
							
											ASensorEventQueue_enableSensor(sensorEventQueue, accelerometerSensor);
							 | 
						||
| 
								 | 
							
											ASensorEventQueue_setEventRate(sensorEventQueue, accelerometerSensor, (1000L / 60) * 1000);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										if (gyroSensor != NULL) {
							 | 
						||
| 
								 | 
							
											ASensorEventQueue_enableSensor(sensorEventQueue, gyroSensor);
							 | 
						||
| 
								 | 
							
											ASensorEventQueue_setEventRate(sensorEventQueue, gyroSensor, (1000L / 60) * 1000);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case APP_CMD_LOST_FOCUS:
							 | 
						||
| 
								 | 
							
										if (accelerometerSensor != NULL) {
							 | 
						||
| 
								 | 
							
											ASensorEventQueue_disableSensor(sensorEventQueue, accelerometerSensor);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										if (gyroSensor != NULL) {
							 | 
						||
| 
								 | 
							
											ASensorEventQueue_disableSensor(sensorEventQueue, gyroSensor);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case APP_CMD_START:
							 | 
						||
| 
								 | 
							
										updateAppForegroundStatus(displayIsInitialized, true);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case APP_CMD_RESUME:
							 | 
						||
| 
								 | 
							
										kinc_internal_resume_callback();
							 | 
						||
| 
								 | 
							
										resumeAudio();
							 | 
						||
| 
								 | 
							
										paused = false;
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case APP_CMD_PAUSE:
							 | 
						||
| 
								 | 
							
										kinc_internal_pause_callback();
							 | 
						||
| 
								 | 
							
										pauseAudio();
							 | 
						||
| 
								 | 
							
										paused = true;
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case APP_CMD_STOP:
							 | 
						||
| 
								 | 
							
										updateAppForegroundStatus(displayIsInitialized, false);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case APP_CMD_DESTROY:
							 | 
						||
| 
								 | 
							
										kinc_internal_shutdown_callback();
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case APP_CMD_CONFIG_CHANGED: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void resize(ANativeActivity *activity, ANativeWindow *window) {
							 | 
						||
| 
								 | 
							
									activityJustResized = true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								ANativeActivity *kinc_android_get_activity(void) {
							 | 
						||
| 
								 | 
							
									return activity;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								AAssetManager *kinc_android_get_asset_manager(void) {
							 | 
						||
| 
								 | 
							
									return activity->assetManager;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								jclass kinc_android_find_class(JNIEnv *env, const char *name) {
							 | 
						||
| 
								 | 
							
									jobject nativeActivity = activity->clazz;
							 | 
						||
| 
								 | 
							
									jclass acl = (*env)->GetObjectClass(env, nativeActivity);
							 | 
						||
| 
								 | 
							
									jmethodID getClassLoader = (*env)->GetMethodID(env, acl, "getClassLoader", "()Ljava/lang/ClassLoader;");
							 | 
						||
| 
								 | 
							
									jobject cls = (*env)->CallObjectMethod(env, nativeActivity, getClassLoader);
							 | 
						||
| 
								 | 
							
									jclass classLoader = (*env)->FindClass(env, "java/lang/ClassLoader");
							 | 
						||
| 
								 | 
							
									jmethodID findClass = (*env)->GetMethodID(env, classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
							 | 
						||
| 
								 | 
							
									jstring strClassName = (*env)->NewStringUTF(env, name);
							 | 
						||
| 
								 | 
							
									jclass clazz = (jclass)((*env)->CallObjectMethod(env, cls, findClass, strClassName));
							 | 
						||
| 
								 | 
							
									(*env)->DeleteLocalRef(env, strClassName);
							 | 
						||
| 
								 | 
							
									return clazz;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define UNICODE_STACK_SIZE 256
							 | 
						||
| 
								 | 
							
								static uint16_t unicode_stack[UNICODE_STACK_SIZE];
							 | 
						||
| 
								 | 
							
								static int unicode_stack_index = 0;
							 | 
						||
| 
								 | 
							
								static kinc_mutex_t unicode_mutex;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								JNIEXPORT void JNICALL Java_tech_kinc_KincActivity_nativeKincKeyPress(JNIEnv *env, jobject jobj, jstring chars) {
							 | 
						||
| 
								 | 
							
									const jchar *text = (*env)->GetStringChars(env, chars, NULL);
							 | 
						||
| 
								 | 
							
									const jsize length = (*env)->GetStringLength(env, chars);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									kinc_mutex_lock(&unicode_mutex);
							 | 
						||
| 
								 | 
							
									for (jsize i = 0; i < length && unicode_stack_index < UNICODE_STACK_SIZE; ++i) {
							 | 
						||
| 
								 | 
							
										unicode_stack[unicode_stack_index++] = text[i];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									kinc_mutex_unlock(&unicode_mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									(*env)->ReleaseStringChars(env, chars, text);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void KincAndroidKeyboardInit() {
							 | 
						||
| 
								 | 
							
									JNIEnv *env;
							 | 
						||
| 
								 | 
							
									(*activity->vm)->AttachCurrentThread(activity->vm, &env, NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									jclass clazz = kinc_android_find_class(env, "tech.kinc.KincActivity");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// String chars
							 | 
						||
| 
								 | 
							
									JNINativeMethod methodTable[] = {{"nativeKincKeyPress", "(Ljava/lang/String;)V", (void *)Java_tech_kinc_KincActivity_nativeKincKeyPress}};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int methodTableSize = sizeof(methodTable) / sizeof(methodTable[0]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int failure = (*env)->RegisterNatives(env, clazz, methodTable, methodTableSize);
							 | 
						||
| 
								 | 
							
									if (failure != 0) {
							 | 
						||
| 
								 | 
							
										kinc_log(KINC_LOG_LEVEL_WARNING, "Failed to register KincActivity.nativeKincKeyPress");
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									(*activity->vm)->DetachCurrentThread(activity->vm);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static bool keyboard_active = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_keyboard_show() {
							 | 
						||
| 
								 | 
							
									keyboard_active = true;
							 | 
						||
| 
								 | 
							
									JNIEnv *env;
							 | 
						||
| 
								 | 
							
									(*activity->vm)->AttachCurrentThread(activity->vm, &env, NULL);
							 | 
						||
| 
								 | 
							
									jclass koreActivityClass = kinc_android_find_class(env, "tech.kinc.KincActivity");
							 | 
						||
| 
								 | 
							
									(*env)->CallStaticVoidMethod(env, koreActivityClass, (*env)->GetStaticMethodID(env, koreActivityClass, "showKeyboard", "()V"));
							 | 
						||
| 
								 | 
							
									(*activity->vm)->DetachCurrentThread(activity->vm);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_keyboard_hide() {
							 | 
						||
| 
								 | 
							
									keyboard_active = false;
							 | 
						||
| 
								 | 
							
									JNIEnv *env;
							 | 
						||
| 
								 | 
							
									(*activity->vm)->AttachCurrentThread(activity->vm, &env, NULL);
							 | 
						||
| 
								 | 
							
									jclass koreActivityClass = kinc_android_find_class(env, "tech.kinc.KincActivity");
							 | 
						||
| 
								 | 
							
									(*env)->CallStaticVoidMethod(env, koreActivityClass, (*env)->GetStaticMethodID(env, koreActivityClass, "hideKeyboard", "()V"));
							 | 
						||
| 
								 | 
							
									(*activity->vm)->DetachCurrentThread(activity->vm);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool kinc_keyboard_active() {
							 | 
						||
| 
								 | 
							
									return keyboard_active;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_load_url(const char *url) {
							 | 
						||
| 
								 | 
							
									JNIEnv *env;
							 | 
						||
| 
								 | 
							
									(*activity->vm)->AttachCurrentThread(activity->vm, &env, NULL);
							 | 
						||
| 
								 | 
							
									jclass koreActivityClass = kinc_android_find_class(env, "tech.kinc.KincActivity");
							 | 
						||
| 
								 | 
							
									jstring jurl = (*env)->NewStringUTF(env, url);
							 | 
						||
| 
								 | 
							
									(*env)->CallStaticVoidMethod(env, koreActivityClass, (*env)->GetStaticMethodID(env, koreActivityClass, "loadURL", "(Ljava/lang/String;)V"), jurl);
							 | 
						||
| 
								 | 
							
									(*activity->vm)->DetachCurrentThread(activity->vm);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_vibrate(int ms) {
							 | 
						||
| 
								 | 
							
									JNIEnv *env;
							 | 
						||
| 
								 | 
							
									(*activity->vm)->AttachCurrentThread(activity->vm, &env, NULL);
							 | 
						||
| 
								 | 
							
									jclass koreActivityClass = kinc_android_find_class(env, "tech.kinc.KincActivity");
							 | 
						||
| 
								 | 
							
									(*env)->CallStaticVoidMethod(env, koreActivityClass, (*env)->GetStaticMethodID(env, koreActivityClass, "vibrate", "(I)V"), ms);
							 | 
						||
| 
								 | 
							
									(*activity->vm)->DetachCurrentThread(activity->vm);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const char *kinc_language() {
							 | 
						||
| 
								 | 
							
									JNIEnv *env;
							 | 
						||
| 
								 | 
							
									(*activity->vm)->AttachCurrentThread(activity->vm, &env, NULL);
							 | 
						||
| 
								 | 
							
									jclass koreActivityClass = kinc_android_find_class(env, "tech.kinc.KincActivity");
							 | 
						||
| 
								 | 
							
									jstring s = (jstring)(*env)->CallStaticObjectMethod(env, koreActivityClass,
							 | 
						||
| 
								 | 
							
									                                                    (*env)->GetStaticMethodID(env, koreActivityClass, "getLanguage", "()Ljava/lang/String;"));
							 | 
						||
| 
								 | 
							
									const char *str = (*env)->GetStringUTFChars(env, s, 0);
							 | 
						||
| 
								 | 
							
									(*activity->vm)->DetachCurrentThread(activity->vm);
							 | 
						||
| 
								 | 
							
									return str;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef KINC_VULKAN
							 | 
						||
| 
								 | 
							
								bool kinc_vulkan_internal_get_size(int *width, int *height);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef KINC_EGL
							 | 
						||
| 
								 | 
							
								extern int kinc_egl_width(int window);
							 | 
						||
| 
								 | 
							
								extern int kinc_egl_height(int window);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_android_width() {
							 | 
						||
| 
								 | 
							
								#if defined(KINC_EGL)
							 | 
						||
| 
								 | 
							
									return kinc_egl_width(0);
							 | 
						||
| 
								 | 
							
								#elif defined(KINC_VULKAN)
							 | 
						||
| 
								 | 
							
									int width, height;
							 | 
						||
| 
								 | 
							
									if (kinc_vulkan_internal_get_size(&width, &height)) {
							 | 
						||
| 
								 | 
							
										return width;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
									{ return ANativeWindow_getWidth(app->window); }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_android_height() {
							 | 
						||
| 
								 | 
							
								#if defined(KINC_EGL)
							 | 
						||
| 
								 | 
							
									return kinc_egl_height(0);
							 | 
						||
| 
								 | 
							
								#elif defined(KINC_VULKAN)
							 | 
						||
| 
								 | 
							
									int width, height;
							 | 
						||
| 
								 | 
							
									if (kinc_vulkan_internal_get_size(&width, &height)) {
							 | 
						||
| 
								 | 
							
										return height;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
									{ return ANativeWindow_getHeight(app->window); }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const char *kinc_internal_save_path() {
							 | 
						||
| 
								 | 
							
									return kinc_android_get_activity()->internalDataPath;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const char *kinc_system_id() {
							 | 
						||
| 
								 | 
							
									return "Android";
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static const char *videoFormats[] = {"ts", NULL};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const char **kinc_video_formats() {
							 | 
						||
| 
								 | 
							
									return videoFormats;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_set_keep_screen_on(bool on) {
							 | 
						||
| 
								 | 
							
									if (on) {
							 | 
						||
| 
								 | 
							
										ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_KEEP_SCREEN_ON, 0);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else {
							 | 
						||
| 
								 | 
							
										ANativeActivity_setWindowFlags(activity, 0, AWINDOW_FLAG_KEEP_SCREEN_ON);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <kinc/input/acceleration.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/input/rotation.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/window.h>
							 | 
						||
| 
								 | 
							
								#include <sys/time.h>
							 | 
						||
| 
								 | 
							
								#include <time.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static __kernel_time_t start_sec = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								double kinc_frequency() {
							 | 
						||
| 
								 | 
							
									return 1000000.0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								kinc_ticks_t kinc_timestamp() {
							 | 
						||
| 
								 | 
							
									struct timeval now;
							 | 
						||
| 
								 | 
							
									gettimeofday(&now, NULL);
							 | 
						||
| 
								 | 
							
									return (kinc_ticks_t)(now.tv_sec - start_sec) * 1000000 + (kinc_ticks_t)(now.tv_usec);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								double kinc_time() {
							 | 
						||
| 
								 | 
							
									struct timeval now;
							 | 
						||
| 
								 | 
							
									gettimeofday(&now, NULL);
							 | 
						||
| 
								 | 
							
									return (double)(now.tv_sec - start_sec) + (now.tv_usec / 1000000.0);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_internal_resize(int window, int width, int height);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool kinc_internal_handle_messages(void) {
							 | 
						||
| 
								 | 
							
									kinc_mutex_lock(&unicode_mutex);
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < unicode_stack_index; ++i) {
							 | 
						||
| 
								 | 
							
										kinc_internal_keyboard_trigger_key_press(unicode_stack[i]);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									unicode_stack_index = 0;
							 | 
						||
| 
								 | 
							
									kinc_mutex_unlock(&unicode_mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int ident;
							 | 
						||
| 
								 | 
							
									int events;
							 | 
						||
| 
								 | 
							
									struct android_poll_source *source;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									while ((ident = ALooper_pollAll(paused ? -1 : 0, NULL, &events, (void **)&source)) >= 0) {
							 | 
						||
| 
								 | 
							
										if (source != NULL) {
							 | 
						||
| 
								 | 
							
											source->process(app, source);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (ident == LOOPER_ID_USER) {
							 | 
						||
| 
								 | 
							
											if (accelerometerSensor != NULL) {
							 | 
						||
| 
								 | 
							
												ASensorEvent event;
							 | 
						||
| 
								 | 
							
												while (ASensorEventQueue_getEvents(sensorEventQueue, &event, 1) > 0) {
							 | 
						||
| 
								 | 
							
													if (event.type == ASENSOR_TYPE_ACCELEROMETER) {
							 | 
						||
| 
								 | 
							
														kinc_internal_on_acceleration(event.acceleration.x, event.acceleration.y, event.acceleration.z);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													else if (event.type == ASENSOR_TYPE_GYROSCOPE) {
							 | 
						||
| 
								 | 
							
														kinc_internal_on_rotation(event.vector.x, event.vector.y, event.vector.z);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (app->destroyRequested != 0) {
							 | 
						||
| 
								 | 
							
											termDisplay();
							 | 
						||
| 
								 | 
							
											kinc_stop();
							 | 
						||
| 
								 | 
							
											return true;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (activityJustResized && app->window != NULL) {
							 | 
						||
| 
								 | 
							
										activityJustResized = false;
							 | 
						||
| 
								 | 
							
										int32_t width = kinc_android_width();
							 | 
						||
| 
								 | 
							
										int32_t height = kinc_android_height();
							 | 
						||
| 
								 | 
							
								#ifdef KINC_VULKAN
							 | 
						||
| 
								 | 
							
										kinc_internal_resize(0, width, height);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
										kinc_internal_call_resize_callback(0, width, height);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Get screen rotation
							 | 
						||
| 
								 | 
							
									/*
							 | 
						||
| 
								 | 
							
									JNIEnv* env;
							 | 
						||
| 
								 | 
							
									(*activity->vm)->AttachCurrentThread(&env, NULL);
							 | 
						||
| 
								 | 
							
									jclass koreActivityClass = KoreAndroid::findClass(env, "tech.kode.kore.KoreActivity");
							 | 
						||
| 
								 | 
							
									jmethodID koreActivityGetRotation = (*env)->GetStaticMethodID(koreActivityClass, "getRotation", "()I");
							 | 
						||
| 
								 | 
							
									screenRotation = (*env)->CallStaticIntMethod(koreActivityClass, koreActivityGetRotation);
							 | 
						||
| 
								 | 
							
									(*activity->vm)->DetachCurrentThread();
							 | 
						||
| 
								 | 
							
									*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool kinc_mouse_can_lock(void) {
							 | 
						||
| 
								 | 
							
									return false;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_mouse_show() {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_mouse_hide() {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_mouse_set_position(int window, int x, int y) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_internal_mouse_lock(int window) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_internal_mouse_unlock(void) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_mouse_get_position(int window, int *x, int *y) {
							 | 
						||
| 
								 | 
							
									x = 0;
							 | 
						||
| 
								 | 
							
									y = 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_mouse_set_cursor(int cursor_index) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_login() {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_unlock_achievement(int id) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool kinc_gamepad_connected(int num) {
							 | 
						||
| 
								 | 
							
									return num == 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_gamepad_rumble(int gamepad, float left, float right) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void initAndroidFileReader();
							 | 
						||
| 
								 | 
							
								void KoreAndroidVideoInit();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void android_main(struct android_app *application) {
							 | 
						||
| 
								 | 
							
									app_dummy();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									struct timeval now;
							 | 
						||
| 
								 | 
							
									gettimeofday(&now, NULL);
							 | 
						||
| 
								 | 
							
									start_sec = now.tv_sec;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									app = application;
							 | 
						||
| 
								 | 
							
									activity = application->activity;
							 | 
						||
| 
								 | 
							
									initAndroidFileReader();
							 | 
						||
| 
								 | 
							
									KoreAndroidVideoInit();
							 | 
						||
| 
								 | 
							
									KincAndroidKeyboardInit();
							 | 
						||
| 
								 | 
							
									application->onAppCmd = cmd;
							 | 
						||
| 
								 | 
							
									application->onInputEvent = input;
							 | 
						||
| 
								 | 
							
									activity->callbacks->onNativeWindowResized = resize;
							 | 
						||
| 
								 | 
							
									// #ifndef KINC_VULKAN
							 | 
						||
| 
								 | 
							
									// 	glContext = ndk_helper::GLContext::GetInstance();
							 | 
						||
| 
								 | 
							
									// #endif
							 | 
						||
| 
								 | 
							
									sensorManager = ASensorManager_getInstance();
							 | 
						||
| 
								 | 
							
									accelerometerSensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_ACCELEROMETER);
							 | 
						||
| 
								 | 
							
									gyroSensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_GYROSCOPE);
							 | 
						||
| 
								 | 
							
									sensorEventQueue = ASensorManager_createEventQueue(sensorManager, application->looper, LOOPER_ID_USER, NULL, NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									JNIEnv *env = NULL;
							 | 
						||
| 
								 | 
							
									(*kinc_android_get_activity()->vm)->AttachCurrentThread(kinc_android_get_activity()->vm, &env, NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									jclass koreMoviePlayerClass = kinc_android_find_class(env, "tech.kinc.KincMoviePlayer");
							 | 
						||
| 
								 | 
							
									jmethodID updateAll = (*env)->GetStaticMethodID(env, koreMoviePlayerClass, "updateAll", "()V");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									while (!started) {
							 | 
						||
| 
								 | 
							
										kinc_internal_handle_messages();
							 | 
						||
| 
								 | 
							
										(*env)->CallStaticVoidMethod(env, koreMoviePlayerClass, updateAll);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									(*kinc_android_get_activity()->vm)->DetachCurrentThread(kinc_android_get_activity()->vm);
							 | 
						||
| 
								 | 
							
									kickstart(0, NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									(*activity->vm)->AttachCurrentThread(activity->vm, &env, NULL);
							 | 
						||
| 
								 | 
							
									jclass koreActivityClass = kinc_android_find_class(env, "tech.kinc.KincActivity");
							 | 
						||
| 
								 | 
							
									jmethodID FinishHim = (*env)->GetStaticMethodID(env, koreActivityClass, "stop", "()V");
							 | 
						||
| 
								 | 
							
									(*env)->CallStaticVoidMethod(env, koreActivityClass, FinishHim);
							 | 
						||
| 
								 | 
							
									(*activity->vm)->DetachCurrentThread(activity->vm);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef KINC_KONG
							 | 
						||
| 
								 | 
							
								void kong_init(void);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_init(const char *name, int width, int height, struct kinc_window_options *win, struct kinc_framebuffer_options *frame) {
							 | 
						||
| 
								 | 
							
									kinc_mutex_init(&unicode_mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									kinc_window_options_t default_win;
							 | 
						||
| 
								 | 
							
									if (win == NULL) {
							 | 
						||
| 
								 | 
							
										kinc_window_options_set_defaults(&default_win);
							 | 
						||
| 
								 | 
							
										win = &default_win;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									win->width = width;
							 | 
						||
| 
								 | 
							
									win->height = height;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									kinc_framebuffer_options_t default_frame;
							 | 
						||
| 
								 | 
							
									if (frame == NULL) {
							 | 
						||
| 
								 | 
							
										kinc_framebuffer_options_set_defaults(&default_frame);
							 | 
						||
| 
								 | 
							
										frame = &default_frame;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									kinc_g4_internal_init();
							 | 
						||
| 
								 | 
							
									kinc_g4_internal_init_window(0, frame->depth_bits, frame->stencil_bits, true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef KINC_KONG
							 | 
						||
| 
								 | 
							
									kong_init();
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									kinc_internal_gamepad_trigger_connect(0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_internal_shutdown(void) {
							 | 
						||
| 
								 | 
							
									kinc_internal_gamepad_trigger_disconnect(0);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const char *kinc_gamepad_vendor(int gamepad) {
							 | 
						||
| 
								 | 
							
									return "Google";
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const char *kinc_gamepad_product_name(int gamepad) {
							 | 
						||
| 
								 | 
							
									return "gamepad";
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <kinc/io/filereader.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define CLASS_NAME "android/app/NativeActivity"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void initAndroidFileReader(void) {
							 | 
						||
| 
								 | 
							
									if (activity == NULL) {
							 | 
						||
| 
								 | 
							
										kinc_log(KINC_LOG_LEVEL_ERROR, "Android activity is NULL");
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									JNIEnv *env;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									(*activity->vm)->AttachCurrentThread(activity->vm, &env, NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									jclass android_app_NativeActivity = (*env)->FindClass(env, CLASS_NAME);
							 | 
						||
| 
								 | 
							
									jmethodID getExternalFilesDir = (*env)->GetMethodID(env, android_app_NativeActivity, "getExternalFilesDir", "(Ljava/lang/String;)Ljava/io/File;");
							 | 
						||
| 
								 | 
							
									jobject file = (*env)->CallObjectMethod(env, activity->clazz, getExternalFilesDir, NULL);
							 | 
						||
| 
								 | 
							
									jclass java_io_File = (*env)->FindClass(env, "java/io/File");
							 | 
						||
| 
								 | 
							
									jmethodID getPath = (*env)->GetMethodID(env, java_io_File, "getPath", "()Ljava/lang/String;");
							 | 
						||
| 
								 | 
							
									jstring jPath = (*env)->CallObjectMethod(env, file, getPath);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const char *path = (*env)->GetStringUTFChars(env, jPath, NULL);
							 | 
						||
| 
								 | 
							
									char *externalFilesDir = malloc(strlen(path) + 1);
							 | 
						||
| 
								 | 
							
									strcpy(externalFilesDir, path);
							 | 
						||
| 
								 | 
							
									kinc_internal_set_files_location(externalFilesDir);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									(*env)->ReleaseStringUTFChars(env, jPath, path);
							 | 
						||
| 
								 | 
							
									(*env)->DeleteLocalRef(env, jPath);
							 | 
						||
| 
								 | 
							
									(*activity->vm)->DetachCurrentThread(activity->vm);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static bool kinc_aasset_reader_close(kinc_file_reader_t *reader) {
							 | 
						||
| 
								 | 
							
									AAsset_close((struct AAsset *)reader->data);
							 | 
						||
| 
								 | 
							
									return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static size_t kinc_aasset_reader_read(kinc_file_reader_t *reader, void *data, size_t size) {
							 | 
						||
| 
								 | 
							
									return AAsset_read((struct AAsset *)reader->data, data, size);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static size_t kinc_aasset_reader_pos(kinc_file_reader_t *reader) {
							 | 
						||
| 
								 | 
							
									return (size_t)AAsset_seek((struct AAsset *)reader->data, 0, SEEK_CUR);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static bool kinc_aasset_reader_seek(kinc_file_reader_t *reader, size_t pos) {
							 | 
						||
| 
								 | 
							
									AAsset_seek((struct AAsset *)reader->data, pos, SEEK_SET);
							 | 
						||
| 
								 | 
							
									return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static bool kinc_aasset_reader_open(kinc_file_reader_t *reader, const char *filename, int type) {
							 | 
						||
| 
								 | 
							
									if (type != KINC_FILE_TYPE_ASSET)
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									reader->data = AAssetManager_open(kinc_android_get_asset_manager(), filename, AASSET_MODE_RANDOM);
							 | 
						||
| 
								 | 
							
									if (reader->data == NULL)
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									reader->size = AAsset_getLength((struct AAsset *)reader->data);
							 | 
						||
| 
								 | 
							
									reader->close = kinc_aasset_reader_close;
							 | 
						||
| 
								 | 
							
									reader->read = kinc_aasset_reader_read;
							 | 
						||
| 
								 | 
							
									reader->pos = kinc_aasset_reader_pos;
							 | 
						||
| 
								 | 
							
									reader->seek = kinc_aasset_reader_seek;
							 | 
						||
| 
								 | 
							
									return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool kinc_file_reader_open(kinc_file_reader_t *reader, const char *filename, int type) {
							 | 
						||
| 
								 | 
							
									memset(reader, 0, sizeof(*reader));
							 | 
						||
| 
								 | 
							
									return kinc_internal_file_reader_callback(reader, filename, type) ||
							 | 
						||
| 
								 | 
							
									       kinc_internal_file_reader_open(reader, filename, type) ||
							 | 
						||
| 
								 | 
							
									       kinc_aasset_reader_open(reader, filename, type);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_cpu_cores(void) {
							 | 
						||
| 
								 | 
							
									return kinc_hardware_threads();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_hardware_threads(void) {
							 | 
						||
| 
								 | 
							
									return sysconf(_SC_NPROCESSORS_ONLN);
							 | 
						||
| 
								 | 
							
								}
							 |