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