Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0cbe4654 authored by Harry Cutts's avatar Harry Cutts Committed by Android (Google) Code Review
Browse files

Merge "Set up a GestureInterpreter and feed it events"

parents 7444d85f 1f48a445
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -132,6 +132,7 @@ cc_library_shared {
        // This should consist only of dependencies from inputflinger. Other dependencies should be
        // in cc_defaults so that they are included in the tests.
        "libinputflinger_base",
        "libjsoncpp",
    ],
    export_header_lib_headers: [
        "libinputreader_headers",
@@ -146,5 +147,6 @@ cc_library_shared {
    },
    static_libs: [
        "libc++fs",
        "libchrome-gestures",
    ],
}
+2 −1
Original line number Diff line number Diff line
@@ -211,7 +211,8 @@ void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
    // Touchscreens and touchpad devices.
    // TODO(b/251196347): replace this with a proper flag.
    constexpr bool ENABLE_NEW_TOUCHPAD_STACK = false;
    if (ENABLE_NEW_TOUCHPAD_STACK && classes.test(InputDeviceClass::TOUCHPAD)) {
    if (ENABLE_NEW_TOUCHPAD_STACK && classes.test(InputDeviceClass::TOUCHPAD) &&
        classes.test(InputDeviceClass::TOUCH_MT)) {
        mappers.push_back(std::make_unique<TouchpadInputMapper>(*contextPtr));
    } else if (classes.test(InputDeviceClass::TOUCH_MT)) {
        mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));
+147 −3
Original line number Diff line number Diff line
@@ -16,21 +16,165 @@

#include "../Macros.h"

#include <log/log_main.h>
#include <chrono>
#include "TouchpadInputMapper.h"

namespace android {

namespace {

short getMaxTouchCount(const InputDeviceContext& context) {
    if (context.hasKeyCode(BTN_TOOL_QUINTTAP)) return 5;
    if (context.hasKeyCode(BTN_TOOL_QUADTAP)) return 4;
    if (context.hasKeyCode(BTN_TOOL_TRIPLETAP)) return 3;
    if (context.hasKeyCode(BTN_TOOL_DOUBLETAP)) return 2;
    if (context.hasKeyCode(BTN_TOOL_FINGER)) return 1;
    return 0;
}

HardwareProperties createHardwareProperties(const InputDeviceContext& context) {
    HardwareProperties props;
    RawAbsoluteAxisInfo absMtPositionX;
    context.getAbsoluteAxisInfo(ABS_MT_POSITION_X, &absMtPositionX);
    props.left = absMtPositionX.minValue;
    props.right = absMtPositionX.maxValue;
    props.res_x = absMtPositionX.resolution;

    RawAbsoluteAxisInfo absMtPositionY;
    context.getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &absMtPositionY);
    props.top = absMtPositionY.minValue;
    props.bottom = absMtPositionY.maxValue;
    props.res_y = absMtPositionY.resolution;

    RawAbsoluteAxisInfo absMtOrientation;
    context.getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &absMtOrientation);
    props.orientation_minimum = absMtOrientation.minValue;
    props.orientation_maximum = absMtOrientation.maxValue;

    RawAbsoluteAxisInfo absMtSlot;
    context.getAbsoluteAxisInfo(ABS_MT_SLOT, &absMtSlot);
    props.max_finger_cnt = absMtSlot.maxValue - absMtSlot.minValue + 1;
    props.max_touch_cnt = getMaxTouchCount(context);

    // T5R2 ("Track 5, Report 2") is a feature of some old Synaptics touchpads that could track 5
    // fingers but only report the coordinates of 2 of them. We don't know of any external touchpads
    // that did this, so assume false.
    props.supports_t5r2 = false;

    props.support_semi_mt = context.hasInputProperty(INPUT_PROP_SEMI_MT);
    props.is_button_pad = context.hasInputProperty(INPUT_PROP_BUTTONPAD);

    // Mouse-only properties, which will always be false.
    props.has_wheel = false;
    props.wheel_is_hi_res = false;

    // Linux Kernel haptic touchpad support isn't merged yet, so for now assume that no touchpads
    // are haptic.
    props.is_haptic_pad = false;
    return props;
}

void gestureInterpreterCallback(void* clientData, const struct Gesture* gesture) {
    // TODO(b/251196347): turn the gesture into a NotifyArgs and dispatch it.
    ALOGD("Gesture ready: %s", gesture->String().c_str());
}

} // namespace

TouchpadInputMapper::TouchpadInputMapper(InputDeviceContext& deviceContext)
      : InputMapper(deviceContext) {}
      : InputMapper(deviceContext),
        mGestureInterpreter(NewGestureInterpreter(), DeleteGestureInterpreter),
        mTouchButtonAccumulator(deviceContext) {
    mGestureInterpreter->Initialize(GESTURES_DEVCLASS_TOUCHPAD);
    mGestureInterpreter->SetHardwareProperties(createHardwareProperties(deviceContext));
    mGestureInterpreter->SetCallback(gestureInterpreterCallback, nullptr);
    // TODO(b/251196347): set a property provider, so we can change gesture properties.
    // TODO(b/251196347): set a timer provider, so the library can use timers.

    RawAbsoluteAxisInfo slotAxisInfo;
    getAbsoluteAxisInfo(ABS_MT_SLOT, &slotAxisInfo);
    if (!slotAxisInfo.valid || slotAxisInfo.maxValue <= 0) {
        ALOGW("Touchpad \"%s\" doesn't have a valid ABS_MT_SLOT axis, and probably won't work "
              "properly.",
              getDeviceName().c_str());
    }
    mMotionAccumulator.configure(getDeviceContext(), slotAxisInfo.maxValue + 1, true);
    mTouchButtonAccumulator.configure();
}

