Example #1
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)
static void android_input_poll(void *data)
{
   (void)data;

   RARCH_PERFORMANCE_INIT(input_poll);
   RARCH_PERFORMANCE_START(input_poll);

   struct android_app* android_app = g_android.app;

   g_extern.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))
   {
      AInputEvent* event = NULL;
      AInputQueue_getEvent(android_app->inputQueue, &event);

      if (AInputQueue_preDispatchEvent(android_app->inputQueue, event))
         continue;

      int32_t handled = 1;

      int source = AInputEvent_getSource(event);
      int id = AInputEvent_getDeviceId(event);

      int type_event = AInputEvent_getType(event);
      int state_id = state_device_ids[id];

      if(state_id == -1)
         state_id = state_device_ids[id] = pads_connected++;

      int action = 0;
#ifdef RARCH_INPUT_DEBUG
      char msg[128];
#endif

      if(type_event == AINPUT_EVENT_TYPE_MOTION)
      {
         action = AMotionEvent_getAction(event);
         int8_t motion_action = action & AMOTION_EVENT_ACTION_MASK;
         size_t motion_pointer = action >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;

         float x = AMotionEvent_getX(event, motion_pointer);
         float y = AMotionEvent_getY(event, motion_pointer);

         if(source & ~(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_MOUSE))
         {
            state[state_id] &= ~((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[state_id] |= PRESSED_LEFT(x, y)  ? (1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT)  : 0;
            state[state_id] |= PRESSED_RIGHT(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0;
            state[state_id] |= PRESSED_UP(x, y)    ? (1ULL << RETRO_DEVICE_ID_JOYPAD_UP)    : 0;
            state[state_id] |= PRESSED_DOWN(x, y)  ? (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN)  : 0;
         }
         else
         {
            bool mouse_is_not_dirty = (source == AINPUT_SOURCE_MOUSE && action != AMOTION_EVENT_ACTION_DOWN);
            bool pointer_is_not_dirty = (action == AMOTION_EVENT_ACTION_UP ||
                  action == AMOTION_EVENT_ACTION_CANCEL || action == AMOTION_EVENT_ACTION_POINTER_UP);

            pointer_dirty = !(mouse_is_not_dirty || pointer_is_not_dirty);

            if (pointer_dirty)
               input_translate_coord_viewport(x, y, &pointer_x, &pointer_y);
         }
#ifdef RARCH_INPUT_DEBUG
         snprintf(msg, sizeof(msg), "Pad %d : x = %.2f, y = %.2f, src %d.\n", state_id, x, y, source);
#endif
      }
      else
      {