|  | /* | 
|  | * Copyright (C) 2019 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | #pragma once | 
|  |  | 
|  | #include <stdint.h> | 
|  | #include <ui/Rotation.h> | 
|  |  | 
|  | #include "CursorButtonAccumulator.h" | 
|  | #include "CursorScrollAccumulator.h" | 
|  | #include "EventHub.h" | 
|  | #include "InputMapper.h" | 
|  | #include "InputReaderBase.h" | 
|  | #include "TouchButtonAccumulator.h" | 
|  |  | 
|  | namespace android { | 
|  |  | 
|  | // Maximum amount of latency to add to touch events while waiting for data from an | 
|  | // external stylus. | 
|  | static constexpr nsecs_t EXTERNAL_STYLUS_DATA_TIMEOUT = ms2ns(72); | 
|  |  | 
|  | // Maximum amount of time to wait on touch data before pushing out new pressure data. | 
|  | static constexpr nsecs_t TOUCH_DATA_TIMEOUT = ms2ns(20); | 
|  |  | 
|  | /* Raw axis information from the driver. */ | 
|  | struct RawPointerAxes { | 
|  | RawAbsoluteAxisInfo x{}; | 
|  | RawAbsoluteAxisInfo y{}; | 
|  | RawAbsoluteAxisInfo pressure{}; | 
|  | RawAbsoluteAxisInfo touchMajor{}; | 
|  | RawAbsoluteAxisInfo touchMinor{}; | 
|  | RawAbsoluteAxisInfo toolMajor{}; | 
|  | RawAbsoluteAxisInfo toolMinor{}; | 
|  | RawAbsoluteAxisInfo orientation{}; | 
|  | RawAbsoluteAxisInfo distance{}; | 
|  | RawAbsoluteAxisInfo tiltX{}; | 
|  | RawAbsoluteAxisInfo tiltY{}; | 
|  | RawAbsoluteAxisInfo trackingId{}; | 
|  | RawAbsoluteAxisInfo slot{}; | 
|  |  | 
|  | inline int32_t getRawWidth() const { return x.maxValue - x.minValue + 1; } | 
|  | inline int32_t getRawHeight() const { return y.maxValue - y.minValue + 1; } | 
|  | inline void clear() { *this = RawPointerAxes(); } | 
|  | }; | 
|  |  | 
|  | using PropertiesArray = std::array<PointerProperties, MAX_POINTERS>; | 
|  | using CoordsArray = std::array<PointerCoords, MAX_POINTERS>; | 
|  | using IdToIndexArray = std::array<uint32_t, MAX_POINTER_ID + 1>; | 
|  |  | 
|  | /* Raw data for a collection of pointers including a pointer id mapping table. */ | 
|  | struct RawPointerData { | 
|  | struct Pointer { | 
|  | uint32_t id{0xFFFFFFFF}; | 
|  | int32_t x{}; | 
|  | int32_t y{}; | 
|  | int32_t pressure{}; | 
|  | int32_t touchMajor{}; | 
|  | int32_t touchMinor{}; | 
|  | int32_t toolMajor{}; | 
|  | int32_t toolMinor{}; | 
|  | int32_t orientation{}; | 
|  | int32_t distance{}; | 
|  | int32_t tiltX{}; | 
|  | int32_t tiltY{}; | 
|  | // A fully decoded AMOTION_EVENT_TOOL_TYPE constant. | 
|  | int32_t toolType{AMOTION_EVENT_TOOL_TYPE_UNKNOWN}; | 
|  | bool isHovering{false}; | 
|  | }; | 
|  |  | 
|  | uint32_t pointerCount{}; | 
|  | std::array<Pointer, MAX_POINTERS> pointers{}; | 
|  | BitSet32 hoveringIdBits{}, touchingIdBits{}, canceledIdBits{}; | 
|  | IdToIndexArray idToIndex{}; | 
|  |  | 
|  | inline void clear() { *this = RawPointerData(); } | 
|  |  | 
|  | void getCentroidOfTouchingPointers(float* outX, float* outY) const; | 
|  |  | 
|  | inline void markIdBit(uint32_t id, bool isHovering) { | 
|  | if (isHovering) { | 
|  | hoveringIdBits.markBit(id); | 
|  | } else { | 
|  | touchingIdBits.markBit(id); | 
|  | } | 
|  | } | 
|  |  | 
|  | inline void clearIdBits() { | 
|  | hoveringIdBits.clear(); | 
|  | touchingIdBits.clear(); | 
|  | canceledIdBits.clear(); | 
|  | } | 
|  |  | 
|  | inline const Pointer& pointerForId(uint32_t id) const { return pointers[idToIndex[id]]; } | 
|  |  | 
|  | inline bool isHovering(uint32_t pointerIndex) { return pointers[pointerIndex].isHovering; } | 
|  | }; | 
|  |  | 
|  | /* Cooked data for a collection of pointers including a pointer id mapping table. */ | 
|  | struct CookedPointerData { | 
|  | uint32_t pointerCount{}; | 
|  | PropertiesArray pointerProperties{}; | 
|  | CoordsArray pointerCoords{}; | 
|  | BitSet32 hoveringIdBits{}, touchingIdBits{}, canceledIdBits{}, validIdBits{}; | 
|  | IdToIndexArray idToIndex{}; | 
|  |  | 
|  | inline void clear() { *this = CookedPointerData(); } | 
|  |  | 
|  | inline const PointerCoords& pointerCoordsForId(uint32_t id) const { | 
|  | return pointerCoords[idToIndex[id]]; | 
|  | } | 
|  |  | 
|  | inline PointerCoords& editPointerCoordsWithId(uint32_t id) { | 
|  | return pointerCoords[idToIndex[id]]; | 
|  | } | 
|  |  | 
|  | inline PointerProperties& editPointerPropertiesWithId(uint32_t id) { | 
|  | return pointerProperties[idToIndex[id]]; | 
|  | } | 
|  |  | 
|  | inline bool isHovering(uint32_t pointerIndex) const { | 
|  | return hoveringIdBits.hasBit(pointerProperties[pointerIndex].id); | 
|  | } | 
|  |  | 
|  | inline bool isTouching(uint32_t pointerIndex) const { | 
|  | return touchingIdBits.hasBit(pointerProperties[pointerIndex].id); | 
|  | } | 
|  |  | 
|  | inline bool hasPointerCoordsForId(uint32_t id) const { return validIdBits.hasBit(id); } | 
|  | }; | 
|  |  | 
|  | class TouchInputMapper : public InputMapper { | 
|  | public: | 
|  | explicit TouchInputMapper(InputDeviceContext& deviceContext); | 
|  | ~TouchInputMapper() override; | 
|  |  | 
|  | uint32_t getSources() const override; | 
|  | void populateDeviceInfo(InputDeviceInfo* deviceInfo) override; | 
|  | void dump(std::string& dump) override; | 
|  | [[nodiscard]] std::list<NotifyArgs> configure(nsecs_t when, | 
|  | const InputReaderConfiguration* config, | 
|  | uint32_t changes) override; | 
|  | [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override; | 
|  | [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override; | 
|  |  | 
|  | int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode) override; | 
|  | int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) override; | 
|  | bool markSupportedKeyCodes(uint32_t sourceMask, const std::vector<int32_t>& keyCodes, | 
|  | uint8_t* outFlags) override; | 
|  |  | 
|  | [[nodiscard]] std::list<NotifyArgs> cancelTouch(nsecs_t when, nsecs_t readTime) override; | 
|  | [[nodiscard]] std::list<NotifyArgs> timeoutExpired(nsecs_t when) override; | 
|  | [[nodiscard]] std::list<NotifyArgs> updateExternalStylusState( | 
|  | const StylusState& state) override; | 
|  | std::optional<int32_t> getAssociatedDisplayId() override; | 
|  |  | 
|  | protected: | 
|  | CursorButtonAccumulator mCursorButtonAccumulator; | 
|  | CursorScrollAccumulator mCursorScrollAccumulator; | 
|  | TouchButtonAccumulator mTouchButtonAccumulator; | 
|  |  | 
|  | struct VirtualKey { | 
|  | int32_t keyCode; | 
|  | int32_t scanCode; | 
|  | uint32_t flags; | 
|  |  | 
|  | // computed hit box, specified in touch screen coords based on known display size | 
|  | int32_t hitLeft; | 
|  | int32_t hitTop; | 
|  | int32_t hitRight; | 
|  | int32_t hitBottom; | 
|  |  | 
|  | inline bool isHit(int32_t x, int32_t y) const { | 
|  | return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom; | 
|  | } | 
|  | }; | 
|  |  | 
|  | // Input sources and device mode. | 
|  | uint32_t mSource; | 
|  |  | 
|  | enum class DeviceMode { | 
|  | DISABLED,   // input is disabled | 
|  | DIRECT,     // direct mapping (touchscreen) | 
|  | UNSCALED,   // unscaled mapping (touchpad) | 
|  | NAVIGATION, // unscaled mapping with assist gesture (touch navigation) | 
|  | POINTER,    // pointer mapping (pointer) | 
|  |  | 
|  | ftl_last = POINTER | 
|  | }; | 
|  | DeviceMode mDeviceMode; | 
|  |  | 
|  | // The reader's configuration. | 
|  | InputReaderConfiguration mConfig; | 
|  |  | 
|  | // Immutable configuration parameters. | 
|  | struct Parameters { | 
|  | enum class DeviceType { | 
|  | TOUCH_SCREEN, | 
|  | TOUCH_NAVIGATION, | 
|  | POINTER, | 
|  |  | 
|  | ftl_last = POINTER | 
|  | }; | 
|  |  | 
|  | DeviceType deviceType; | 
|  | bool hasAssociatedDisplay; | 
|  | bool associatedDisplayIsExternal; | 
|  | bool orientationAware; | 
|  |  | 
|  | ui::Rotation orientation; | 
|  |  | 
|  | bool hasButtonUnderPad; | 
|  | std::string uniqueDisplayId; | 
|  |  | 
|  | enum class GestureMode { | 
|  | SINGLE_TOUCH, | 
|  | MULTI_TOUCH, | 
|  |  | 
|  | ftl_last = MULTI_TOUCH | 
|  | }; | 
|  | GestureMode gestureMode; | 
|  |  | 
|  | bool wake; | 
|  |  | 
|  | // Whether the device supports the Universal Stylus Initiative (USI) protocol for styluses. | 
|  | bool supportsUsi; | 
|  |  | 
|  | // Allows touches while the display is off. | 
|  | bool enableForInactiveViewport; | 
|  | } mParameters; | 
|  |  | 
|  | // Immutable calibration parameters in parsed form. | 
|  | struct Calibration { | 
|  | // Size | 
|  | enum class SizeCalibration { | 
|  | DEFAULT, | 
|  | NONE, | 
|  | GEOMETRIC, | 
|  | DIAMETER, | 
|  | BOX, | 
|  | AREA, | 
|  | ftl_last = AREA | 
|  | }; | 
|  |  | 
|  | SizeCalibration sizeCalibration; | 
|  |  | 
|  | std::optional<float> sizeScale; | 
|  | std::optional<float> sizeBias; | 
|  | std::optional<bool> sizeIsSummed; | 
|  |  | 
|  | // Pressure | 
|  | enum class PressureCalibration { | 
|  | DEFAULT, | 
|  | NONE, | 
|  | PHYSICAL, | 
|  | AMPLITUDE, | 
|  | }; | 
|  |  | 
|  | PressureCalibration pressureCalibration; | 
|  | std::optional<float> pressureScale; | 
|  |  | 
|  | // Orientation | 
|  | enum class OrientationCalibration { | 
|  | DEFAULT, | 
|  | NONE, | 
|  | INTERPOLATED, | 
|  | VECTOR, | 
|  | }; | 
|  |  | 
|  | OrientationCalibration orientationCalibration; | 
|  |  | 
|  | // Distance | 
|  | enum class DistanceCalibration { | 
|  | DEFAULT, | 
|  | NONE, | 
|  | SCALED, | 
|  | }; | 
|  |  | 
|  | DistanceCalibration distanceCalibration; | 
|  | std::optional<float> distanceScale; | 
|  |  | 
|  | inline void applySizeScaleAndBias(float& outSize) const { | 
|  | if (sizeScale) { | 
|  | outSize *= *sizeScale; | 
|  | } | 
|  | if (sizeBias) { | 
|  | outSize += *sizeBias; | 
|  | } | 
|  | if (outSize < 0) { | 
|  | outSize = 0; | 
|  | } | 
|  | } | 
|  | } mCalibration; | 
|  |  | 
|  | // Affine location transformation/calibration | 
|  | struct TouchAffineTransformation mAffineTransform; | 
|  |  | 
|  | RawPointerAxes mRawPointerAxes; | 
|  |  | 
|  | struct RawState { | 
|  | nsecs_t when{std::numeric_limits<nsecs_t>::min()}; | 
|  | nsecs_t readTime{}; | 
|  |  | 
|  | // Raw pointer sample data. | 
|  | RawPointerData rawPointerData{}; | 
|  |  | 
|  | int32_t buttonState{}; | 
|  |  | 
|  | // Scroll state. | 
|  | int32_t rawVScroll{}; | 
|  | int32_t rawHScroll{}; | 
|  |  | 
|  | inline void clear() { *this = RawState(); } | 
|  | }; | 
|  |  | 
|  | struct CookedState { | 
|  | // Cooked pointer sample data. | 
|  | CookedPointerData cookedPointerData{}; | 
|  |  | 
|  | // Id bits used to differentiate fingers, stylus and mouse tools. | 
|  | BitSet32 fingerIdBits{}; | 
|  | BitSet32 stylusIdBits{}; | 
|  | BitSet32 mouseIdBits{}; | 
|  |  | 
|  | int32_t buttonState{}; | 
|  |  | 
|  | inline void clear() { *this = CookedState(); } | 
|  | }; | 
|  |  | 
|  | std::vector<RawState> mRawStatesPending; | 
|  | RawState mCurrentRawState; | 
|  | CookedState mCurrentCookedState; | 
|  | RawState mLastRawState; | 
|  | CookedState mLastCookedState; | 
|  |  | 
|  | // State provided by an external stylus | 
|  | StylusState mExternalStylusState; | 
|  | // If an external stylus is capable of reporting pointer-specific data like pressure, we will | 
|  | // attempt to fuse the pointer data reported by the stylus to the first touch pointer. This is | 
|  | // the id of the pointer to which the external stylus data is fused. | 
|  | std::optional<uint32_t> mFusedStylusPointerId; | 
|  | 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; | 
|  |  | 
|  | // Have we assigned pointer IDs for this stream | 
|  | bool mHavePointerIds; | 
|  |  | 
|  | // Is the current stream of direct touch events aborted | 
|  | bool mCurrentMotionAborted; | 
|  |  | 
|  | // The time the primary pointer last went down. | 
|  | nsecs_t mDownTime; | 
|  |  | 
|  | // The pointer controller, or null if the device is not a pointer. | 
|  | std::shared_ptr<PointerControllerInterface> mPointerController; | 
|  |  | 
|  | std::vector<VirtualKey> mVirtualKeys; | 
|  |  | 
|  | virtual void configureParameters(); | 
|  | virtual void dumpParameters(std::string& dump); | 
|  | virtual void configureRawPointerAxes(); | 
|  | virtual void dumpRawPointerAxes(std::string& dump); | 
|  | virtual void configureInputDevice(nsecs_t when, bool* outResetNeeded); | 
|  | virtual void dumpDisplay(std::string& dump); | 
|  | virtual void configureVirtualKeys(); | 
|  | virtual void dumpVirtualKeys(std::string& dump); | 
|  | virtual void parseCalibration(); | 
|  | virtual void resolveCalibration(); | 
|  | virtual void dumpCalibration(std::string& dump); | 
|  | virtual void updateAffineTransformation(); | 
|  | virtual void dumpAffineTransformation(std::string& dump); | 
|  | virtual void resolveExternalStylusPresence(); | 
|  | virtual bool hasStylus() const = 0; | 
|  | virtual bool hasExternalStylus() const; | 
|  |  | 
|  | virtual void syncTouch(nsecs_t when, RawState* outState) = 0; | 
|  |  | 
|  | private: | 
|  | // The current viewport. | 
|  | // The components of the viewport are specified in the display's rotated orientation. | 
|  | DisplayViewport mViewport; | 
|  |  | 
|  | // We refer to the display as being in the "natural orientation" when there is no rotation | 
|  | // applied. The display size obtained from the viewport in the natural orientation. | 
|  | // Always starts at (0, 0). | 
|  | ui::Size mDisplayBounds{ui::kInvalidSize}; | 
|  |  | 
|  | // The physical frame is the rectangle in the rotated display's coordinate space that maps to | 
|  | // the logical display frame. | 
|  | Rect mPhysicalFrameInRotatedDisplay{Rect::INVALID_RECT}; | 
|  |  | 
|  | // The orientation of the input device relative to that of the display panel. It specifies | 
|  | // the rotation of the input device coordinates required to produce the display panel | 
|  | // orientation, so it will depend on whether the device is orientation aware. | 
|  | ui::Rotation mInputDeviceOrientation; | 
|  |  | 
|  | // The transform that maps the input device's raw coordinate space to the un-rotated display's | 
|  | // coordinate space. InputReader generates events in the un-rotated display's coordinate space. | 
|  | ui::Transform mRawToDisplay; | 
|  |  | 
|  | // The transform that maps the input device's raw coordinate space to the rotated display's | 
|  | // coordinate space. This used to perform hit-testing of raw events with the physical frame in | 
|  | // the rotated coordinate space. See mPhysicalFrameInRotatedDisplay. | 
|  | ui::Transform mRawToRotatedDisplay; | 
|  |  | 
|  | // The transform used for non-planar raw axes, such as orientation and tilt. | 
|  | ui::Transform mRawRotation; | 
|  |  | 
|  | float mGeometricScale; | 
|  |  | 
|  | float mPressureScale; | 
|  |  | 
|  | float mSizeScale; | 
|  |  | 
|  | float mOrientationScale; | 
|  |  | 
|  | float mDistanceScale; | 
|  |  | 
|  | bool mHaveTilt; | 
|  | float mTiltXCenter; | 
|  | float mTiltXScale; | 
|  | float mTiltYCenter; | 
|  | float mTiltYScale; | 
|  |  | 
|  | bool mExternalStylusConnected; | 
|  |  | 
|  | // Oriented motion ranges for input device info. | 
|  | struct OrientedRanges { | 
|  | InputDeviceInfo::MotionRange x; | 
|  | InputDeviceInfo::MotionRange y; | 
|  | InputDeviceInfo::MotionRange pressure; | 
|  |  | 
|  | std::optional<InputDeviceInfo::MotionRange> size; | 
|  |  | 
|  | std::optional<InputDeviceInfo::MotionRange> touchMajor; | 
|  | std::optional<InputDeviceInfo::MotionRange> touchMinor; | 
|  |  | 
|  | std::optional<InputDeviceInfo::MotionRange> toolMajor; | 
|  | std::optional<InputDeviceInfo::MotionRange> toolMinor; | 
|  |  | 
|  | std::optional<InputDeviceInfo::MotionRange> orientation; | 
|  |  | 
|  | std::optional<InputDeviceInfo::MotionRange> distance; | 
|  |  | 
|  | std::optional<InputDeviceInfo::MotionRange> tilt; | 
|  |  | 
|  | void clear() { | 
|  | size = std::nullopt; | 
|  | touchMajor = std::nullopt; | 
|  | touchMinor = std::nullopt; | 
|  | toolMajor = std::nullopt; | 
|  | toolMinor = std::nullopt; | 
|  | orientation = std::nullopt; | 
|  | distance = std::nullopt; | 
|  | tilt = std::nullopt; | 
|  | } | 
|  | } mOrientedRanges; | 
|  |  | 
|  | // Oriented dimensions and precision. | 
|  | float mOrientedXPrecision; | 
|  | float mOrientedYPrecision; | 
|  |  | 
|  | struct CurrentVirtualKeyState { | 
|  | bool down; | 
|  | bool ignored; | 
|  | nsecs_t downTime; | 
|  | int32_t keyCode; | 
|  | int32_t scanCode; | 
|  | } mCurrentVirtualKey; | 
|  |  | 
|  | // Scale factor for gesture or mouse based pointer movements. | 
|  | float mPointerXMovementScale; | 
|  | float mPointerYMovementScale; | 
|  |  | 
|  | // Scale factor for gesture based zooming and other freeform motions. | 
|  | float mPointerXZoomScale; | 
|  | float mPointerYZoomScale; | 
|  |  | 
|  | // The maximum swipe width between pointers to detect a swipe gesture | 
|  | // in the number of pixels.Touches that are wider than this are translated | 
|  | // into freeform gestures. | 
|  | float mPointerGestureMaxSwipeWidth; | 
|  |  | 
|  | struct PointerDistanceHeapElement { | 
|  | uint32_t currentPointerIndex : 8 {}; | 
|  | uint32_t lastPointerIndex : 8 {}; | 
|  | uint64_t distance : 48 {}; // squared distance | 
|  | }; | 
|  |  | 
|  | enum class PointerUsage { | 
|  | NONE, | 
|  | GESTURES, | 
|  | STYLUS, | 
|  | MOUSE, | 
|  | }; | 
|  | PointerUsage mPointerUsage; | 
|  |  | 
|  | struct PointerGesture { | 
|  | enum class Mode { | 
|  | // No fingers, button is not pressed. | 
|  | // Nothing happening. | 
|  | NEUTRAL, | 
|  |  | 
|  | // No fingers, button is not pressed. | 
|  | // Tap detected. | 
|  | // Emits DOWN and UP events at the pointer location. | 
|  | TAP, | 
|  |  | 
|  | // Exactly one finger dragging following a tap. | 
|  | // Pointer follows the active finger. | 
|  | // Emits DOWN, MOVE and UP events at the pointer location. | 
|  | // | 
|  | // Detect double-taps when the finger goes up while in TAP_DRAG mode. | 
|  | TAP_DRAG, | 
|  |  | 
|  | // Button is pressed. | 
|  | // Pointer follows the active finger if there is one.  Other fingers are ignored. | 
|  | // Emits DOWN, MOVE and UP events at the pointer location. | 
|  | BUTTON_CLICK_OR_DRAG, | 
|  |  | 
|  | // Exactly one finger, button is not pressed. | 
|  | // Pointer follows the active finger. | 
|  | // Emits HOVER_MOVE events at the pointer location. | 
|  | // | 
|  | // Detect taps when the finger goes up while in HOVER mode. | 
|  | HOVER, | 
|  |  | 
|  | // Exactly two fingers but neither have moved enough to clearly indicate | 
|  | // whether a swipe or freeform gesture was intended.  We consider the | 
|  | // pointer to be pressed so this enables clicking or long-pressing on buttons. | 
|  | // Pointer does not move. | 
|  | // Emits DOWN, MOVE and UP events with a single stationary pointer coordinate. | 
|  | PRESS, | 
|  |  | 
|  | // Exactly two fingers moving in the same direction, button is not pressed. | 
|  | // Pointer does not move. | 
|  | // Emits DOWN, MOVE and UP events with a single pointer coordinate that | 
|  | // follows the midpoint between both fingers. | 
|  | SWIPE, | 
|  |  | 
|  | // Two or more fingers moving in arbitrary directions, button is not pressed. | 
|  | // Pointer does not move. | 
|  | // Emits DOWN, POINTER_DOWN, MOVE, POINTER_UP and UP events that follow | 
|  | // each finger individually relative to the initial centroid of the finger. | 
|  | FREEFORM, | 
|  |  | 
|  | // Waiting for quiet time to end before starting the next gesture. | 
|  | QUIET, | 
|  | }; | 
|  |  | 
|  | // When a gesture is sent to an unfocused window, return true if it can bring that window | 
|  | // into focus, false otherwise. | 
|  | static bool canGestureAffectWindowFocus(Mode mode) { | 
|  | switch (mode) { | 
|  | case Mode::TAP: | 
|  | case Mode::TAP_DRAG: | 
|  | case Mode::BUTTON_CLICK_OR_DRAG: | 
|  | // Taps can affect window focus. | 
|  | return true; | 
|  | case Mode::FREEFORM: | 
|  | case Mode::HOVER: | 
|  | case Mode::NEUTRAL: | 
|  | case Mode::PRESS: | 
|  | case Mode::QUIET: | 
|  | case Mode::SWIPE: | 
|  | // Most gestures can be performed on an unfocused window, so they should not | 
|  | // not affect window focus. | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Time the first finger went down. | 
|  | nsecs_t firstTouchTime; | 
|  |  | 
|  | // The active pointer id from the raw touch data. | 
|  | int32_t activeTouchId; // -1 if none | 
|  |  | 
|  | // The active pointer id from the gesture last delivered to the application. | 
|  | int32_t activeGestureId; // -1 if none | 
|  |  | 
|  | // Pointer coords and ids for the current and previous pointer gesture. | 
|  | Mode currentGestureMode; | 
|  | BitSet32 currentGestureIdBits; | 
|  | IdToIndexArray currentGestureIdToIndex{}; | 
|  | PropertiesArray currentGestureProperties{}; | 
|  | CoordsArray currentGestureCoords{}; | 
|  |  | 
|  | Mode lastGestureMode; | 
|  | BitSet32 lastGestureIdBits; | 
|  | IdToIndexArray lastGestureIdToIndex{}; | 
|  | PropertiesArray lastGestureProperties{}; | 
|  | CoordsArray lastGestureCoords{}; | 
|  |  | 
|  | // Time the pointer gesture last went down. | 
|  | nsecs_t downTime; | 
|  |  | 
|  | // Time when the pointer went down for a TAP. | 
|  | nsecs_t tapDownTime; | 
|  |  | 
|  | // Time when the pointer went up for a TAP. | 
|  | nsecs_t tapUpTime; | 
|  |  | 
|  | // Location of initial tap. | 
|  | float tapX, tapY; | 
|  |  | 
|  | // Time we started waiting for quiescence. | 
|  | nsecs_t quietTime; | 
|  |  | 
|  | // Reference points for multitouch gestures. | 
|  | float referenceTouchX; // reference touch X/Y coordinates in surface units | 
|  | float referenceTouchY; | 
|  | float referenceGestureX; // reference gesture X/Y coordinates in pixels | 
|  | float referenceGestureY; | 
|  |  | 
|  | // Distance that each pointer has traveled which has not yet been | 
|  | // subsumed into the reference gesture position. | 
|  | BitSet32 referenceIdBits; | 
|  | struct Delta { | 
|  | float dx, dy; | 
|  | }; | 
|  | Delta referenceDeltas[MAX_POINTER_ID + 1]; | 
|  |  | 
|  | // Describes how touch ids are mapped to gesture ids for freeform gestures. | 
|  | uint32_t freeformTouchToGestureIdMap[MAX_POINTER_ID + 1]; | 
|  |  | 
|  | // A velocity tracker for determining whether to switch active pointers during drags. | 
|  | VelocityTracker velocityTracker; | 
|  |  | 
|  | void reset() { | 
|  | firstTouchTime = LLONG_MIN; | 
|  | activeTouchId = -1; | 
|  | activeGestureId = -1; | 
|  | currentGestureMode = Mode::NEUTRAL; | 
|  | currentGestureIdBits.clear(); | 
|  | lastGestureMode = Mode::NEUTRAL; | 
|  | lastGestureIdBits.clear(); | 
|  | downTime = 0; | 
|  | velocityTracker.clear(); | 
|  | resetTap(); | 
|  | resetQuietTime(); | 
|  | } | 
|  |  | 
|  | void resetTap() { | 
|  | tapDownTime = LLONG_MIN; | 
|  | tapUpTime = LLONG_MIN; | 
|  | } | 
|  |  | 
|  | void resetQuietTime() { quietTime = LLONG_MIN; } | 
|  | } mPointerGesture; | 
|  |  | 
|  | struct PointerSimple { | 
|  | PointerCoords currentCoords; | 
|  | PointerProperties currentProperties; | 
|  | PointerCoords lastCoords; | 
|  | PointerProperties lastProperties; | 
|  |  | 
|  | // True if the pointer is down. | 
|  | bool down; | 
|  |  | 
|  | // True if the pointer is hovering. | 
|  | bool hovering; | 
|  |  | 
|  | // Time the pointer last went down. | 
|  | nsecs_t downTime; | 
|  |  | 
|  | // Values reported for the last pointer event. | 
|  | uint32_t source; | 
|  | int32_t displayId; | 
|  | float lastCursorX; | 
|  | float lastCursorY; | 
|  |  | 
|  | void reset() { | 
|  | currentCoords.clear(); | 
|  | currentProperties.clear(); | 
|  | lastCoords.clear(); | 
|  | lastProperties.clear(); | 
|  | down = false; | 
|  | hovering = false; | 
|  | downTime = 0; | 
|  | source = 0; | 
|  | displayId = ADISPLAY_ID_NONE; | 
|  | lastCursorX = 0.f; | 
|  | lastCursorY = 0.f; | 
|  | } | 
|  | } mPointerSimple; | 
|  |  | 
|  | // The pointer and scroll velocity controls. | 
|  | VelocityControl mPointerVelocityControl; | 
|  | VelocityControl mWheelXVelocityControl; | 
|  | VelocityControl mWheelYVelocityControl; | 
|  |  | 
|  | std::optional<DisplayViewport> findViewport(); | 
|  |  | 
|  | void resetExternalStylus(); | 
|  | void clearStylusDataPendingFlags(); | 
|  |  | 
|  | int32_t clampResolution(const char* axisName, int32_t resolution) const; | 
|  | void initializeOrientedRanges(); | 
|  | void initializeSizeRanges(); | 
|  |  | 
|  | [[nodiscard]] std::list<NotifyArgs> sync(nsecs_t when, nsecs_t readTime); | 
|  |  | 
|  | [[nodiscard]] std::list<NotifyArgs> consumeRawTouches(nsecs_t when, nsecs_t readTime, | 
|  | uint32_t policyFlags, bool& outConsumed); | 
|  | [[nodiscard]] std::list<NotifyArgs> processRawTouches(bool timeout); | 
|  | [[nodiscard]] std::list<NotifyArgs> cookAndDispatch(nsecs_t when, nsecs_t readTime); | 
|  | [[nodiscard]] NotifyKeyArgs dispatchVirtualKey(nsecs_t when, nsecs_t readTime, | 
|  | uint32_t policyFlags, int32_t keyEventAction, | 
|  | int32_t keyEventFlags); | 
|  |  | 
|  | [[nodiscard]] std::list<NotifyArgs> dispatchTouches(nsecs_t when, nsecs_t readTime, | 
|  | uint32_t policyFlags); | 
|  | [[nodiscard]] std::list<NotifyArgs> dispatchHoverExit(nsecs_t when, nsecs_t readTime, | 
|  | uint32_t policyFlags); | 
|  | [[nodiscard]] std::list<NotifyArgs> dispatchHoverEnterAndMove(nsecs_t when, nsecs_t readTime, | 
|  | uint32_t policyFlags); | 
|  | [[nodiscard]] std::list<NotifyArgs> dispatchButtonRelease(nsecs_t when, nsecs_t readTime, | 
|  | uint32_t policyFlags); | 
|  | [[nodiscard]] std::list<NotifyArgs> dispatchButtonPress(nsecs_t when, nsecs_t readTime, | 
|  | uint32_t policyFlags); | 
|  | const BitSet32& findActiveIdBits(const CookedPointerData& cookedPointerData); | 
|  | void cookPointerData(); | 
|  | [[nodiscard]] std::list<NotifyArgs> abortTouches(nsecs_t when, nsecs_t readTime, | 
|  | uint32_t policyFlags); | 
|  |  | 
|  | [[nodiscard]] std::list<NotifyArgs> dispatchPointerUsage(nsecs_t when, nsecs_t readTime, | 
|  | uint32_t policyFlags, | 
|  | PointerUsage pointerUsage); | 
|  | [[nodiscard]] std::list<NotifyArgs> abortPointerUsage(nsecs_t when, nsecs_t readTime, | 
|  | uint32_t policyFlags); | 
|  |  | 
|  | [[nodiscard]] std::list<NotifyArgs> dispatchPointerGestures(nsecs_t when, nsecs_t readTime, | 
|  | uint32_t policyFlags, | 
|  | bool isTimeout); | 
|  | [[nodiscard]] std::list<NotifyArgs> abortPointerGestures(nsecs_t when, nsecs_t readTime, | 
|  | uint32_t policyFlags); | 
|  | bool preparePointerGestures(nsecs_t when, bool* outCancelPreviousGesture, | 
|  | bool* outFinishPreviousGesture, bool isTimeout); | 
|  |  | 
|  | // Returns true if we're in a period of "quiet time" when touchpad gestures should be ignored. | 
|  | bool checkForTouchpadQuietTime(nsecs_t when); | 
|  |  | 
|  | std::pair<int32_t, float> getFastestFinger(); | 
|  |  | 
|  | void prepareMultiFingerPointerGestures(nsecs_t when, bool* outCancelPreviousGesture, | 
|  | bool* outFinishPreviousGesture); | 
|  |  | 
|  | // Moves the on-screen mouse pointer based on the movement of the pointer of the given ID | 
|  | // between the last and current events. Uses a relative motion. | 
|  | void moveMousePointerFromPointerDelta(nsecs_t when, uint32_t pointerId); | 
|  |  | 
|  | [[nodiscard]] std::list<NotifyArgs> dispatchPointerStylus(nsecs_t when, nsecs_t readTime, | 
|  | uint32_t policyFlags); | 
|  | [[nodiscard]] std::list<NotifyArgs> abortPointerStylus(nsecs_t when, nsecs_t readTime, | 
|  | uint32_t policyFlags); | 
|  |  | 
|  | [[nodiscard]] std::list<NotifyArgs> dispatchPointerMouse(nsecs_t when, nsecs_t readTime, | 
|  | uint32_t policyFlags); | 
|  | [[nodiscard]] std::list<NotifyArgs> abortPointerMouse(nsecs_t when, nsecs_t readTime, | 
|  | uint32_t policyFlags); | 
|  |  | 
|  | [[nodiscard]] std::list<NotifyArgs> dispatchPointerSimple(nsecs_t when, nsecs_t readTime, | 
|  | uint32_t policyFlags, bool down, | 
|  | bool hovering); | 
|  | [[nodiscard]] std::list<NotifyArgs> abortPointerSimple(nsecs_t when, nsecs_t readTime, | 
|  | uint32_t policyFlags); | 
|  |  | 
|  | // Attempts to assign a pointer id to the external stylus. Returns true if the state should be | 
|  | // withheld from further processing while waiting for data from the stylus. | 
|  | bool assignExternalStylusId(const RawState& state, bool timeout); | 
|  | void applyExternalStylusButtonState(nsecs_t when); | 
|  | void applyExternalStylusTouchState(nsecs_t when); | 
|  |  | 
|  | // Dispatches a motion event. | 
|  | // If the changedId is >= 0 and the action is POINTER_DOWN or POINTER_UP, the | 
|  | // method will take care of setting the index and transmuting the action to DOWN or UP | 
|  | // it is the first / last pointer to go down / up. | 
|  | [[nodiscard]] NotifyMotionArgs dispatchMotion( | 
|  | nsecs_t when, nsecs_t readTime, uint32_t policyFlags, uint32_t source, int32_t action, | 
|  | int32_t actionButton, int32_t flags, int32_t metaState, int32_t buttonState, | 
|  | int32_t edgeFlags, const PropertiesArray& properties, const CoordsArray& coords, | 
|  | const IdToIndexArray& idToIndex, BitSet32 idBits, int32_t changedId, float xPrecision, | 
|  | float yPrecision, nsecs_t downTime, MotionClassification classification); | 
|  |  | 
|  | // Returns if this touch device is a touch screen with an associated display. | 
|  | bool isTouchScreen(); | 
|  | // Updates touch spots if they are enabled. Should only be used when this device is a | 
|  | // touchscreen. | 
|  | void updateTouchSpots(); | 
|  |  | 
|  | bool isPointInsidePhysicalFrame(int32_t x, int32_t y) const; | 
|  | const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y); | 
|  |  | 
|  | static void assignPointerIds(const RawState& last, RawState& current); | 
|  |  | 
|  | void computeInputTransforms(); | 
|  |  | 
|  | void configureDeviceType(); | 
|  | }; | 
|  |  | 
|  | } // namespace android |