Example #1
0
/**
 * Convert an Android key event to ASCII.
 */
static unsigned char key_ascii(struct android_app* app, AInputEvent* event) {
  int32_t code = AKeyEvent_getKeyCode(event);

  /* Handle a few special cases: */
  switch (code) {
  case AKEYCODE_DEL:
    return 8;
  case AKEYCODE_FORWARD_DEL:
    return 127;
  case AKEYCODE_ESCAPE:
    return 27;
  }

  /* Get usable JNI context */
  JNIEnv* env = app->activity->env;
  JavaVM* vm = app->activity->vm;
  (*vm)->AttachCurrentThread(vm, &env, NULL);

  jclass KeyEventClass = (*env)->FindClass(env, "android/view/KeyEvent");
  jmethodID KeyEventConstructor = (*env)->GetMethodID(env, KeyEventClass, "<init>", "(II)V");
  jobject keyEvent = (*env)->NewObject(env, KeyEventClass, KeyEventConstructor,
				       AKeyEvent_getAction(event), AKeyEvent_getKeyCode(event));
  jmethodID KeyEvent_getUnicodeChar = (*env)->GetMethodID(env, KeyEventClass, "getUnicodeChar", "(I)I");
  int ascii = (*env)->CallIntMethod(env, keyEvent, KeyEvent_getUnicodeChar, AKeyEvent_getMetaState(event));

  /* LOGI("getUnicodeChar(%d) = %d ('%c')", AKeyEvent_getKeyCode(event), ascii, ascii); */

  return ascii;
}
Example #2
0
/*
* IN_Android_KeyEvent2UCS
*/
static wchar_t IN_Android_KeyEvent2UCS( const AInputEvent *event )
{
	JNIEnv *env = Sys_Android_GetJNIEnv();
	static jclass mapClass;
	static jmethodID load, get;
	jobject map;
	unsigned int ucs;

	if( !mapClass )
	{
		jclass mapClassRef;

		mapClassRef = (*env)->FindClass( env, "android/view/KeyCharacterMap" );
		mapClass = (*env)->NewGlobalRef( env, mapClassRef );
		load = (*env)->GetStaticMethodID( env, mapClass, "load", "(I)Landroid/view/KeyCharacterMap;" );
		get = (*env)->GetMethodID( env, mapClass, "get", "(II)I" );
		(*env)->DeleteLocalRef( env, mapClassRef );
	}

	map = (*env)->CallStaticObjectMethod( env, mapClass, load, AInputEvent_getDeviceId( event ) );
	ucs = (*env)->CallIntMethod( env, map, get, AKeyEvent_getKeyCode( event ), AKeyEvent_getMetaState( event ) );
	(*env)->DeleteLocalRef( env, map );

	return ucs;
}
Example #3
0
int32_t getKeyRune(JNIEnv* env, AInputEvent* e) {
	return (int32_t)(*env)->CallIntMethod(
		env,
		current_ctx,
		key_rune_method,
		AInputEvent_getDeviceId(e),
		AKeyEvent_getKeyCode(e),
		AKeyEvent_getMetaState(e)
	);
}
Example #4
0
int WindowImplAndroid::getUnicode(AInputEvent* event)
{
    // Retrieve activity states
    ActivityStates* states = getActivity(NULL);
    Lock lock(states->mutex);

    // Initializes JNI
    jint lResult;
    jint lFlags = 0;

    JavaVM* lJavaVM = states->activity->vm;
    JNIEnv* lJNIEnv = states->activity->env;

    JavaVMAttachArgs lJavaVMAttachArgs;
    lJavaVMAttachArgs.version = JNI_VERSION_1_6;
    lJavaVMAttachArgs.name = "NativeThread";
    lJavaVMAttachArgs.group = NULL;

    lResult=lJavaVM->AttachCurrentThread(&lJNIEnv, &lJavaVMAttachArgs);

    if (lResult == JNI_ERR)
        err() << "Failed to initialize JNI, couldn't get the Unicode value" << std::endl;

    // Retrieve key data from the input event
    jlong downTime = AKeyEvent_getDownTime(event);
    jlong eventTime = AKeyEvent_getEventTime(event);
    jint action = AKeyEvent_getAction(event);
    jint code = AKeyEvent_getKeyCode(event);
    jint repeat = AKeyEvent_getRepeatCount(event); // not sure!
    jint metaState = AKeyEvent_getMetaState(event);
    jint deviceId = AInputEvent_getDeviceId(event);
    jint scancode = AKeyEvent_getScanCode(event);
    jint flags = AKeyEvent_getFlags(event);
    jint source = AInputEvent_getSource(event);

    // Construct a KeyEvent object from the event data
    jclass ClassKeyEvent = lJNIEnv->FindClass("android/view/KeyEvent");
    jmethodID KeyEventConstructor = lJNIEnv->GetMethodID(ClassKeyEvent, "<init>", "(JJIIIIIIII)V");
    jobject ObjectKeyEvent = lJNIEnv->NewObject(ClassKeyEvent, KeyEventConstructor, downTime, eventTime, action, code, repeat, metaState, deviceId, scancode, flags, source);

    // Call its getUnicodeChar() method to get the Unicode value
    jmethodID MethodGetUnicode = lJNIEnv->GetMethodID(ClassKeyEvent, "getUnicodeChar", "(I)I");
    int unicode = lJNIEnv->CallIntMethod(ObjectKeyEvent, MethodGetUnicode, metaState);

    lJNIEnv->DeleteLocalRef(ClassKeyEvent);
    lJNIEnv->DeleteLocalRef(ObjectKeyEvent);

    // Detach this thread from the JVM
    lJavaVM->DetachCurrentThread();

    return unicode;
}
Example #5
0
extern "C" int AndroidGetKeyText( AInputEvent *event )
{
   int result = 0;
    // Attaches the current thread to the JVM. 
    jint lResult; 
    jint lFlags = 0; 

    JavaVM* lJavaVM = engine.app->activity->vm; 
    JNIEnv* lJNIEnv = engine.app->activity->env; 

    JavaVMAttachArgs lJavaVMAttachArgs; 
    lJavaVMAttachArgs.version = JNI_VERSION_1_6; 
    lJavaVMAttachArgs.name = "NativeThread"; 
    lJavaVMAttachArgs.group = NULL; 

    lResult=lJavaVM->AttachCurrentThread(&lJNIEnv, &lJavaVMAttachArgs);
    if (lResult == JNI_ERR) { 
        return 0;
    } 

    // Retrieves NativeActivity. 
    jobject lNativeActivity = engine.app->activity->clazz; 
	jclass ClassNativeActivity = lJNIEnv->GetObjectClass(lNativeActivity);

	jmethodID MethodSetFlags = lJNIEnv->GetMethodID(      ClassNativeActivity, "getKeyText", "(JJIIIIIII)I");
   lprintf( "..." );
		if( MethodSetFlags )
			result = lJNIEnv->CallIntMethod( lNativeActivity,  MethodSetFlags
													 , AKeyEvent_getDownTime(event)
													 , AKeyEvent_getEventTime(event)
													 , AKeyEvent_getAction(event)
													 , AKeyEvent_getKeyCode(event)
													 , AKeyEvent_getRepeatCount(event)
													 , AKeyEvent_getMetaState(event)
													 , AInputEvent_getDeviceId(event)
													 , AKeyEvent_getScanCode(event)
													 , AKeyEvent_getFlags(event)
													 );
		else
		{
         lprintf( "Failed to get method." );
			result = 0;
		}


	// Finished with the JVM. 
		lJavaVM->DetachCurrentThread();
      return result;
}
    bool InputService::onKeyboardEvent(AInputEvent* pEvent) {
#ifdef INPUTSERVICE_LOG_EVENTS
         packt_Log_debug("AKeyEvent_getAction=%d", AKeyEvent_getAction(pEvent));
         packt_Log_debug("AKeyEvent_getFlags=%d", AKeyEvent_getFlags(pEvent));
         packt_Log_debug("AKeyEvent_getKeyCode=%d", AKeyEvent_getKeyCode(pEvent));
         packt_Log_debug("AKeyEvent_getScanCode=%d", AKeyEvent_getScanCode(pEvent));
         packt_Log_debug("AKeyEvent_getMetaState=%d", AKeyEvent_getMetaState(pEvent));
         packt_Log_debug("AKeyEvent_getRepeatCount=%d", AKeyEvent_getRepeatCount(pEvent));
         packt_Log_debug("AKeyEvent_getDownTime=%lld", AKeyEvent_getDownTime(pEvent));
         packt_Log_debug("AKeyEvent_getEventTime=%lld", AKeyEvent_getEventTime(pEvent));
#endif
        const float ORTHOGONAL_MOVE = 1.0f;

        if (AKeyEvent_getAction(pEvent) == AKEY_EVENT_ACTION_DOWN) {
            switch (AKeyEvent_getKeyCode(pEvent)) {
            case AKEYCODE_DPAD_LEFT:
                mHorizontal = -ORTHOGONAL_MOVE;
                break;
            case AKEYCODE_DPAD_RIGHT:
                mHorizontal = ORTHOGONAL_MOVE;
                break;
            case AKEYCODE_DPAD_DOWN:
                mVertical = -ORTHOGONAL_MOVE;
                break;
            case AKEYCODE_DPAD_UP:
                mVertical = ORTHOGONAL_MOVE;
                break;
            case AKEYCODE_BACK:
                return false;
            }
        } else {
            switch (AKeyEvent_getKeyCode(pEvent)) {
            case AKEYCODE_DPAD_LEFT:
            case AKEYCODE_DPAD_RIGHT:
                mHorizontal = 0.0f;
                break;
            case AKEYCODE_DPAD_DOWN:
            case AKEYCODE_DPAD_UP:
                mVertical = 0.0f;
                break;
            case AKEYCODE_MENU:
                mMenuKey = true;
                break;
            case AKEYCODE_BACK:
                return false;
            }
        }
        return true;
    }
