1 /*
2  * Copyright (c) 2021-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 "js_input_monitor.h"
17 
18 #include <cinttypes>
19 
20 #include "define_multimodal.h"
21 #include "error_multimodal.h"
22 #include "input_manager.h"
23 #include "js_input_monitor_manager.h"
24 #include "util_napi_value.h"
25 #include "napi_constants.h"
26 #include "securec.h"
27 
28 #undef MMI_LOG_TAG
29 #define MMI_LOG_TAG "JsInputMonitor"
30 
31 namespace OHOS {
32 namespace MMI {
33 namespace {
34 constexpr int32_t AXIS_TYPE_SCROLL_VERTICAL { 0 };
35 constexpr int32_t AXIS_TYPE_SCROLL_HORIZONTAL { 1 };
36 constexpr int32_t AXIS_TYPE_PINCH { 2 };
37 constexpr int32_t NAPI_ERR { 3 };
38 constexpr int32_t CANCEL { 0 };
39 constexpr int32_t MOVE { 1 };
40 constexpr int32_t BUTTON_DOWN { 2 };
41 constexpr int32_t BUTTON_UP { 3 };
42 constexpr int32_t AXIS_BEGIN { 4 };
43 constexpr int32_t AXIS_UPDATE { 5 };
44 constexpr int32_t AXIS_END { 6 };
45 constexpr int32_t MIDDLE { 1 };
46 constexpr int32_t RIGHT { 2 };
47 constexpr int32_t MOUSE_FLOW { 10 };
48 constexpr int32_t ONE_FINGERS { 1 };
49 constexpr int32_t THREE_FINGERS { 3 };
50 constexpr int32_t INJECTION_EVENT_FLAG { 10000 };
51 constexpr int32_t FOUR_FINGERS { 4 };
52 constexpr int32_t GESTURE_BEGIN { 1 };
53 constexpr int32_t GESTURE_UPDATE { 2 };
54 constexpr int32_t GESTURE_END { 3 };
55 const std::string INVALID_TYPE_NAME { "" };
56 #ifdef OHOS_BUILD_ENABLE_FINGERPRINT
57 constexpr int32_t FINGERPRINT_DOWN { 0 };
58 constexpr int32_t FINGERPRINT_UP { 1 };
59 constexpr int32_t FINGERPRINT_SLIDE { 2 };
60 constexpr int32_t FINGERPRINT_RETOUCH { 3 };
61 constexpr int32_t FINGERPRINT_CLICK { 4 };
62 constexpr int32_t FINGERPRINT_CANCEL { 5 };
63 #endif // OHOS_BUILD_ENABLE_FINGERPRINT
64 
65 enum TypeName : int32_t {
66     TOUCH = 0,
67     MOUSE = 1,
68     PINCH = 2,
69     THREE_FINGERS_SWIPE = 3,
70     FOUR_FINGERS_SWIPE = 4,
71     ROTATE = 5,
72     THREE_FINGERS_TAP = 6,
73     JOYSTICK = 7,
74     FINGERPRINT = 8,
75     SWIPE_INWARD = 9,
76 };
77 
78 std::map<std::string, int32_t> TO_GESTURE_TYPE = {
79     { "touch", TOUCH },
80     { "mouse", MOUSE },
81     { "pinch", PINCH },
82     { "threeFingersSwipe", THREE_FINGERS_SWIPE },
83     { "fourFingersSwipe", FOUR_FINGERS_SWIPE },
84     { "rotate", ROTATE },
85     { "threeFingersTap", THREE_FINGERS_TAP },
86     { "joystick", JOYSTICK},
87     { "fingerprint", FINGERPRINT},
88     { "swipeInward", SWIPE_INWARD},
89 };
90 
91 struct MonitorInfo {
92     int32_t monitorId;
93     int32_t fingers;
94 };
95 
CleanData(MonitorInfo ** monitorInfo,uv_work_t ** work)96 void CleanData(MonitorInfo** monitorInfo, uv_work_t** work)
97 {
98     if (*monitorInfo != nullptr) {
99         delete *monitorInfo;
100         *monitorInfo = nullptr;
101     }
102     if (*work != nullptr) {
103         delete *work;
104         *work = nullptr;
105     }
106 }
107 } // namespace
108 
109 std::map<std::string, int32_t> TO_HANDLE_EVENT_TYPE = {
110     { "none", HANDLE_EVENT_TYPE_NONE },
111     { "key", HANDLE_EVENT_TYPE_KEY },
112     { "pointer", HANDLE_EVENT_TYPE_POINTER },
113     { "touch", HANDLE_EVENT_TYPE_TOUCH },
114     { "mouse", HANDLE_EVENT_TYPE_MOUSE },
115     { "pinch", HANDLE_EVENT_TYPE_PINCH },
116     { "threeFingersSwipe", HANDLE_EVENT_TYPE_THREEFINGERSSWIP },
117     { "fourFingersSwipe", HANDLE_EVENT_TYPE_FOURFINGERSSWIP },
118     { "swipeInward", HANDLE_EVENT_TYPE_SWIPEINWARD },
119     { "rotate", HANDLE_EVENT_TYPE_ROTATE },
120     { "threeFingersTap", HANDLE_EVENT_TYPE_THREEFINGERSTAP },
121     { "fingerprint", HANDLE_EVENT_TYPE_FINGERPRINT },
122 };
123 
Start(const std::string & typeName)124 int32_t InputMonitor::Start(const std::string &typeName)
125 {
126     CALL_DEBUG_ENTER;
127     std::lock_guard<std::mutex> guard(mutex_);
128     if (monitorId_ < 0) {
129         int32_t eventType = 0;
130         auto it = TO_HANDLE_EVENT_TYPE.find(typeName.c_str());
131         if (it != TO_HANDLE_EVENT_TYPE.end()) {
132             eventType = it->second;
133         }
134         monitorId_ = InputManager::GetInstance()->AddMonitor(shared_from_this(), eventType);
135     }
136     return monitorId_;
137 }
138 
Stop()139 void InputMonitor::Stop()
140 {
141     CALL_DEBUG_ENTER;
142     std::lock_guard<std::mutex> guard(mutex_);
143     if (monitorId_ < 0) {
144         MMI_HILOGE("Invalid values");
145         return;
146     }
147     InputManager::GetInstance()->RemoveMonitor(monitorId_);
148     monitorId_ = -1;
149     return;
150 }
151 
GetTypeName() const152 std::string InputMonitor::GetTypeName() const
153 {
154     return typeName_;
155 }
156 
SetTypeName(const std::string & typeName)157 void InputMonitor::SetTypeName(const std::string &typeName)
158 {
159     typeName_ = typeName;
160 }
161 
SetCallback(std::function<void (std::shared_ptr<PointerEvent>)> callback)162 void InputMonitor::SetCallback(std::function<void(std::shared_ptr<PointerEvent>)> callback)
163 {
164     std::lock_guard<std::mutex> guard(mutex_);
165     callback_ = callback;
166 }
167 
OnInputEvent(std::shared_ptr<PointerEvent> pointerEvent) const168 void InputMonitor::OnInputEvent(std::shared_ptr<PointerEvent> pointerEvent) const
169 {
170     CALL_DEBUG_ENTER;
171     CHKPV(pointerEvent);
172     if (pointerEvent->GetSourceType() == PointerEvent::SOURCE_TYPE_MOUSE
173         && pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_MOVE) {
174         if (++flowCtrl_ < MOUSE_FLOW) {
175             return;
176         } else {
177             flowCtrl_ = 0;
178         }
179     }
180     std::function<void(std::shared_ptr<PointerEvent>)> callback;
181     {
182         std::lock_guard<std::mutex> guard(mutex_);
183         auto typeName = JS_INPUT_MONITOR_MGR.GetMonitorTypeName(id_, fingers_);
184         if (typeName == INVALID_TYPE_NAME) {
185             MMI_HILOGE("Failed to process pointer event, id:%{public}d", id_);
186             return;
187         }
188         if (pointerEvent->GetSourceType() == PointerEvent::SOURCE_TYPE_TOUCHSCREEN) {
189             if (typeName  != "touch") {
190                 return;
191             }
192             SetConsumeState(pointerEvent);
193         }
194         if (pointerEvent->GetSourceType() == PointerEvent::SOURCE_TYPE_MOUSE) {
195             if (typeName != "mouse" && typeName != "pinch" && typeName != "rotate") {
196                 return;
197             }
198             SetConsumeState(pointerEvent);
199         }
200         if (pointerEvent->GetSourceType() == PointerEvent::SOURCE_TYPE_TOUCHPAD) {
201             if (!IsGestureEvent(pointerEvent)) {
202                 return;
203             }
204         }
205         callback = callback_;
206     }
207     CHKPV(callback);
208     callback(pointerEvent);
209 }
210 
SetConsumeState(std::shared_ptr<PointerEvent> pointerEvent) const211 void InputMonitor::SetConsumeState(std::shared_ptr<PointerEvent> pointerEvent) const
212 {
213     CHKPV(pointerEvent);
214     if (pointerEvent->GetPointerIds().size() == 1) {
215         if (pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_DOWN) {
216             consumed_ = false;
217         }
218     }
219 }
220 
IsGestureEvent(std::shared_ptr<PointerEvent> pointerEvent) const221 bool InputMonitor::IsGestureEvent(std::shared_ptr<PointerEvent> pointerEvent) const
222 {
223     CHKPF(pointerEvent);
224     auto jsMonitor = JS_INPUT_MONITOR_MGR.GetMonitor(id_, fingers_);
225     CHKPF(jsMonitor);
226     auto ret = jsMonitor->GetTypeName();
227     if (ret != "pinch" && ret != "threeFingersSwipe" &&
228         ret != "fourFingersSwipe" && ret != "threeFingersTap" &&
229         ret != "swipeInward") {
230         return false;
231     }
232     if (pointerEvent->GetPointerIds().size() == 1) {
233         if (pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_AXIS_BEGIN ||
234             PointerEvent::POINTER_ACTION_SWIPE_BEGIN) {
235             consumed_ = false;
236         }
237     }
238     return true;
239 }
240 
SetId(int32_t id)241 void InputMonitor::SetId(int32_t id)
242 {
243     id_ = id;
244 }
245 
SetFingers(int32_t fingers)246 void InputMonitor::SetFingers(int32_t fingers)
247 {
248     fingers_ = fingers;
249 }
250 
SetHotRectArea(std::vector<Rect> hotRectArea)251 void InputMonitor::SetHotRectArea(std::vector<Rect> hotRectArea)
252 {
253     hotRectArea_ = hotRectArea;
254 }
255 
GetHotRectArea()256 std::vector<Rect> InputMonitor::GetHotRectArea()
257 {
258     return hotRectArea_;
259 }
260 
SetRectTotal(uint32_t rectTotal)261 void InputMonitor::SetRectTotal(uint32_t rectTotal)
262 {
263     rectTotal_ = rectTotal;
264 }
265 
GetRectTotal()266 uint32_t InputMonitor::GetRectTotal()
267 {
268     return rectTotal_;
269 }
270 
OnInputEvent(std::shared_ptr<KeyEvent> keyEvent) const271 void InputMonitor::OnInputEvent(std::shared_ptr<KeyEvent> keyEvent) const {}
272 
OnInputEvent(std::shared_ptr<AxisEvent> axisEvent) const273 void InputMonitor::OnInputEvent(std::shared_ptr<AxisEvent> axisEvent) const {}
274 
MarkConsumed(int32_t eventId)275 void InputMonitor::MarkConsumed(int32_t eventId)
276 {
277     std::lock_guard<std::mutex> guard(mutex_);
278     if (consumed_) {
279         MMI_HILOGD("The consumed_ is true");
280         return;
281     }
282     if (monitorId_ < 0) {
283         MMI_HILOGE("Invalid values");
284         return;
285     }
286     InputManager::GetInstance()->MarkConsumed(monitorId_, eventId);
287     consumed_ = true;
288 }
289 
JsInputMonitor(napi_env jsEnv,const std::string & typeName,std::vector<Rect> rectParam,int32_t rectTotal,napi_value callback,int32_t id,int32_t fingers)290 JsInputMonitor::JsInputMonitor(napi_env jsEnv, const std::string &typeName, std::vector<Rect> rectParam,
291     int32_t rectTotal, napi_value callback, int32_t id, int32_t fingers)
292     : monitor_(std::make_shared<InputMonitor>()), jsEnv_(jsEnv), typeName_(typeName), monitorId_(id),
293     fingers_(fingers)
294 {
295     SetCallback(callback);
296     CHKPV(monitor_);
297     monitor_->SetCallback([jsId = id, jsFingers = fingers](std::shared_ptr<PointerEvent> pointerEvent) {
298         JS_INPUT_MONITOR_MGR.OnPointerEventByMonitorId(jsId, jsFingers, pointerEvent);
299     });
300     monitor_->SetTypeName(typeName_);
301     monitor_->SetId(monitorId_);
302     monitor_->SetFingers(fingers_);
303     if (rectTotal != 0) {
304         monitor_->SetHotRectArea(rectParam);
305         monitor_->SetRectTotal(rectTotal);
306     }
307 }
308 
JsInputMonitor(napi_env jsEnv,const std::string & typeName,napi_value callback,int32_t id,int32_t fingers)309 JsInputMonitor::JsInputMonitor(napi_env jsEnv, const std::string &typeName,
310     napi_value callback, int32_t id, int32_t fingers)
311     : monitor_(std::make_shared<InputMonitor>()), jsEnv_(jsEnv), typeName_(typeName), monitorId_(id),
312     fingers_(fingers)
313 {
314     SetCallback(callback);
315     CHKPV(monitor_);
316     monitor_->SetCallback([jsId = id, jsFingers = fingers](std::shared_ptr<PointerEvent> pointerEvent) {
317         JS_INPUT_MONITOR_MGR.OnPointerEventByMonitorId(jsId, jsFingers, pointerEvent);
318     });
319     monitor_->SetTypeName(typeName_);
320     monitor_->SetId(monitorId_);
321     monitor_->SetFingers(fingers_);
322 }
323 
SetCallback(napi_value callback)324 void JsInputMonitor::SetCallback(napi_value callback)
325 {
326     if (receiver_ == nullptr && jsEnv_ != nullptr) {
327         uint32_t refCount = 1;
328         auto status = napi_create_reference(jsEnv_, callback, refCount, &receiver_);
329         if (status != napi_ok) {
330             THROWERR(jsEnv_, "napi_create_reference is failed");
331             return;
332         }
333     }
334 }
335 
MarkConsumed(int32_t eventId)336 void JsInputMonitor::MarkConsumed(int32_t eventId)
337 {
338     CHKPV(monitor_);
339     monitor_->MarkConsumed(eventId);
340 }
341 
IsMatch(napi_env jsEnv,napi_value callback)342 int32_t JsInputMonitor::IsMatch(napi_env jsEnv, napi_value callback)
343 {
344     CHKPR(callback, ERROR_NULL_POINTER);
345     if (jsEnv_ == jsEnv) {
346         napi_value handlerTemp = nullptr;
347         auto status = napi_get_reference_value(jsEnv_, receiver_, &handlerTemp);
348         if (status != napi_ok) {
349             THROWERR(jsEnv_, "napi_get_reference_value is failed");
350             return NAPI_ERR;
351         }
352         bool isEquals = false;
353         status = napi_strict_equals(jsEnv_, handlerTemp, callback, &isEquals);
354         if (status != napi_ok) {
355             THROWERR(jsEnv_, "napi_strict_equals is failed");
356             return NAPI_ERR;
357         }
358         if (isEquals) {
359             MMI_HILOGI("Js callback match success");
360             return RET_OK;
361         }
362         MMI_HILOGI("Js callback match failed");
363         return RET_ERR;
364     }
365     MMI_HILOGI("Js callback match failed");
366     return RET_ERR;
367 }
368 
IsMatch(napi_env jsEnv)369 int32_t JsInputMonitor::IsMatch(napi_env jsEnv)
370 {
371     if (jsEnv_ == jsEnv) {
372         MMI_HILOGI("Env match success");
373         return RET_OK;
374     }
375     MMI_HILOGI("Env match failed");
376     return RET_ERR;
377 }
378 
GetInputEventFunc(const std::shared_ptr<InputEvent> inputEvent)379 MapFun JsInputMonitor::GetInputEventFunc(const std::shared_ptr<InputEvent> inputEvent)
380 {
381     MapFun mapFunc;
382     mapFunc["id"] = [inputEvent] { return inputEvent->GetId(); };
383     mapFunc["deviceId"] = [inputEvent] { return inputEvent->GetDeviceId(); };
384     mapFunc["actionTime"] = [inputEvent] { return inputEvent->GetActionTime(); };
385     mapFunc["screenId"] = [inputEvent] { return inputEvent->GetTargetDisplayId(); };
386     mapFunc["windowId"] = [inputEvent] { return inputEvent->GetTargetWindowId(); };
387 
388     return mapFunc;
389 }
390 
SetInputEventProperty(const std::shared_ptr<InputEvent> inputEvent,napi_value result)391 int32_t JsInputMonitor::SetInputEventProperty(const std::shared_ptr<InputEvent> inputEvent, napi_value result)
392 {
393     CHKPR(inputEvent, ERROR_NULL_POINTER);
394     auto mapFun = GetInputEventFunc(inputEvent);
395     for (const auto &it : mapFun) {
396         auto setProperty = "Set" + it.first;
397         CHKRR(SetNameProperty(jsEnv_, result, it.first, it.second()), setProperty, RET_ERR);
398     }
399     return RET_OK;
400 }
401 
GetAction(int32_t action) const402 int32_t JsInputMonitor::GetAction(int32_t action) const
403 {
404     switch (action) {
405         case PointerEvent::POINTER_ACTION_CANCEL: {
406             return static_cast<int32_t>(JsTouchEvent::Action::CANCEL);
407         }
408         case PointerEvent::POINTER_ACTION_DOWN: {
409             return static_cast<int32_t>(JsTouchEvent::Action::DOWN);
410         }
411         case PointerEvent::POINTER_ACTION_MOVE: {
412             return static_cast<int32_t>(JsTouchEvent::Action::MOVE);
413         }
414         case PointerEvent::POINTER_ACTION_UP: {
415             return static_cast<int32_t>(JsTouchEvent::Action::UP);
416         }
417         case PointerEvent::POINTER_ACTION_PULL_DOWN: {
418             return static_cast<int32_t>(JsTouchEvent::Action::PULL_DOWN);
419         }
420         case PointerEvent::POINTER_ACTION_PULL_MOVE: {
421             return static_cast<int32_t>(JsTouchEvent::Action::PULL_MOVE);
422         }
423         case PointerEvent::POINTER_ACTION_PULL_UP: {
424             return static_cast<int32_t>(JsTouchEvent::Action::PULL_UP);
425         }
426         default: {
427             return RET_ERR;
428         }
429     }
430 }
431 
GetSourceType(int32_t sourceType) const432 int32_t JsInputMonitor::GetSourceType(int32_t sourceType) const
433 {
434     switch (sourceType) {
435         case PointerEvent::SOURCE_TYPE_TOUCHSCREEN: {
436             return static_cast<int32_t>(JsTouchEvent::SourceType::TOUCH_SCREEN);
437         }
438         case PointerEvent::SOURCE_TYPE_TOUCHPAD: {
439             return static_cast<int32_t>(JsTouchEvent::SourceType::TOUCH_PAD);
440         }
441         default: {
442             return RET_ERR;
443         }
444     }
445 }
446 
GetJsPointerItem(const PointerEvent::PointerItem & item,napi_value value) const447 int32_t JsInputMonitor::GetJsPointerItem(const PointerEvent::PointerItem &item, napi_value value) const
448 {
449     CHKRR(SetNameProperty(jsEnv_, value, "id", item.GetPointerId()), "Set id", RET_ERR);
450     CHKRR(SetNameProperty(jsEnv_, value, "pressedTime", item.GetDownTime()), "Set pressedTime", RET_ERR);
451     CHKRR(SetNameProperty(jsEnv_, value, "screenX", item.GetDisplayX()), "Set screenX", RET_ERR);
452     CHKRR(SetNameProperty(jsEnv_, value, "screenY", item.GetDisplayY()), "Set screenY", RET_ERR);
453     CHKRR(SetNameProperty(jsEnv_, value, "windowX", item.GetWindowX()), "Set windowX", RET_ERR);
454     CHKRR(SetNameProperty(jsEnv_, value, "windowY", item.GetWindowY()), "Set windowY", RET_ERR);
455     CHKRR(SetNameProperty(jsEnv_, value, "pressure", item.GetPressure()), "Set pressure", RET_ERR);
456     CHKRR(SetNameProperty(jsEnv_, value, "width", item.GetWidth()), "Set width", RET_ERR);
457     CHKRR(SetNameProperty(jsEnv_, value, "height", item.GetHeight()), "Set height", RET_ERR);
458     CHKRR(SetNameProperty(jsEnv_, value, "tiltX", item.GetTiltX()), "Set tiltX", RET_ERR);
459     CHKRR(SetNameProperty(jsEnv_, value, "tiltY", item.GetTiltY()), "Set tiltY", RET_ERR);
460     CHKRR(SetNameProperty(jsEnv_, value, "toolX", item.GetToolDisplayX()), "Set toolX", RET_ERR);
461     CHKRR(SetNameProperty(jsEnv_, value, "toolY", item.GetToolDisplayY()), "Set toolY", RET_ERR);
462     CHKRR(SetNameProperty(jsEnv_, value, "toolWidth", item.GetToolWidth()), "Set toolWidth", RET_ERR);
463     CHKRR(SetNameProperty(jsEnv_, value, "toolHeight", item.GetToolHeight()), "Set toolHeight", RET_ERR);
464     CHKRR(SetNameProperty(jsEnv_, value, "rawX", item.GetRawDx()), "Set rawX", RET_ERR);
465     CHKRR(SetNameProperty(jsEnv_, value, "rawY", item.GetRawDy()), "Set rawY", RET_ERR);
466     CHKRR(SetNameProperty(jsEnv_, value, "toolType", item.GetToolType()), "Set toolType", RET_ERR);
467     return RET_OK;
468 }
469 
TransformPointerEvent(const std::shared_ptr<PointerEvent> pointerEvent,napi_value result)470 int32_t JsInputMonitor::TransformPointerEvent(const std::shared_ptr<PointerEvent> pointerEvent, napi_value result)
471 {
472     CHKPR(pointerEvent, ERROR_NULL_POINTER);
473     if (SetInputEventProperty(pointerEvent, result) != RET_OK) {
474         MMI_HILOGE("Set inputEvent property failed");
475         return RET_ERR;
476     }
477     if (SetNameProperty(jsEnv_, result, "action", GetAction(pointerEvent->GetPointerAction())) != napi_ok) {
478         MMI_HILOGE("Set action property failed");
479         return RET_ERR;
480     }
481     if (SetNameProperty(jsEnv_, result, "sourceType", GetSourceType(pointerEvent->GetSourceType())) != napi_ok) {
482         MMI_HILOGE("Set sourceType property failed");
483         return RET_ERR;
484     }
485     napi_value pointers = nullptr;
486     CHKRR(napi_create_array(jsEnv_, &pointers), "napi_create_array is", RET_ERR);
487     std::vector<PointerEvent::PointerItem> pointerItems;
488     for (const auto &item : pointerEvent->GetPointerIds()) {
489         PointerEvent::PointerItem pointerItem;
490         if (!pointerEvent->GetPointerItem(item, pointerItem)) {
491             MMI_HILOGE("Get pointer item failed");
492             return RET_ERR;
493         }
494         pointerItems.push_back(pointerItem);
495     }
496     uint32_t index = 0;
497     for (const auto &it : pointerItems) {
498         napi_value element = nullptr;
499         CHKRR(napi_create_object(jsEnv_, &element), "napi_create_object is", RET_ERR);
500         if (GetJsPointerItem(it, element) != RET_OK) {
501             MMI_HILOGE("Transform pointerItem failed");
502             return RET_ERR;
503         }
504         CHKRR(napi_set_element(jsEnv_, pointers, index, element), "napi_set_element is", RET_ERR);
505         ++index;
506     }
507     CHKRR(SetNameProperty(jsEnv_, result, "touches", pointers), "Set touches", RET_ERR);
508     return RET_OK;
509 }
510 
TransformPinchEvent(std::shared_ptr<PointerEvent> pointerEvent,napi_value result)511 int32_t JsInputMonitor::TransformPinchEvent(std::shared_ptr<PointerEvent> pointerEvent, napi_value result)
512 {
513     CHKPR(pointerEvent, ERROR_NULL_POINTER);
514     int32_t actionValue = GetPinchAction(pointerEvent->GetPointerAction());
515     if (actionValue == RET_ERR) {
516         MMI_HILOGE("Get action value failed");
517         return RET_ERR;
518     }
519     if (SetNameProperty(jsEnv_, result, "type", actionValue) != napi_ok) {
520         MMI_HILOGE("Set type property failed");
521         return RET_ERR;
522     }
523     if (SetNameProperty(jsEnv_, result, "scale",
524         pointerEvent->GetAxisValue(PointerEvent::AXIS_TYPE_PINCH)) != napi_ok) {
525         MMI_HILOGE("Set scale property failed");
526         return RET_ERR;
527     }
528     return RET_OK;
529 }
530 
TransformRotateEvent(std::shared_ptr<PointerEvent> pointerEvent,napi_value result)531 int32_t JsInputMonitor::TransformRotateEvent(std::shared_ptr<PointerEvent> pointerEvent, napi_value result)
532 {
533     CHKPR(pointerEvent, ERROR_NULL_POINTER);
534     int32_t actionValue = GetRotateAction(pointerEvent->GetPointerAction());
535     if (actionValue == RET_ERR) {
536         MMI_HILOGE("Get action value failed");
537         return RET_ERR;
538     }
539     if (SetNameProperty(jsEnv_, result, "type", actionValue) != napi_ok) {
540         MMI_HILOGE("Set type property failed");
541         return RET_ERR;
542     }
543     if (SetNameProperty(jsEnv_, result, "angle",
544         pointerEvent->GetAxisValue(PointerEvent::AXIS_TYPE_ROTATE)) != napi_ok) {
545         MMI_HILOGE("Set scale property failed");
546         return RET_ERR;
547     }
548     return RET_OK;
549 }
550 
GetPinchAction(int32_t action) const551 int32_t JsInputMonitor::GetPinchAction(int32_t action) const
552 {
553     switch (action) {
554         case PointerEvent::POINTER_ACTION_AXIS_BEGIN: {
555             return GESTURE_BEGIN;
556         }
557         case PointerEvent::POINTER_ACTION_AXIS_UPDATE: {
558             return GESTURE_UPDATE;
559         }
560         case PointerEvent::POINTER_ACTION_AXIS_END: {
561             return GESTURE_END;
562         }
563         default: {
564             MMI_HILOGD("Abnormal pointer action in pinch event");
565             return RET_ERR;
566         }
567     }
568 }
569 
GetRotateAction(int32_t action) const570 int32_t JsInputMonitor::GetRotateAction(int32_t action) const
571 {
572     switch (action) {
573         case PointerEvent::POINTER_ACTION_ROTATE_BEGIN: {
574             return GESTURE_BEGIN;
575         }
576         case PointerEvent::POINTER_ACTION_ROTATE_UPDATE: {
577             return GESTURE_UPDATE;
578         }
579         case PointerEvent::POINTER_ACTION_ROTATE_END: {
580             return GESTURE_END;
581         }
582         default: {
583             MMI_HILOGD("Abnormal pointer action in pinch event");
584             return RET_ERR;
585         }
586     }
587 }
588 
TransformSwipeEvent(std::shared_ptr<PointerEvent> pointerEvent,napi_value result)589 int32_t JsInputMonitor::TransformSwipeEvent(std::shared_ptr<PointerEvent> pointerEvent, napi_value result)
590 {
591     CHKPR(pointerEvent, ERROR_NULL_POINTER);
592     int32_t actionValue = GetSwipeAction(pointerEvent->GetPointerAction());
593     if (actionValue == RET_ERR) {
594         if (pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_UPDATE) {
595             MMI_HILOGE("Get action value failed");
596         }
597         return RET_ERR;
598     }
599     if (SetNameProperty(jsEnv_, result, "type", actionValue) != napi_ok) {
600         MMI_HILOGE("Set type property failed");
601         return RET_ERR;
602     }
603     PointerEvent::PointerItem pointeritem;
604     int32_t pointerId = 0;
605     if (INJECTION_EVENT_FLAG <= pointerEvent->GetPointerId()) {
606         pointerId = pointerEvent->GetPointerId();
607     }
608     if (!pointerEvent->GetPointerItem(pointerId, pointeritem)) {
609         MMI_HILOGE("Can't find this pointerItem");
610         return RET_ERR;
611     }
612     if (SetNameProperty(jsEnv_, result, "x", pointeritem.GetDisplayX()) != napi_ok) {
613         MMI_HILOGE("Set displayX property failed");
614         return RET_ERR;
615     }
616     if (SetNameProperty(jsEnv_, result, "y", pointeritem.GetDisplayY()) != napi_ok) {
617         MMI_HILOGE("Set displayY property failed");
618         return RET_ERR;
619     }
620     return RET_OK;
621 }
622 
GetSwipeAction(int32_t action) const623 int32_t JsInputMonitor::GetSwipeAction(int32_t action) const
624 {
625     switch (action) {
626         case PointerEvent::POINTER_ACTION_SWIPE_BEGIN: {
627             return GESTURE_BEGIN;
628         }
629         case PointerEvent::POINTER_ACTION_SWIPE_UPDATE: {
630             return GESTURE_UPDATE;
631         }
632         case PointerEvent::POINTER_ACTION_SWIPE_END: {
633             return GESTURE_END;
634         }
635         default: {
636             MMI_HILOGD("Abnormal pointer action in swipe event");
637             return RET_ERR;
638         }
639     }
640 }
641 
TransformMultiTapEvent(std::shared_ptr<PointerEvent> pointerEvent,napi_value result)642 int32_t JsInputMonitor::TransformMultiTapEvent(std::shared_ptr<PointerEvent> pointerEvent, napi_value result)
643 {
644     CHKPR(pointerEvent, ERROR_NULL_POINTER);
645     int32_t actionValue = GetMultiTapAction(pointerEvent->GetPointerAction());
646     if (actionValue == RET_ERR) {
647         MMI_HILOGE("Get action value failed");
648         return RET_ERR;
649     }
650     if (SetNameProperty(jsEnv_, result, "type", actionValue) != napi_ok) {
651         MMI_HILOGE("Set type property failed");
652         return RET_ERR;
653     }
654     return RET_OK;
655 }
656 
GetMultiTapAction(int32_t action) const657 int32_t JsInputMonitor::GetMultiTapAction(int32_t action) const
658 {
659     switch (action) {
660         case PointerEvent::POINTER_ACTION_TRIPTAP: {
661             return GESTURE_END;
662         }
663         default: {
664             MMI_HILOGD("Abnormal pointer action in multi tap event");
665             return RET_ERR;
666         }
667     }
668 }
669 
TransformSwipeInwardEvent(std::shared_ptr<PointerEvent> pointerEvent,napi_value result)670 int32_t JsInputMonitor::TransformSwipeInwardEvent(std::shared_ptr<PointerEvent> pointerEvent, napi_value result)
671 {
672     CHKPR(pointerEvent, ERROR_NULL_POINTER);
673     int32_t actionValue = pointerEvent->GetPointerAction();
674     if (actionValue == RET_ERR) {
675         MMI_HILOGE("Get action value failed");
676         return RET_ERR;
677     }
678     int32_t actionTypeTemp = actionValue;
679     switch (actionTypeTemp) {
680         case PointerEvent::POINTER_ACTION_DOWN: {
681             actionValue = GESTURE_BEGIN;
682             break;
683         }
684         case PointerEvent::POINTER_ACTION_MOVE: {
685             actionValue = GESTURE_UPDATE;
686             break;
687         }
688         case PointerEvent::POINTER_ACTION_UP:
689         case PointerEvent::POINTER_ACTION_CANCEL: {
690             actionValue = GESTURE_END;
691             break;
692         }
693         default: {
694             MMI_HILOGE("Abnormal pointer action in swipe event");
695             return RET_ERR;
696         }
697     }
698     if (SetNameProperty(jsEnv_, result, "type", actionValue) != napi_ok) {
699         MMI_HILOGE("Set type property failed");
700         return RET_ERR;
701     }
702     PointerEvent::PointerItem pointeritem;
703     int32_t pointerId = 0;
704     if (!pointerEvent->GetPointerItem(pointerId, pointeritem)) {
705         MMI_HILOGE("Can't find this pointerItem");
706         return RET_ERR;
707     }
708     if (SetNameProperty(jsEnv_, result, "x", pointeritem.GetDisplayX()) != napi_ok) {
709         MMI_HILOGE("Set displayX property failed");
710         return RET_ERR;
711     }
712     if (SetNameProperty(jsEnv_, result, "y", pointeritem.GetDisplayY()) != napi_ok) {
713         MMI_HILOGE("Set displayY property failed");
714         return RET_ERR;
715     }
716     return RET_OK;
717 }
718 
719 #ifdef OHOS_BUILD_ENABLE_FINGERPRINT
GetFingerprintAction(int32_t action) const720 int32_t JsInputMonitor::GetFingerprintAction(int32_t action) const
721 {
722     MMI_HILOGD("GetFingerprintAction enter, action is %{public}d", action);
723     switch (action) {
724         case PointerEvent::POINTER_ACTION_FINGERPRINT_DOWN: {
725             return FINGERPRINT_DOWN;
726         }
727         case PointerEvent::POINTER_ACTION_FINGERPRINT_UP: {
728             return FINGERPRINT_UP;
729         }
730         case PointerEvent::POINTER_ACTION_FINGERPRINT_SLIDE: {
731             return FINGERPRINT_SLIDE;
732         }
733         case PointerEvent::POINTER_ACTION_FINGERPRINT_RETOUCH: {
734             return FINGERPRINT_RETOUCH;
735         }
736         case PointerEvent::POINTER_ACTION_FINGERPRINT_CLICK: {
737             return FINGERPRINT_CLICK;
738         }
739         case PointerEvent::POINTER_ACTION_FINGERPRINT_CANCEL: {
740             return FINGERPRINT_CANCEL;
741         }
742         default: {
743             MMI_HILOGE("wrong action is %{public}d", action);
744             return RET_ERR;
745         }
746     }
747 }
748 #endif // OHOS_BUILD_ENABLE_FINGERPRINT
749 
GetFuns(const std::shared_ptr<PointerEvent> pointerEvent,const PointerEvent::PointerItem & item)750 MapFun JsInputMonitor::GetFuns(const std::shared_ptr<PointerEvent> pointerEvent, const PointerEvent::PointerItem& item)
751 {
752     MapFun mapFun;
753     mapFun["actionTime"] = [pointerEvent] { return pointerEvent->GetActionTime(); };
754     mapFun["screenId"] = [pointerEvent] { return pointerEvent->GetTargetDisplayId(); };
755     mapFun["windowId"] = [pointerEvent] { return pointerEvent->GetTargetWindowId(); };
756     mapFun["deviceId"] = [item] { return item.GetDeviceId(); };
757     mapFun["windowX"] = [item] { return item.GetWindowX(); };
758     mapFun["windowY"] = [item] { return item.GetWindowY(); };
759     mapFun["screenX"] = [item] { return item.GetDisplayX(); };
760     mapFun["screenY"] = [item] { return item.GetDisplayY(); };
761     mapFun["rawDeltaX"] = [item] { return item.GetRawDx(); };
762     mapFun["rawDeltaY"] = [item] { return item.GetRawDy(); };
763     return mapFun;
764 }
765 
SetMouseProperty(const std::shared_ptr<PointerEvent> pointerEvent,const PointerEvent::PointerItem & item,napi_value result)766 bool JsInputMonitor::SetMouseProperty(const std::shared_ptr<PointerEvent> pointerEvent,
767     const PointerEvent::PointerItem& item, napi_value result)
768 {
769     CHKPF(pointerEvent);
770     int32_t buttonId = pointerEvent->GetButtonId();
771     if (buttonId == PointerEvent::MOUSE_BUTTON_MIDDLE) {
772         buttonId = MIDDLE;
773     } else if (buttonId == PointerEvent::MOUSE_BUTTON_RIGHT) {
774         buttonId = RIGHT;
775     }
776     if (SetNameProperty(jsEnv_, result, "button", buttonId) != napi_ok) {
777         THROWERR(jsEnv_, "Set property failed");
778         return false;
779     }
780 
781     auto mapFun = GetFuns(pointerEvent, item);
782     for (const auto &it : mapFun) {
783         if (SetNameProperty(jsEnv_, result, it.first, it.second()) != napi_ok) {
784             THROWERR(jsEnv_, "Set property failed");
785             return false;
786         }
787     }
788     return true;
789 }
790 
GetAxesValue(const std::shared_ptr<PointerEvent> pointerEvent,napi_value element)791 bool JsInputMonitor::GetAxesValue(const std::shared_ptr<PointerEvent> pointerEvent, napi_value element)
792 {
793     CALL_DEBUG_ENTER;
794     CHKPF(pointerEvent);
795     double axisValue = -1.0;
796     int32_t axis = -1;
797     if (pointerEvent->HasAxis(PointerEvent::AXIS_TYPE_SCROLL_VERTICAL)) {
798         axisValue = pointerEvent->GetAxisValue(PointerEvent::AXIS_TYPE_SCROLL_VERTICAL);
799         axis = AXIS_TYPE_SCROLL_VERTICAL;
800     }
801     if (pointerEvent->HasAxis(PointerEvent::AXIS_TYPE_SCROLL_HORIZONTAL)) {
802         axisValue = pointerEvent->GetAxisValue(PointerEvent::AXIS_TYPE_SCROLL_HORIZONTAL);
803         axis = AXIS_TYPE_SCROLL_HORIZONTAL;
804     }
805     if (pointerEvent->HasAxis(PointerEvent::AXIS_TYPE_PINCH)) {
806         axisValue = pointerEvent->GetAxisValue(PointerEvent::AXIS_TYPE_PINCH);
807         axis = AXIS_TYPE_PINCH;
808     }
809     if (SetNameProperty(jsEnv_, element, "axis", axis) != napi_ok) {
810         THROWERR(jsEnv_, "Set property of axis failed");
811         return false;
812     }
813     if (SetNameProperty(jsEnv_, element, "value", axisValue) != napi_ok) {
814         THROWERR(jsEnv_, "Set property of value failed");
815         return false;
816     }
817     return true;
818 }
819 
GetMousePointerItem(const std::shared_ptr<PointerEvent> pointerEvent,napi_value result)820 int32_t JsInputMonitor::GetMousePointerItem(const std::shared_ptr<PointerEvent> pointerEvent, napi_value result)
821 {
822     CALL_DEBUG_ENTER;
823     CHKPR(pointerEvent, ERROR_NULL_POINTER);
824     napi_value axes = nullptr;
825     napi_status status = napi_create_array(jsEnv_, &axes);
826     if (status != napi_ok || axes == nullptr) {
827         THROWERR(jsEnv_, "napi_create_array is failed");
828         return RET_ERR;
829     }
830     uint32_t index = 0;
831     int32_t currentPointerId = pointerEvent->GetPointerId();
832     std::vector<int32_t> pointerIds { pointerEvent->GetPointerIds() };
833     for (const auto& pointerId : pointerIds) {
834         if (pointerId == currentPointerId) {
835             PointerEvent::PointerItem item;
836             if (!pointerEvent->GetPointerItem(pointerId, item)) {
837                 MMI_HILOGE("Invalid pointer:%{public}d", pointerId);
838                 return RET_ERR;
839             }
840             if (SetNameProperty(jsEnv_, result, "id", currentPointerId) != napi_ok) {
841                 THROWERR(jsEnv_, "Set property of id failed");
842                 return false;
843             }
844             if (!SetMouseProperty(pointerEvent, item, result)) {
845                 MMI_HILOGE("Set property of mouse failed");
846                 return RET_ERR;
847             }
848         }
849         napi_value element = nullptr;
850         if (napi_create_object(jsEnv_, &element) != napi_ok) {
851             THROWERR(jsEnv_, "napi_create_object is failed");
852             return false;
853         }
854         if (!GetAxesValue(pointerEvent, element)) {
855             THROWERR(jsEnv_, "Get axesValue failed");
856             return RET_ERR;
857         }
858         status = napi_set_element(jsEnv_, axes, index, element);
859         if (status != napi_ok) {
860             THROWERR(jsEnv_, "Napi set element in axes failed");
861             return RET_ERR;
862         }
863         ++index;
864     }
865     if (SetNameProperty(jsEnv_, result, "axes", axes) != napi_ok) {
866         THROWERR(jsEnv_, "Set property of axes failed");
867         return RET_ERR;
868     }
869     return RET_OK;
870 }
871 
GetPressedButtons(const std::set<int32_t> & pressedButtons,napi_value result)872 bool JsInputMonitor::GetPressedButtons(const std::set<int32_t>& pressedButtons, napi_value result)
873 {
874     CALL_DEBUG_ENTER;
875     napi_value value = nullptr;
876     napi_status status = napi_create_array(jsEnv_, &value);
877     if (status != napi_ok || value == nullptr) {
878         THROWERR(jsEnv_, "napi_create_array is failed");
879         return false;
880     }
881     uint32_t index = 0;
882     for (const auto &item : pressedButtons) {
883         int32_t buttonId = item;
884         if (buttonId == PointerEvent::MOUSE_BUTTON_MIDDLE) {
885             buttonId = MIDDLE;
886         } else if (buttonId == PointerEvent::MOUSE_BUTTON_RIGHT) {
887             buttonId = RIGHT;
888         }
889         napi_value element = nullptr;
890         if (napi_create_int32(jsEnv_, buttonId, &element) != napi_ok) {
891             THROWERR(jsEnv_, "Napi create int32 failed");
892             return false;
893         }
894         status = napi_set_element(jsEnv_, value, index, element);
895         if (status != napi_ok) {
896             THROWERR(jsEnv_, "Napi set element failed");
897             return false;
898         }
899         ++index;
900     }
901     if (SetNameProperty(jsEnv_, result, "pressedButtons", value) != napi_ok) {
902         THROWERR(jsEnv_, "Set property of pressedButtons failed");
903         return false;
904     }
905     return true;
906 }
907 
GetPressedKeys(const std::vector<int32_t> & pressedKeys,napi_value result)908 bool JsInputMonitor::GetPressedKeys(const std::vector<int32_t>& pressedKeys, napi_value result)
909 {
910     CALL_DEBUG_ENTER;
911     napi_value value = nullptr;
912     napi_status status = napi_create_array(jsEnv_, &value);
913     if (status != napi_ok || value == nullptr) {
914         THROWERR(jsEnv_, "napi_create_array is failed");
915         return false;
916     }
917     uint32_t index = 0;
918     for (const auto &it : pressedKeys) {
919         napi_value element = nullptr;
920         if (napi_create_int32(jsEnv_, it, &element) != napi_ok) {
921             THROWERR(jsEnv_, "Napi create int32 failed");
922             return false;
923         }
924         status = napi_set_element(jsEnv_, value, index, element);
925         if (status != napi_ok) {
926             THROWERR(jsEnv_, "Napi set element failed");
927             return false;
928         }
929         ++index;
930     }
931     if (SetNameProperty(jsEnv_, result, "pressedKeys", value) != napi_ok) {
932         THROWERR(jsEnv_, "Set property of pressedKeys failed");
933         return false;
934     }
935     return true;
936 }
937 
HasKeyCode(const std::vector<int32_t> & pressedKeys,int32_t keyCode)938 bool JsInputMonitor::HasKeyCode(const std::vector<int32_t>& pressedKeys, int32_t keyCode)
939 {
940     return std::find(pressedKeys.begin(), pressedKeys.end(), keyCode) != pressedKeys.end();
941 }
942 
GetPressedKey(const std::vector<int32_t> & pressedKeys,napi_value result)943 bool JsInputMonitor::GetPressedKey(const std::vector<int32_t>& pressedKeys, napi_value result)
944 {
945     CALL_DEBUG_ENTER;
946     bool isExists = HasKeyCode(pressedKeys, KeyEvent::KEYCODE_CTRL_LEFT)
947         || HasKeyCode(pressedKeys, KeyEvent::KEYCODE_CTRL_RIGHT);
948     if (SetNameProperty(jsEnv_, result, "ctrlKey", isExists) != napi_ok) {
949         THROWERR(jsEnv_, "Set ctrlKey with failed");
950         return false;
951     }
952     isExists = HasKeyCode(pressedKeys, KeyEvent::KEYCODE_ALT_LEFT)
953         || HasKeyCode(pressedKeys, KeyEvent::KEYCODE_ALT_RIGHT);
954     if (SetNameProperty(jsEnv_, result, "altKey", isExists) != napi_ok) {
955         THROWERR(jsEnv_, "Set altKey failed");
956         return false;
957     }
958     isExists = HasKeyCode(pressedKeys, KeyEvent::KEYCODE_SHIFT_LEFT)
959         || HasKeyCode(pressedKeys, KeyEvent::KEYCODE_SHIFT_RIGHT);
960     if (SetNameProperty(jsEnv_, result, "shiftKey", isExists) != napi_ok) {
961         THROWERR(jsEnv_, "Set shiftKey failed");
962         return false;
963     }
964     isExists = HasKeyCode(pressedKeys, KeyEvent::KEYCODE_META_LEFT)
965         || HasKeyCode(pressedKeys, KeyEvent::KEYCODE_META_RIGHT);
966     if (SetNameProperty(jsEnv_, result, "logoKey", isExists) != napi_ok) {
967         THROWERR(jsEnv_, "Set logoKey failed");
968         return false;
969     }
970     isExists = HasKeyCode(pressedKeys, KeyEvent::KEYCODE_FN);
971     if (SetNameProperty(jsEnv_, result, "fnKey", isExists) != napi_ok) {
972         THROWERR(jsEnv_, "Set fnKey failed");
973         return false;
974     }
975     return true;
976 }
977 
TransformTsActionValue(int32_t pointerAction)978 int32_t JsInputMonitor::TransformTsActionValue(int32_t pointerAction)
979 {
980     switch (pointerAction) {
981         case PointerEvent::POINTER_ACTION_CANCEL: {
982             return CANCEL;
983         }
984         case PointerEvent::POINTER_ACTION_MOVE:
985         case PointerEvent::POINTER_ACTION_PULL_MOVE: {
986             return MOVE;
987         }
988         case PointerEvent::POINTER_ACTION_BUTTON_DOWN:
989         case PointerEvent::POINTER_ACTION_PULL_DOWN: {
990             return BUTTON_DOWN;
991         }
992         case PointerEvent::POINTER_ACTION_BUTTON_UP:
993         case PointerEvent::POINTER_ACTION_PULL_UP: {
994             return BUTTON_UP;
995         }
996         case PointerEvent::POINTER_ACTION_AXIS_BEGIN: {
997             return AXIS_BEGIN;
998         }
999         case PointerEvent::POINTER_ACTION_AXIS_UPDATE: {
1000             return AXIS_UPDATE;
1001         }
1002         case PointerEvent::POINTER_ACTION_AXIS_END: {
1003             return AXIS_END;
1004         }
1005         default: {
1006             MMI_HILOGD("Abnormal pointer action");
1007             return RET_ERR;
1008         }
1009     }
1010 }
1011 
TransformMousePointerEvent(std::shared_ptr<PointerEvent> pointerEvent,napi_value result)1012 int32_t JsInputMonitor::TransformMousePointerEvent(std::shared_ptr<PointerEvent> pointerEvent, napi_value result)
1013 {
1014     CALL_DEBUG_ENTER;
1015     CHKPR(pointerEvent, ERROR_NULL_POINTER);
1016     int32_t actionValue = TransformTsActionValue(pointerEvent->GetPointerAction());
1017     if (actionValue == RET_ERR) {
1018         MMI_HILOGD("Transform action value failed");
1019         return RET_ERR;
1020     }
1021     if (SetNameProperty(jsEnv_, result, "action", actionValue) != napi_ok) {
1022         MMI_HILOGE("Set property of action failed");
1023         return RET_ERR;
1024     }
1025     std::vector<int32_t> pressedKeys = pointerEvent->GetPressedKeys();
1026     if (!GetPressedKeys(pressedKeys, result)) {
1027         MMI_HILOGE("Get pressedButtons failed");
1028         return RET_ERR;
1029     }
1030     if (!GetPressedKey(pressedKeys, result)) {
1031         MMI_HILOGE("Get singlePressedKey failed");
1032         return RET_ERR;
1033     }
1034     if (GetMousePointerItem(pointerEvent, result) != RET_OK) {
1035         MMI_HILOGE("Get item of mousePointer failed");
1036         return RET_ERR;
1037     }
1038     std::set<int32_t> pressedButtons = pointerEvent->GetPressedButtons();
1039     if (!GetPressedButtons(pressedButtons, result)) {
1040         MMI_HILOGE("Get pressedKeys failed");
1041         return RET_ERR;
1042     }
1043     return RET_OK;
1044 }
1045 
1046 #ifdef OHOS_BUILD_ENABLE_FINGERPRINT
TransformFingerprintEvent(const std::shared_ptr<PointerEvent> pointerEvent,napi_value result)1047 int32_t JsInputMonitor::TransformFingerprintEvent(const std::shared_ptr<PointerEvent> pointerEvent, napi_value result)
1048 {
1049     CALL_DEBUG_ENTER;
1050     CHKPR(pointerEvent, ERROR_NULL_POINTER);
1051     int32_t actionValue = GetFingerprintAction(pointerEvent->GetPointerAction());
1052     if (actionValue == RET_ERR) {
1053         MMI_HILOGW("Get action value failed");
1054         return RET_ERR;
1055     }
1056     if (SetNameProperty(jsEnv_, result, "action", actionValue) != napi_ok) {
1057         MMI_HILOGW("Set name property failed");
1058         return RET_ERR;
1059     }
1060     if (SetNameProperty(jsEnv_, result, "distanceX", pointerEvent->GetFingerprintDistanceX()) != napi_ok) {
1061         MMI_HILOGW("Set distanceX property failed");
1062         return RET_ERR;
1063     }
1064     if (SetNameProperty(jsEnv_, result, "distanceY", pointerEvent->GetFingerprintDistanceY()) != napi_ok) {
1065         MMI_HILOGW("Set distanceY property failed");
1066         return RET_ERR;
1067     }
1068     MMI_HILOGD("jsfingerprint key:%{public}d, x:%{public}f, y:%{public}f", actionValue,
1069         pointerEvent->GetFingerprintDistanceX(), pointerEvent->GetFingerprintDistanceY());
1070     return RET_OK;
1071 }
1072 #endif // OHOS_BUILD_ENABLE_FINGERPRINT
1073 
Start(const std::string & typeName)1074 int32_t JsInputMonitor::Start(const std::string &typeName)
1075 {
1076     CALL_DEBUG_ENTER;
1077     CHKPF(monitor_);
1078     if (isMonitoring_) {
1079         MMI_HILOGW("Js is monitoring");
1080         return RET_OK;
1081     }
1082     int32_t ret = monitor_->Start(typeName);
1083     if (ret >= 0) {
1084         isMonitoring_ = true;
1085     }
1086     return ret;
1087 }
1088 
~JsInputMonitor()1089 JsInputMonitor::~JsInputMonitor()
1090 {
1091     CALL_DEBUG_ENTER;
1092     if (isMonitoring_) {
1093         isMonitoring_ = false;
1094         if (monitor_ != nullptr) {
1095             monitor_->Stop();
1096         }
1097     }
1098     uint32_t refCount = 0;
1099     auto status = napi_reference_unref(jsEnv_, receiver_, &refCount);
1100     if (status != napi_ok) {
1101         THROWERR(jsEnv_, "napi_reference_unref is failed");
1102         return;
1103     }
1104 }
1105 
Stop()1106 void JsInputMonitor::Stop()
1107 {
1108     CALL_DEBUG_ENTER;
1109     CHKPV(monitor_);
1110     if (isMonitoring_) {
1111         isMonitoring_ = false;
1112         if (monitor_ != nullptr) {
1113             monitor_->Stop();
1114         }
1115     }
1116 }
1117 
GetId() const1118 int32_t JsInputMonitor::GetId() const
1119 {
1120     return monitorId_;
1121 }
1122 
GetFingers() const1123 int32_t JsInputMonitor::GetFingers() const
1124 {
1125     return fingers_;
1126 }
1127 
GetTypeName() const1128 std::string JsInputMonitor::GetTypeName() const
1129 {
1130     return typeName_;
1131 }
1132 
OnPointerEvent(std::shared_ptr<PointerEvent> pointerEvent)1133 void JsInputMonitor::OnPointerEvent(std::shared_ptr<PointerEvent> pointerEvent)
1134 {
1135     CALL_DEBUG_ENTER;
1136     if (!isMonitoring_) {
1137         MMI_HILOGE("Js monitor stop");
1138         return;
1139     }
1140     CHKPV(monitor_);
1141     CHKPV(pointerEvent);
1142     {
1143         std::lock_guard<std::mutex> guard(mutex_);
1144         if (!evQueue_.empty()) {
1145             if (IsBeginAndEnd(pointerEvent)) {
1146                 std::queue<std::shared_ptr<PointerEvent>> tmp;
1147                 std::swap(evQueue_, tmp);
1148             }
1149         }
1150         evQueue_.push(pointerEvent);
1151     }
1152 
1153     if (!evQueue_.empty()) {
1154         uv_work_t *work = new (std::nothrow) uv_work_t;
1155         CHKPV(work);
1156         MonitorInfo *monitorInfo = new (std::nothrow) MonitorInfo();
1157         if (monitorInfo == nullptr) {
1158             MMI_HILOGE("monitorInfo is nullptr");
1159             delete work;
1160             work = nullptr;
1161             return;
1162         }
1163         monitorInfo->monitorId = monitorId_;
1164         monitorInfo->fingers = fingers_;
1165         work->data = monitorInfo;
1166         uv_loop_s *loop = nullptr;
1167         auto status = napi_get_uv_event_loop(jsEnv_, &loop);
1168         if (status != napi_ok) {
1169             THROWERR(jsEnv_, "napi_get_uv_event_loop is failed");
1170             CleanData(&monitorInfo, &work);
1171             return;
1172         }
1173         int32_t ret = uv_queue_work_with_qos(
1174             loop, work,
1175             [](uv_work_t *work) {
1176                 MMI_HILOGD("uv_queue_work callback function is called");
1177             },
1178             &JsInputMonitor::JsCallback, uv_qos_user_initiated);
1179         if (ret != 0) {
1180             MMI_HILOGE("add uv_queue failed, ret is %{public}d", ret);
1181             CleanData(&monitorInfo, &work);
1182         }
1183     }
1184 }
1185 
IsBeginAndEnd(std::shared_ptr<PointerEvent> pointerEvent)1186 bool JsInputMonitor::IsBeginAndEnd(std::shared_ptr<PointerEvent> pointerEvent)
1187 {
1188     CHKPF(pointerEvent);
1189     bool res = pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_DOWN ||
1190         pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_UP ||
1191         pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_SWIPE_BEGIN ||
1192         pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_SWIPE_END;
1193     return res;
1194 }
1195 
JsCallback(uv_work_t * work,int32_t status)1196 void JsInputMonitor::JsCallback(uv_work_t *work, int32_t status)
1197 {
1198     CALL_DEBUG_ENTER;
1199     CHKPV(work);
1200     auto temp = static_cast<MonitorInfo*>(work->data);
1201     delete work;
1202     work = nullptr;
1203     auto jsMonitor { JS_INPUT_MONITOR_MGR.GetMonitor(temp->monitorId, temp->fingers) };
1204     CHKPV(jsMonitor);
1205     jsMonitor->OnPointerEventInJsThread(jsMonitor->GetTypeName(), temp->fingers);
1206     delete temp;
1207     temp = nullptr;
1208 }
1209 
OnPointerEventInJsThread(const std::string & typeName,int32_t fingers)1210 void JsInputMonitor::OnPointerEventInJsThread(const std::string &typeName, int32_t fingers)
1211 {
1212     CALL_DEBUG_ENTER;
1213     {
1214         std::lock_guard<std::mutex> guard(mutex_);
1215         if (!isMonitoring_) {
1216             MMI_HILOGE("Js monitor stop");
1217             return;
1218         }
1219         CHKPV(jsEnv_);
1220         CHKPV(receiver_);
1221         while (!evQueue_.empty()) {
1222             if (!isMonitoring_) {
1223                 MMI_HILOGE("Js monitor stop handle callback");
1224                 break;
1225             }
1226             napi_handle_scope scope = nullptr;
1227             napi_open_handle_scope(jsEnv_, &scope);
1228             CHKPV(scope);
1229             auto pointerEvent = evQueue_.front();
1230             if (pointerEvent == nullptr) {
1231                 MMI_HILOGE("scope is nullptr");
1232                 napi_close_handle_scope(jsEnv_, scope);
1233                 continue;
1234             }
1235             evQueue_.pop();
1236             pointerQueue_.push(pointerEvent);
1237             napi_close_handle_scope(jsEnv_, scope);
1238         }
1239     }
1240 
1241     std::lock_guard<std::mutex> guard(resourcesmutex_);
1242     while (!pointerQueue_.empty()) {
1243         auto pointerEventItem = pointerQueue_.front();
1244         pointerQueue_.pop();
1245         napi_handle_scope scope = nullptr;
1246         napi_open_handle_scope(jsEnv_, &scope);
1247         CHKPV(scope);
1248         LogTracer lt(pointerEventItem->GetId(), pointerEventItem->GetEventType(), pointerEventItem->GetPointerAction());
1249         napi_value napiPointer = nullptr;
1250         auto status = napi_create_object(jsEnv_, &napiPointer);
1251         if (status != napi_ok) {
1252             pointerEventItem->MarkProcessed();
1253             napi_close_handle_scope(jsEnv_, scope);
1254             break;
1255         }
1256         auto ret = RET_ERR;
1257         switch (TO_GESTURE_TYPE[typeName.c_str()]) {
1258             case TypeName::TOUCH: {
1259                 ret = TransformPointerEvent(pointerEventItem, napiPointer);
1260                 break;
1261             }
1262             case TypeName::MOUSE: {
1263                 ret = TransformMousePointerEvent(pointerEventItem, napiPointer);
1264                 break;
1265             }
1266             case TypeName::ROTATE: {
1267                 if (!IsRotate(pointerEventItem)) {
1268                     napi_close_handle_scope(jsEnv_, scope);
1269                     continue;
1270                 }
1271                 ret = TransformRotateEvent(pointerEventItem, napiPointer);
1272                 break;
1273             }
1274             case TypeName::PINCH: {
1275                 if (!IsPinch(pointerEventItem, fingers)) {
1276                     napi_close_handle_scope(jsEnv_, scope);
1277                     continue;
1278                 }
1279                 ret = TransformPinchEvent(pointerEventItem, napiPointer);
1280                 break;
1281             }
1282             case TypeName::THREE_FINGERS_SWIPE: {
1283                 if (!IsThreeFingersSwipe(pointerEventItem)) {
1284                     napi_close_handle_scope(jsEnv_, scope);
1285                     continue;
1286                 }
1287                 ret = TransformSwipeEvent(pointerEventItem, napiPointer);
1288                 break;
1289             }
1290             case TypeName::FOUR_FINGERS_SWIPE: {
1291                 if (!IsFourFingersSwipe(pointerEventItem)) {
1292                     napi_close_handle_scope(jsEnv_, scope);
1293                     continue;
1294                 }
1295                 ret = TransformSwipeEvent(pointerEventItem, napiPointer);
1296                 break;
1297             }
1298             case TypeName::THREE_FINGERS_TAP: {
1299                 if (!IsThreeFingersTap(pointerEventItem)) {
1300                 }
1301                 ret = TransformMultiTapEvent(pointerEventItem, napiPointer);
1302                 break;
1303             }
1304             case TypeName::SWIPE_INWARD: {
1305                 if (!IsSwipeInward(pointerEventItem)) {
1306                     napi_close_handle_scope(jsEnv_, scope);
1307                     continue;
1308                 }
1309                 ret = TransformSwipeInwardEvent(pointerEventItem, napiPointer);
1310                 break;
1311             }
1312 #ifdef OHOS_BUILD_ENABLE_FINGERPRINT
1313             case TypeName::FINGERPRINT: {
1314                 if (!IsFingerprint(pointerEventItem)) {
1315                     napi_close_handle_scope(jsEnv_, scope);
1316                     continue;
1317                 }
1318                 ret = TransformFingerprintEvent(pointerEventItem, napiPointer);
1319                 break;
1320             }
1321 #endif // OHOS_BUILD_ENABLE_FINGERPRINT
1322             default: {
1323                 MMI_HILOGE("This event is invalid");
1324                 break;
1325             }
1326         }
1327         bool checkFlag = ret != RET_OK || napiPointer == nullptr;
1328         if (checkFlag) {
1329             napi_close_handle_scope(jsEnv_, scope);
1330             break;
1331         }
1332         napi_value callback = nullptr;
1333         status = napi_get_reference_value(jsEnv_, receiver_, &callback);
1334         if (status != napi_ok) {
1335             pointerEventItem->MarkProcessed();
1336             napi_close_handle_scope(jsEnv_, scope);
1337             break;
1338         }
1339         napi_value result = nullptr;
1340         if (monitor_->GetRectTotal() == 0
1341             || IsLocaledWithinRect(jsEnv_, napiPointer, monitor_->GetRectTotal(), monitor_->GetHotRectArea())) {
1342             status = napi_call_function(jsEnv_, nullptr, callback, 1, &napiPointer, &result);
1343             if (status != napi_ok) {
1344                 pointerEventItem->MarkProcessed();
1345                 napi_close_handle_scope(jsEnv_, scope);
1346                 break;
1347             }
1348         }
1349         bool typeNameFlag = typeName == "touch" || typeName == "pinch" || typeName == "threeFingersSwipe" ||
1350             typeName == "fourFingersSwipe" || typeName == "rotate" || typeName == "threeFingersTap" ||
1351             typeName == "fingerprint" || typeName == "swipeInward";
1352         if (typeNameFlag) {
1353             if (pointerEventItem->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_UPDATE &&
1354                 pointerEventItem->GetPointerAction() != PointerEvent::POINTER_ACTION_PULL_MOVE) {
1355                 MMI_HILOGI("pointer:%{public}d,pointerAction:%{public}s", pointerEventItem->GetPointerId(),
1356                     pointerEventItem->DumpPointerAction());
1357             }
1358             bool retValue = false;
1359             status = napi_get_value_bool(jsEnv_, result, &retValue);
1360             if (status != napi_ok) {
1361                 napi_close_handle_scope(jsEnv_, scope);
1362                 return;
1363             }
1364             CheckConsumed(retValue, pointerEventItem);
1365         }
1366         napi_close_handle_scope(jsEnv_, scope);
1367     }
1368 }
1369 
IsLocaledWithinRect(napi_env env,napi_value napiPointer,uint32_t rectTotal,std::vector<Rect> hotRectArea)1370 bool JsInputMonitor::IsLocaledWithinRect(napi_env env, napi_value napiPointer,
1371     uint32_t rectTotal, std::vector<Rect> hotRectArea)
1372 {
1373     napi_value xProperty;
1374     CHKRF(napi_get_named_property(env, napiPointer, "screenX", &xProperty), GET_NAMED_PROPERTY);
1375     CHKPF(xProperty);
1376     int32_t xInt { 0 };
1377     CHKRF(napi_get_value_int32(env, xProperty, &xInt), GET_VALUE_INT32);
1378 
1379     napi_value yProperty;
1380     CHKRF(napi_get_named_property(env, napiPointer, "screenY", &yProperty), GET_NAMED_PROPERTY);
1381     CHKPF(yProperty);
1382     int32_t yInt { 0 };
1383     CHKRF(napi_get_value_int32(env, yProperty, &yInt), GET_VALUE_INT32);
1384 
1385     for (uint32_t i = 0; i < rectTotal; i++) {
1386         int32_t hotAreaX = hotRectArea.at(i).x;
1387         int32_t hotAreaY = hotRectArea.at(i).y;
1388         int32_t hotAreaWidth = hotRectArea.at(i).width;
1389         int32_t hotAreaHeight = hotRectArea.at(i).height;
1390         if ((xInt >= hotAreaX) && (xInt <= hotAreaX + hotAreaWidth)
1391             && (yInt >= hotAreaY) && (yInt <= hotAreaY + hotAreaHeight)) {
1392             return true;
1393         }
1394     }
1395     return false;
1396 }
1397 
CheckConsumed(bool retValue,std::shared_ptr<PointerEvent> pointerEvent)1398 void JsInputMonitor::CheckConsumed(bool retValue, std::shared_ptr<PointerEvent> pointerEvent)
1399 {
1400     CALL_DEBUG_ENTER;
1401     CHKPV(pointerEvent);
1402     if (retValue) {
1403         auto eventId = pointerEvent->GetId();
1404         MarkConsumed(eventId);
1405     }
1406 }
1407 
IsPinch(std::shared_ptr<PointerEvent> pointerEvent,const int32_t fingers)1408 bool JsInputMonitor::IsPinch(std::shared_ptr<PointerEvent> pointerEvent, const int32_t fingers)
1409 {
1410     CHKPF(pointerEvent);
1411     if ((fingers > 0 && ((pointerEvent->GetSourceType() != PointerEvent::SOURCE_TYPE_MOUSE &&
1412         pointerEvent->GetSourceType() != PointerEvent::SOURCE_TYPE_TOUCHPAD) ||
1413         pointerEvent->GetFingerCount() != fingers)) ||
1414         (fingers == 0 && (pointerEvent->GetSourceType() != PointerEvent::SOURCE_TYPE_TOUCHPAD ||
1415         pointerEvent->GetFingerCount() < THREE_FINGERS))) {
1416         return false;
1417     }
1418     if ((pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_AXIS_BEGIN &&
1419         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_AXIS_UPDATE &&
1420         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_AXIS_END)) {
1421         return false;
1422     }
1423     return true;
1424 }
1425 
IsRotate(std::shared_ptr<PointerEvent> pointerEvent)1426 bool JsInputMonitor::IsRotate(std::shared_ptr<PointerEvent> pointerEvent)
1427 {
1428     CHKPF(pointerEvent);
1429     if (pointerEvent->GetSourceType() != PointerEvent::SOURCE_TYPE_MOUSE ||
1430         (pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_ROTATE_BEGIN &&
1431         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_ROTATE_UPDATE &&
1432         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_ROTATE_END)) {
1433         return false;
1434     }
1435     return true;
1436 }
1437 
1438 
IsThreeFingersSwipe(std::shared_ptr<PointerEvent> pointerEvent)1439 bool JsInputMonitor::IsThreeFingersSwipe(std::shared_ptr<PointerEvent> pointerEvent)
1440 {
1441     CHKPF(pointerEvent);
1442     if (pointerEvent->GetSourceType() != PointerEvent::SOURCE_TYPE_TOUCHPAD ||
1443         pointerEvent->GetFingerCount() != THREE_FINGERS ||
1444         (pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_BEGIN &&
1445         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_UPDATE &&
1446         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_END)) {
1447         return false;
1448     }
1449     return true;
1450 }
1451 
IsFourFingersSwipe(std::shared_ptr<PointerEvent> pointerEvent)1452 bool JsInputMonitor::IsFourFingersSwipe(std::shared_ptr<PointerEvent> pointerEvent)
1453 {
1454     CHKPF(pointerEvent);
1455     if (pointerEvent->GetSourceType() != PointerEvent::SOURCE_TYPE_TOUCHPAD ||
1456         pointerEvent->GetFingerCount() != FOUR_FINGERS ||
1457         (pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_BEGIN &&
1458         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_UPDATE &&
1459         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_END)) {
1460         return false;
1461     }
1462     return true;
1463 }
1464 
IsThreeFingersTap(std::shared_ptr<PointerEvent> pointerEvent)1465 bool JsInputMonitor::IsThreeFingersTap(std::shared_ptr<PointerEvent> pointerEvent)
1466 {
1467     CHKPR(pointerEvent, ERROR_NULL_POINTER);
1468     if (pointerEvent->GetSourceType() != PointerEvent::SOURCE_TYPE_TOUCHPAD ||
1469         pointerEvent->GetFingerCount() != THREE_FINGERS ||
1470         (pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_TRIPTAP)) {
1471         return false;
1472     }
1473     return true;
1474 }
1475 
IsSwipeInward(std::shared_ptr<PointerEvent> pointerEvent)1476 bool JsInputMonitor::IsSwipeInward(std::shared_ptr<PointerEvent> pointerEvent)
1477 {
1478     CHKPF(pointerEvent);
1479     if (pointerEvent->GetSourceType() != PointerEvent::SOURCE_TYPE_TOUCHPAD) {
1480         MMI_HILOGE("failed to do swipe inward, wrong source: %{public}d ", pointerEvent->GetSourceType());
1481         return false;
1482     } else if (pointerEvent->GetPointerCount() != ONE_FINGERS) {
1483         MMI_HILOGE("failed to do swipe inward, more than one finger");
1484         return false;
1485     } else if (pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_DOWN &&
1486         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_MOVE &&
1487         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_UP &&
1488         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_CANCEL) {
1489         MMI_HILOGE("failed to do swipe inward, wrong action");
1490         return false;
1491     }
1492     return true;
1493 }
1494 
1495 #ifdef OHOS_BUILD_ENABLE_FINGERPRINT
IsFingerprint(std::shared_ptr<PointerEvent> pointerEvent)1496 bool JsInputMonitor::IsFingerprint(std::shared_ptr<PointerEvent> pointerEvent)
1497 {
1498     CHKPR(pointerEvent, ERROR_NULL_POINTER);
1499     if (pointerEvent->GetSourceType() == PointerEvent::SOURCE_TYPE_FINGERPRINT &&
1500         ((PointerEvent::POINTER_ACTION_FINGERPRINT_DOWN <= pointerEvent->GetPointerAction() &&
1501         pointerEvent->GetPointerAction() <= PointerEvent::POINTER_ACTION_FINGERPRINT_CLICK) ||
1502         pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_FINGERPRINT_CANCEL)) {
1503         return true;
1504     }
1505     MMI_HILOGD("not fingerprint event");
1506     return false;
1507 }
1508 #endif // OHOS_BUILD_ENABLE_FINGERPRINT
1509 } // namespace MMI
1510 } // namespace OHOS
1511