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

Commit 124ea44d authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

Ensure stylus buttons generate events consistently

Add tests to verify that a touchscreen stylus and fused/unfused external
styluses generate button events consistently.

Make changes in TouchInputMapper to enforce consistentcy for external
stylus buttons. In particular, we allow the external stylus's button
state to be applied to the touches even when there is no fusion in
progress.

Bug: 246394583
Test: atest inputflinger_tests
Change-Id: I645481db18e1bec8b61d8309aa4f02afcf1a5383
parent 484d55ac
Loading
Loading
Loading
Loading
+23 −7
Original line number Diff line number Diff line
@@ -254,6 +254,8 @@ void TouchInputMapper::dump(std::string& dump) {
    dump += StringPrintf(INDENT4 "External Stylus ID: %" PRId64 "\n", mExternalStylusId);
    dump += StringPrintf(INDENT4 "External Stylus Data Timeout: %" PRId64 "\n",
                         mExternalStylusFusionTimeout);
    dump += StringPrintf(INDENT4 " External Stylus Buttons Applied: 0x%08x",
                         mExternalStylusButtonsApplied);
    dump += INDENT3 "External Stylus State:\n";
    dumpStylusState(dump, mExternalStylusState);

@@ -1413,6 +1415,7 @@ void TouchInputMapper::resetExternalStylus() {
    mExternalStylusId = -1;
    mExternalStylusFusionTimeout = LLONG_MAX;
    mExternalStylusDataPending = false;
    mExternalStylusButtonsApplied = 0;
}

void TouchInputMapper::clearStylusDataPendingFlags() {
@@ -1683,8 +1686,17 @@ bool TouchInputMapper::isTouchScreen() {
}

void TouchInputMapper::applyExternalStylusButtonState(nsecs_t when) {
    if (mDeviceMode == DeviceMode::DIRECT && hasExternalStylus() && mExternalStylusId != -1) {
        mCurrentRawState.buttonState |= mExternalStylusState.buttons;
    if (mDeviceMode == DeviceMode::DIRECT && hasExternalStylus()) {
        // If any of the external buttons are already pressed by the touch device, ignore them.
        const int32_t pressedButtons = ~mCurrentRawState.buttonState & mExternalStylusState.buttons;
        const int32_t releasedButtons =
                mExternalStylusButtonsApplied & ~mExternalStylusState.buttons;

        mCurrentRawState.buttonState |= pressedButtons;
        mCurrentRawState.buttonState &= ~releasedButtons;

        mExternalStylusButtonsApplied |= pressedButtons;
        mExternalStylusButtonsApplied &= ~releasedButtons;
    }
}

@@ -1722,7 +1734,8 @@ bool TouchInputMapper::assignExternalStylusId(const RawState& state, bool timeou
            mExternalStylusId = state.rawPointerData.touchingIdBits.firstMarkedBit();
        } else if (timeout) {
            ALOGD_IF(DEBUG_STYLUS_FUSION, "Timeout expired, assuming touch is not a stylus.");
            resetExternalStylus();
            mExternalStylusId = -1;
            mExternalStylusFusionTimeout = LLONG_MAX;
        } else {
            if (mExternalStylusFusionTimeout == LLONG_MAX) {
                mExternalStylusFusionTimeout = state.when + EXTERNAL_STYLUS_DATA_TIMEOUT;
@@ -1764,11 +1777,14 @@ std::list<NotifyArgs> TouchInputMapper::timeoutExpired(nsecs_t when) {

std::list<NotifyArgs> TouchInputMapper::updateExternalStylusState(const StylusState& state) {
    std::list<NotifyArgs> out;
    const bool buttonsChanged = mExternalStylusState.buttons != state.buttons;
    mExternalStylusState.copyFrom(state);
    if (mExternalStylusId != -1 || mExternalStylusFusionTimeout != LLONG_MAX) {
        // We're either in the middle of a fused stream of data or we're waiting on data before
        // dispatching the initial down, so go ahead and dispatch now that we have fresh stylus
        // data.
    if (mExternalStylusId != -1 || mExternalStylusFusionTimeout != LLONG_MAX || buttonsChanged) {
        // The following three cases are handled here:
        // - We're in the middle of a fused stream of data;
        // - We're waiting on external stylus data before dispatching the initial down; or
        // - Only the button state, which is not reported through a specific pointer, has changed.
        // Go ahead and dispatch now that we have fresh stylus data.
        mExternalStylusDataPending = true;
        out += processRawTouches(false /*timeout*/);
    }
+2 −0
Original line number Diff line number Diff line
@@ -365,6 +365,8 @@ protected:
    int64_t mExternalStylusId;
    nsecs_t mExternalStylusFusionTimeout;
    bool mExternalStylusDataPending;
    // A subset of the buttons in mCurrentRawState that came from an external stylus.
    int32_t mExternalStylusButtonsApplied;

    // True if we sent a HOVER_ENTER event.
    bool mSentHoverEnter;
+135 −69
Original line number Diff line number Diff line
@@ -2837,108 +2837,176 @@ TEST_F(TouchIntegrationTest, NotifiesPolicyWhenStylusGestureStarted) {
    ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId()));
}
TEST_F(TouchIntegrationTest, StylusButtonsGenerateKeyEvents) {
    mDevice->sendKey(BTN_STYLUS, 1);
    mDevice->sendSync();
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
// --- StylusButtonIntegrationTest ---
// Verify the behavior of button presses reported by various kinds of styluses, including buttons
// reported by the touchscreen's device, by a fused external stylus, and by an un-fused external
// stylus.
template <typename UinputStylusDevice>
class StylusButtonIntegrationTest : public TouchIntegrationTest {
protected:
    void SetUp() override {
#if !defined(__ANDROID__)
        GTEST_SKIP();
#endif
        TouchIntegrationTest::SetUp();
        mTouchscreen = mDevice.get();
        mTouchscreenInfo = mDeviceInfo;
        setUpStylusDevice();
    }
    UinputStylusDevice* mStylus{nullptr};
    InputDeviceInfo mStylusInfo{};
    UinputTouchScreen* mTouchscreen{nullptr};
    InputDeviceInfo mTouchscreenInfo{};
private:
    // When we are attempting to test stylus button events that are sent from the touchscreen,
    // use the same Uinput device for the touchscreen and the stylus.
    template <typename T = UinputStylusDevice>
    std::enable_if_t<std::is_same_v<UinputTouchScreen, T>, void> setUpStylusDevice() {
        mStylus = mDevice.get();
        mStylusInfo = mDeviceInfo;
    }
    // When we are attempting to stylus buttons from an external stylus being merged with touches
    // from a touchscreen, create a new Uinput device through which stylus buttons can be injected.
    template <typename T = UinputStylusDevice>
    std::enable_if_t<!std::is_same_v<UinputTouchScreen, T>, void> setUpStylusDevice() {
        mStylusDeviceLifecycleTracker = createUinputDevice<T>();
        mStylus = mStylusDeviceLifecycleTracker.get();
        ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
        ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
        const auto info = findDeviceByName(mStylus->getName());
        ASSERT_TRUE(info);
        mStylusInfo = *info;
    }
    std::unique_ptr<UinputStylusDevice> mStylusDeviceLifecycleTracker{};
    // Hide the base class's device to expose it with a different name for readability.
    using TouchIntegrationTest::mDevice;
    using TouchIntegrationTest::mDeviceInfo;
};
using StylusButtonIntegrationTestTypes =
        ::testing::Types<UinputTouchScreen, UinputExternalStylus, UinputExternalStylusWithPressure>;
TYPED_TEST_SUITE(StylusButtonIntegrationTest, StylusButtonIntegrationTestTypes);
TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsGenerateKeyEvents) {
    const auto stylusId = TestFixture::mStylusInfo.getId();
    TestFixture::mStylus->pressKey(BTN_STYLUS);
    ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
            AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
                  WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
                  WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
    mDevice->sendKey(BTN_STYLUS, 0);
    mDevice->sendSync();
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
    TestFixture::mStylus->releaseKey(BTN_STYLUS);
    ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
            AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
                  WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
                  WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
}
TEST_F(TouchIntegrationTest, StylusButtonsSurroundingTouchGesture) {
    const Point centerPoint = mDevice->getCenterPoint();
TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingTouchGesture) {
    const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
    const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
    const auto stylusId = TestFixture::mStylusInfo.getId();
    // Press the stylus button.
    mDevice->sendKey(BTN_STYLUS, 1);
    mDevice->sendSync();
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
    TestFixture::mStylus->pressKey(BTN_STYLUS);
    ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
            AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
                  WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
                  WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
    // Start and finish a stylus gesture.
    mDevice->sendSlot(FIRST_SLOT);
    mDevice->sendTrackingId(FIRST_TRACKING_ID);
    mDevice->sendToolType(MT_TOOL_PEN);
    mDevice->sendDown(centerPoint);
    mDevice->sendSync();
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
    TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
    TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
    TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
    TestFixture::mTouchscreen->sendDown(centerPoint);
    TestFixture::mTouchscreen->sendSync();
    ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS),
                  WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
                  WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
                  WithDeviceId(touchscreenId))));
    ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS),
                  WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
                  WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
                  WithDeviceId(touchscreenId))));
    mDevice->sendTrackingId(INVALID_TRACKING_ID);
    mDevice->sendSync();
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
    TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
    TestFixture::mTouchscreen->sendSync();
    ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS), WithButtonState(0))));
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS), WithButtonState(0),
                  WithDeviceId(touchscreenId))));
    ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS), WithButtonState(0))));
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS), WithButtonState(0),
                  WithDeviceId(touchscreenId))));
    // Release the stylus button.
    mDevice->sendKey(BTN_STYLUS, 0);
    mDevice->sendSync();
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
    TestFixture::mStylus->releaseKey(BTN_STYLUS);
    ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
            AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
                  WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
                  WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
}
TEST_F(TouchIntegrationTest, StylusButtonsWithinTouchGesture) {
    const Point centerPoint = mDevice->getCenterPoint();
TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsWithinTouchGesture) {
    const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
    const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
    const auto stylusId = TestFixture::mStylusInfo.getId();
    // Start a stylus gesture.
    mDevice->sendSlot(FIRST_SLOT);
    mDevice->sendTrackingId(FIRST_TRACKING_ID);
    mDevice->sendToolType(MT_TOOL_PEN);
    mDevice->sendDown(centerPoint);
    mDevice->sendSync();
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
    TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
    TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
    TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
    TestFixture::mTouchscreen->sendDown(centerPoint);
    TestFixture::mTouchscreen->sendSync();
    ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS), WithButtonState(0))));
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS), WithButtonState(0),
                  WithDeviceId(touchscreenId))));
    // Press and release a stylus button. Each change in button state also generates a MOVE event.
    mDevice->sendKey(BTN_STYLUS, 1);
    mDevice->sendSync();
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
    TestFixture::mStylus->pressKey(BTN_STYLUS);
    ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
            AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
                  WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
                  WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
    ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS),
                  WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
                  WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
                  WithDeviceId(touchscreenId))));
    ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS),
                  WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
                  WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
                  WithDeviceId(touchscreenId))));
    mDevice->sendKey(BTN_STYLUS, 0);
    mDevice->sendSync();
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
    TestFixture::mStylus->releaseKey(BTN_STYLUS);
    ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
            AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
                  WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
                  WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
    ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS), WithButtonState(0))));
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS), WithButtonState(0),
                  WithDeviceId(touchscreenId))));
    ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS), WithButtonState(0))));
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS), WithButtonState(0),
                  WithDeviceId(touchscreenId))));
    // Finish the stylus gesture.
    mDevice->sendTrackingId(INVALID_TRACKING_ID);
    mDevice->sendSync();
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
    TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
    TestFixture::mTouchscreen->sendSync();
    ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS), WithButtonState(0))));
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS), WithButtonState(0),
                  WithDeviceId(touchscreenId))));
}
// --- ExternalStylusIntegrationTest ---
@@ -7951,17 +8019,15 @@ TEST_F(ExternalStylusFusionTest, FusedPointerReportsButtons) {
    // If a touch is not reported within the timeout, a move event is generated to report
    // the new button state.
    handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
    // TODO(prabirmsp): Fix fused stylus button releases being handled inconsistently.
    //   The button release event should be sent here, but isn't.
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
            AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
                  WithButtonState(0))));
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
            AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
                  WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
                  WithButtonState(0))));
    processUp(mapper);
    processSync(mapper);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
            AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
                  WithButtonState(0))));
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
            AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