Example #7
0
static int32_t handle_input(struct android_app* app, AInputEvent* event) {
    /* app->userData is available here */

    if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
        app_has_focus = true;
        return 1;
    } else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) {
        LOGI("Key event: action=%d keyCode=%d metaState=0x%x",
                AKeyEvent_getAction(event),
                AKeyEvent_getKeyCode(event),
                AKeyEvent_getMetaState(event));
    }

    return 0;
}
Example #8
0
static int32_t engine_handle_input(struct android_app *app,
				   AInputEvent * event)
{
	struct engine *engine = (struct engine *) app->userData;
	if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
//		engine->animating = 1;
		return 1;
	} else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) {
		LOGI("Key event: action=%d keyCode=%d metaState=0x%x",
		     AKeyEvent_getAction(event),
		     AKeyEvent_getKeyCode(event),
		     AKeyEvent_getMetaState(event));
	}

	return 0;
}
Example #9
0
int32_t on_key_event(android_app *app, AInputEvent *event)
{
    user_data *p = (user_data *)app->userData;
    game_controller_input *old_keyboard_controller = GetController(p->old_input, 0);
    game_controller_input *new_keyboard_controller = GetController(p->new_input, 0);

    uint action = AKeyEvent_getAction(event);
    if (action == AKEY_EVENT_ACTION_MULTIPLE)
    {
        return 1;
    }
    bool32 is_down = action == AKEY_EVENT_ACTION_DOWN;

    int keycode = AKeyEvent_getKeyCode(event);
    int meta_state = AKeyEvent_getMetaState(event);
    if (keycode == 4)
    {
        return 0;
    }
    else if ((keycode == 51) || (keycode == 19))
    {
        process_keyboard_message(&new_keyboard_controller->MoveUp, is_down);
    }
    else if ((keycode == 29) || (keycode == 21))
    {
        process_keyboard_message(&new_keyboard_controller->MoveLeft, is_down);
    }
    else if ((keycode == 47) || (keycode == 20))
    {
        process_keyboard_message(&new_keyboard_controller->MoveDown, is_down);
    }
    else if ((keycode == 32) || (keycode == 22))
    {
        process_keyboard_message(&new_keyboard_controller->MoveRight, is_down);
    }
    else
    {
        __android_log_print(ANDROID_LOG_INFO, p->app_name, "key event: down %d, keycode %d, meta_state %x", is_down, keycode, meta_state);
    }
    return 1;
}
	bool OuyaInputView::dispatchKeyEvent(AInputEvent* keyEvent)
	{
		int64_t downTime = AKeyEvent_getDownTime(keyEvent);
		int64_t eventTime = AKeyEvent_getEventTime(keyEvent);
		int32_t action = AKeyEvent_getAction(keyEvent);
		int32_t code = AKeyEvent_getKeyCode(keyEvent);
		int32_t repeat = AKeyEvent_getRepeatCount(keyEvent);
		int32_t metaState = AKeyEvent_getMetaState(keyEvent);
		int32_t deviceId = AInputEvent_getDeviceId(keyEvent);
		int32_t scancode = AKeyEvent_getScanCode(keyEvent);
		int32_t flags = AKeyEvent_getFlags(keyEvent);
		int32_t source = AInputEvent_getSource(keyEvent);

#if ENABLE_VERBOSE_LOGGING
		__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "downTime=%lld eventTime=%lld action=%d code=%d repeat=%d metaState=%d deviceId=%d scancode=%d flags=%d source=%d",
			downTime, eventTime, action, code,
			repeat, metaState, deviceId, scancode, flags, source);
