static void process_input(struct android_app* app, struct android_poll_source* source) { AInputEvent* event = NULL; if (AInputQueue_getEvent(app->inputQueue, &event) >= 0) { // HACK: Override back buttom to show / hide keyboard. int type = AInputEvent_getType(event); if(type == AINPUT_EVENT_TYPE_KEY) { if(AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN) { static bool keyboard_shown = false; if( AKeyEvent_getKeyCode(event) == AKEYCODE_BACK ) { displayKeyboard(app,!keyboard_shown); keyboard_shown = !keyboard_shown; AInputQueue_finishEvent(app->inputQueue, event, 1); return; } } } if (AInputQueue_preDispatchEvent(app->inputQueue, event)) { return; } int32_t handled = 0; if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event); AInputQueue_finishEvent(app->inputQueue, event, handled); } else { LOGE("Failure reading next input event: %s\n", strerror(errno)); } }
void StAndroidGlue::processInput() { for(AInputEvent* anEvent = NULL; AInputQueue_getEvent(myInputQueue, &anEvent) >= 0;) { if(AInputQueue_preDispatchEvent(myInputQueue, anEvent)) { continue; } bool isHandled = false; signals.onInputEvent(anEvent, isHandled); AInputQueue_finishEvent(myInputQueue, anEvent, isHandled ? 1 : 0); } }
// Fix per Google for bug https://code.google.com/p/android/issues/detail?id=41755 static void process_input(struct android_app* app, struct android_poll_source* source) { AInputEvent* event = NULL; while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) { if (AInputQueue_preDispatchEvent(app->inputQueue, event)) { continue; } int32_t handled = 0; if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event); AInputQueue_finishEvent(app->inputQueue, event, handled); } }
void cxAndroid::cxAndroidInputExec(cxAndroid *app, AndroidPollSource *source) { AInputEvent* event = NULL; while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) { if (AInputQueue_preDispatchEvent(app->inputQueue, event)) { continue; } int32_t handled = app->HandleInput(event); AInputQueue_finishEvent(app->inputQueue, event, handled); } }
static void process_input(struct android_app* app, struct android_poll_source* source) { AInputEvent* event = NULL; if (AInputQueue_getEvent(app->inputQueue, &event) >= 0) { if (AInputQueue_preDispatchEvent(app->inputQueue, event)) { return; } int32_t handled = 0; if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event); AInputQueue_finishEvent(app->inputQueue, event, handled); } else { LOGW("Failure reading next input event: %s\n", strerror(errno)); } }
// copied from new android_native_app_glue.c static void process_input(struct android_app* app, struct android_poll_source* source) { AInputEvent* event = NULL; int processed = 0; while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) { if (AInputQueue_preDispatchEvent(app->inputQueue, event)) { continue; } int32_t handled = 0; if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event); AInputQueue_finishEvent(app->inputQueue, event, handled); processed = 1; } if (processed == 0) { CXBMCApp::android_printf("process_input: Failure reading next input event: %s", strerror(errno)); } }
static void process_input(struct android_app* app, struct android_poll_source* source) { AInputEvent* event = NULL; int processed = 0; while (AInputQueue_hasEvents( app->inputQueue ) && AInputQueue_getEvent(app->inputQueue, &event) >= 0) { LOGV("New input event: type=%d\n", AInputEvent_getType(event)); if (AInputQueue_preDispatchEvent(app->inputQueue, event)) { continue; } int32_t handled = 0; if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event); AInputQueue_finishEvent(app->inputQueue, event, handled); processed = 1; } if (processed == 0) { LOGE("Failure reading next input event: %s\n", strerror(errno)); } }
static void Sys_Android_ProcessInput( struct android_app *app, struct android_poll_source *source ) { AInputEvent *event = NULL; int32_t handled; while( AInputQueue_getEvent( app->inputQueue, &event ) >= 0 ) { // Instead of calling AInputQueue_preDispatchEvent which hangs the whole engine on API 17 and lower, // let onInputEvent hide the IME using JNI. handled = 0; if( app->onInputEvent ) handled = app->onInputEvent( app, event ); if( ( AInputEvent_getType( event ) == AINPUT_EVENT_TYPE_KEY ) && ( AKeyEvent_getKeyCode( event ) == AKEYCODE_BACK ) ) handled = 1; AInputQueue_finishEvent( app->inputQueue, event, handled ); } }
event_result message_dispatcher::dispatch_message(app& the_app) { if (true) { scoped_lock lock(m_mutex); if (!m_iqueue || !m_looper) return event_result::unhandled; } int fd, events, ident; void *data; ident = ALooper_pollOnce(m_ticker.paused() ? -1 : 0, &fd, &events, &data); if (ident == MSG_ID_SYSTEM) { system_event se; read(fd, &se, sizeof(se)); if (se & system_event::synchronous) { return fire_on_syncevent(the_app, se); } else { return fire_on_asyncevent(the_app, se); } } else if (ident == MSG_ID_INPUT) { scoped_lock lock(m_mutex); AInputEvent *ie = NULL; if (AInputQueue_getEvent(m_iqueue, &ie) < 0) return event_result::unhandled; if (AInputQueue_preDispatchEvent(m_iqueue, ie)) return event_result::handled; event_result result = event_result::unhandled; if (is_key_message(ie)) { result = fire_on_key(the_app, ie); } else if (is_motion_message(ie)) { result = fire_on_motion(the_app, ie); } else if (is_dpad_message(ie)) { result = fire_on_dpad(the_app, ie); } else if (is_external_event(ie)) { result = fire_on_external(the_app, ie); } AInputQueue_finishEvent(m_iqueue, ie, result == event_result::handled ? 1 : 0); return result; } return event_result::unhandled; }
int WindowImplAndroid::processEvent(int fd, int events, void* data) { ActivityStates* states = getActivity(NULL); Lock lock(states->mutex); AInputEvent* _event = NULL; if (AInputQueue_getEvent(states->inputQueue, &_event) >= 0) { if (AInputQueue_preDispatchEvent(states->inputQueue, _event)) return 1; int handled = 0; int32_t type = AInputEvent_getType(_event); if (type == AINPUT_EVENT_TYPE_KEY) { int32_t action = AKeyEvent_getAction(_event); int32_t key = AKeyEvent_getKeyCode(_event); if ((action == AKEY_EVENT_ACTION_DOWN || action == AKEY_EVENT_ACTION_UP || action == AKEY_EVENT_ACTION_MULTIPLE) && key != AKEYCODE_VOLUME_UP && key != AKEYCODE_VOLUME_DOWN) { handled = processKeyEvent(_event, states); } } else if (type == AINPUT_EVENT_TYPE_MOTION) { int32_t action = AMotionEvent_getAction(_event); switch (action & AMOTION_EVENT_ACTION_MASK) { case AMOTION_EVENT_ACTION_SCROLL: { handled = processScrollEvent(_event, states); break; } // todo: should hover_move indeed trigger the event? // case AMOTION_EVENT_ACTION_HOVER_MOVE: case AMOTION_EVENT_ACTION_MOVE: { handled = processMotionEvent(_event, states); break; } // todo: investigate AMOTION_EVENT_OUTSIDE case AMOTION_EVENT_ACTION_POINTER_DOWN: case AMOTION_EVENT_ACTION_DOWN: { handled = processPointerEvent(true, _event, states); break; } case AMOTION_EVENT_ACTION_POINTER_UP: case AMOTION_EVENT_ACTION_UP: case AMOTION_EVENT_ACTION_CANCEL: { handled = processPointerEvent(false, _event, states); break; } } } AInputQueue_finishEvent(states->inputQueue, _event, handled); } return 1; }
void RenderThread::run (void) { // Init state m_windowState = WINDOWSTATE_NOT_CREATED; m_paused = true; m_finish = false; try { while (!m_finish) { if (m_paused || m_windowState != WINDOWSTATE_READY) { // Block until we are not paused and window is ready. Message msg = m_msgQueue.popBack(); processMessage(msg); continue; } // Process available commands { Message msg; if (m_msgQueue.tryPopBack(msg)) { processMessage(msg); continue; } } DE_ASSERT(m_windowState == WINDOWSTATE_READY); // Process input events. // \todo [2013-05-08 pyry] What if system fills up the input queue before we have window ready? while (m_inputQueue && AInputQueue_hasEvents(m_inputQueue) > 0) { AInputEvent* event; TCU_CHECK(AInputQueue_getEvent(m_inputQueue, &event) >= 0); onInputEvent(event); AInputQueue_finishEvent(m_inputQueue, event, 1); } // Everything set up - safe to render. if (!render()) { DBG_PRINT(("RenderThread::run(): render\n")); break; } } } catch (const std::exception& e) { print("RenderThread: %s\n", e.what()); } // Tell activity to finish. DBG_PRINT(("RenderThread::run(): done, waiting for FINISH\n")); m_activity.finish(); // Thread must keep draining message queue until FINISH message is encountered. try { while (!m_finish) { Message msg = m_msgQueue.popBack(); // Ignore all but SYNC and FINISH messages. if (msg.type == MESSAGE_SYNC || msg.type == MESSAGE_FINISH) processMessage(msg); } } catch (const std::exception& e) { die("RenderThread: %s\n", e.what()); } DBG_PRINT(("RenderThread::run(): exiting...\n")); }
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)