+5 −10
Original line number Diff line number Diff line
@@ -160,11 +160,14 @@ void UinputExternalStylusWithPressure::setPressure(int32_t pressure) {
// --- UinputTouchScreen ---

UinputTouchScreen::UinputTouchScreen(const Rect& size)
      : UinputDevice(DEVICE_NAME, PRODUCT_ID), mSize(size) {}
      : UinputKeyboard(DEVICE_NAME, PRODUCT_ID,
                       {BTN_TOUCH, BTN_TOOL_PEN, BTN_STYLUS, BTN_STYLUS2, BTN_STYLUS3}),
        mSize(size) {}

void UinputTouchScreen::configureDevice(int fd, uinput_user_dev* device) {
    UinputKeyboard::configureDevice(fd, device);

    // Setup the touch screen device
    ioctl(fd, UI_SET_EVBIT, EV_KEY);
    ioctl(fd, UI_SET_EVBIT, EV_REL);
    ioctl(fd, UI_SET_EVBIT, EV_ABS);
    ioctl(fd, UI_SET_ABSBIT, ABS_MT_SLOT);
@@ -174,10 +177,6 @@ void UinputTouchScreen::configureDevice(int fd, uinput_user_dev* device) {
    ioctl(fd, UI_SET_ABSBIT, ABS_MT_TRACKING_ID);
    ioctl(fd, UI_SET_ABSBIT, ABS_MT_TOOL_TYPE);
    ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_DIRECT);
    ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH);
    ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS);
    ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS2);
    ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS3);

    device->absmin[ABS_MT_SLOT] = RAW_SLOT_MIN;
    device->absmax[ABS_MT_SLOT] = RAW_SLOT_MAX;
@@ -229,10 +228,6 @@ void UinputTouchScreen::sendSync() {
    injectEvent(EV_SYN, SYN_REPORT, 0);
}

void UinputTouchScreen::sendKey(int32_t scanCode, int32_t value) {
    injectEvent(EV_KEY, scanCode, value);
}

// Get the center x, y base on the range definition.
const Point UinputTouchScreen::getCenterPoint() {
    return Point(mSize.left + mSize.width() / 2, mSize.top + mSize.height() / 2);
+1 −2
Original line number Diff line number Diff line
@@ -168,7 +168,7 @@ private:
// --- UinputTouchScreen ---

// A multi-touch touchscreen device with specific size that also supports styluses.
class UinputTouchScreen : public UinputDevice {
class UinputTouchScreen : public UinputKeyboard {
public:
    static constexpr const char* DEVICE_NAME = "Test Uinput Touch Screen";
    static constexpr int16_t PRODUCT_ID = 47;
@@ -193,7 +193,6 @@ public:
    void sendUp();
    void sendToolType(int32_t toolType);
    void sendSync();
    void sendKey(int32_t scanCode, int32_t value);

    const Point getCenterPoint();