#endif

		return javaDispatchKeyEvent(downTime, eventTime, action, code,
			repeat, metaState, deviceId, scancode, flags, source);
	}
	bool AndroidGameApplication::onKeyEvent(AInputEvent* event)
	{
		int32 action = AKeyEvent_getAction(event);
		int32 flags = AKeyEvent_getFlags(event);
		int32 keyCode = AKeyEvent_getKeyCode(event);
		int32 scanCode = AKeyEvent_getScanCode(event);
		int32 state =  AKeyEvent_getMetaState(event);
		int32 repeatCount = AKeyEvent_getRepeatCount(event);

		LOGI("AndroidGameApplication::onKeyEvent");

		switch(action)
		{
		case AKEY_EVENT_ACTION_DOWN:
			{
				LOGI("AKEY_EVENT_ACTION_DOWN [keyCode = %d, scanCode = %d, repeatCount = %d, flags = 0x%X, state = 0x%X]",
						keyCode, scanCode, repeatCount, flags, state);
				for(std::list<IKeyboardController*>::iterator it = m_keyboardInputHandlers.begin();
						it != m_keyboardInputHandlers.end(); ++it)
				{
					(*it)->onKeyDown(keyCode, flags);
				}
			}
			break;
		case AKEY_EVENT_ACTION_UP:
			{
				LOGI("AKEY_EVENT_ACTION_DOWN [keyCode = %d, scanCode = %d, repeatCount = %d, flags = 0x%X, state = 0x%X]",
										keyCode, scanCode, repeatCount, flags, state);
				for(std::list<IKeyboardController*>::iterator it = m_keyboardInputHandlers.begin();
								it != m_keyboardInputHandlers.end(); ++it)
				{
					(*it)->onKeyUp(keyCode, flags);
				}
			}
			break;
		}

		return true;
	}
Example #12
0
static int32_t handle_input(struct android_app* app, AInputEvent* event) {
    /* app->userData is available here */

    if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
        app_has_focus = true;

	//	LOGI("Motion Event, pressed = %d", (pressed?1:0));
	
	for (int i=0; i< AMotionEvent_getPointerCount(event); ++i)
	  {
	    int action = AMotionEvent_getAction(event);
	    //  LOGI("Motion Event, action = %d", action);
	    if ((action & AMOTION_EVENT_ACTION_DOWN)
		||(action & AMOTION_EVENT_ACTION_POINTER_DOWN))
	      {
		//LOGI("In");
		if (!pressed)
		  {
		    pressed = true;
		    float px = AMotionEvent_getX(event, i);
		    float py = AMotionEvent_getY(event, i);
		    cd->clickat(px,py);
		  }
	      }
	    else
	      pressed = false;

	  }
        return 1;
    } else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) {
        LOGI("Key event: action=%d keyCode=%d metaState=0x%x",
                AKeyEvent_getAction(event),
                AKeyEvent_getKeyCode(event),
                AKeyEvent_getMetaState(event));
    }

    return 0;
}
Example #13
0
static void _log_event(AInputEvent *event) {
    if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) {
        LOGD("DEBUG: Key event: action=%d, keycode=%d, meta=0x%x, source=%d",
            AKeyEvent_getAction(event),
            AKeyEvent_getKeyCode(event),
            AKeyEvent_getMetaState(event),
            (int)(AInputEvent_getSource(event)));
    } else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
        LOGD("DEBUG: Motion event: deviceid=%d, pointerid=%d, sourceid=%d, action=%d, keycode=%d"
         "x,y=%f,%f, raw x,y=%f,%f, source=%d",
        (int)AInputEvent_getDeviceId(event),
        (int)AMotionEvent_getPointerId(event, 0),
        (int)AInputEvent_getSource(event),
        (int)AKeyEvent_getAction(event),
        (int)AKeyEvent_getKeyCode(event),
        (float)AMotionEvent_getX(event,0),
        (float)AMotionEvent_getY(event,0),
        (float)AMotionEvent_getRawX(event,0),
        (float)AMotionEvent_getRawY(event,0),
        (int)(AInputEvent_getSource(event)));
    } else {
        LOGD("DEBUG: other type of event, %d", AInputEvent_getType(event));
    }
}
Example #14
0
/**
 * Process the next input event.
 */
