1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <cinttypes>
17 #include <functional>
18
19 #include "define_multimodal.h"
20 #include "event_log_helper.h"
21 #include "input_device_manager.h"
22 #include "input_event_handler.h"
23 #include "timer_manager.h"
24 #include "util_ex.h"
25
26 #include "crown_transform_processor.h"
27
28 #undef MMI_LOG_DOMAIN
29 #define MMI_LOG_DOMAIN MMI_LOG_DISPATCH
30 #undef MMI_LOG_TAG
31 #define MMI_LOG_TAG "CrownTransformProcessor"
32
33 namespace OHOS {
34 namespace MMI {
35 namespace {
36 const std::string CROWN_SOURCE { "rotary_crown" };
37 const std::string VIRTUAL_CROWN_SOURCE { "Virtual Crown" };
38 constexpr double DEGREE_ZERO { 0.0 };
39 constexpr double VELOCITY_ZERO { 0.0 };
40 constexpr uint64_t MICROSECONDS_PER_SECOND = 1000 * 1000;
41 }
42
CrownTransformProcessor()43 CrownTransformProcessor::CrownTransformProcessor()
44 : pointerEvent_(PointerEvent::Create())
45 {}
46
~CrownTransformProcessor()47 CrownTransformProcessor::~CrownTransformProcessor()
48 {}
49
GetPointerEvent() const50 std::shared_ptr<PointerEvent> CrownTransformProcessor::GetPointerEvent() const
51 {
52 return pointerEvent_;
53 }
54
IsCrownEvent(struct libinput_event * event)55 bool CrownTransformProcessor::IsCrownEvent(struct libinput_event *event)
56 {
57 CALL_DEBUG_ENTER;
58 CHKPF(event);
59 auto device = libinput_event_get_device(event);
60 CHKPF(device);
61 std::string name = libinput_device_get_name(device);
62 if (name == CROWN_SOURCE || name == VIRTUAL_CROWN_SOURCE) {
63 auto type = libinput_event_get_type(event);
64 if (type == LIBINPUT_EVENT_POINTER_AXIS) {
65 struct libinput_event_pointer *pointerEvent = libinput_event_get_pointer_event(event);
66 CHKPF(pointerEvent);
67 auto source = libinput_event_pointer_get_axis_source(pointerEvent);
68 if (source != LIBINPUT_POINTER_AXIS_SOURCE_WHEEL) {
69 MMI_HILOGD("Not crown event, axis source:%{public}d", source);
70 return false;
71 }
72 return true;
73 } else {
74 MMI_HILOGD("Not crown event, type:%{public}d", type);
75 return false;
76 }
77 }
78
79 MMI_HILOGD("Not crown event, device name:%{public}s", name.c_str());
80 return false;
81 }
82
NormalizeRotateEvent(struct libinput_event * event)83 int32_t CrownTransformProcessor::NormalizeRotateEvent(struct libinput_event *event)
84 {
85 CALL_DEBUG_ENTER;
86 CHKPR(event, ERROR_NULL_POINTER);
87
88 auto device = libinput_event_get_device(event);
89 CHKPR(device, ERROR_NULL_POINTER);
90 int32_t deviceId = INPUT_DEV_MGR->FindInputDeviceId(device);
91 if (deviceId < 0) {
92 MMI_HILOGE("The deviceId is invalid, deviceId:%{public}d", deviceId);
93 return RET_ERR;
94 }
95 deviceId_ = deviceId;
96
97 struct libinput_event_pointer *rawPointerEvent = libinput_event_get_pointer_event(event);
98 CHKPR(rawPointerEvent, ERROR_NULL_POINTER);
99 libinput_pointer_axis_source source = libinput_event_pointer_get_axis_source(rawPointerEvent);
100 if (source == LIBINPUT_POINTER_AXIS_SOURCE_WHEEL) {
101 if (TimerMgr->IsExist(timerId_)) {
102 HandleCrownRotateUpdate(rawPointerEvent);
103 TimerMgr->ResetTimer(timerId_);
104 } else {
105 static constexpr int32_t timeout = 100;
106 std::weak_ptr<CrownTransformProcessor> weakPtr = shared_from_this();
107
108 timerId_ = TimerMgr->AddTimer(timeout, 1, [weakPtr]() {
109 CALL_DEBUG_ENTER;
110 auto sharedProcessor = weakPtr.lock();
111 CHKPV(sharedProcessor);
112 sharedProcessor->timerId_ = -1;
113 auto pointerEvent = sharedProcessor->GetPointerEvent();
114 CHKPV(pointerEvent);
115 sharedProcessor->HandleCrownRotateEnd();
116 #ifdef OHOS_BUILD_ENABLE_POINTER
117 auto inputEventNormalizeHandler = InputHandler->GetEventNormalizeHandler();
118 CHKPV(inputEventNormalizeHandler);
119 inputEventNormalizeHandler->HandlePointerEvent(pointerEvent);
120 #endif // OHOS_BUILD_ENABLE_POINTER
121 });
122
123 HandleCrownRotateBegin(rawPointerEvent);
124 }
125
126 #ifdef OHOS_BUILD_ENABLE_POINTER
127 auto inputEventNormalizeHandler = InputHandler->GetEventNormalizeHandler();
128 CHKPR(inputEventNormalizeHandler, ERROR_NULL_POINTER);
129 inputEventNormalizeHandler->HandlePointerEvent(pointerEvent_);
130 #endif // OHOS_BUILD_ENABLE_POINTER
131 DumpInner();
132 return RET_OK;
133 } else {
134 MMI_HILOGE("The source is invalid, source:%{public}d", source);
135 return RET_ERR;
136 }
137 }
138
HandleCrownRotateBegin(struct libinput_event_pointer * rawPointerEvent)139 int32_t CrownTransformProcessor::HandleCrownRotateBegin(struct libinput_event_pointer *rawPointerEvent)
140 {
141 CALL_DEBUG_ENTER;
142 return HandleCrownRotateBeginAndUpdate(rawPointerEvent, PointerEvent::POINTER_ACTION_AXIS_BEGIN);
143 }
144
HandleCrownRotateUpdate(struct libinput_event_pointer * rawPointerEvent)145 int32_t CrownTransformProcessor::HandleCrownRotateUpdate(struct libinput_event_pointer *rawPointerEvent)
146 {
147 CALL_DEBUG_ENTER;
148 return HandleCrownRotateBeginAndUpdate(rawPointerEvent, PointerEvent::POINTER_ACTION_AXIS_UPDATE);
149 }
150
HandleCrownRotateEnd()151 int32_t CrownTransformProcessor::HandleCrownRotateEnd()
152 {
153 CALL_DEBUG_ENTER;
154 lastTime_ = 0;
155 HandleCrownRotatePostInner(VELOCITY_ZERO, DEGREE_ZERO, PointerEvent::POINTER_ACTION_AXIS_END);
156 return RET_OK;
157 }
158
HandleCrownRotateBeginAndUpdate(struct libinput_event_pointer * rawPointerEvent,int32_t action)159 int32_t CrownTransformProcessor::HandleCrownRotateBeginAndUpdate(struct libinput_event_pointer *rawPointerEvent,
160 int32_t action)
161 {
162 CALL_DEBUG_ENTER;
163 CHKPR(rawPointerEvent, ERROR_NULL_POINTER);
164
165 uint64_t currentTime = libinput_event_pointer_get_time_usec(rawPointerEvent);
166 double degree = libinput_event_pointer_get_axis_value_discrete(rawPointerEvent,
167 LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
168 double velocity = VELOCITY_ZERO;
169
170 if (action == PointerEvent::POINTER_ACTION_AXIS_BEGIN) {
171 lastTime_ = currentTime;
172 } else if (action == PointerEvent::POINTER_ACTION_AXIS_UPDATE) {
173 if (currentTime > lastTime_) {
174 velocity = (degree * MICROSECONDS_PER_SECOND) / (currentTime - lastTime_);
175 } else {
176 degree = DEGREE_ZERO;
177 }
178 lastTime_ = currentTime;
179 } else {
180 MMI_HILOGE("The action is invalid, action:%{public}d", action);
181 return RET_ERR;
182 }
183
184 MMI_HILOGD("Crown degree:%{public}f, velocity:%{public}f, currentTime:%{public}" PRId64
185 " action:%{public}d", degree, velocity, currentTime, action);
186 HandleCrownRotatePostInner(velocity, degree, action);
187 return RET_OK;
188 }
189
HandleCrownRotatePostInner(double velocity,double degree,int32_t action)190 void CrownTransformProcessor::HandleCrownRotatePostInner(double velocity, double degree, int32_t action)
191 {
192 CALL_DEBUG_ENTER;
193 CHKPV(pointerEvent_);
194
195 #ifdef OHOS_BUILD_ENABLE_POINTER
196 auto mouseInfo = WIN_MGR->GetMouseInfo();
197
198 PointerEvent::PointerItem pointerItem;
199 pointerItem.SetDisplayX(mouseInfo.physicalX);
200 pointerItem.SetDisplayY(mouseInfo.physicalY);
201 pointerItem.SetWindowX(0);
202 pointerItem.SetWindowY(0);
203 pointerItem.SetPointerId(0);
204 pointerItem.SetPressed(false);
205 int64_t time = GetSysClockTime();
206 pointerItem.SetDownTime(time);
207 pointerItem.SetWidth(0);
208 pointerItem.SetHeight(0);
209 pointerItem.SetPressure(0);
210 pointerItem.SetToolType(PointerEvent::TOOL_TYPE_MOUSE);
211 pointerItem.SetDeviceId(deviceId_);
212 pointerItem.SetRawDx(0);
213 pointerItem.SetRawDy(0);
214
215 pointerEvent_->UpdateId();
216 pointerEvent_->UpdatePointerItem(pointerEvent_->GetPointerId(), pointerItem);
217 pointerEvent_->SetVelocity(velocity);
218 pointerEvent_->SetAxisValue(PointerEvent::AXIS_TYPE_SCROLL_VERTICAL, degree);
219 pointerEvent_->SetPointerAction(action);
220 pointerEvent_->SetActionTime(time);
221 pointerEvent_->SetActionStartTime(time);
222 pointerEvent_->SetSourceType(PointerEvent::SOURCE_TYPE_CROWN);
223 pointerEvent_->SetButtonId(PointerEvent::BUTTON_NONE);
224 pointerEvent_->SetPointerId(0);
225 pointerEvent_->SetDeviceId(deviceId_);
226 pointerEvent_->SetTargetDisplayId(mouseInfo.displayId);
227 pointerEvent_->SetTargetWindowId(-1);
228 pointerEvent_->SetAgentWindowId(-1);
229 #endif // OHOS_BUILD_ENABLE_POINTER
230 StartLogTraceId(pointerEvent_->GetId(), pointerEvent_->GetEventType(), pointerEvent_->GetPointerAction());
231 }
232
DumpInner()233 void CrownTransformProcessor::DumpInner()
234 {
235 EventLogHelper::PrintEventData(pointerEvent_, MMI_LOG_HEADER);
236 auto device = INPUT_DEV_MGR->GetInputDevice(pointerEvent_->GetDeviceId());
237 CHKPV(device);
238 MMI_HILOGI("The crown device id:%{public}d, event created by:%{public}s", pointerEvent_->GetId(),
239 device->GetName().c_str());
240 }
241
Dump(int32_t fd,const std::vector<std::string> & args)242 void CrownTransformProcessor::Dump(int32_t fd, const std::vector<std::string> &args)
243 {
244 CALL_DEBUG_ENTER;
245 CHKPV(pointerEvent_);
246 mprintf(fd, "Crown device state information:\t");
247 mprintf(fd,
248 "PointerId:%{public}d | SourceType:%{public}s | PointerAction:%{public}s | ActionTime:%{public}lld"
249 " | Velocity:%{public}f | AxisValue:%{public}f | AgentWindowId:%{public}d | TargetWindowId:%{public}d\t",
250 pointerEvent_->GetPointerId(), pointerEvent_->DumpSourceType(), pointerEvent_->DumpPointerAction(),
251 static_cast<long long>(pointerEvent_->GetActionTime()), pointerEvent_->GetVelocity(),
252 pointerEvent_->GetAxisValue(PointerEvent::AXIS_TYPE_SCROLL_VERTICAL),
253 pointerEvent_->GetAgentWindowId(), pointerEvent_->GetTargetWindowId());
254 }
255 } // namespace MMI
256 } // namespace OHOS