/* * 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. */ // clang-format off #include "../Macros.h" // clang-format on #include "RotaryEncoderInputMapper.h" #include "CursorScrollAccumulator.h" namespace android { RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDeviceContext& deviceContext) : InputMapper(deviceContext), mOrientation(DISPLAY_ORIENTATION_0) { mSource = AINPUT_SOURCE_ROTARY_ENCODER; } RotaryEncoderInputMapper::~RotaryEncoderInputMapper() {} uint32_t RotaryEncoderInputMapper::getSources() { return mSource; } void RotaryEncoderInputMapper::populateDeviceInfo(InputDeviceInfo* info) { InputMapper::populateDeviceInfo(info); if (mRotaryEncoderScrollAccumulator.haveRelativeVWheel()) { float res = 0.0f; if (!getDeviceContext().getConfiguration().tryGetProperty(String8("device.res"), res)) { ALOGW("Rotary Encoder device configuration file didn't specify resolution!\n"); } if (!getDeviceContext().getConfiguration().tryGetProperty(String8("device.scalingFactor"), mScalingFactor)) { ALOGW("Rotary Encoder device configuration file didn't specify scaling factor," "default to 1.0!\n"); mScalingFactor = 1.0f; } info->addMotionRange(AMOTION_EVENT_AXIS_SCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, res * mScalingFactor); } } void RotaryEncoderInputMapper::dump(std::string& dump) { dump += INDENT2 "Rotary Encoder Input Mapper:\n"; dump += StringPrintf(INDENT3 "HaveWheel: %s\n", toString(mRotaryEncoderScrollAccumulator.haveRelativeVWheel())); } void RotaryEncoderInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) { InputMapper::configure(when, config, changes); if (!changes) { mRotaryEncoderScrollAccumulator.configure(getDeviceContext()); } if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { std::optional internalViewport = config->getDisplayViewportByType(ViewportType::INTERNAL); if (internalViewport) { mOrientation = internalViewport->orientation; } else { mOrientation = DISPLAY_ORIENTATION_0; } } } void RotaryEncoderInputMapper::reset(nsecs_t when) { mRotaryEncoderScrollAccumulator.reset(getDeviceContext()); InputMapper::reset(when); } void RotaryEncoderInputMapper::process(const RawEvent* rawEvent) { mRotaryEncoderScrollAccumulator.process(rawEvent); if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { sync(rawEvent->when, rawEvent->readTime); } } void RotaryEncoderInputMapper::sync(nsecs_t when, nsecs_t readTime) { PointerCoords pointerCoords; pointerCoords.clear(); PointerProperties pointerProperties; pointerProperties.clear(); pointerProperties.id = 0; pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN; float scroll = mRotaryEncoderScrollAccumulator.getRelativeVWheel(); bool scrolled = scroll != 0; // This is not a pointer, so it's not associated with a display. int32_t displayId = ADISPLAY_ID_NONE; // Moving the rotary encoder should wake the device (if specified). uint32_t policyFlags = 0; if (scrolled && getDeviceContext().isExternal()) { policyFlags |= POLICY_FLAG_WAKE; } if (mOrientation == DISPLAY_ORIENTATION_180) { scroll = -scroll; } // Send motion event. if (scrolled) { int32_t metaState = getContext()->getGlobalMetaState(); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor); NotifyMotionArgs scrollArgs(getContext()->getNextId(), when, readTime, getDeviceId(), mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, /* buttonState */ 0, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, /* videoFrames */ {}); getListener()->notifyMotion(&scrollArgs); } mRotaryEncoderScrollAccumulator.finishSync(); } } // namespace android