static
int32_t
engine_handle_input( struct android_app* app, AInputEvent* event )
{
	JNIEnv *jni;
	(*jVM)->AttachCurrentThread(jVM, &jni, NULL);

	struct ENGINE* engine = (struct ENGINE*)app->userData;
    if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY){
        int device = AInputEvent_getDeviceId(event);
        int action = AKeyEvent_getAction(event);
        int keyCode = AKeyEvent_getKeyCode(event);
        if(jni && g_pActivity){
            if((*jni)->ExceptionCheck(jni)) {
                (*jni)->ExceptionDescribe(jni);
                (*jni)->ExceptionClear(jni);
            }
            (*jni)->CallIntMethod(jni, g_pActivity, javaOnNDKKey, device, keyCode, action, AKeyEvent_getMetaState(event));
            if (!(keyCode == AKEYCODE_MENU || keyCode == AKEYCODE_BACK || keyCode == AKEYCODE_BUTTON_THUMBR || keyCode == AKEYCODE_VOLUME_UP || keyCode == AKEYCODE_VOLUME_DOWN || keyCode == AKEYCODE_BUTTON_SELECT)) {
                return 1;
            }
        }
    } else if( AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION ) {
        int device = AInputEvent_getDeviceId( event );
        int nSourceId		= AInputEvent_getSource( event );
        int nPointerCount	= AMotionEvent_getPointerCount( event );
        int n;

        jboolean newTouch = JNI_TRUE;
        for( n = 0 ; n < nPointerCount ; ++n )
        {
            int nPointerId	= AMotionEvent_getPointerId( event, n );
            int nAction		= AMOTION_EVENT_ACTION_MASK & AMotionEvent_getAction( event );
            int nRawAction	= AMotionEvent_getAction( event );

            struct TOUCHSTATE *touchstate = 0;
            if( nSourceId == AINPUT_SOURCE_TOUCHPAD ) {
                touchstate = engine->touchstate_pad;
            } else {
                touchstate = engine->touchstate_screen;
            }

            if( nAction == AMOTION_EVENT_ACTION_POINTER_DOWN || nAction == AMOTION_EVENT_ACTION_POINTER_UP )
            {
                int nPointerIndex = (AMotionEvent_getAction( event ) & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
                nPointerId = AMotionEvent_getPointerId( event, nPointerIndex );
            }

            if( nAction == AMOTION_EVENT_ACTION_DOWN || nAction == AMOTION_EVENT_ACTION_POINTER_DOWN )
            {
                touchstate[nPointerId].down = 1;
            }
            else if( nAction == AMOTION_EVENT_ACTION_UP || nAction == AMOTION_EVENT_ACTION_POINTER_UP || nAction == AMOTION_EVENT_ACTION_CANCEL )
            {
                touchstate[nPointerId].down = 0;
            }

            if (touchstate[nPointerId].down == 1)
            {
                touchstate[nPointerId].x = AMotionEvent_getX( event, n );
                touchstate[nPointerId].y = AMotionEvent_getY( event, n );
            }

            if( jni && g_pActivity && isXperiaPlay) {
//                (*jni)->CallVoidMethod( jni, g_pActivity, javaOnNDKTouch, device, nSourceId, nRawAction, touchstate[nPointerId].x, touchstate[nPointerId].y, newTouch);
                (*jni)->CallVoidMethod( jni, g_pActivity, javaOnNDKTouch, device, nSourceId, nRawAction, touchstate[nPointerId].x, touchstate[nPointerId].y);
            }
            newTouch = JNI_FALSE;
        }
Example #15
0
s32 CIrrDeviceAndroid::handleInput(android_app* app, AInputEvent* androidEvent)
{
	CIrrDeviceAndroid* device = (CIrrDeviceAndroid*)app->userData;
	s32 status = 0;

	switch ( AInputEvent_getType(androidEvent) )
	{
		case AINPUT_EVENT_TYPE_MOTION:
		{
			SEvent event;
			event.EventType = EET_TOUCH_INPUT_EVENT;

			s32 eventAction = AMotionEvent_getAction(androidEvent);
			s32 eventType =  eventAction & AMOTION_EVENT_ACTION_MASK;

#if 0
			// Useful for debugging. We might have to pass some of those infos on at some point.
			// but preferably device independent (so iphone can use same irrlicht flags).
			int32_t flags = AMotionEvent_getFlags(androidEvent);
			os::Printer::log("flags: ", core::stringc(flags).c_str(), ELL_DEBUG);
			int32_t metaState = AMotionEvent_getMetaState(androidEvent);
			os::Printer::log("metaState: ", core::stringc(metaState).c_str(), ELL_DEBUG);
			int32_t edgeFlags = AMotionEvent_getEdgeFlags(androidEvent);
			os::Printer::log("edgeFlags: ", core::stringc(flags).c_str(), ELL_DEBUG);			
#endif

			bool touchReceived = true;

			switch (eventType)
			{
			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;
			}

			if (touchReceived)
			{
				// Process all touches for move action.
				if (event.TouchInput.Event == ETIE_MOVED)
				{
					s32 pointerCount = AMotionEvent_getPointerCount(androidEvent);

					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);
			// os::Printer::log("keyCode: ", core::stringc(keyCode).c_str(), ELL_DEBUG);
			
			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->Initialized && 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.
					// And we have to do that as someone else can have detached the thread in the meantime.
					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;
					}
				}
				if ( event.KeyInput.Key == KEY_BACK )
				{
					event.KeyInput.Char =  0x08;	// same key-code as on other operating systems. Otherwise we have to handle too much system specific stuff in the editbox.
				}
				//os::Printer::log("char-code: ", core::stringc((int)event.KeyInput.Char).c_str(), ELL_DEBUG);
				
			}
			else
			{
				// os::Printer::log("keyCode: ", core::stringc(keyCode).c_str(), ELL_DEBUG);
				event.KeyInput.Char = 0;
			}

			device->postEventFromUser(event);
		}
		break;
		default:
		break;
	}

	return status;
}
Example #16
0
    int32_t onKey(const int32_t& action, void* data)
    {
        auto event = static_cast<AInputEvent*>(data);

        const int32_t metakey = AKeyEvent_getMetaState(event);
        const int32_t key = AKeyEvent_getKeyCode(event);
        const int32_t scanCode = AKeyEvent_getScanCode(event);

        int jopKey = Input::getJopKey(key);

        const int mod = ((metakey & AMETA_SHIFT_ON) != 0) * Keyboard::Modifier::Shift
                      | ((metakey & AMETA_ALT_ON)   != 0) * Keyboard::Modifier::Alt
                      | ((metakey & AMETA_CTRL_ON)  != 0) * Keyboard::Modifier::Control;

        int32_t device = AInputEvent_getSource(event);

        auto& windowRef = Engine::getMainWindow();

        switch (action)
        {
            case AKEY_EVENT_ACTION_DOWN:
            {      
                auto state = ActivityState::get();

                if (jopKey != Keyboard::Unknown)
                {
                    state->activeKey = jopKey;
                    windowRef.getEventHandler()->keyPressed(jopKey, scanCode, mod);
                }
                
                if (Controller::controllersPresent())
                {
                    jopKey = Input::getJopControllerButton(key);

                    if (jopKey != Controller::XBox::Unknown)
                    {
                        state->activeControllerButtons[jopKey] = true;
                        windowRef.getEventHandler()->controllerButtonPressed(0, jopKey);
                    }
                }

                return 1;
            }
            case AKEY_EVENT_ACTION_UP:
            {
                auto state = ActivityState::get();

                if (jopKey != Keyboard::Unknown)
                {
                    state->activeKey = -1;
                    windowRef.getEventHandler()->keyReleased(jopKey, scanCode, mod);
                }

                if (Controller::controllersPresent())
                {
                    jopKey = Input::getJopControllerButton(key);

                    if (jopKey != Controller::XBox::Unknown)
                    {
                        state->activeControllerButtons[jopKey] = false;
                        windowRef.getEventHandler()->controllerButtonReleased(0, jopKey);
                    }
                } 

                return 1;
            }
            case AKEY_EVENT_ACTION_MULTIPLE:
            {
                if (jopKey != 0)
                {
                    windowRef.getEventHandler()->keyPressed(jopKey, scanCode, mod);
                    windowRef.getEventHandler()->keyReleased(jopKey, scanCode, mod);
                } 

                if (Controller::controllersPresent())
                {
                    jopKey = Input::getJopControllerButton(key);

                    if (jopKey != Controller::XBox::Unknown)
                    {
                        windowRef.getEventHandler()->controllerButtonPressed(0, jopKey);
                        windowRef.getEventHandler()->controllerButtonReleased(0, jopKey);
                    }
                }

                return 1;
            }
        }

        return 0;
    }
