Search code examples
candroid-ndkmouse

AMotionEvent_getButtonState returns 0 for every button during mouse button release


I'm trying to get mouse events in a NativeActivity Application.

But in the case AMOTION_EVENT_ACTION_BUTTON_RELEASE, AMotionEvent_getButtonState returns 0 for everything

In the handle_app_input callback, I have the following:

// LOGI is a macro for logging to Logcat

int32_t handle_app_input(struct android_app* app, AInputEvent* event)
{
    int32_t event_type = AInputEvent_getType(event);
    
    switch(event_type)
    {
        case AINPUT_EVENT_TYPE_MOTION:
        {
            int32_t motion_input_action = AMotionEvent_getAction(event);
            int32_t event_pointer_index = (motion_input_action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
            motion_input_action &= AMOTION_EVENT_ACTION_MASK;
            
            switch(motion_input_action)
            {
                case AMOTION_EVENT_ACTION_BUTTON_PRESS:
                {
                    int32_t mouse_button_state = AMotionEvent_getButtonState(event);
                    LOGI("Mouse Button Press: %d", mouse_button_state);
                    
                    break;
                }
                case AMOTION_EVENT_ACTION_BUTTON_RELEASE:
                {
                    int32_t mouse_button_state = AMotionEvent_getButtonState(event);
                    LOGI("Mouse Button Release: %d", mouse_button_state);                   
                    
                    break;
                }
                default:
                    break;
            }
        }
        return 1;
    }
    
    return 0;
}

In the case AMOTION_EVENT_ACTION_BUTTON_PRESS, AMotionEvent_getButtonState returns appropriately.

But in the case AMOTION_EVENT_ACTION_BUTTON_RELEASE, AMotionEvent_getButtonState returns 0 for everything

When I press the mouse button, Mouse Button Press: 1 gets logged

But when I release the mouse button Mouse Button Press: 1 doesn't get logged!

Instead I get Mouse Button Press: 0

Why is this happening? How can I fix it?


Solution

  • You're using the wrong function:

    AMotionEvent_getButtonState
    Get the button state of all buttons that are pressed.

    When a button is released, it is no longer pressed, so you get 0 as the result.

    You should probably be using AMotionEvent_getActionButton instead:

    AMotionEvent_getActionButton
    Get the action button for the motion event. Returns a valid action button when the event is associated with a button press or button release action.


    Another alternative might be to save the value of AMotionEvent_getActionButton from the AMOTION_EVENT_ACTION_BUTTON_PRESS event, and compare it against the value you get when AMOTION_EVENT_ACTION_BUTTON_RELEASE occurs:

    case AMOTION_EVENT_ACTION_BUTTON_PRESS: {
        // pressed_buttons is a global/instance variable which keeps its value across multiple handle_app_input invocations.
        pressed_buttons = AMotionEvent_getButtonState(event);
        ...
        break;
    }
    case AMOTION_EVENT_ACTION_BUTTON_RELEASE: {
        int32_t button_state = AMotionEvent_getButtonState(event);
        // Calculate which buttons have gone from being pressed to not pressed.
        int32_t released_buttons = (button_state ^ pressed_buttons) & pressed_buttons;
        pressed_buttons = button_state;
        ...
        break;
    }