1 /* 2 * Copyright 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // clang-format off 18 #include "../Macros.h" 19 // clang-format on 20 #include "gestures/HardwareStateConverter.h" 21 22 #include <chrono> 23 #include <vector> 24 25 #include <linux/input-event-codes.h> 26 27 namespace android { 28 HardwareStateConverter(const InputDeviceContext & deviceContext,MultiTouchMotionAccumulator & motionAccumulator)29HardwareStateConverter::HardwareStateConverter(const InputDeviceContext& deviceContext, 30 MultiTouchMotionAccumulator& motionAccumulator) 31 : mDeviceContext(deviceContext), 32 mMotionAccumulator(motionAccumulator), 33 mTouchButtonAccumulator(deviceContext) { 34 mTouchButtonAccumulator.configure(); 35 } 36 processRawEvent(const RawEvent * rawEvent)37std::optional<SelfContainedHardwareState> HardwareStateConverter::processRawEvent( 38 const RawEvent* rawEvent) { 39 std::optional<SelfContainedHardwareState> out; 40 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { 41 out = produceHardwareState(rawEvent->when); 42 mMotionAccumulator.finishSync(); 43 mMscTimestamp = 0; 44 } 45 if (rawEvent->type == EV_MSC && rawEvent->code == MSC_TIMESTAMP) { 46 mMscTimestamp = rawEvent->value; 47 } 48 mCursorButtonAccumulator.process(rawEvent); 49 mMotionAccumulator.process(rawEvent); 50 mTouchButtonAccumulator.process(rawEvent); 51 return out; 52 } 53 produceHardwareState(nsecs_t when)54SelfContainedHardwareState HardwareStateConverter::produceHardwareState(nsecs_t when) { 55 SelfContainedHardwareState schs; 56 // The gestures library uses doubles to represent timestamps in seconds. 57 schs.state.timestamp = std::chrono::duration<stime_t>(std::chrono::nanoseconds(when)).count(); 58 schs.state.msc_timestamp = 59 std::chrono::duration<stime_t>(std::chrono::microseconds(mMscTimestamp)).count(); 60 61 schs.state.buttons_down = 0; 62 if (mCursorButtonAccumulator.isLeftPressed()) { 63 schs.state.buttons_down |= GESTURES_BUTTON_LEFT; 64 } 65 if (mCursorButtonAccumulator.isMiddlePressed()) { 66 schs.state.buttons_down |= GESTURES_BUTTON_MIDDLE; 67 } 68 if (mCursorButtonAccumulator.isRightPressed()) { 69 schs.state.buttons_down |= GESTURES_BUTTON_RIGHT; 70 } 71 if (mCursorButtonAccumulator.isBackPressed() || mCursorButtonAccumulator.isSidePressed()) { 72 schs.state.buttons_down |= GESTURES_BUTTON_BACK; 73 } 74 if (mCursorButtonAccumulator.isForwardPressed() || mCursorButtonAccumulator.isExtraPressed()) { 75 schs.state.buttons_down |= GESTURES_BUTTON_FORWARD; 76 } 77 78 schs.fingers.clear(); 79 size_t numPalms = 0; 80 for (size_t i = 0; i < mMotionAccumulator.getSlotCount(); i++) { 81 MultiTouchMotionAccumulator::Slot slot = mMotionAccumulator.getSlot(i); 82 if (!slot.isInUse()) { 83 continue; 84 } 85 // Some touchpads continue to report contacts even after they've identified them as palms. 86 // We want to exclude these contacts from the HardwareStates. 87 if (slot.getToolType() == ToolType::PALM) { 88 numPalms++; 89 continue; 90 } 91 92 FingerState& fingerState = schs.fingers.emplace_back(); 93 fingerState = {}; 94 fingerState.touch_major = slot.getTouchMajor(); 95 fingerState.touch_minor = slot.getTouchMinor(); 96 fingerState.width_major = slot.getToolMajor(); 97 fingerState.width_minor = slot.getToolMinor(); 98 fingerState.pressure = slot.getPressure(); 99 fingerState.orientation = slot.getOrientation(); 100 fingerState.position_x = slot.getX(); 101 fingerState.position_y = slot.getY(); 102 fingerState.tracking_id = slot.getTrackingId(); 103 } 104 schs.state.fingers = schs.fingers.data(); 105 schs.state.finger_cnt = schs.fingers.size(); 106 schs.state.touch_cnt = mTouchButtonAccumulator.getTouchCount() - numPalms; 107 return schs; 108 } 109 reset()110void HardwareStateConverter::reset() { 111 mCursorButtonAccumulator.reset(mDeviceContext); 112 mTouchButtonAccumulator.reset(); 113 mMscTimestamp = 0; 114 } 115 116 } // namespace android 117