- Handle Android keyboard input in the engine.
- Extend example to show/hide a soft keyboard - Extend example to use fake mouse-events for gui (as it's probably going to take a long time until I get to working on a better solution) Input-handling needs some JNI calls. I've put that in a new jni namespace (check CKeyEventWrapper files). The general idea is that every time we add a jni wrapper to Irrlicht we create a wrapper class which wraps just those functions which are needed internally. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@4887 dfc29bdd-3216-0410-991c-e03cc46cb475master
parent
6c8e9ec729
commit
cc428473cc
|
@ -2,6 +2,7 @@
|
|||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "android_tools.h"
|
||||
#include <android/log.h> // for the occasional debugging, style: __android_log_print(ANDROID_LOG_VERBOSE, "Irrlicht", "%s\n", "We do log");
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
@ -113,5 +114,69 @@ bool getDisplayMetrics(android_app* app, SDisplayMetrics & metrics)
|
|||
return true;
|
||||
}
|
||||
|
||||
void setSoftInputVisibility(android_app* app, bool visible)
|
||||
{
|
||||
// NOTE: Unfortunately ANativeActivity_showSoftInput from the NDK does not work and Google does not care.
|
||||
|
||||
if (!app || !app->activity || !app->activity->vm )
|
||||
return;
|
||||
|
||||
JNIEnv* jni = 0;
|
||||
app->activity->vm->AttachCurrentThread(&jni, NULL);
|
||||
if (!jni )
|
||||
return;
|
||||
|
||||
// get all the classes we want to access from the JVM (could be cached)
|
||||
jclass classNativeActivity = jni->FindClass("android/app/NativeActivity");
|
||||
jclass classInputMethodManager = jni->FindClass("android/view/inputmethod/InputMethodManager");
|
||||
jclass classWindow = jni->FindClass("android/view/Window");
|
||||
jclass classView = jni->FindClass("android/view/View");
|
||||
|
||||
if (classNativeActivity && classInputMethodManager && classWindow)
|
||||
{
|
||||
// Get all the methods we want to access from the JVM classes (could be cached)
|
||||
jmethodID mid_getSystemService = jni->GetMethodID(classNativeActivity, "getSystemService","(Ljava/lang/String;)Ljava/lang/Object;");
|
||||
jmethodID mid_showSoftInput = jni->GetMethodID(classInputMethodManager, "showSoftInput", "(Landroid/view/View;I)Z");
|
||||
jmethodID mid_hideSoftInput = jni->GetMethodID(classInputMethodManager, "hideSoftInputFromWindow", "(Landroid/os/IBinder;I)Z");
|
||||
jmethodID mid_getWindow = jni->GetMethodID(classNativeActivity, "getWindow", "()Landroid/view/Window;");
|
||||
jmethodID mid_getWindowToken = jni->GetMethodID(classView, "getWindowToken", "()Landroid/os/IBinder;");
|
||||
jmethodID mid_getDecorView = jni->GetMethodID(classWindow, "getDecorView", "()Landroid/view/View;");
|
||||
|
||||
if ( mid_getSystemService && mid_showSoftInput && mid_hideSoftInput && mid_getWindow && mid_getDecorView && mid_getWindowToken )
|
||||
{
|
||||
jstring paramInput = jni->NewStringUTF("input_method");
|
||||
jobject objInputMethodManager = jni->CallObjectMethod(app->activity->clazz, mid_getSystemService, paramInput);
|
||||
jni->DeleteLocalRef(paramInput);
|
||||
|
||||
jobject objWindow = jni->CallObjectMethod(app->activity->clazz, mid_getWindow);
|
||||
|
||||
if ( visible && objInputMethodManager && objWindow)
|
||||
{
|
||||
jobject objDecorView = jni->CallObjectMethod(objWindow, mid_getDecorView);
|
||||
if ( objDecorView )
|
||||
{
|
||||
int showFlags = 0;
|
||||
jni->CallObjectMethod(objInputMethodManager, mid_showSoftInput, objDecorView, showFlags);
|
||||
}
|
||||
}
|
||||
else if ( !visible && objInputMethodManager && objWindow )
|
||||
{
|
||||
jobject objDecorView = jni->CallObjectMethod(objWindow, mid_getDecorView);
|
||||
if ( objDecorView )
|
||||
{
|
||||
jobject objBinder = jni->CallObjectMethod(objDecorView, mid_getWindowToken);
|
||||
if ( objBinder )
|
||||
{
|
||||
int hideFlags = 0;
|
||||
jni->CallBooleanMethod(objInputMethodManager, mid_hideSoftInput, objBinder, hideFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
app->activity->vm->DetachCurrentThread();
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace irr
|
||||
|
|
|
@ -23,9 +23,10 @@ struct SDisplayMetrics
|
|||
irr::f32 ydpi;
|
||||
};
|
||||
|
||||
// Access SDisplayMetrics
|
||||
//! Access SDisplayMetrics
|
||||
extern bool getDisplayMetrics(android_app* app, SDisplayMetrics & metrics);
|
||||
|
||||
extern void setSoftInputVisibility(android_app* app, bool visible);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <android_native_app_glue.h>
|
||||
#include "android_tools.h"
|
||||
#include "android/window.h"
|
||||
|
||||
using namespace irr;
|
||||
using namespace core;
|
||||
|
@ -31,7 +32,7 @@ enum GUI_IDS
|
|||
class MyEventReceiver : public IEventReceiver
|
||||
{
|
||||
public:
|
||||
MyEventReceiver(IrrlichtDevice *device ) : Device(device), SpriteToMove(0), TouchID(-1)
|
||||
MyEventReceiver(IrrlichtDevice *device, android_app* app ) : Device(device), AndroidApp(app), SpriteToMove(0), TouchID(-1)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -39,6 +40,21 @@ public:
|
|||
{
|
||||
if (event.EventType == EET_TOUCH_INPUT_EVENT)
|
||||
{
|
||||
/*
|
||||
For now we fake mouse-events. Touch-events will be handled inside Irrlicht in the future, but until
|
||||
that is implemented you can use this workaround to get a GUI which works at least for simple elements like
|
||||
buttons. That workaround does ignore multi-touch events - if you need several buttons pressed at the same
|
||||
time you have to handle that yourself.
|
||||
*/
|
||||
SEvent fakeMouseEvent;
|
||||
fakeMouseEvent.EventType = EET_MOUSE_INPUT_EVENT;
|
||||
fakeMouseEvent.MouseInput.X = event.TouchInput.X;
|
||||
fakeMouseEvent.MouseInput.Y = event.TouchInput.Y;
|
||||
fakeMouseEvent.MouseInput.Shift = false;
|
||||
fakeMouseEvent.MouseInput.Control = false;
|
||||
fakeMouseEvent.MouseInput.ButtonStates = 0;
|
||||
fakeMouseEvent.MouseInput.Event = EMIE_COUNT;
|
||||
|
||||
switch (event.TouchInput.Event)
|
||||
{
|
||||
case ETIE_PRESSED_DOWN:
|
||||
|
@ -46,6 +62,8 @@ public:
|
|||
// We only work with the first for now.
|
||||
if ( TouchID == -1 )
|
||||
{
|
||||
fakeMouseEvent.MouseInput.Event = EMIE_LMOUSE_PRESSED_DOWN;
|
||||
|
||||
position2d<s32> touchPoint(event.TouchInput.X, event.TouchInput.Y);
|
||||
IGUIElement * logo = Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId ( GUI_IRR_LOGO );
|
||||
if ( logo && logo->isPointInside (touchPoint) )
|
||||
|
@ -59,24 +77,64 @@ public:
|
|||
break;
|
||||
}
|
||||
case ETIE_MOVED:
|
||||
if ( SpriteToMove && TouchID == event.TouchInput.ID )
|
||||
if ( TouchID == event.TouchInput.ID )
|
||||
{
|
||||
position2d<s32> touchPoint(event.TouchInput.X, event.TouchInput.Y);
|
||||
MoveSprite(touchPoint);
|
||||
fakeMouseEvent.MouseInput.Event = EMIE_MOUSE_MOVED;
|
||||
fakeMouseEvent.MouseInput.ButtonStates = EMBSM_LEFT;
|
||||
|
||||
if ( SpriteToMove && TouchID == event.TouchInput.ID )
|
||||
{
|
||||
|
||||
position2d<s32> touchPoint(event.TouchInput.X, event.TouchInput.Y);
|
||||
MoveSprite(touchPoint);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ETIE_LEFT_UP:
|
||||
if ( SpriteToMove && TouchID == event.TouchInput.ID )
|
||||
if ( TouchID == event.TouchInput.ID )
|
||||
{
|
||||
TouchID = -1;
|
||||
position2d<s32> touchPoint(event.TouchInput.X, event.TouchInput.Y);
|
||||
MoveSprite(touchPoint);
|
||||
SpriteToMove = 0;
|
||||
fakeMouseEvent.MouseInput.Event = EMIE_LMOUSE_LEFT_UP;
|
||||
|
||||
if ( SpriteToMove )
|
||||
{
|
||||
TouchID = -1;
|
||||
position2d<s32> touchPoint(event.TouchInput.X, event.TouchInput.Y);
|
||||
MoveSprite(touchPoint);
|
||||
SpriteToMove = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ( fakeMouseEvent.MouseInput.Event != EMIE_COUNT )
|
||||
{
|
||||
Device->postEventFromUser(fakeMouseEvent);
|
||||
}
|
||||
}
|
||||
else if ( event.EventType == EET_GUI_EVENT )
|
||||
{
|
||||
/*
|
||||
Show and hide the soft input keyboard when an edit-box get's the focus.
|
||||
*/
|
||||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case EGET_ELEMENT_FOCUS_LOST:
|
||||
if ( event.GUIEvent.Caller->getType() == EGUIET_EDIT_BOX )
|
||||
{
|
||||
android::setSoftInputVisibility(AndroidApp, false);
|
||||
}
|
||||
break;
|
||||
case EGET_ELEMENT_FOCUSED:
|
||||
if ( event.GUIEvent.Caller->getType() == EGUIET_EDIT_BOX )
|
||||
{
|
||||
android::setSoftInputVisibility(AndroidApp, true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -90,6 +148,7 @@ public:
|
|||
|
||||
private:
|
||||
IrrlichtDevice * Device;
|
||||
android_app* AndroidApp;
|
||||
irr::gui::IGUIElement * SpriteToMove;
|
||||
irr::core::rect<s32> SpriteStartRect;
|
||||
irr::core::position2d<irr::s32> TouchStartPos;
|
||||
|
@ -108,7 +167,7 @@ IrrlichtDevice *startup(android_app* app)
|
|||
{
|
||||
// create device
|
||||
SIrrlichtCreationParameters param;
|
||||
// param.DriverType = EDT_OGLES1; // android:glEsVersion in AndroidManifest.xml should be "0x00010000"
|
||||
// param.DriverType = EDT_OGLES1; // android:glEsVersion in AndroidManifest.xml should be "0x00010000" (requesting 0x00020000 will also guarantee that ES1 works)
|
||||
param.DriverType = EDT_OGLES2; // android:glEsVersion in AndroidManifest.xml should be "0x00020000"
|
||||
param.WindowSize = dimension2d<u32>(0,0); // using 0,0 it will automatically set it to the maximal size
|
||||
param.PrivateData = app;
|
||||
|
@ -128,7 +187,7 @@ IrrlichtDevice *startup(android_app* app)
|
|||
|
||||
/* Mainloop.
|
||||
*/
|
||||
int run ( IrrlichtDevice *device )
|
||||
int mainloop( IrrlichtDevice *device )
|
||||
{
|
||||
IGUIElement *stat = device->getGUIEnvironment()->getRootGUIElement()->getElementFromId ( GUI_INFO_FPS );
|
||||
|
||||
|
@ -162,7 +221,9 @@ int example_helloworld(android_app* app)
|
|||
if (device == 0)
|
||||
return 1;
|
||||
|
||||
MyEventReceiver receiver(device);
|
||||
// ANativeActivity_setWindowFlags(app->activity, AWINDOW_FLAG_FULLSCREEN, 0);
|
||||
|
||||
MyEventReceiver receiver(device, app);
|
||||
device->setEventReceiver(&receiver);
|
||||
|
||||
IVideoDriver* driver = device->getVideoDriver();
|
||||
|
@ -228,10 +289,11 @@ int example_helloworld(android_app* app)
|
|||
// A field to show some text. Comment out stat->setText in run() if you want to see the dpi instead of the fps.
|
||||
IGUIStaticText *text = guienv->addStaticText(stringw(displayMetrics.xdpi).c_str(),
|
||||
rect<s32>(15,15,300,60), false, false, 0, GUI_INFO_FPS );
|
||||
guienv->addEditBox( L"", rect<s32>(15,70,300,100));
|
||||
|
||||
// add irrlicht logo
|
||||
IGUIImage * logo = guienv->addImage(driver->getTexture(mediaPath + "irrlichtlogo3.png"),
|
||||
core::position2d<s32>(10,40), true, 0, GUI_IRR_LOGO);
|
||||
core::position2d<s32>(10,110), true, 0, GUI_IRR_LOGO);
|
||||
s32 minLogoWidth = windowWidth/3;
|
||||
if ( logo && logo->getRelativePosition().getWidth() < minLogoWidth )
|
||||
{
|
||||
|
@ -280,7 +342,7 @@ int example_helloworld(android_app* app)
|
|||
/*
|
||||
Mainloop. Application never quit themself in Android. The OS is responsible for that.
|
||||
*/
|
||||
run(device);
|
||||
mainloop(device);
|
||||
|
||||
/* Cleanup */
|
||||
device->setEventReceiver(0);
|
||||
|
|
|
@ -349,6 +349,10 @@ struct SEvent
|
|||
//! Key which has been pressed or released
|
||||
EKEY_CODE Key;
|
||||
|
||||
//! System dependent code. Only set for systems which are described below, otherwise undefined.
|
||||
//! Android: int32_t with physical key as returned by AKeyEvent_getKeyCode
|
||||
u32 SystemKeyCode;
|
||||
|
||||
//! If not true, then the key was left up
|
||||
bool PressedDown:1;
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace irr
|
|||
|
||||
enum EKEY_CODE
|
||||
{
|
||||
KEY_UNKNOWN = 0x0,
|
||||
KEY_LBUTTON = 0x01, // Left mouse button
|
||||
KEY_RBUTTON = 0x02, // Right mouse button
|
||||
KEY_CANCEL = 0x03, // Control-break processing
|
||||
|
@ -141,6 +142,20 @@ namespace irr
|
|||
KEY_RCONTROL = 0xA3, // Right CONTROL key
|
||||
KEY_LMENU = 0xA4, // Left MENU key
|
||||
KEY_RMENU = 0xA5, // Right MENU key
|
||||
KEY_BROWSER_BACK = 0xA6, // Browser Back key
|
||||
KEY_BROWSER_FORWARD = 0xA7, // Browser Forward key
|
||||
KEY_BROWSER_REFRESH = 0xA8, // Browser Refresh key
|
||||
KEY_BROWSER_STOP = 0xA9, // Browser Stop key
|
||||
KEY_BROWSER_SEARCH = 0xAA, // Browser Search key
|
||||
KEY_BROWSER_FAVORITES =0xAB, // Browser Favorites key
|
||||
KEY_BROWSER_HOME = 0xAC, // Browser Start and Home key
|
||||
KEY_VOLUME_MUTE = 0xAD, // Volume Mute key
|
||||
KEY_VOLUME_DOWN = 0xAE, // Volume Down key
|
||||
KEY_VOLUME_UP = 0xAF, // Volume Up key
|
||||
KEY_MEDIA_NEXT_TRACK = 0xB0, // Next Track key
|
||||
KEY_MEDIA_PREV_TRACK = 0xB1, // Previous Track key
|
||||
KEY_MEDIA_STOP = 0xB2, // Stop Media key
|
||||
KEY_MEDIA_PLAY_PAUSE = 0xB3, // Play/Pause Media key
|
||||
KEY_OEM_1 = 0xBA, // for US ";:"
|
||||
KEY_PLUS = 0xBB, // Plus Key "+"
|
||||
KEY_COMMA = 0xBC, // Comma Key ","
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "CFileSystem.h"
|
||||
#include "CAndroidAssetReader.h"
|
||||
#include "CAndroidAssetFileArchive.h"
|
||||
#include "CKeyEventWrapper.h"
|
||||
#include "CEGLManager.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
|
@ -32,7 +33,7 @@ namespace irr
|
|||
{
|
||||
|
||||
CIrrDeviceAndroid::CIrrDeviceAndroid(const SIrrlichtCreationParameters& param)
|
||||
: CIrrDeviceStub(param), Focused(false), Initialized(false), Paused(true)
|
||||
: CIrrDeviceStub(param), Focused(false), Initialized(false), Paused(true), JNIEnvAttachedToVM(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CIrrDeviceAndroid");
|
||||
|
@ -48,6 +49,8 @@ CIrrDeviceAndroid::CIrrDeviceAndroid(const SIrrlichtCreationParameters& param)
|
|||
// OS invokes to send the native activity messages.
|
||||
Android->onAppCmd = handleAndroidCommand;
|
||||
|
||||
createKeyMap();
|
||||
|
||||
// Create a sensor manager to receive touch screen events from the java activity.
|
||||
SensorManager = ASensorManager_getInstance();
|
||||
SensorEventQueue = ASensorManager_createEventQueue(SensorManager, Android->looper, LOOPER_ID_USER, 0, 0);
|
||||
|
@ -267,69 +270,164 @@ void CIrrDeviceAndroid::handleAndroidCommand(android_app* app, int32_t cmd)
|
|||
s32 CIrrDeviceAndroid::handleInput(android_app* app, AInputEvent* androidEvent)
|
||||
{
|
||||
CIrrDeviceAndroid* device = (CIrrDeviceAndroid*)app->userData;
|
||||
s32 Status = 0;
|
||||
s32 status = 0;
|
||||
|
||||
if (AInputEvent_getType(androidEvent) == AINPUT_EVENT_TYPE_MOTION)
|
||||
switch ( AInputEvent_getType(androidEvent) )
|
||||
{
|
||||
SEvent Event;
|
||||
Event.EventType = EET_TOUCH_INPUT_EVENT;
|
||||
|
||||
s32 EventAction = AMotionEvent_getAction(androidEvent);
|
||||
s32 EventType = EventAction & AMOTION_EVENT_ACTION_MASK;
|
||||
|
||||
bool TouchReceived = true;
|
||||
|
||||
switch (EventType)
|
||||
case AINPUT_EVENT_TYPE_MOTION:
|
||||
{
|
||||
case AMOTION_EVENT_ACTION_DOWN:
|
||||
case AMOTION_EVENT_ACTION_POINTER_DOWN:
|
||||
Event.TouchInput.Event = ETIE_PRESSED_DOWN;
|
||||
break;
|
||||
case AMOTION_EVENT_ACTION_MOVE:
|
||||
Event.TouchInput.Event = ETIE_MOVED;
|
||||
break;
|
||||
case AMOTION_EVENT_ACTION_UP:
|
||||
case AMOTION_EVENT_ACTION_POINTER_UP:
|
||||
case AMOTION_EVENT_ACTION_CANCEL:
|
||||
Event.TouchInput.Event = ETIE_LEFT_UP;
|
||||
break;
|
||||
default:
|
||||
TouchReceived = false;
|
||||
break;
|
||||
}
|
||||
SEvent event;
|
||||
event.EventType = EET_TOUCH_INPUT_EVENT;
|
||||
|
||||
if (TouchReceived)
|
||||
{
|
||||
// Process all touches for move action.
|
||||
if (Event.TouchInput.Event == ETIE_MOVED)
|
||||
s32 eventAction = AMotionEvent_getAction(androidEvent);
|
||||
s32 eventType = eventAction & AMOTION_EVENT_ACTION_MASK;
|
||||
|
||||
bool touchReceived = true;
|
||||
|
||||
switch (eventType)
|
||||
{
|
||||
s32 PointerCount = AMotionEvent_getPointerCount(androidEvent);
|
||||
case AMOTION_EVENT_ACTION_DOWN:
|
||||
case AMOTION_EVENT_ACTION_POINTER_DOWN:
|
||||
event.TouchInput.Event = ETIE_PRESSED_DOWN;
|
||||
break;
|
||||
case AMOTION_EVENT_ACTION_MOVE:
|
||||
event.TouchInput.Event = ETIE_MOVED;
|
||||
break;
|
||||
case AMOTION_EVENT_ACTION_UP:
|
||||
case AMOTION_EVENT_ACTION_POINTER_UP:
|
||||
case AMOTION_EVENT_ACTION_CANCEL:
|
||||
event.TouchInput.Event = ETIE_LEFT_UP;
|
||||
break;
|
||||
default:
|
||||
touchReceived = false;
|
||||
break;
|
||||
}
|
||||
|
||||
for (s32 i = 0; i < PointerCount; ++i)
|
||||
if (touchReceived)
|
||||
{
|
||||
// Process all touches for move action.
|
||||
if (event.TouchInput.Event == ETIE_MOVED)
|
||||
{
|
||||
Event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, i);
|
||||
Event.TouchInput.X = AMotionEvent_getX(androidEvent, i);
|
||||
Event.TouchInput.Y = AMotionEvent_getY(androidEvent, i);
|
||||
s32 pointerCount = AMotionEvent_getPointerCount(androidEvent);
|
||||
|
||||
device->postEventFromUser(Event);
|
||||
for (s32 i = 0; i < pointerCount; ++i)
|
||||
{
|
||||
event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, i);
|
||||
event.TouchInput.X = AMotionEvent_getX(androidEvent, i);
|
||||
event.TouchInput.Y = AMotionEvent_getY(androidEvent, i);
|
||||
|
||||
device->postEventFromUser(event);
|
||||
}
|
||||
}
|
||||
else // Process one touch for other actions.
|
||||
{
|
||||
s32 pointerIndex = (eventAction & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
||||
|
||||
event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, pointerIndex);
|
||||
event.TouchInput.X = AMotionEvent_getX(androidEvent, pointerIndex);
|
||||
event.TouchInput.Y = AMotionEvent_getY(androidEvent, pointerIndex);
|
||||
|
||||
device->postEventFromUser(event);
|
||||
}
|
||||
|
||||
status = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AINPUT_EVENT_TYPE_KEY:
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_KEY_INPUT_EVENT;
|
||||
|
||||
int32_t keyCode = AKeyEvent_getKeyCode(androidEvent);
|
||||
int32_t keyAction = AKeyEvent_getAction(androidEvent);
|
||||
int32_t keyMetaState = AKeyEvent_getMetaState(androidEvent);
|
||||
|
||||
if ( keyCode >= 0 && (u32)keyCode < device->KeyMap.size() )
|
||||
event.KeyInput.Key = device->KeyMap[keyCode];
|
||||
else
|
||||
event.KeyInput.Key = KEY_UNKNOWN;
|
||||
event.KeyInput.SystemKeyCode = (u32)keyCode;
|
||||
if ( keyAction == AKEY_EVENT_ACTION_DOWN )
|
||||
event.KeyInput.PressedDown = true;
|
||||
else if ( keyAction == AKEY_EVENT_ACTION_UP )
|
||||
event.KeyInput.PressedDown = false;
|
||||
else if ( keyAction == AKEY_EVENT_ACTION_MULTIPLE )
|
||||
{
|
||||
// TODO: Multiple duplicate key events have occurred in a row,
|
||||
// or a complex string is being delivered. The repeat_count
|
||||
// property of the key event contains the number of times the
|
||||
// given key code should be executed.
|
||||
// I guess this might necessary for more complicated i18n key input,
|
||||
// but don't see yet how to handle this correctly.
|
||||
}
|
||||
|
||||
/* no use for meta keys so far.
|
||||
if ( keyMetaState & AMETA_ALT_ON
|
||||
|| keyMetaState & AMETA_ALT_LEFT_ON
|
||||
|| keyMetaState & AMETA_ALT_RIGHT_ON )
|
||||
;
|
||||
// what is a sym?
|
||||
if ( keyMetaState & AMETA_SYM_ON )
|
||||
;
|
||||
*/
|
||||
if ( keyMetaState & AMETA_SHIFT_ON
|
||||
|| keyMetaState & AMETA_SHIFT_LEFT_ON
|
||||
|| keyMetaState & AMETA_SHIFT_RIGHT_ON )
|
||||
event.KeyInput.Shift = true;
|
||||
else
|
||||
event.KeyInput.Shift = false;
|
||||
event.KeyInput.Control = false;
|
||||
|
||||
// Having memory allocations + going through JNI for each key-press is pretty bad (slow).
|
||||
// So we do it only for those keys which are likely text-characters and avoid it for all other keys.
|
||||
// So it's fast for keys like game controller input and special keys. And text keys are typically
|
||||
// only used or entering text and not for gaming on Android, so speed likely doesn't matter there too much.
|
||||
if ( event.KeyInput.Key > 0 )
|
||||
{
|
||||
// TODO:
|
||||
// Not sure why we have to attach a JNIEnv here, but it won't work when doing that in the constructor or
|
||||
// trying to use the activity->env. My best guess is that the event-handling happens in an own thread.
|
||||
// It means JNIEnvAttachedToVM will never get detached as I don't know a safe way where to do that
|
||||
// (we could attach & detach each time, but that would probably be slow)
|
||||
// Also - it has to be each time as it get's invalid when the application mode changes.
|
||||
if ( device->Android && device->Android->activity && device->Android->activity->vm )
|
||||
{
|
||||
JavaVMAttachArgs attachArgs;
|
||||
attachArgs.version = JNI_VERSION_1_6;
|
||||
attachArgs.name = 0;
|
||||
attachArgs.group = NULL;
|
||||
|
||||
// Not a big problem calling it each time - it's a no-op when the thread already is attached
|
||||
jint result = device->Android->activity->vm->AttachCurrentThread(&device->JNIEnvAttachedToVM, &attachArgs);
|
||||
if(result == JNI_ERR)
|
||||
{
|
||||
os::Printer::log("AttachCurrentThread for the JNI environment failed.", ELL_WARNING);
|
||||
device->JNIEnvAttachedToVM = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( device->JNIEnvAttachedToVM )
|
||||
{
|
||||
jni::CKeyEventWrapper * keyEventWrapper = new jni::CKeyEventWrapper(device->JNIEnvAttachedToVM, keyAction, keyCode);
|
||||
event.KeyInput.Char = keyEventWrapper->getUnicodeChar(keyMetaState);
|
||||
delete keyEventWrapper;
|
||||
}
|
||||
}
|
||||
else // Process one touch for other actions.
|
||||
else
|
||||
{
|
||||
s32 PointerIndex = (EventAction & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
||||
|
||||
Event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, PointerIndex);
|
||||
Event.TouchInput.X = AMotionEvent_getX(androidEvent, PointerIndex);
|
||||
Event.TouchInput.Y = AMotionEvent_getY(androidEvent, PointerIndex);
|
||||
|
||||
device->postEventFromUser(Event);
|
||||
// os::Printer::log("keyCode: ", core::stringc(keyCode).c_str(), ELL_DEBUG);
|
||||
event.KeyInput.Char = 0;
|
||||
}
|
||||
|
||||
Status = 1;
|
||||
device->postEventFromUser(event);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return Status;
|
||||
return status;
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::createDriver()
|
||||
|
@ -371,6 +469,238 @@ video::SExposedVideoData& CIrrDeviceAndroid::getExposedVideoData()
|
|||
return ExposedVideoData;
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::createKeyMap()
|
||||
{
|
||||
KeyMap.set_used(223);
|
||||
|
||||
KeyMap[0] = KEY_UNKNOWN; // AKEYCODE_UNKNOWN
|
||||
KeyMap[1] = KEY_LBUTTON; // AKEYCODE_SOFT_LEFT
|
||||
KeyMap[2] = KEY_RBUTTON; // AKEYCODE_SOFT_RIGHT
|
||||
KeyMap[3] = KEY_HOME; // AKEYCODE_HOME
|
||||
KeyMap[4] = KEY_BACK; // AKEYCODE_BACK
|
||||
KeyMap[5] = KEY_UNKNOWN; // AKEYCODE_CALL
|
||||
KeyMap[6] = KEY_UNKNOWN; // AKEYCODE_ENDCALL
|
||||
KeyMap[7] = KEY_KEY_0; // AKEYCODE_0
|
||||
KeyMap[8] = KEY_KEY_1; // AKEYCODE_1
|
||||
KeyMap[9] = KEY_KEY_2; // AKEYCODE_2
|
||||
KeyMap[10] = KEY_KEY_3; // AKEYCODE_3
|
||||
KeyMap[11] = KEY_KEY_4; // AKEYCODE_4
|
||||
KeyMap[12] = KEY_KEY_5; // AKEYCODE_5
|
||||
KeyMap[13] = KEY_KEY_6; // AKEYCODE_6
|
||||
KeyMap[14] = KEY_KEY_7; // AKEYCODE_7
|
||||
KeyMap[15] = KEY_KEY_8; // AKEYCODE_8
|
||||
KeyMap[16] = KEY_KEY_9; // AKEYCODE_9
|
||||
KeyMap[17] = KEY_UNKNOWN; // AKEYCODE_STAR
|
||||
KeyMap[18] = KEY_UNKNOWN; // AKEYCODE_POUND
|
||||
KeyMap[19] = KEY_UP; // AKEYCODE_DPAD_UP
|
||||
KeyMap[20] = KEY_DOWN; // AKEYCODE_DPAD_DOWN
|
||||
KeyMap[21] = KEY_LEFT; // AKEYCODE_DPAD_LEFT
|
||||
KeyMap[22] = KEY_RIGHT; // AKEYCODE_DPAD_RIGHT
|
||||
KeyMap[23] = KEY_SELECT; // AKEYCODE_DPAD_CENTER
|
||||
KeyMap[24] = KEY_VOLUME_DOWN; // AKEYCODE_VOLUME_UP
|
||||
KeyMap[25] = KEY_VOLUME_UP; // AKEYCODE_VOLUME_DOWN
|
||||
KeyMap[26] = KEY_UNKNOWN; // AKEYCODE_POWER
|
||||
KeyMap[27] = KEY_UNKNOWN; // AKEYCODE_CAMERA
|
||||
KeyMap[28] = KEY_CLEAR; // AKEYCODE_CLEAR
|
||||
KeyMap[29] = KEY_KEY_A; // AKEYCODE_A
|
||||
KeyMap[30] = KEY_KEY_B; // AKEYCODE_B
|
||||
KeyMap[31] = KEY_KEY_C; // AKEYCODE_C
|
||||
KeyMap[32] = KEY_KEY_D; // AKEYCODE_D
|
||||
KeyMap[33] = KEY_KEY_E; // AKEYCODE_E
|
||||
KeyMap[34] = KEY_KEY_F; // AKEYCODE_F
|
||||
KeyMap[35] = KEY_KEY_G; // AKEYCODE_G
|
||||
KeyMap[36] = KEY_KEY_H; // AKEYCODE_H
|
||||
KeyMap[37] = KEY_KEY_I; // AKEYCODE_I
|
||||
KeyMap[38] = KEY_KEY_J; // AKEYCODE_J
|
||||
KeyMap[39] = KEY_KEY_K; // AKEYCODE_K
|
||||
KeyMap[40] = KEY_KEY_L; // AKEYCODE_L
|
||||
KeyMap[41] = KEY_KEY_M; // AKEYCODE_M
|
||||
KeyMap[42] = KEY_KEY_N; // AKEYCODE_N
|
||||
KeyMap[43] = KEY_KEY_O; // AKEYCODE_O
|
||||
KeyMap[44] = KEY_KEY_P; // AKEYCODE_P
|
||||
KeyMap[45] = KEY_KEY_Q; // AKEYCODE_Q
|
||||
KeyMap[46] = KEY_KEY_R; // AKEYCODE_R
|
||||
KeyMap[47] = KEY_KEY_S; // AKEYCODE_S
|
||||
KeyMap[48] = KEY_KEY_T; // AKEYCODE_T
|
||||
KeyMap[49] = KEY_KEY_U; // AKEYCODE_U
|
||||
KeyMap[50] = KEY_KEY_V; // AKEYCODE_V
|
||||
KeyMap[51] = KEY_KEY_W; // AKEYCODE_W
|
||||
KeyMap[52] = KEY_KEY_X; // AKEYCODE_X
|
||||
KeyMap[53] = KEY_KEY_Y; // AKEYCODE_Y
|
||||
KeyMap[54] = KEY_KEY_Z; // AKEYCODE_Z
|
||||
KeyMap[55] = KEY_COMMA; // AKEYCODE_COMMA
|
||||
KeyMap[56] = KEY_PERIOD; // AKEYCODE_PERIOD
|
||||
KeyMap[57] = KEY_MENU; // AKEYCODE_ALT_LEFT
|
||||
KeyMap[58] = KEY_MENU; // AKEYCODE_ALT_RIGHT
|
||||
KeyMap[59] = KEY_LSHIFT; // AKEYCODE_SHIFT_LEFT
|
||||
KeyMap[60] = KEY_RSHIFT; // AKEYCODE_SHIFT_RIGHT
|
||||
KeyMap[61] = KEY_TAB; // AKEYCODE_TAB
|
||||
KeyMap[62] = KEY_SPACE; // AKEYCODE_SPACE
|
||||
KeyMap[63] = KEY_UNKNOWN; // AKEYCODE_SYM
|
||||
KeyMap[64] = KEY_UNKNOWN; // AKEYCODE_EXPLORER
|
||||
KeyMap[65] = KEY_UNKNOWN; // AKEYCODE_ENVELOPE
|
||||
KeyMap[66] = KEY_RETURN; // AKEYCODE_ENTER
|
||||
KeyMap[67] = KEY_BACK; // AKEYCODE_DEL
|
||||
KeyMap[68] = KEY_OEM_3; // AKEYCODE_GRAVE
|
||||
KeyMap[69] = KEY_MINUS; // AKEYCODE_MINUS
|
||||
KeyMap[70] = KEY_UNKNOWN; // AKEYCODE_EQUALS
|
||||
KeyMap[71] = KEY_UNKNOWN; // AKEYCODE_LEFT_BRACKET
|
||||
KeyMap[72] = KEY_UNKNOWN; // AKEYCODE_RIGHT_BRACKET
|
||||
KeyMap[73] = KEY_UNKNOWN; // AKEYCODE_BACKSLASH
|
||||
KeyMap[74] = KEY_UNKNOWN; // AKEYCODE_SEMICOLON
|
||||
KeyMap[75] = KEY_UNKNOWN; // AKEYCODE_APOSTROPHE
|
||||
KeyMap[76] = KEY_UNKNOWN; // AKEYCODE_SLASH
|
||||
KeyMap[77] = KEY_UNKNOWN; // AKEYCODE_AT
|
||||
KeyMap[78] = KEY_UNKNOWN; // AKEYCODE_NUM
|
||||
KeyMap[79] = KEY_UNKNOWN; // AKEYCODE_HEADSETHOOK
|
||||
KeyMap[80] = KEY_UNKNOWN; // AKEYCODE_FOCUS (*Camera* focus)
|
||||
KeyMap[81] = KEY_PLUS; // AKEYCODE_PLUS
|
||||
KeyMap[82] = KEY_MENU; // AKEYCODE_MENU
|
||||
KeyMap[83] = KEY_UNKNOWN; // AKEYCODE_NOTIFICATION
|
||||
KeyMap[84] = KEY_UNKNOWN; // AKEYCODE_SEARCH
|
||||
KeyMap[85] = KEY_MEDIA_PLAY_PAUSE; // AKEYCODE_MEDIA_PLAY_PAUSE
|
||||
KeyMap[86] = KEY_MEDIA_STOP; // AKEYCODE_MEDIA_STOP
|
||||
KeyMap[87] = KEY_MEDIA_NEXT_TRACK; // AKEYCODE_MEDIA_NEXT
|
||||
KeyMap[88] = KEY_MEDIA_PREV_TRACK; // AKEYCODE_MEDIA_PREVIOUS
|
||||
KeyMap[89] = KEY_UNKNOWN; // AKEYCODE_MEDIA_REWIND
|
||||
KeyMap[90] = KEY_UNKNOWN; // AKEYCODE_MEDIA_FAST_FORWARD
|
||||
KeyMap[91] = KEY_VOLUME_MUTE; // AKEYCODE_MUTE
|
||||
KeyMap[92] = KEY_PRIOR; // AKEYCODE_PAGE_UP
|
||||
KeyMap[93] = KEY_NEXT; // AKEYCODE_PAGE_DOWN
|
||||
KeyMap[94] = KEY_UNKNOWN; // AKEYCODE_PICTSYMBOLS
|
||||
KeyMap[95] = KEY_UNKNOWN; // AKEYCODE_SWITCH_CHARSET
|
||||
|
||||
// following look like controller inputs
|
||||
KeyMap[96] = KEY_UNKNOWN; // AKEYCODE_BUTTON_A
|
||||
KeyMap[97] = KEY_UNKNOWN; // AKEYCODE_BUTTON_B
|
||||
KeyMap[98] = KEY_UNKNOWN; // AKEYCODE_BUTTON_C
|
||||
KeyMap[99] = KEY_UNKNOWN; // AKEYCODE_BUTTON_X
|
||||
KeyMap[100] = KEY_UNKNOWN; // AKEYCODE_BUTTON_Y
|
||||
KeyMap[101] = KEY_UNKNOWN; // AKEYCODE_BUTTON_Z
|
||||
KeyMap[102] = KEY_UNKNOWN; // AKEYCODE_BUTTON_L1
|
||||
KeyMap[103] = KEY_UNKNOWN; // AKEYCODE_BUTTON_R1
|
||||
KeyMap[104] = KEY_UNKNOWN; // AKEYCODE_BUTTON_L2
|
||||
KeyMap[105] = KEY_UNKNOWN; // AKEYCODE_BUTTON_R2
|
||||
KeyMap[106] = KEY_UNKNOWN; // AKEYCODE_BUTTON_THUMBL
|
||||
KeyMap[107] = KEY_UNKNOWN; // AKEYCODE_BUTTON_THUMBR
|
||||
KeyMap[108] = KEY_UNKNOWN; // AKEYCODE_BUTTON_START
|
||||
KeyMap[109] = KEY_UNKNOWN; // AKEYCODE_BUTTON_SELECT
|
||||
KeyMap[110] = KEY_UNKNOWN; // AKEYCODE_BUTTON_MODE
|
||||
|
||||
KeyMap[111] = KEY_ESCAPE; // AKEYCODE_ESCAPE
|
||||
KeyMap[112] = KEY_DELETE; // AKEYCODE_FORWARD_DEL
|
||||
KeyMap[113] = KEY_CONTROL; // AKEYCODE_CTRL_LEFT
|
||||
KeyMap[114] = KEY_CONTROL; // AKEYCODE_CTRL_RIGHT
|
||||
KeyMap[115] = KEY_CAPITAL; // AKEYCODE_CAPS_LOCK
|
||||
KeyMap[116] = KEY_SCROLL; // AKEYCODE_SCROLL_LOCK
|
||||
KeyMap[117] = KEY_UNKNOWN; // AKEYCODE_META_LEFT
|
||||
KeyMap[118] = KEY_UNKNOWN; // AKEYCODE_META_RIGHT
|
||||
KeyMap[119] = KEY_UNKNOWN; // AKEYCODE_FUNCTION
|
||||
KeyMap[120] = KEY_SNAPSHOT; // AKEYCODE_SYSRQ
|
||||
KeyMap[121] = KEY_PAUSE; // AKEYCODE_BREAK
|
||||
KeyMap[122] = KEY_HOME; // AKEYCODE_MOVE_HOME
|
||||
KeyMap[123] = KEY_END; // AKEYCODE_MOVE_END
|
||||
KeyMap[124] = KEY_INSERT; // AKEYCODE_INSERT
|
||||
KeyMap[125] = KEY_UNKNOWN; // AKEYCODE_FORWARD
|
||||
KeyMap[126] = KEY_PLAY; // AKEYCODE_MEDIA_PLAY
|
||||
KeyMap[127] = KEY_MEDIA_PLAY_PAUSE; // AKEYCODE_MEDIA_PAUSE
|
||||
KeyMap[128] = KEY_UNKNOWN; // AKEYCODE_MEDIA_CLOSE
|
||||
KeyMap[129] = KEY_UNKNOWN; // AKEYCODE_MEDIA_EJECT
|
||||
KeyMap[130] = KEY_UNKNOWN; // AKEYCODE_MEDIA_RECORD
|
||||
KeyMap[131] = KEY_F1; // AKEYCODE_F1
|
||||
KeyMap[132] = KEY_F2; // AKEYCODE_F2
|
||||
KeyMap[133] = KEY_F3; // AKEYCODE_F3
|
||||
KeyMap[134] = KEY_F4; // AKEYCODE_F4
|
||||
KeyMap[135] = KEY_F5; // AKEYCODE_F5
|
||||
KeyMap[136] = KEY_F6; // AKEYCODE_F6
|
||||
KeyMap[137] = KEY_F7; // AKEYCODE_F7
|
||||
KeyMap[138] = KEY_F8; // AKEYCODE_F8
|
||||
KeyMap[139] = KEY_F9; // AKEYCODE_F9
|
||||
KeyMap[140] = KEY_F10; // AKEYCODE_F10
|
||||
KeyMap[141] = KEY_F11; // AKEYCODE_F11
|
||||
KeyMap[142] = KEY_F12; // AKEYCODE_F12
|
||||
KeyMap[143] = KEY_NUMLOCK; // AKEYCODE_NUM_LOCK
|
||||
KeyMap[144] = KEY_NUMPAD0; // AKEYCODE_NUMPAD_0
|
||||
KeyMap[145] = KEY_NUMPAD1; // AKEYCODE_NUMPAD_1
|
||||
KeyMap[146] = KEY_NUMPAD2; // AKEYCODE_NUMPAD_2
|
||||
KeyMap[147] = KEY_NUMPAD3; // AKEYCODE_NUMPAD_3
|
||||
KeyMap[148] = KEY_NUMPAD4; // AKEYCODE_NUMPAD_4
|
||||
KeyMap[149] = KEY_NUMPAD5; // AKEYCODE_NUMPAD_5
|
||||
KeyMap[150] = KEY_NUMPAD6; // AKEYCODE_NUMPAD_6
|
||||
KeyMap[151] = KEY_NUMPAD7; // AKEYCODE_NUMPAD_7
|
||||
KeyMap[152] = KEY_NUMPAD8; // AKEYCODE_NUMPAD_8
|
||||
KeyMap[153] = KEY_NUMPAD9; // AKEYCODE_NUMPAD_9
|
||||
KeyMap[154] = KEY_DIVIDE; // AKEYCODE_NUMPAD_DIVIDE
|
||||
KeyMap[155] = KEY_MULTIPLY; // AKEYCODE_NUMPAD_MULTIPLY
|
||||
KeyMap[156] = KEY_SUBTRACT; // AKEYCODE_NUMPAD_SUBTRACT
|
||||
KeyMap[157] = KEY_ADD; // AKEYCODE_NUMPAD_ADD
|
||||
KeyMap[158] = KEY_UNKNOWN; // AKEYCODE_NUMPAD_DOT
|
||||
KeyMap[159] = KEY_COMMA; // AKEYCODE_NUMPAD_COMMA
|
||||
KeyMap[160] = KEY_RETURN; // AKEYCODE_NUMPAD_ENTER
|
||||
KeyMap[161] = KEY_UNKNOWN; // AKEYCODE_NUMPAD_EQUALS
|
||||
KeyMap[162] = KEY_UNKNOWN; // AKEYCODE_NUMPAD_LEFT_PAREN
|
||||
KeyMap[163] = KEY_UNKNOWN; // AKEYCODE_NUMPAD_RIGHT_PAREN
|
||||
KeyMap[164] = KEY_VOLUME_MUTE; // AKEYCODE_VOLUME_MUTE
|
||||
KeyMap[165] = KEY_UNKNOWN; // AKEYCODE_INFO
|
||||
KeyMap[166] = KEY_UNKNOWN; // AKEYCODE_CHANNEL_UP
|
||||
KeyMap[167] = KEY_UNKNOWN; // AKEYCODE_CHANNEL_DOWN
|
||||
KeyMap[168] = KEY_ZOOM; // AKEYCODE_ZOOM_IN
|
||||
KeyMap[169] = KEY_UNKNOWN; // AKEYCODE_ZOOM_OUT
|
||||
KeyMap[170] = KEY_UNKNOWN; // AKEYCODE_TV
|
||||
KeyMap[171] = KEY_UNKNOWN; // AKEYCODE_WINDOW
|
||||
KeyMap[172] = KEY_UNKNOWN; // AKEYCODE_GUIDE
|
||||
KeyMap[173] = KEY_UNKNOWN; // AKEYCODE_DVR
|
||||
KeyMap[174] = KEY_UNKNOWN; // AKEYCODE_BOOKMARK
|
||||
KeyMap[175] = KEY_UNKNOWN; // AKEYCODE_CAPTIONS
|
||||
KeyMap[176] = KEY_UNKNOWN; // AKEYCODE_SETTINGS
|
||||
KeyMap[177] = KEY_UNKNOWN; // AKEYCODE_TV_POWER
|
||||
KeyMap[178] = KEY_UNKNOWN; // AKEYCODE_TV_INPUT
|
||||
KeyMap[179] = KEY_UNKNOWN; // AKEYCODE_STB_POWER
|
||||
KeyMap[180] = KEY_UNKNOWN; // AKEYCODE_STB_INPUT
|
||||
KeyMap[181] = KEY_UNKNOWN; // AKEYCODE_AVR_POWER
|
||||
KeyMap[182] = KEY_UNKNOWN; // AKEYCODE_AVR_INPUT
|
||||
KeyMap[183] = KEY_UNKNOWN; // AKEYCODE_PROG_RED
|
||||
KeyMap[184] = KEY_UNKNOWN; // AKEYCODE_PROG_GREEN
|
||||
KeyMap[185] = KEY_UNKNOWN; // AKEYCODE_PROG_YELLOW
|
||||
KeyMap[186] = KEY_UNKNOWN; // AKEYCODE_PROG_BLUE
|
||||
KeyMap[187] = KEY_UNKNOWN; // AKEYCODE_APP_SWITCH
|
||||
KeyMap[188] = KEY_UNKNOWN; // AKEYCODE_BUTTON_1
|
||||
KeyMap[189] = KEY_UNKNOWN; // AKEYCODE_BUTTON_2
|
||||
KeyMap[190] = KEY_UNKNOWN; // AKEYCODE_BUTTON_3
|
||||
KeyMap[191] = KEY_UNKNOWN; // AKEYCODE_BUTTON_4
|
||||
KeyMap[192] = KEY_UNKNOWN; // AKEYCODE_BUTTON_5
|
||||
KeyMap[193] = KEY_UNKNOWN; // AKEYCODE_BUTTON_6
|
||||
KeyMap[194] = KEY_UNKNOWN; // AKEYCODE_BUTTON_7
|
||||
KeyMap[195] = KEY_UNKNOWN; // AKEYCODE_BUTTON_8
|
||||
KeyMap[196] = KEY_UNKNOWN; // AKEYCODE_BUTTON_9
|
||||
KeyMap[197] = KEY_UNKNOWN; // AKEYCODE_BUTTON_10
|
||||
KeyMap[198] = KEY_UNKNOWN; // AKEYCODE_BUTTON_11
|
||||
KeyMap[199] = KEY_UNKNOWN; // AKEYCODE_BUTTON_12
|
||||
KeyMap[200] = KEY_UNKNOWN; // AKEYCODE_BUTTON_13
|
||||
KeyMap[201] = KEY_UNKNOWN; // AKEYCODE_BUTTON_14
|
||||
KeyMap[202] = KEY_UNKNOWN; // AKEYCODE_BUTTON_15
|
||||
KeyMap[203] = KEY_UNKNOWN; // AKEYCODE_BUTTON_16
|
||||
KeyMap[204] = KEY_UNKNOWN; // AKEYCODE_LANGUAGE_SWITCH
|
||||
KeyMap[205] = KEY_UNKNOWN; // AKEYCODE_MANNER_MODE
|
||||
KeyMap[206] = KEY_UNKNOWN; // AKEYCODE_3D_MODE
|
||||
KeyMap[207] = KEY_UNKNOWN; // AKEYCODE_CONTACTS
|
||||
KeyMap[208] = KEY_UNKNOWN; // AKEYCODE_CALENDAR
|
||||
KeyMap[209] = KEY_UNKNOWN; // AKEYCODE_MUSIC
|
||||
KeyMap[210] = KEY_UNKNOWN; // AKEYCODE_CALCULATOR
|
||||
KeyMap[211] = KEY_UNKNOWN; // AKEYCODE_ZENKAKU_HANKAKU
|
||||
KeyMap[212] = KEY_UNKNOWN; // AKEYCODE_EISU
|
||||
KeyMap[213] = KEY_UNKNOWN; // AKEYCODE_MUHENKAN
|
||||
KeyMap[214] = KEY_UNKNOWN; // AKEYCODE_HENKAN
|
||||
KeyMap[215] = KEY_UNKNOWN; // AKEYCODE_KATAKANA_HIRAGANA
|
||||
KeyMap[216] = KEY_UNKNOWN; // AKEYCODE_YEN
|
||||
KeyMap[217] = KEY_UNKNOWN; // AKEYCODE_RO
|
||||
KeyMap[218] = KEY_UNKNOWN; // AKEYCODE_KANA
|
||||
KeyMap[219] = KEY_UNKNOWN; // AKEYCODE_ASSIST
|
||||
KeyMap[220] = KEY_UNKNOWN; // AKEYCODE_BRIGHTNESS_DOWN
|
||||
KeyMap[221] = KEY_UNKNOWN; // AKEYCODE_BRIGHTNESS_UP ,
|
||||
KeyMap[222] = KEY_UNKNOWN; // AKEYCODE_MEDIA_AUDIO_TRACK
|
||||
}
|
||||
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
|
|
@ -64,6 +64,8 @@ namespace irr
|
|||
|
||||
void createDriver();
|
||||
|
||||
void createKeyMap();
|
||||
|
||||
video::SExposedVideoData& getExposedVideoData();
|
||||
|
||||
android_app* Android;
|
||||
|
@ -74,7 +76,11 @@ namespace irr
|
|||
bool Initialized;
|
||||
bool Paused;
|
||||
|
||||
JNIEnv* JNIEnvAttachedToVM;
|
||||
|
||||
video::SExposedVideoData ExposedVideoData;
|
||||
|
||||
core::array<EKEY_CODE> KeyMap;
|
||||
};
|
||||
|
||||
} // end namespace irr
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CKeyEventWrapper.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace jni
|
||||
{
|
||||
|
||||
jclass CKeyEventWrapper::Class_KeyEvent = 0;
|
||||
jmethodID CKeyEventWrapper::Method_constructor = 0;
|
||||
jmethodID CKeyEventWrapper::Method_getUnicodeChar = 0;
|
||||
|
||||
CKeyEventWrapper::CKeyEventWrapper(JNIEnv* jniEnv, int action, int code)
|
||||
: JniEnv(jniEnv), JniKeyEvent(0)
|
||||
{
|
||||
if ( JniEnv )
|
||||
{
|
||||
if (!Class_KeyEvent )
|
||||
{
|
||||
// Find java classes & functions on first call
|
||||
os::Printer::log("CKeyEventWrapper first initialize", ELL_DEBUG);
|
||||
Class_KeyEvent = JniEnv->FindClass("android/view/KeyEvent");
|
||||
Method_constructor = JniEnv->GetMethodID(Class_KeyEvent, "<init>", "(II)V");
|
||||
Method_getUnicodeChar = JniEnv->GetMethodID(Class_KeyEvent, "getUnicodeChar", "(I)I");
|
||||
}
|
||||
|
||||
if ( Class_KeyEvent && Method_constructor )
|
||||
{
|
||||
JniKeyEvent = JniEnv->NewObject(Class_KeyEvent, Method_constructor, action, code);
|
||||
}
|
||||
else
|
||||
{
|
||||
os::Printer::log("CKeyEventWrapper didn't find JNI classes/methods", ELL_WARNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CKeyEventWrapper::~CKeyEventWrapper()
|
||||
{
|
||||
JniEnv->DeleteLocalRef(JniKeyEvent);
|
||||
}
|
||||
|
||||
int CKeyEventWrapper::getUnicodeChar(int metaState)
|
||||
{
|
||||
return JniEnv->CallIntMethod(JniKeyEvent, Method_getUnicodeChar, metaState);
|
||||
}
|
||||
|
||||
} // namespace jni
|
||||
} // namespace irr
|
||||
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
|
@ -0,0 +1,43 @@
|
|||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_IRR_KEY_EVENT_WRAPPER_H_INCLUDED__
|
||||
#define __C_IRR_KEY_EVENT_WRAPPER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
struct android_app;
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace jni
|
||||
{
|
||||
|
||||
//! Minimal JNI wrapper class around android.view.KeyEvent
|
||||
//! NOTE: Only functions we actually use in the engine are wrapped
|
||||
//! This is currently not written to support multithreading - meaning threads are not attached/detached to the Java VM (to be discussed)
|
||||
class CKeyEventWrapper
|
||||
{
|
||||
public:
|
||||
CKeyEventWrapper(JNIEnv* jniEnv, int action, int code);
|
||||
~CKeyEventWrapper();
|
||||
|
||||
int getUnicodeChar(int metaState);
|
||||
|
||||
private:
|
||||
static jclass Class_KeyEvent;
|
||||
static jmethodID Method_getUnicodeChar;
|
||||
static jmethodID Method_constructor;
|
||||
JNIEnv* JniEnv;
|
||||
jobject JniKeyEvent; // this object in java
|
||||
};
|
||||
|
||||
} // namespace jni
|
||||
} // namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
#endif // __C_IRR_KEY_EVENT_WRAPPER_H_INCLUDED__
|
|
@ -20,6 +20,7 @@ LOCAL_SRC_FILES := \
|
|||
Android/CIrrDeviceAndroid.cpp \
|
||||
Android/CAndroidAssetReader.cpp \
|
||||
Android/CAndroidAssetFileArchive.cpp \
|
||||
Android/CKeyEventWrapper.cpp \
|
||||
aesGladman/aescrypt.cpp \
|
||||
aesGladman/aeskey.cpp \
|
||||
aesGladman/aestab.cpp \
|
||||
|
|
Loading…
Reference in New Issue