uint32_t TouchpadInputMapper::getSources() const {
    return AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD;
}

std::list<NotifyArgs> TouchpadInputMapper::reset(nsecs_t when) {
    mCursorButtonAccumulator.reset(getDeviceContext());
    mTouchButtonAccumulator.reset();
    mMscTimestamp = 0;
    return InputMapper::reset(when);
}

std::list<NotifyArgs> TouchpadInputMapper::process(const RawEvent* rawEvent) {
    ALOGD("TODO: process event type=0x%x code=0x%x value=0x%x", rawEvent->type, rawEvent->code,
          rawEvent->value);
    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
        sync(rawEvent->when);
    }
    if (rawEvent->type == EV_MSC && rawEvent->code == MSC_TIMESTAMP) {
        mMscTimestamp = rawEvent->value;
    }
    mCursorButtonAccumulator.process(rawEvent);
    mMotionAccumulator.process(rawEvent);
    mTouchButtonAccumulator.process(rawEvent);
    return {};
}

void TouchpadInputMapper::sync(nsecs_t when) {
    HardwareState hwState;
    // The gestures library uses doubles to represent timestamps in seconds.
    hwState.timestamp = std::chrono::duration<stime_t>(std::chrono::nanoseconds(when)).count();
    hwState.msc_timestamp =
            std::chrono::duration<stime_t>(std::chrono::microseconds(mMscTimestamp)).count();

    hwState.buttons_down = 0;
    if (mCursorButtonAccumulator.isLeftPressed()) {
        hwState.buttons_down |= GESTURES_BUTTON_LEFT;
    }
    if (mCursorButtonAccumulator.isMiddlePressed()) {
        hwState.buttons_down |= GESTURES_BUTTON_MIDDLE;
    }
    if (mCursorButtonAccumulator.isRightPressed()) {
        hwState.buttons_down |= GESTURES_BUTTON_RIGHT;
    }
    if (mCursorButtonAccumulator.isBackPressed() || mCursorButtonAccumulator.isSidePressed()) {
        hwState.buttons_down |= GESTURES_BUTTON_BACK;
    }
    if (mCursorButtonAccumulator.isForwardPressed() || mCursorButtonAccumulator.isExtraPressed()) {
        hwState.buttons_down |= GESTURES_BUTTON_FORWARD;
    }

    std::vector<FingerState> fingers;
    for (size_t i = 0; i < mMotionAccumulator.getSlotCount(); i++) {
        MultiTouchMotionAccumulator::Slot slot = mMotionAccumulator.getSlot(i);
        if (slot.isInUse()) {
            FingerState& fingerState = fingers.emplace_back();
            fingerState = {};
            fingerState.touch_major = slot.getTouchMajor();
            fingerState.touch_minor = slot.getTouchMinor();
            fingerState.width_major = slot.getToolMajor();
            fingerState.width_minor = slot.getToolMinor();
            fingerState.pressure = slot.getPressure();
            fingerState.orientation = slot.getOrientation();
            fingerState.position_x = slot.getX();
            fingerState.position_y = slot.getY();
            fingerState.tracking_id = slot.getTrackingId();
        }
    }
    hwState.fingers = fingers.data();
    hwState.finger_cnt = fingers.size();
    hwState.touch_cnt = mTouchButtonAccumulator.getTouchCount();

    mGestureInterpreter->PushHardwareState(&hwState);
    mMotionAccumulator.finishSync();
    mMscTimestamp = 0;
}

} // namespace android
+21 −2
Original line number Diff line number Diff line
@@ -16,10 +16,17 @@

#pragma once

#include <memory>

#include "EventHub.h"
#include "InputDevice.h"
#include "InputMapper.h"
#include "NotifyArgs.h"
#include "accumulator/CursorButtonAccumulator.h"
#include "accumulator/MultiTouchMotionAccumulator.h"
#include "accumulator/TouchButtonAccumulator.h"

#include "include/gestures.h"

namespace android {

@@ -27,8 +34,20 @@ class TouchpadInputMapper : public InputMapper {
public:
    explicit TouchpadInputMapper(InputDeviceContext& deviceContext);

    virtual uint32_t getSources() const override;
    [[nodiscard]] virtual std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
    uint32_t getSources() const override;
    [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
    [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;

private:
    void sync(nsecs_t when);

    std::unique_ptr<gestures::GestureInterpreter, void (*)(gestures::GestureInterpreter*)>
            mGestureInterpreter;

    CursorButtonAccumulator mCursorButtonAccumulator;
    MultiTouchMotionAccumulator mMotionAccumulator;
    TouchButtonAccumulator mTouchButtonAccumulator;
    int32_t mMscTimestamp = 0;
};

} // namespace android
+8 −0
Original line number Diff line number Diff line
@@ -32,6 +32,14 @@ public:
    void process(const RawEvent* rawEvent);

    uint32_t getButtonState() const;
    inline bool isLeftPressed() const { return mBtnLeft; }
    inline bool isRightPressed() const { return mBtnRight; }
    inline bool isMiddlePressed() const { return mBtnMiddle; }
    inline bool isBackPressed() const { return mBtnBack; }
    inline bool isSidePressed() const { return mBtnSide; }
    inline bool isForwardPressed() const { return mBtnForward; }
    inline bool isExtraPressed() const { return mBtnExtra; }
    inline bool isTaskPressed() const { return mBtnTask; }

private:
    bool mBtnLeft;
Loading