Example #17
0
int WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* states)
{
    int32_t device = AInputEvent_getSource(_event);
    int32_t action = AKeyEvent_getAction(_event);

    int32_t key = AKeyEvent_getKeyCode(_event);
    int32_t metakey = AKeyEvent_getMetaState(_event);

    Event event;
    event.key.code    = androidKeyToSF(key);
    event.key.alt     = metakey & AMETA_ALT_ON;
    event.key.control = false;
    event.key.shift   = metakey & AMETA_SHIFT_ON;

    switch (action)
    {
    case AKEY_EVENT_ACTION_DOWN:
        event.type = Event::KeyPressed;
        forwardEvent(event);
        return 1;
    case AKEY_EVENT_ACTION_UP:
        event.type = Event::KeyReleased;
        forwardEvent(event);

        if (int unicode = getUnicode(_event))
        {
            event.type = Event::TextEntered;
            event.text.unicode = unicode;
            forwardEvent(event);
        }
        return 1;
    case AKEY_EVENT_ACTION_MULTIPLE:
        // Since complex inputs don't get separate key down/up events
        // both have to be faked at once
        event.type = Event::KeyPressed;
        forwardEvent(event);
        event.type = Event::KeyReleased;
        forwardEvent(event);

        // This requires some special treatment, since this might represent
        // a repetition of key presses or a complete sequence
        if (key == AKEYCODE_UNKNOWN)
        {
            // This is a unique sequence, which is not yet exposed in the NDK
            // http://code.google.com/p/android/issues/detail?id=33998
            return 0;
        }
        else if (int unicode = getUnicode(_event)) // This is a repeated sequence
        {
            event.type = Event::TextEntered;
            event.text.unicode = unicode;

            int32_t repeats = AKeyEvent_getRepeatCount(_event);
            for (int32_t i = 0; i < repeats; ++i)
                forwardEvent(event);
            return 1;
        }
        break;
    }
    return 0;
}
Example #18
0
static void android_input_poll(void *data)
{
   (void)data;

   RARCH_PERFORMANCE_INIT(input_poll);
   RARCH_PERFORMANCE_START(input_poll);

   bool debug_enable = g_settings.input.debug_enable;
   struct android_app* android_app = (struct android_app*)g_android;
   uint64_t *lifecycle_state = &g_extern.lifecycle_state;

   *lifecycle_state &= ~((1ULL << RARCH_RESET) | (1ULL << RARCH_REWIND) | (1ULL << RARCH_FAST_FORWARD_KEY) | (1ULL << RARCH_FAST_FORWARD_HOLD_KEY) | (1ULL << RARCH_MUTE) | (1ULL << RARCH_SAVE_STATE_KEY) | (1ULL << RARCH_LOAD_STATE_KEY) | (1ULL << RARCH_STATE_SLOT_PLUS) | (1ULL << RARCH_STATE_SLOT_MINUS));

   // Read all pending events.
   while (AInputQueue_hasEvents(android_app->inputQueue) > 0)
   {
      AInputEvent* event = NULL;
      if (AInputQueue_getEvent(android_app->inputQueue, &event) < 0)
         break;

      bool long_msg_enable = false;
      int32_t handled = 1;
      int action = 0;
      char msg[128];
      msg[0] = 0;

      int source = AInputEvent_getSource(event);
      int id = AInputEvent_getDeviceId(event);
      if (id == zeus_second_id)
         id = zeus_id;
      int keycode = AKeyEvent_getKeyCode(event);

      int type_event = AInputEvent_getType(event);
      int state_id = -1;

      if (source & (AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD))
         state_id = 0; // touch overlay is always player 1
      else
      {
         for (unsigned i = 0; i < pads_connected; i++)
            if (state_device_ids[i] == id)
               state_id = i;
      }

      if (state_id < 0)
      {
         state_id = pads_connected;
         state_device_ids[pads_connected++] = id;

         input_autodetect_setup(android_app, msg, sizeof(msg), state_id, id, source);
         long_msg_enable = true;
      }

      if (keycode == AKEYCODE_BACK )
      {
         int meta = AKeyEvent_getMetaState(event);
         if (!(meta & AMETA_ALT_ON))
         {
            *lifecycle_state |= (1ULL << RARCH_QUIT_KEY);
            AInputQueue_finishEvent(android_app->inputQueue, event, handled);
            break;
         }
      }

      if (type_event == AINPUT_EVENT_TYPE_MOTION)
      {
         float x = 0.0f;
         float y = 0.0f;
         action = AMotionEvent_getAction(event);
         size_t motion_pointer = action >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
         action &= AMOTION_EVENT_ACTION_MASK;

         if (source & ~(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_MOUSE))
         {
            if (g_settings.input.dpad_emulation[state_id] != DPAD_EMULATION_NONE)
            {
               uint64_t *state_cur = &state[state_id];
               x = AMotionEvent_getX(event, motion_pointer);
               y = AMotionEvent_getY(event, motion_pointer);
               *state_cur &= ~((1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT) | (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT) |
                     (1ULL << RETRO_DEVICE_ID_JOYPAD_UP) | (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN));
               *state_cur |= PRESSED_LEFT(x, y)  ? (1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT)  : 0;
               *state_cur |= PRESSED_RIGHT(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0;
               *state_cur |= PRESSED_UP(x, y)    ? (1ULL << RETRO_DEVICE_ID_JOYPAD_UP)    : 0;
               *state_cur |= PRESSED_DOWN(x, y)  ? (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN)  : 0;
            }
         }
         else
         {
            bool keyup = (action == AMOTION_EVENT_ACTION_UP ||
                  action == AMOTION_EVENT_ACTION_CANCEL || action == AMOTION_EVENT_ACTION_POINTER_UP) ||
               (source == AINPUT_SOURCE_MOUSE && action != AMOTION_EVENT_ACTION_DOWN);

            if (keyup && motion_pointer < MAX_TOUCH)
            {
               memmove(pointer + motion_pointer, pointer + motion_pointer + 1, (MAX_TOUCH - motion_pointer - 1) * sizeof(struct input_pointer));
               if (pointer_count > 0)
                  pointer_count--;
            }
            else
            {
               int pointer_max = min(AMotionEvent_getPointerCount(event), MAX_TOUCH);
               for (motion_pointer = 0; motion_pointer < pointer_max; motion_pointer++)
               {
                  x = AMotionEvent_getX(event, motion_pointer);
                  y = AMotionEvent_getY(event, motion_pointer);

                  input_translate_coord_viewport(x, y,
                        &pointer[motion_pointer].x, &pointer[motion_pointer].y,
                        &pointer[motion_pointer].full_x, &pointer[motion_pointer].full_y);

                  pointer_count = max(pointer_count, motion_pointer + 1);
               }
            }
         }

         if (debug_enable)
            snprintf(msg, sizeof(msg), "Pad %d : x = %.2f, y = %.2f, src %d.\n", state_id, x, y, source);
      }
      else if (type_event == AINPUT_EVENT_TYPE_KEY)
Example #19
0
/**
 * Process the next input event.
 */
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
{
	struct engine* engine = (struct engine*)app->userData;
	switch(AInputEvent_getType(event))
	{
	case AINPUT_EVENT_TYPE_MOTION:
		{
		int32_t action = AMotionEvent_getAction(event );
		int pointer = ( action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK ) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
		int p = AMotionEvent_getPointerCount( event );
#ifdef DEBUG_TOUCH_INPUT
		LOGI( "pointer (full action)%04x (pointer)%d (number points)%d", action, pointer, p );
#endif
		{
			int n;
			for( n = 0; n < engine->nPoints; n++ )
			{
				engine->points[n].flags.new_event = 0;
				if( engine->points[n].flags.end_event )
				{
					int m;
					for( m = n; m < (engine->nPoints-1); m++ )
					{
						if( engine->input_point_map[m+1] == m+1 )
							engine->input_point_map[m] = m;
						else
						{
							if( engine->input_point_map[m+1] < n )
								engine->input_point_map[m] = engine->input_point_map[m+1];
							else
								engine->input_point_map[m] = engine->input_point_map[m+1] - 1;

						}
						engine->points[m] = engine->points[m+1];
					}
					engine->nPoints--;
					n--;
				}
			}
		}

		switch( action & AMOTION_EVENT_ACTION_MASK )
		{
		case AMOTION_EVENT_ACTION_DOWN:
			// primary pointer down.
			//if( engine->nPoints )
			//{
			//	LOGI( "Pointer Event Down (pointer0) and there's already pointers..." );
			//}
			engine->points[0].x = AMotionEvent_getX( event, pointer );
			engine->points[0].y = AMotionEvent_getY( event, pointer );
			engine->points[0].flags.new_event = 1;
			engine->points[0].flags.end_event = 0;
			engine->nPoints++;
			engine->input_point_map[0] = 0;
			break;
		case AMOTION_EVENT_ACTION_UP:
			// primary pointer up.
			engine->points[0].flags.new_event = 0;
			engine->points[0].flags.end_event = 1;
			break;
		case AMOTION_EVENT_ACTION_MOVE:
			{
				int n;
				for( n = 0; n < p; n++ )
				{
					// points may have come in as 'new' in the wrong order,
					// reference the input point map to fill in the correct point location
					int actual = engine->input_point_map[n];
					engine->points[actual].x = AMotionEvent_getX( event, n );
					engine->points[actual].y = AMotionEvent_getY( event, n );
					engine->points[actual].flags.new_event = 0;
					engine->points[actual].flags.end_event = 0;
				}
			}
			break;
		case AMOTION_EVENT_ACTION_POINTER_DOWN:
			// the new pointer might not be the last one, so we insert it.
			// at the end, before dispatch, new points are moved to the end
			// and mapping begins.  this code should not reference the map
			if( pointer < engine->nPoints )
			{
				int c;
#ifdef DEBUG_TOUCH_INPUT
				LOGI( "insert point new. %d", engine->nPoints-1 );
#endif
				for( c = engine->nPoints; c >= pointer; c-- )
				{
#ifdef DEBUG_TOUCH_INPUT
					LOGI( "Set %d to %d", c, engine->input_point_map[c-1] );
#endif
					engine->input_point_map[c] = engine->input_point_map[c-1]; // save still in the same target...
				}
#ifdef DEBUG_TOUCH_INPUT
				LOGI( "Set %d to %d", pointer, engine->nPoints );
#endif
				engine->input_point_map[pointer] = engine->nPoints; // and the new one maps to the last.
				// now just save in last and don't swap twice.
				engine->points[engine->nPoints].x = AMotionEvent_getX( event, pointer );
				engine->points[engine->nPoints].y = AMotionEvent_getY( event, pointer );
				pointer = engine->nPoints;
			}
			else
			{
				engine->points[pointer].x = AMotionEvent_getX( event, pointer );
				engine->points[pointer].y = AMotionEvent_getY( event, pointer );
				engine->input_point_map[pointer] = pointer;
			}
			// primary pointer down.
			engine->points[pointer].flags.new_event = 1;
			engine->points[pointer].flags.end_event = 0;
			// always initialize the
			engine->nPoints++;
			break;
		case AMOTION_EVENT_ACTION_POINTER_UP:
			{
				// a up pointer may be remapped already, set the actual entry for the point
				int actual = engine->input_point_map[pointer];
				int n;
				engine->points[actual].flags.new_event = 0;
				engine->points[actual].flags.end_event = 1;

#ifdef DEBUG_TOUCH_INPUT
				LOGI( "Set point %d (map %d) to ended", pointer, actual );
#endif
				// any release event will reset the other input points appropriately(?)
				for( n = 0; n < engine->nPoints; n++ )
				{
					int other;
					if( engine->input_point_map[n] != n )
					{
						int m;
#ifdef DEBUG_TOUCH_INPUT
						LOGI( "reorder to natural input order" );
#endif
						memcpy( engine->tmp_points, engine->points, engine->nPoints * sizeof( struct input_point ) );
						// m is the point currently mapped to this position.
						// data from engine[n] and engine[m] need to swap
						for( m = 0; m < engine->nPoints; m++ )
						{
							engine->points[m] = engine->tmp_points[other = engine->input_point_map[m]];
							engine->input_point_map[m] = m;
#ifdef DEBUG_TOUCH_INPUT
							LOGI( "move point %d to %d", other, m );
#endif
						}
						break;
					}
				}
			}
			break;
		default:
#ifdef DEBUG_TOUCH_INPUT
			LOGI( "Motion Event ignored..." );
#endif
			break;
		}

		{
			int n;
#ifdef DEBUG_TOUCH_INPUT
			for( n = 0; n < engine->nPoints; n++ )
			{
				LOGI( "Point : %d %d %g %g %d %d", n, engine->input_point_map[n], engine->points[n].x , engine->points[n].y, engine->points[n].flags.new_event, engine->points[n].flags.end_event );
			}
#endif
		}

		BagVidlibPureglSendTouchEvents( engine->nPoints, engine->points );
		//engine->state.animating = 1;
		//engine->state.x = AMotionEvent_getX(event, 0);
		//engine->state.y = AMotionEvent_getY(event, 0);
		return 1;
		}
	case AINPUT_EVENT_TYPE_KEY:
		{
			int32_t key_val = AKeyEvent_getKeyCode(event);
			//int32_t key_char = AKeyEvent_getKeyChar(event);
			int32_t key_mods = AKeyEvent_getMetaState( event );
			int32_t key_pressed = AKeyEvent_getAction( event );
			int realmod = 0;
         //lprintf( "key char is %d (%c)", key_char, key_char );
			if( ( key_mods & 0x3000 ) == 0x3000 )
				realmod |= KEY_MOD_CTRL;
			if( ( key_mods & 0x12 ) == 0x12 )
				realmod |= KEY_MOD_ALT;
			if( ( key_mods & 0x41 ) == 0x41 )
				realmod |= KEY_MOD_SHIFT;
			key_mods = realmod;
#ifdef DEBUG_KEY_INPUT
			LOGI("Received key event: %d %d %d\n", key_pressed, key_val, key_mods );
#endif
			{
				engine->key_text = AndroidGetKeyText( event );
            lprintf( "Event translates to %d(%04x)%c", engine->key_text, engine->key_text ,engine->key_text );
			}

			if( key_val )
			{
				int used;
				if( key_pressed == AKEY_EVENT_ACTION_MULTIPLE )
				{
					int count = AKeyEvent_getRepeatCount( event );
					int n;
					for( n = 0; n < count; n++ )
					{
						used = BagVidlibPureglSendKeyEvents( 1, key_val, key_mods );
						used = BagVidlibPureglSendKeyEvents( 0, key_val, key_mods );
					}
				}
				else
					used = BagVidlibPureglSendKeyEvents( (key_pressed==AKEY_EVENT_ACTION_DOWN)?1:0, key_val, key_mods );
				return used;
			}
			break;
		}
	default:
		LOGI( "Unhandled Motion Event ignored..." );
		break;
	}
	return 0;
}
Example #20
0
bool CAndroidKey::onKeyboardEvent(AInputEvent* event)
{
  CXBMCApp::android_printf("%s", __PRETTY_FUNCTION__);
  if (event == NULL)
    return false;

  int32_t keycode = AKeyEvent_getKeyCode(event);
  int32_t flags = AKeyEvent_getFlags(event);
  int32_t state = AKeyEvent_getMetaState(event);
  int32_t repeatCount = AKeyEvent_getRepeatCount(event);

  // Check if we got some special key
  uint16_t sym = XBMCK_UNKNOWN;
  for (unsigned int index = 0; index < sizeof(keyMap) / sizeof(KeyMap); index++)
  {
    if (keycode == keyMap[index].nativeKey)
    {
      sym = keyMap[index].xbmcKey;
      break;
    }
  }
  
  // check if this is a key we don't want to handle
  if (sym == XBMCK_LAST)
    return false;

  uint16_t modifiers = 0;
  if (state & AMETA_ALT_LEFT_ON)
    modifiers |= XBMCKMOD_LALT;
  if (state & AMETA_ALT_RIGHT_ON)
    modifiers |= XBMCKMOD_RALT;
  if (state & AMETA_SHIFT_LEFT_ON)
    modifiers |= XBMCKMOD_LSHIFT;
  if (state & AMETA_SHIFT_RIGHT_ON)
    modifiers |= XBMCKMOD_RSHIFT;
  /* TODO:
  if (state & AMETA_SYM_ON)
    modifiers |= 0x000?;*/

  switch (AKeyEvent_getAction(event))
  {
    case AKEY_EVENT_ACTION_DOWN:
      CXBMCApp::android_printf("CXBMCApp: key down (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)",
                      keycode, repeatCount, flags,
                      (state & AMETA_ALT_ON) ? "yes" : "no",
                      (state & AMETA_SHIFT_ON) ? "yes" : "no",
                      (state & AMETA_SYM_ON) ? "yes" : "no");
      XBMC_Key((uint8_t)keycode, sym, modifiers, false);
      return true;

    case AKEY_EVENT_ACTION_UP:
      CXBMCApp::android_printf("CXBMCApp: key up (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)",
                      keycode, repeatCount, flags,
                      (state & AMETA_ALT_ON) ? "yes" : "no",
                      (state & AMETA_SHIFT_ON) ? "yes" : "no",
                     (state & AMETA_SYM_ON) ? "yes" : "no");
      XBMC_Key((uint8_t)keycode, sym, modifiers, true);
      return true;

    case AKEY_EVENT_ACTION_MULTIPLE:
      CXBMCApp::android_printf("CXBMCApp: key multiple (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)",
                      keycode, repeatCount, flags,
                      (state & AMETA_ALT_ON) ? "yes" : "no",
                      (state & AMETA_SHIFT_ON) ? "yes" : "no",
                      (state & AMETA_SYM_ON) ? "yes" : "no");
      break;

    default:
      CXBMCApp::android_printf("CXBMCApp: unknown key (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)",
                      keycode, repeatCount, flags,
                      (state & AMETA_ALT_ON) ? "yes" : "no",
                      (state & AMETA_SHIFT_ON) ? "yes" : "no",
                      (state & AMETA_SYM_ON) ? "yes" : "no");
      break;
  }

  return false;
}
Example #21
0
bool CAndroidKey::onKeyboardEvent(AInputEvent *event)
{
  if (event == NULL)
    return false;

  int32_t flags   = AKeyEvent_getFlags(event);
  int32_t state   = AKeyEvent_getMetaState(event);
  int32_t action  = AKeyEvent_getAction(event);
  int32_t repeat  = AKeyEvent_getRepeatCount(event);
  int32_t keycode = AKeyEvent_getKeyCode(event);

  int32_t deviceId = AInputEvent_getDeviceId(event);
  CJNIKeyCharacterMap map = CJNIKeyCharacterMap::load(deviceId);
  uint16_t unicode = map.get(keycode, state);

  // Check if we got some special key
  uint16_t sym = XBMCK_UNKNOWN;
  for (unsigned int index = 0; index < sizeof(keyMap) / sizeof(KeyMap); index++)
  {
    if (keycode == keyMap[index].nativeKey)
    {
      sym = keyMap[index].xbmcKey;
      break;
    }
  }
  if (m_handleMediaKeys)
  {
    for (unsigned int index = 0; index < sizeof(MediakeyMap) / sizeof(KeyMap); index++)
    {
      if (keycode == MediakeyMap[index].nativeKey)
      {
        sym = MediakeyMap[index].xbmcKey;
        break;
      }
    }
  }

  // check if this is a key we don't want to handle
  if (sym == XBMCK_LAST || sym == XBMCK_UNKNOWN)
  {
    CXBMCApp::android_printf("CAndroidKey: key ignored (code: %d)", keycode);
    return false;
  }

  uint16_t modifiers = 0;
  if (state & AMETA_ALT_LEFT_ON)
    modifiers |= XBMCKMOD_LALT;
  if (state & AMETA_ALT_RIGHT_ON)
    modifiers |= XBMCKMOD_RALT;
  if (state & AMETA_SHIFT_LEFT_ON)
    modifiers |= XBMCKMOD_LSHIFT;
  if (state & AMETA_SHIFT_RIGHT_ON)
    modifiers |= XBMCKMOD_RSHIFT;
  if (state & AMETA_CTRL_LEFT_ON)
    modifiers |= XBMCKMOD_LCTRL;
  if (state & AMETA_CTRL_RIGHT_ON)
    modifiers |= XBMCKMOD_RCTRL;
  /* TODO:
  if (state & AMETA_SYM_ON)
    modifiers |= 0x000?;*/

  switch (action)
  {
    case AKEY_EVENT_ACTION_DOWN:
#if 1
      CXBMCApp::android_printf("CAndroidKey: key down (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)",
        keycode, repeat, flags,
        (state & AMETA_ALT_ON) ? "yes" : "no",
        (state & AMETA_SHIFT_ON) ? "yes" : "no",
        (state & AMETA_SYM_ON) ? "yes" : "no");
#endif
      XBMC_Key((uint8_t)keycode, sym, modifiers, unicode, false);
      return true;

    case AKEY_EVENT_ACTION_UP:
#if 1
      CXBMCApp::android_printf("CAndroidKey: key up (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)",
        keycode, repeat, flags,
        (state & AMETA_ALT_ON) ? "yes" : "no",
        (state & AMETA_SHIFT_ON) ? "yes" : "no",
        (state & AMETA_SYM_ON) ? "yes" : "no");
#endif
      XBMC_Key((uint8_t)keycode, sym, modifiers, unicode, true);
      return true;

    case AKEY_EVENT_ACTION_MULTIPLE:
#if 1
      CXBMCApp::android_printf("CAndroidKey: key multiple (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)",
        keycode, repeat, flags,
        (state & AMETA_ALT_ON) ? "yes" : "no",
        (state & AMETA_SHIFT_ON) ? "yes" : "no",
        (state & AMETA_SYM_ON) ? "yes" : "no");
#endif
      break;

    default:
#if 1
      CXBMCApp::android_printf("CAndroidKey: unknown key (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)",
        keycode, repeat, flags,
        (state & AMETA_ALT_ON) ? "yes" : "no",
        (state & AMETA_SHIFT_ON) ? "yes" : "no",
        (state & AMETA_SYM_ON) ? "yes" : "no");
#endif
      break;
  }

  return false;
}