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 <com_android_input_flags.h> 26 #include <linux/input-event-codes.h> 27 28 namespace input_flags = com::android::input::flags; 29 30 namespace android { 31 32 const bool REPORT_PALMS_TO_GESTURES_LIBRARY = input_flags::report_palms_to_gestures_library(); 33 HardwareStateConverter(const InputDeviceContext & deviceContext,MultiTouchMotionAccumulator & motionAccumulator)34HardwareStateConverter::HardwareStateConverter(const InputDeviceContext& deviceContext, 35 MultiTouchMotionAccumulator& motionAccumulator) 36 : mDeviceContext(deviceContext), 37 mMotionAccumulator(motionAccumulator), 38 mTouchButtonAccumulator(deviceContext) { 39 mTouchButtonAccumulator.configure(); 40 } 41 processRawEvent(const RawEvent & rawEvent)42std::optional<SelfContainedHardwareState> HardwareStateConverter::processRawEvent( 43 const RawEvent& rawEvent) { 44 std::optional<SelfContainedHardwareState> out; 45 if (rawEvent.type == EV_SYN && rawEvent.code == SYN_REPORT) { 46 out = produceHardwareState(rawEvent.when); 47 mMotionAccumulator.finishSync(); 48 mMscTimestamp = 0; 49 } 50 if (rawEvent.type == EV_MSC && rawEvent.code == MSC_TIMESTAMP) { 51 mMscTimestamp = rawEvent.value; 52 } 53 mCursorButtonAccumulator.process(rawEvent); 54 mMotionAccumulator.process(rawEvent); 55 mTouchButtonAccumulator.process(rawEvent); 56 return out; 57 } 58 produceHardwareState(nsecs_t when)59SelfContainedHardwareState HardwareStateConverter::produceHardwareState(nsecs_t when) { 60 SelfContainedHardwareState schs; 61 // The gestures library uses doubles to represent timestamps in seconds. 62 schs.state.timestamp = std::chrono::duration<stime_t>(std::chrono::nanoseconds(when)).count(); 63 schs.state.msc_timestamp = 64 std::chrono::duration<stime_t>(std::chrono::microseconds(mMscTimestamp)).count(); 65 66 schs.state.buttons_down = 0; 67 if (mCursorButtonAccumulator.isLeftPressed()) { 68 schs.state.buttons_down |= GESTURES_BUTTON_LEFT; 69 } 70 if (mCursorButtonAccumulator.isMiddlePressed()) { 71 schs.state.buttons_down |= GESTURES_BUTTON_MIDDLE; 72 } 73 if (mCursorButtonAccumulator.isRightPressed()) { 74 schs.state.buttons_down |= GESTURES_BUTTON_RIGHT; 75 } 76 if (mCursorButtonAccumulator.isBackPressed() || mCursorButtonAccumulator.isSidePressed()) { 77 schs.state.buttons_down |= GESTURES_BUTTON_BACK; 78 } 79 if (mCursorButtonAccumulator.isForwardPressed() || mCursorButtonAccumulator.isExtraPressed()) { 80 schs.state.buttons_down |= GESTURES_BUTTON_FORWARD; 81 } 82 83 schs.fingers.clear(); 84 size_t numPalms = 0; 85 for (size_t i = 0; i < mMotionAccumulator.getSlotCount(); i++) { 86 MultiTouchMotionAccumulator::Slot slot = mMotionAccumulator.getSlot(i); 87 if (!slot.isInUse()) { 88 continue; 89 } 90 // Some touchpads continue to report contacts even after they've identified them as palms. 91 // We want to exclude these contacts from the HardwareStates. 92 if (!REPORT_PALMS_TO_GESTURES_LIBRARY && slot.getToolType() == ToolType::PALM) { 93 numPalms++; 94 continue; 95 } 96 97 FingerState& fingerState = schs.fingers.emplace_back(); 98 fingerState = {}; 99 fingerState.touch_major = slot.getTouchMajor(); 100 fingerState.touch_minor = slot.getTouchMinor(); 101 fingerState.width_major = slot.getToolMajor(); 102 fingerState.width_minor = slot.getToolMinor(); 103 fingerState.pressure = slot.getPressure(); 104 fingerState.orientation = slot.getOrientation(); 105 fingerState.position_x = slot.getX(); 106 fingerState.position_y = slot.getY(); 107 fingerState.tracking_id = slot.getTrackingId(); 108 if (REPORT_PALMS_TO_GESTURES_LIBRARY) { 109 fingerState.tool_type = slot.getToolType() == ToolType::PALM 110 ? FingerState::ToolType::kPalm 111 : FingerState::ToolType::kFinger; 112 } 113 } 114 schs.state.fingers = schs.fingers.data(); 115 schs.state.finger_cnt = schs.fingers.size(); 116 schs.state.touch_cnt = mTouchButtonAccumulator.getTouchCount() - numPalms; 117 return schs; 118 } 119 reset()120void HardwareStateConverter::reset() { 121 mCursorButtonAccumulator.reset(mDeviceContext); 122 mTouchButtonAccumulator.reset(); 123 mMscTimestamp = 0; 124 } 125 126 } // namespace android 127