• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     PRE_KEY = 10,
77 };
78 
79 enum InputKeyEventAction  {
80     /** Cancellation of a key action. */
81     KEY_ACTION_CANCEL = 0,
82     /** Pressing of a key. */
83     KEY_ACTION_DOWN = 1,
84     /** Release of a key. */
85     KEY_ACTION_UP = 2,
86 };
87 
88 std::map<std::string, int32_t> TO_GESTURE_TYPE = {
89     { "touch", TOUCH },
90     { "mouse", MOUSE },
91     { "pinch", PINCH },
92     { "threeFingersSwipe", THREE_FINGERS_SWIPE },
93     { "fourFingersSwipe", FOUR_FINGERS_SWIPE },
94     { "rotate", ROTATE },
95     { "threeFingersTap", THREE_FINGERS_TAP },
96     { "joystick", JOYSTICK},
97     { "fingerprint", FINGERPRINT},
98     { "swipeInward", SWIPE_INWARD},
99 };
100 
101 std::map<std::string, int32_t> TO_PRE_MONITOR_TYPE = {
102     { "keyPressed", PRE_KEY },
103 };
104 
105 struct MonitorInfo {
106     int32_t monitorId;
107     int32_t fingers;
108 };
109 
CleanData(MonitorInfo ** monitorInfo,uv_work_t ** work)110 void CleanData(MonitorInfo** monitorInfo, uv_work_t** work)
111 {
112     if (*monitorInfo != nullptr) {
113         delete *monitorInfo;
114         *monitorInfo = nullptr;
115     }
116     if (*work != nullptr) {
117         delete *work;
118         *work = nullptr;
119     }
120 }
121 } // namespace
122 
123 std::map<std::string, int32_t> TO_HANDLE_EVENT_TYPE = {
124     { "none", HANDLE_EVENT_TYPE_NONE },
125     { "key", HANDLE_EVENT_TYPE_KEY },
126     { "pointer", HANDLE_EVENT_TYPE_POINTER },
127     { "touch", HANDLE_EVENT_TYPE_TOUCH },
128     { "mouse", HANDLE_EVENT_TYPE_MOUSE },
129     { "pinch", HANDLE_EVENT_TYPE_PINCH },
130     { "threeFingersSwipe", HANDLE_EVENT_TYPE_THREEFINGERSSWIP },
131     { "fourFingersSwipe", HANDLE_EVENT_TYPE_FOURFINGERSSWIP },
132     { "swipeInward", HANDLE_EVENT_TYPE_SWIPEINWARD },
133     { "rotate", HANDLE_EVENT_TYPE_ROTATE },
134     { "threeFingersTap", HANDLE_EVENT_TYPE_THREEFINGERSTAP },
135     { "fingerprint", HANDLE_EVENT_TYPE_FINGERPRINT },
136 };
137 
138 std::map<std::string, int32_t> TO_HANDLE_PRE_EVENT_TYPE = {
139     { "keyPressed", HANDLE_EVENT_TYPE_PRE_KEY },
140 };
141 
Start(const std::string & typeName)142 int32_t InputMonitor::Start(const std::string &typeName)
143 {
144     CALL_DEBUG_ENTER;
145     std::lock_guard<std::mutex> guard(mutex_);
146     if (monitorId_ < 0) {
147         int32_t eventType = 0;
148         auto it = TO_HANDLE_EVENT_TYPE.find(typeName.c_str());
149         if (it != TO_HANDLE_EVENT_TYPE.end()) {
150             eventType = it->second;
151         }
152         auto iter = TO_HANDLE_PRE_EVENT_TYPE.find(typeName.c_str());
153         if (iter != TO_HANDLE_PRE_EVENT_TYPE.end()) {
154             eventType = iter->second;
155         }
156         monitorId_ = InputManager::GetInstance()->AddMonitor(shared_from_this(), eventType);
157     }
158     return monitorId_;
159 }
160 
Stop()161 void InputMonitor::Stop()
162 {
163     CALL_DEBUG_ENTER;
164     std::lock_guard<std::mutex> guard(mutex_);
165     if (monitorId_ < 0) {
166         MMI_HILOGE("Invalid values");
167         return;
168     }
169     auto iter = TO_HANDLE_PRE_EVENT_TYPE.find(typeName_.c_str());
170     if (iter != TO_HANDLE_PRE_EVENT_TYPE.end()) {
171         InputManager::GetInstance()->RemovePreMonitor(monitorId_);
172         monitorId_ = -1;
173         return;
174     }
175     InputManager::GetInstance()->RemoveMonitor(monitorId_);
176     monitorId_ = -1;
177     return;
178 }
179 
GetTypeName() const180 std::string InputMonitor::GetTypeName() const
181 {
182     return typeName_;
183 }
184 
SetTypeName(const std::string & typeName)185 void InputMonitor::SetTypeName(const std::string &typeName)
186 {
187     typeName_ = typeName;
188 }
189 
SetCallback(std::function<void (std::shared_ptr<PointerEvent>)> callback)190 void InputMonitor::SetCallback(std::function<void(std::shared_ptr<PointerEvent>)> callback)
191 {
192     std::lock_guard<std::mutex> guard(mutex_);
193     callback_ = callback;
194 }
195 
SetKeyCallback(std::function<void (std::shared_ptr<KeyEvent>)> keyCallback)196 void InputMonitor::SetKeyCallback(std::function<void(std::shared_ptr<KeyEvent>)> keyCallback)
197 {
198     std::lock_guard<std::mutex> guard(mutex_);
199     keyCallback_ = keyCallback;
200 }
201 
SetKeys(std::vector<int32_t> keys)202 void InputMonitor::SetKeys(std::vector<int32_t> keys)
203 {
204     keys_ = keys;
205 }
206 
OnInputEvent(std::shared_ptr<PointerEvent> pointerEvent) const207 void InputMonitor::OnInputEvent(std::shared_ptr<PointerEvent> pointerEvent) const
208 {
209     CALL_DEBUG_ENTER;
210     CHKPV(pointerEvent);
211     if (pointerEvent->GetSourceType() == PointerEvent::SOURCE_TYPE_MOUSE
212         && pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_MOVE) {
213         if (++flowCtrl_ < MOUSE_FLOW) {
214             return;
215         } else {
216             flowCtrl_ = 0;
217         }
218     }
219     std::function<void(std::shared_ptr<PointerEvent>)> callback;
220     {
221         std::lock_guard<std::mutex> guard(mutex_);
222         auto typeName = JS_INPUT_MONITOR_MGR.GetMonitorTypeName(id_, fingers_);
223         if (typeName == INVALID_TYPE_NAME) {
224             MMI_HILOGE("Failed to process pointer event, id:%{public}d", id_);
225             return;
226         }
227         if (pointerEvent->GetSourceType() == PointerEvent::SOURCE_TYPE_TOUCHSCREEN) {
228             if (typeName  != "touch") {
229                 return;
230             }
231             SetConsumeState(pointerEvent);
232         }
233         if (pointerEvent->GetSourceType() == PointerEvent::SOURCE_TYPE_MOUSE) {
234             if (typeName != "mouse" && typeName != "pinch" && typeName != "rotate") {
235                 return;
236             }
237             SetConsumeState(pointerEvent);
238         }
239         if (pointerEvent->GetSourceType() == PointerEvent::SOURCE_TYPE_TOUCHPAD) {
240             if (!IsGestureEvent(pointerEvent)) {
241                 return;
242             }
243         }
244         callback = callback_;
245     }
246     CHKPV(callback);
247     callback(pointerEvent);
248 }
249 
SetConsumeState(std::shared_ptr<PointerEvent> pointerEvent) const250 void InputMonitor::SetConsumeState(std::shared_ptr<PointerEvent> pointerEvent) const
251 {
252     CHKPV(pointerEvent);
253     if (pointerEvent->GetPointerIds().size() == 1) {
254         if (pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_DOWN) {
255             consumed_ = false;
256         }
257     }
258 }
259 
IsGestureEvent(std::shared_ptr<PointerEvent> pointerEvent) const260 bool InputMonitor::IsGestureEvent(std::shared_ptr<PointerEvent> pointerEvent) const
261 {
262     CHKPF(pointerEvent);
263     auto jsMonitor = JS_INPUT_MONITOR_MGR.GetMonitor(id_, fingers_);
264     CHKPF(jsMonitor);
265     auto ret = jsMonitor->GetTypeName();
266     if (ret != "pinch" && ret != "threeFingersSwipe" &&
267         ret != "fourFingersSwipe" && ret != "threeFingersTap" &&
268         ret != "swipeInward") {
269         return false;
270     }
271     if (pointerEvent->GetPointerIds().size() == 1) {
272         if (pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_AXIS_BEGIN ||
273             PointerEvent::POINTER_ACTION_SWIPE_BEGIN) {
274             consumed_ = false;
275         }
276     }
277     return true;
278 }
279 
SetId(int32_t id)280 void InputMonitor::SetId(int32_t id)
281 {
282     id_ = id;
283 }
284 
SetFingers(int32_t fingers)285 void InputMonitor::SetFingers(int32_t fingers)
286 {
287     fingers_ = fingers;
288 }
289 
SetHotRectArea(std::vector<Rect> hotRectArea)290 void InputMonitor::SetHotRectArea(std::vector<Rect> hotRectArea)
291 {
292     hotRectArea_ = hotRectArea;
293 }
294 
GetHotRectArea()295 std::vector<Rect> InputMonitor::GetHotRectArea()
296 {
297     return hotRectArea_;
298 }
299 
SetRectTotal(uint32_t rectTotal)300 void InputMonitor::SetRectTotal(uint32_t rectTotal)
301 {
302     rectTotal_ = rectTotal;
303 }
304 
GetRectTotal()305 uint32_t InputMonitor::GetRectTotal()
306 {
307     return rectTotal_;
308 }
309 
OnInputEvent(std::shared_ptr<KeyEvent> keyEvent) const310 void InputMonitor::OnInputEvent(std::shared_ptr<KeyEvent> keyEvent) const
311 {
312     CALL_DEBUG_ENTER;
313     CHKPV(keyEvent);
314     std::function<void(std::shared_ptr<KeyEvent>)> callback;
315     {
316         std::lock_guard<std::mutex> guard(mutex_);
317         auto typeName = JS_INPUT_MONITOR_MGR.GetPreMonitorTypeName(id_);
318         if (typeName == INVALID_TYPE_NAME || typeName != "keyPressed") {
319             MMI_HILOGE("Failed to process key event, id:%{public}d", id_);
320             return;
321         }
322         callback = keyCallback_;
323     }
324     CHKPV(callback);
325     callback(keyEvent);
326 }
327 
OnInputEvent(std::shared_ptr<AxisEvent> axisEvent) const328 void InputMonitor::OnInputEvent(std::shared_ptr<AxisEvent> axisEvent) const {}
329 
MarkConsumed(int32_t eventId)330 void InputMonitor::MarkConsumed(int32_t eventId)
331 {
332     std::lock_guard<std::mutex> guard(mutex_);
333     if (consumed_) {
334         MMI_HILOGD("The consumed_ is true");
335         return;
336     }
337     if (monitorId_ < 0) {
338         MMI_HILOGE("Invalid values");
339         return;
340     }
341     InputManager::GetInstance()->MarkConsumed(monitorId_, eventId);
342     consumed_ = true;
343 }
344 
JsInputMonitor(napi_env jsEnv,const std::string & typeName,std::vector<Rect> rectParam,int32_t rectTotal,napi_value callback,int32_t id,int32_t fingers)345 JsInputMonitor::JsInputMonitor(napi_env jsEnv, const std::string &typeName, std::vector<Rect> rectParam,
346     int32_t rectTotal, napi_value callback, int32_t id, int32_t fingers)
347     : monitor_(std::make_shared<InputMonitor>()), jsEnv_(jsEnv), typeName_(typeName), monitorId_(id),
348     fingers_(fingers)
349 {
350     SetCallback(callback);
351     CHKPV(monitor_);
352     monitor_->SetCallback([jsId = id, jsFingers = fingers](std::shared_ptr<PointerEvent> pointerEvent) {
353         JS_INPUT_MONITOR_MGR.OnPointerEventByMonitorId(jsId, jsFingers, pointerEvent);
354     });
355     monitor_->SetTypeName(typeName_);
356     monitor_->SetId(monitorId_);
357     monitor_->SetFingers(fingers_);
358     if (rectTotal != 0) {
359         monitor_->SetHotRectArea(rectParam);
360         monitor_->SetRectTotal(rectTotal);
361     }
362 }
363 
JsInputMonitor(napi_env jsEnv,const std::string & typeName,napi_value callback,int32_t id,int32_t fingers)364 JsInputMonitor::JsInputMonitor(napi_env jsEnv, const std::string &typeName,
365     napi_value callback, int32_t id, int32_t fingers)
366     : monitor_(std::make_shared<InputMonitor>()), jsEnv_(jsEnv), typeName_(typeName), monitorId_(id),
367     fingers_(fingers)
368 {
369     SetCallback(callback);
370     CHKPV(monitor_);
371     monitor_->SetCallback([jsId = id, jsFingers = fingers](std::shared_ptr<PointerEvent> pointerEvent) {
372         JS_INPUT_MONITOR_MGR.OnPointerEventByMonitorId(jsId, jsFingers, pointerEvent);
373     });
374     monitor_->SetTypeName(typeName_);
375     monitor_->SetId(monitorId_);
376     monitor_->SetFingers(fingers_);
377 }
378 
JsInputMonitor(napi_env jsEnv,const std::string & typeName,napi_value callback,int32_t id,std::vector<int32_t> keys)379 JsInputMonitor::JsInputMonitor(napi_env jsEnv, const std::string &typeName,
380     napi_value callback, int32_t id, std::vector<int32_t> keys)
381     : monitor_(std::make_shared<InputMonitor>()), jsEnv_(jsEnv), typeName_(typeName), monitorId_(id),
382     keys_(keys)
383 {
384     SetCallback(callback);
385     CHKPV(monitor_);
386     monitor_->SetKeyCallback([jsId = id](std::shared_ptr<KeyEvent> keyEvent) {
387         JS_INPUT_MONITOR_MGR.OnKeyEventByMonitorId(jsId, keyEvent);
388     });
389     monitor_->SetTypeName(typeName_);
390     monitor_->SetId(monitorId_);
391     monitor_->SetKeys(keys_);
392 }
393 
SetCallback(napi_value callback)394 void JsInputMonitor::SetCallback(napi_value callback)
395 {
396     if (receiver_ == nullptr && jsEnv_ != nullptr) {
397         uint32_t refCount = 1;
398         auto status = napi_create_reference(jsEnv_, callback, refCount, &receiver_);
399         if (status != napi_ok) {
400             THROWERR(jsEnv_, "napi_create_reference is failed");
401             return;
402         }
403     }
404 }
405 
MarkConsumed(int32_t eventId)406 void JsInputMonitor::MarkConsumed(int32_t eventId)
407 {
408     CHKPV(monitor_);
409     monitor_->MarkConsumed(eventId);
410 }
411 
IsMatch(napi_env jsEnv,napi_value callback)412 int32_t JsInputMonitor::IsMatch(napi_env jsEnv, napi_value callback)
413 {
414     CHKPR(callback, ERROR_NULL_POINTER);
415     if (jsEnv_ == jsEnv) {
416         napi_value handlerTemp = nullptr;
417         auto status = napi_get_reference_value(jsEnv_, receiver_, &handlerTemp);
418         if (status != napi_ok) {
419             THROWERR(jsEnv_, "napi_get_reference_value is failed");
420             return NAPI_ERR;
421         }
422         bool isEquals = false;
423         status = napi_strict_equals(jsEnv_, handlerTemp, callback, &isEquals);
424         if (status != napi_ok) {
425             THROWERR(jsEnv_, "napi_strict_equals is failed");
426             return NAPI_ERR;
427         }
428         if (isEquals) {
429             MMI_HILOGI("Js callback match success");
430             return RET_OK;
431         }
432         MMI_HILOGI("Js callback match failed");
433         return RET_ERR;
434     }
435     MMI_HILOGI("Js callback match failed");
436     return RET_ERR;
437 }
438 
IsMatch(napi_env jsEnv)439 int32_t JsInputMonitor::IsMatch(napi_env jsEnv)
440 {
441     if (jsEnv_ == jsEnv) {
442         MMI_HILOGI("Env match success");
443         return RET_OK;
444     }
445     MMI_HILOGI("Env match failed");
446     return RET_ERR;
447 }
448 
GetInputEventFunc(const std::shared_ptr<InputEvent> inputEvent)449 MapFun JsInputMonitor::GetInputEventFunc(const std::shared_ptr<InputEvent> inputEvent)
450 {
451     MapFun mapFunc;
452     mapFunc["id"] = [inputEvent] { return inputEvent->GetId(); };
453     mapFunc["deviceId"] = [inputEvent] { return inputEvent->GetDeviceId(); };
454     mapFunc["actionTime"] = [inputEvent] { return inputEvent->GetActionTime(); };
455     mapFunc["screenId"] = [inputEvent] { return inputEvent->GetTargetDisplayId(); };
456     mapFunc["windowId"] = [inputEvent] { return inputEvent->GetTargetWindowId(); };
457 
458     return mapFunc;
459 }
460 
SetInputEventProperty(const std::shared_ptr<InputEvent> inputEvent,napi_value result)461 int32_t JsInputMonitor::SetInputEventProperty(const std::shared_ptr<InputEvent> inputEvent, napi_value result)
462 {
463     CHKPR(inputEvent, ERROR_NULL_POINTER);
464     auto mapFun = GetInputEventFunc(inputEvent);
465     for (const auto &it : mapFun) {
466         auto setProperty = "Set" + it.first;
467         CHKRR(SetNameProperty(jsEnv_, result, it.first, it.second()), setProperty, RET_ERR);
468     }
469     return RET_OK;
470 }
471 
GetAction(int32_t action) const472 int32_t JsInputMonitor::GetAction(int32_t action) const
473 {
474     switch (action) {
475         case PointerEvent::POINTER_ACTION_CANCEL: {
476             return static_cast<int32_t>(JsTouchEvent::Action::CANCEL);
477         }
478         case PointerEvent::POINTER_ACTION_DOWN: {
479             return static_cast<int32_t>(JsTouchEvent::Action::DOWN);
480         }
481         case PointerEvent::POINTER_ACTION_MOVE: {
482             return static_cast<int32_t>(JsTouchEvent::Action::MOVE);
483         }
484         case PointerEvent::POINTER_ACTION_UP: {
485             return static_cast<int32_t>(JsTouchEvent::Action::UP);
486         }
487         case PointerEvent::POINTER_ACTION_PULL_DOWN: {
488             return static_cast<int32_t>(JsTouchEvent::Action::PULL_DOWN);
489         }
490         case PointerEvent::POINTER_ACTION_PULL_MOVE: {
491             return static_cast<int32_t>(JsTouchEvent::Action::PULL_MOVE);
492         }
493         case PointerEvent::POINTER_ACTION_PULL_UP: {
494             return static_cast<int32_t>(JsTouchEvent::Action::PULL_UP);
495         }
496         default: {
497             return RET_ERR;
498         }
499     }
500 }
501 
GetSourceType(int32_t sourceType) const502 int32_t JsInputMonitor::GetSourceType(int32_t sourceType) const
503 {
504     switch (sourceType) {
505         case PointerEvent::SOURCE_TYPE_TOUCHSCREEN: {
506             return static_cast<int32_t>(JsTouchEvent::SourceType::TOUCH_SCREEN);
507         }
508         case PointerEvent::SOURCE_TYPE_TOUCHPAD: {
509             return static_cast<int32_t>(JsTouchEvent::SourceType::TOUCH_PAD);
510         }
511         default: {
512             return RET_ERR;
513         }
514     }
515 }
516 
GetJsPointerItem(const PointerEvent::PointerItem & item,napi_value value) const517 int32_t JsInputMonitor::GetJsPointerItem(const PointerEvent::PointerItem &item, napi_value value) const
518 {
519     CHKRR(SetNameProperty(jsEnv_, value, "id", item.GetPointerId()), "Set id", RET_ERR);
520     CHKRR(SetNameProperty(jsEnv_, value, "pressedTime", item.GetDownTime()), "Set pressedTime", RET_ERR);
521     CHKRR(SetNameProperty(jsEnv_, value, "screenX", item.GetDisplayX()), "Set screenX", RET_ERR);
522     CHKRR(SetNameProperty(jsEnv_, value, "screenY", item.GetDisplayY()), "Set screenY", RET_ERR);
523     CHKRR(SetNameProperty(jsEnv_, value, "windowX", item.GetWindowX()), "Set windowX", RET_ERR);
524     CHKRR(SetNameProperty(jsEnv_, value, "windowY", item.GetWindowY()), "Set windowY", RET_ERR);
525     CHKRR(SetNameProperty(jsEnv_, value, "pressure", item.GetPressure()), "Set pressure", RET_ERR);
526     CHKRR(SetNameProperty(jsEnv_, value, "width", item.GetWidth()), "Set width", RET_ERR);
527     CHKRR(SetNameProperty(jsEnv_, value, "height", item.GetHeight()), "Set height", RET_ERR);
528     CHKRR(SetNameProperty(jsEnv_, value, "tiltX", item.GetTiltX()), "Set tiltX", RET_ERR);
529     CHKRR(SetNameProperty(jsEnv_, value, "tiltY", item.GetTiltY()), "Set tiltY", RET_ERR);
530     CHKRR(SetNameProperty(jsEnv_, value, "toolX", item.GetToolDisplayX()), "Set toolX", RET_ERR);
531     CHKRR(SetNameProperty(jsEnv_, value, "toolY", item.GetToolDisplayY()), "Set toolY", RET_ERR);
532     CHKRR(SetNameProperty(jsEnv_, value, "toolWidth", item.GetToolWidth()), "Set toolWidth", RET_ERR);
533     CHKRR(SetNameProperty(jsEnv_, value, "toolHeight", item.GetToolHeight()), "Set toolHeight", RET_ERR);
534     CHKRR(SetNameProperty(jsEnv_, value, "rawX", item.GetRawDx()), "Set rawX", RET_ERR);
535     CHKRR(SetNameProperty(jsEnv_, value, "rawY", item.GetRawDy()), "Set rawY", RET_ERR);
536     CHKRR(SetNameProperty(jsEnv_, value, "toolType", item.GetToolType()), "Set toolType", RET_ERR);
537     CHKRR(SetNameProperty(jsEnv_, value, "fixedDisplayX", item.GetFixedDisplayX()), "Set fixedDisplayX", RET_ERR);
538     CHKRR(SetNameProperty(jsEnv_, value, "fixedDisplayY", item.GetFixedDisplayY()), "Set fixedDisplayY", RET_ERR);
539     return RET_OK;
540 }
541 
TransformPointerEvent(const std::shared_ptr<PointerEvent> pointerEvent,napi_value result)542 int32_t JsInputMonitor::TransformPointerEvent(const std::shared_ptr<PointerEvent> pointerEvent, napi_value result)
543 {
544     CHKPR(pointerEvent, ERROR_NULL_POINTER);
545     if (SetInputEventProperty(pointerEvent, result) != RET_OK) {
546         MMI_HILOGE("Set inputEvent property failed");
547         return RET_ERR;
548     }
549     if (SetNameProperty(jsEnv_, result, "action", GetAction(pointerEvent->GetPointerAction())) != napi_ok) {
550         MMI_HILOGE("Set action property failed");
551         return RET_ERR;
552     }
553     if (SetNameProperty(jsEnv_, result, "sourceType", GetSourceType(pointerEvent->GetSourceType())) != napi_ok) {
554         MMI_HILOGE("Set sourceType property failed");
555         return RET_ERR;
556     }
557     napi_value pointers = nullptr;
558     CHKRR(napi_create_array(jsEnv_, &pointers), "napi_create_array is", RET_ERR);
559     std::vector<PointerEvent::PointerItem> pointerItems;
560     for (const auto &item : pointerEvent->GetPointerIds()) {
561         PointerEvent::PointerItem pointerItem;
562         if (!pointerEvent->GetPointerItem(item, pointerItem)) {
563             MMI_HILOGE("Get pointer item failed");
564             return RET_ERR;
565         }
566         pointerItems.push_back(pointerItem);
567     }
568     uint32_t index = 0;
569     for (const auto &it : pointerItems) {
570         napi_value element = nullptr;
571         CHKRR(napi_create_object(jsEnv_, &element), "napi_create_object is", RET_ERR);
572         if (GetJsPointerItem(it, element) != RET_OK) {
573             MMI_HILOGE("Transform pointerItem failed");
574             return RET_ERR;
575         }
576         CHKRR(napi_set_element(jsEnv_, pointers, index, element), "napi_set_element is", RET_ERR);
577         ++index;
578     }
579     CHKRR(SetNameProperty(jsEnv_, result, "touches", pointers), "Set touches", RET_ERR);
580     CHKRR(SetNameProperty(jsEnv_, result, "fixedMode", pointerEvent->GetFixedModeStr()), "Set fixedMode", RET_ERR);
581     return RET_OK;
582 }
583 
TransformPinchEvent(std::shared_ptr<PointerEvent> pointerEvent,napi_value result)584 int32_t JsInputMonitor::TransformPinchEvent(std::shared_ptr<PointerEvent> pointerEvent, napi_value result)
585 {
586     CHKPR(pointerEvent, ERROR_NULL_POINTER);
587     int32_t actionValue = GetPinchAction(pointerEvent->GetPointerAction());
588     if (actionValue == RET_ERR) {
589         MMI_HILOGE("Get action value failed");
590         return RET_ERR;
591     }
592     if (SetNameProperty(jsEnv_, result, "type", actionValue) != napi_ok) {
593         MMI_HILOGE("Set type property failed");
594         return RET_ERR;
595     }
596     if (SetNameProperty(jsEnv_, result, "scale",
597         pointerEvent->GetAxisValue(PointerEvent::AXIS_TYPE_PINCH)) != napi_ok) {
598         MMI_HILOGE("Set scale property failed");
599         return RET_ERR;
600     }
601     return RET_OK;
602 }
603 
TransformRotateEvent(std::shared_ptr<PointerEvent> pointerEvent,napi_value result)604 int32_t JsInputMonitor::TransformRotateEvent(std::shared_ptr<PointerEvent> pointerEvent, napi_value result)
605 {
606     CHKPR(pointerEvent, ERROR_NULL_POINTER);
607     int32_t actionValue = GetRotateAction(pointerEvent->GetPointerAction());
608     if (actionValue == RET_ERR) {
609         MMI_HILOGE("Get action value failed");
610         return RET_ERR;
611     }
612     if (SetNameProperty(jsEnv_, result, "type", actionValue) != napi_ok) {
613         MMI_HILOGE("Set type property failed");
614         return RET_ERR;
615     }
616     if (SetNameProperty(jsEnv_, result, "angle",
617         pointerEvent->GetAxisValue(PointerEvent::AXIS_TYPE_ROTATE)) != napi_ok) {
618         MMI_HILOGE("Set scale property failed");
619         return RET_ERR;
620     }
621     return RET_OK;
622 }
623 
GetPinchAction(int32_t action) const624 int32_t JsInputMonitor::GetPinchAction(int32_t action) const
625 {
626     switch (action) {
627         case PointerEvent::POINTER_ACTION_AXIS_BEGIN: {
628             return GESTURE_BEGIN;
629         }
630         case PointerEvent::POINTER_ACTION_AXIS_UPDATE: {
631             return GESTURE_UPDATE;
632         }
633         case PointerEvent::POINTER_ACTION_AXIS_END: {
634             return GESTURE_END;
635         }
636         default: {
637             MMI_HILOGD("Abnormal pointer action in pinch event");
638             return RET_ERR;
639         }
640     }
641 }
642 
GetRotateAction(int32_t action) const643 int32_t JsInputMonitor::GetRotateAction(int32_t action) const
644 {
645     switch (action) {
646         case PointerEvent::POINTER_ACTION_ROTATE_BEGIN: {
647             return GESTURE_BEGIN;
648         }
649         case PointerEvent::POINTER_ACTION_ROTATE_UPDATE: {
650             return GESTURE_UPDATE;
651         }
652         case PointerEvent::POINTER_ACTION_ROTATE_END: {
653             return GESTURE_END;
654         }
655         default: {
656             MMI_HILOGD("Abnormal pointer action in pinch event");
657             return RET_ERR;
658         }
659     }
660 }
661 
TransformSwipeEvent(std::shared_ptr<PointerEvent> pointerEvent,napi_value result)662 int32_t JsInputMonitor::TransformSwipeEvent(std::shared_ptr<PointerEvent> pointerEvent, napi_value result)
663 {
664     CHKPR(pointerEvent, ERROR_NULL_POINTER);
665     int32_t actionValue = GetSwipeAction(pointerEvent->GetPointerAction());
666     if (actionValue == RET_ERR) {
667         if (pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_UPDATE) {
668             MMI_HILOGE("Get action value failed");
669         }
670         return RET_ERR;
671     }
672     if (SetNameProperty(jsEnv_, result, "type", actionValue) != napi_ok) {
673         MMI_HILOGE("Set type property failed");
674         return RET_ERR;
675     }
676     PointerEvent::PointerItem pointeritem;
677     int32_t pointerId = 0;
678     if (INJECTION_EVENT_FLAG <= pointerEvent->GetPointerId()) {
679         pointerId = pointerEvent->GetPointerId();
680     }
681     if (!pointerEvent->GetPointerItem(pointerId, pointeritem)) {
682         MMI_HILOGE("Can't find this pointerItem");
683         return RET_ERR;
684     }
685     if (SetNameProperty(jsEnv_, result, "x", pointeritem.GetDisplayX()) != napi_ok) {
686         MMI_HILOGE("Set displayX property failed");
687         return RET_ERR;
688     }
689     if (SetNameProperty(jsEnv_, result, "y", pointeritem.GetDisplayY()) != napi_ok) {
690         MMI_HILOGE("Set displayY property failed");
691         return RET_ERR;
692     }
693     return RET_OK;
694 }
695 
GetSwipeAction(int32_t action) const696 int32_t JsInputMonitor::GetSwipeAction(int32_t action) const
697 {
698     switch (action) {
699         case PointerEvent::POINTER_ACTION_SWIPE_BEGIN: {
700             return GESTURE_BEGIN;
701         }
702         case PointerEvent::POINTER_ACTION_SWIPE_UPDATE: {
703             return GESTURE_UPDATE;
704         }
705         case PointerEvent::POINTER_ACTION_SWIPE_END: {
706             return GESTURE_END;
707         }
708         default: {
709             MMI_HILOGD("Abnormal pointer action in swipe event");
710             return RET_ERR;
711         }
712     }
713 }
714 
TransformMultiTapEvent(std::shared_ptr<PointerEvent> pointerEvent,napi_value result)715 int32_t JsInputMonitor::TransformMultiTapEvent(std::shared_ptr<PointerEvent> pointerEvent, napi_value result)
716 {
717     CHKPR(pointerEvent, ERROR_NULL_POINTER);
718     int32_t actionValue = GetMultiTapAction(pointerEvent->GetPointerAction());
719     if (actionValue == RET_ERR) {
720         MMI_HILOGE("Get action value failed");
721         return RET_ERR;
722     }
723     if (SetNameProperty(jsEnv_, result, "type", actionValue) != napi_ok) {
724         MMI_HILOGE("Set type property failed");
725         return RET_ERR;
726     }
727     return RET_OK;
728 }
729 
GetMultiTapAction(int32_t action) const730 int32_t JsInputMonitor::GetMultiTapAction(int32_t action) const
731 {
732     switch (action) {
733         case PointerEvent::POINTER_ACTION_TRIPTAP: {
734             return GESTURE_END;
735         }
736         default: {
737             MMI_HILOGD("Abnormal pointer action in multi tap event");
738             return RET_ERR;
739         }
740     }
741 }
742 
TransformSwipeInwardEvent(std::shared_ptr<PointerEvent> pointerEvent,napi_value result)743 int32_t JsInputMonitor::TransformSwipeInwardEvent(std::shared_ptr<PointerEvent> pointerEvent, napi_value result)
744 {
745     CHKPR(pointerEvent, ERROR_NULL_POINTER);
746     int32_t actionValue = pointerEvent->GetPointerAction();
747     if (actionValue == RET_ERR) {
748         MMI_HILOGE("Get action value failed");
749         return RET_ERR;
750     }
751     int32_t actionTypeTemp = actionValue;
752     switch (actionTypeTemp) {
753         case PointerEvent::POINTER_ACTION_DOWN: {
754             actionValue = GESTURE_BEGIN;
755             break;
756         }
757         case PointerEvent::POINTER_ACTION_MOVE: {
758             actionValue = GESTURE_UPDATE;
759             break;
760         }
761         case PointerEvent::POINTER_ACTION_UP:
762         case PointerEvent::POINTER_ACTION_CANCEL: {
763             actionValue = GESTURE_END;
764             break;
765         }
766         default: {
767             MMI_HILOGE("Abnormal pointer action in swipe event");
768             return RET_ERR;
769         }
770     }
771     if (SetNameProperty(jsEnv_, result, "type", actionValue) != napi_ok) {
772         MMI_HILOGE("Set type property failed");
773         return RET_ERR;
774     }
775     PointerEvent::PointerItem pointeritem;
776     int32_t pointerId = 0;
777     if (!pointerEvent->GetPointerItem(pointerId, pointeritem)) {
778         MMI_HILOGE("Can't find this pointerItem");
779         return RET_ERR;
780     }
781     if (SetNameProperty(jsEnv_, result, "x", pointeritem.GetDisplayX()) != napi_ok) {
782         MMI_HILOGE("Set displayX property failed");
783         return RET_ERR;
784     }
785     if (SetNameProperty(jsEnv_, result, "y", pointeritem.GetDisplayY()) != napi_ok) {
786         MMI_HILOGE("Set displayY property failed");
787         return RET_ERR;
788     }
789     return RET_OK;
790 }
791 
792 #ifdef OHOS_BUILD_ENABLE_FINGERPRINT
GetFingerprintAction(int32_t action) const793 int32_t JsInputMonitor::GetFingerprintAction(int32_t action) const
794 {
795     MMI_HILOGD("GetFingerprintAction enter, action is %{public}d", action);
796     switch (action) {
797         case PointerEvent::POINTER_ACTION_FINGERPRINT_DOWN: {
798             return FINGERPRINT_DOWN;
799         }
800         case PointerEvent::POINTER_ACTION_FINGERPRINT_UP: {
801             return FINGERPRINT_UP;
802         }
803         case PointerEvent::POINTER_ACTION_FINGERPRINT_SLIDE: {
804             return FINGERPRINT_SLIDE;
805         }
806         case PointerEvent::POINTER_ACTION_FINGERPRINT_RETOUCH: {
807             return FINGERPRINT_RETOUCH;
808         }
809         case PointerEvent::POINTER_ACTION_FINGERPRINT_CLICK: {
810             return FINGERPRINT_CLICK;
811         }
812         case PointerEvent::POINTER_ACTION_FINGERPRINT_CANCEL: {
813             return FINGERPRINT_CANCEL;
814         }
815         default: {
816             MMI_HILOGE("wrong action is %{public}d", action);
817             return RET_ERR;
818         }
819     }
820 }
821 #endif // OHOS_BUILD_ENABLE_FINGERPRINT
822 
GetFuns(const std::shared_ptr<PointerEvent> pointerEvent,const PointerEvent::PointerItem & item)823 MapFun JsInputMonitor::GetFuns(const std::shared_ptr<PointerEvent> pointerEvent, const PointerEvent::PointerItem& item)
824 {
825     MapFun mapFun;
826     mapFun["actionTime"] = [pointerEvent] { return pointerEvent->GetActionTime(); };
827     mapFun["screenId"] = [pointerEvent] { return pointerEvent->GetTargetDisplayId(); };
828     mapFun["windowId"] = [pointerEvent] { return pointerEvent->GetTargetWindowId(); };
829     mapFun["deviceId"] = [item] { return item.GetDeviceId(); };
830     mapFun["windowX"] = [item] { return item.GetWindowX(); };
831     mapFun["windowY"] = [item] { return item.GetWindowY(); };
832     mapFun["screenX"] = [item] { return item.GetDisplayX(); };
833     mapFun["screenY"] = [item] { return item.GetDisplayY(); };
834     mapFun["rawDeltaX"] = [item] { return item.GetRawDx(); };
835     mapFun["rawDeltaY"] = [item] { return item.GetRawDy(); };
836     return mapFun;
837 }
838 
SetMouseProperty(const std::shared_ptr<PointerEvent> pointerEvent,const PointerEvent::PointerItem & item,napi_value result)839 bool JsInputMonitor::SetMouseProperty(const std::shared_ptr<PointerEvent> pointerEvent,
840     const PointerEvent::PointerItem& item, napi_value result)
841 {
842     CHKPF(pointerEvent);
843     int32_t buttonId = pointerEvent->GetButtonId();
844     if (buttonId == PointerEvent::MOUSE_BUTTON_MIDDLE) {
845         buttonId = MIDDLE;
846     } else if (buttonId == PointerEvent::MOUSE_BUTTON_RIGHT) {
847         buttonId = RIGHT;
848     }
849     if (SetNameProperty(jsEnv_, result, "button", buttonId) != napi_ok) {
850         THROWERR(jsEnv_, "Set property failed");
851         return false;
852     }
853 
854     auto mapFun = GetFuns(pointerEvent, item);
855     for (const auto &it : mapFun) {
856         if (SetNameProperty(jsEnv_, result, it.first, it.second()) != napi_ok) {
857             THROWERR(jsEnv_, "Set property failed");
858             return false;
859         }
860     }
861     return true;
862 }
863 
GetAxesValue(const std::shared_ptr<PointerEvent> pointerEvent,napi_value element)864 bool JsInputMonitor::GetAxesValue(const std::shared_ptr<PointerEvent> pointerEvent, napi_value element)
865 {
866     CALL_DEBUG_ENTER;
867     CHKPF(pointerEvent);
868     double axisValue = -1.0;
869     int32_t axis = -1;
870     if (pointerEvent->HasAxis(PointerEvent::AXIS_TYPE_SCROLL_VERTICAL)) {
871         axisValue = pointerEvent->GetAxisValue(PointerEvent::AXIS_TYPE_SCROLL_VERTICAL);
872         axis = AXIS_TYPE_SCROLL_VERTICAL;
873     }
874     if (pointerEvent->HasAxis(PointerEvent::AXIS_TYPE_SCROLL_HORIZONTAL)) {
875         axisValue = pointerEvent->GetAxisValue(PointerEvent::AXIS_TYPE_SCROLL_HORIZONTAL);
876         axis = AXIS_TYPE_SCROLL_HORIZONTAL;
877     }
878     if (pointerEvent->HasAxis(PointerEvent::AXIS_TYPE_PINCH)) {
879         axisValue = pointerEvent->GetAxisValue(PointerEvent::AXIS_TYPE_PINCH);
880         axis = AXIS_TYPE_PINCH;
881     }
882     if (SetNameProperty(jsEnv_, element, "axis", axis) != napi_ok) {
883         THROWERR(jsEnv_, "Set property of axis failed");
884         return false;
885     }
886     if (SetNameProperty(jsEnv_, element, "value", axisValue) != napi_ok) {
887         THROWERR(jsEnv_, "Set property of value failed");
888         return false;
889     }
890     return true;
891 }
892 
GetMousePointerItem(const std::shared_ptr<PointerEvent> pointerEvent,napi_value result)893 int32_t JsInputMonitor::GetMousePointerItem(const std::shared_ptr<PointerEvent> pointerEvent, napi_value result)
894 {
895     CALL_DEBUG_ENTER;
896     CHKPR(pointerEvent, ERROR_NULL_POINTER);
897     napi_value axes = nullptr;
898     napi_status status = napi_create_array(jsEnv_, &axes);
899     if (status != napi_ok || axes == nullptr) {
900         THROWERR(jsEnv_, "napi_create_array is failed");
901         return RET_ERR;
902     }
903     uint32_t index = 0;
904     int32_t currentPointerId = pointerEvent->GetPointerId();
905     std::vector<int32_t> pointerIds { pointerEvent->GetPointerIds() };
906     for (const auto& pointerId : pointerIds) {
907         if (pointerId == currentPointerId) {
908             PointerEvent::PointerItem item;
909             if (!pointerEvent->GetPointerItem(pointerId, item)) {
910                 MMI_HILOGE("Invalid pointer:%{public}d", pointerId);
911                 return RET_ERR;
912             }
913             if (SetNameProperty(jsEnv_, result, "id", currentPointerId) != napi_ok) {
914                 THROWERR(jsEnv_, "Set property of id failed");
915                 return false;
916             }
917             if (!SetMouseProperty(pointerEvent, item, result)) {
918                 MMI_HILOGE("Set property of mouse failed");
919                 return RET_ERR;
920             }
921         }
922         napi_value element = nullptr;
923         if (napi_create_object(jsEnv_, &element) != napi_ok) {
924             THROWERR(jsEnv_, "napi_create_object is failed");
925             return false;
926         }
927         if (!GetAxesValue(pointerEvent, element)) {
928             THROWERR(jsEnv_, "Get axesValue failed");
929             return RET_ERR;
930         }
931         status = napi_set_element(jsEnv_, axes, index, element);
932         if (status != napi_ok) {
933             THROWERR(jsEnv_, "Napi set element in axes failed");
934             return RET_ERR;
935         }
936         ++index;
937     }
938     if (SetNameProperty(jsEnv_, result, "axes", axes) != napi_ok) {
939         THROWERR(jsEnv_, "Set property of axes failed");
940         return RET_ERR;
941     }
942     return RET_OK;
943 }
944 
GetPressedButtons(const std::set<int32_t> & pressedButtons,napi_value result)945 bool JsInputMonitor::GetPressedButtons(const std::set<int32_t>& pressedButtons, napi_value result)
946 {
947     CALL_DEBUG_ENTER;
948     napi_value value = nullptr;
949     napi_status status = napi_create_array(jsEnv_, &value);
950     if (status != napi_ok || value == nullptr) {
951         THROWERR(jsEnv_, "napi_create_array is failed");
952         return false;
953     }
954     uint32_t index = 0;
955     for (const auto &item : pressedButtons) {
956         int32_t buttonId = item;
957         if (buttonId == PointerEvent::MOUSE_BUTTON_MIDDLE) {
958             buttonId = MIDDLE;
959         } else if (buttonId == PointerEvent::MOUSE_BUTTON_RIGHT) {
960             buttonId = RIGHT;
961         }
962         napi_value element = nullptr;
963         if (napi_create_int32(jsEnv_, buttonId, &element) != napi_ok) {
964             THROWERR(jsEnv_, "Napi create int32 failed");
965             return false;
966         }
967         status = napi_set_element(jsEnv_, value, index, element);
968         if (status != napi_ok) {
969             THROWERR(jsEnv_, "Napi set element failed");
970             return false;
971         }
972         ++index;
973     }
974     if (SetNameProperty(jsEnv_, result, "pressedButtons", value) != napi_ok) {
975         THROWERR(jsEnv_, "Set property of pressedButtons failed");
976         return false;
977     }
978     return true;
979 }
980 
GetPressedKeys(const std::vector<int32_t> & pressedKeys,napi_value result)981 bool JsInputMonitor::GetPressedKeys(const std::vector<int32_t>& pressedKeys, napi_value result)
982 {
983     CALL_DEBUG_ENTER;
984     napi_value value = nullptr;
985     napi_status status = napi_create_array(jsEnv_, &value);
986     if (status != napi_ok || value == nullptr) {
987         THROWERR(jsEnv_, "napi_create_array is failed");
988         return false;
989     }
990     uint32_t index = 0;
991     for (const auto &it : pressedKeys) {
992         napi_value element = nullptr;
993         if (napi_create_int32(jsEnv_, it, &element) != napi_ok) {
994             THROWERR(jsEnv_, "Napi create int32 failed");
995             return false;
996         }
997         status = napi_set_element(jsEnv_, value, index, element);
998         if (status != napi_ok) {
999             THROWERR(jsEnv_, "Napi set element failed");
1000             return false;
1001         }
1002         ++index;
1003     }
1004     if (SetNameProperty(jsEnv_, result, "pressedKeys", value) != napi_ok) {
1005         THROWERR(jsEnv_, "Set property of pressedKeys failed");
1006         return false;
1007     }
1008     return true;
1009 }
1010 
HasKeyCode(const std::vector<int32_t> & pressedKeys,int32_t keyCode)1011 bool JsInputMonitor::HasKeyCode(const std::vector<int32_t>& pressedKeys, int32_t keyCode)
1012 {
1013     return std::find(pressedKeys.begin(), pressedKeys.end(), keyCode) != pressedKeys.end();
1014 }
1015 
GetPressedKey(const std::vector<int32_t> & pressedKeys,napi_value result)1016 bool JsInputMonitor::GetPressedKey(const std::vector<int32_t>& pressedKeys, napi_value result)
1017 {
1018     CALL_DEBUG_ENTER;
1019     bool isExists = HasKeyCode(pressedKeys, KeyEvent::KEYCODE_CTRL_LEFT)
1020         || HasKeyCode(pressedKeys, KeyEvent::KEYCODE_CTRL_RIGHT);
1021     if (SetNameProperty(jsEnv_, result, "ctrlKey", isExists) != napi_ok) {
1022         THROWERR(jsEnv_, "Set ctrlKey with failed");
1023         return false;
1024     }
1025     isExists = HasKeyCode(pressedKeys, KeyEvent::KEYCODE_ALT_LEFT)
1026         || HasKeyCode(pressedKeys, KeyEvent::KEYCODE_ALT_RIGHT);
1027     if (SetNameProperty(jsEnv_, result, "altKey", isExists) != napi_ok) {
1028         THROWERR(jsEnv_, "Set altKey failed");
1029         return false;
1030     }
1031     isExists = HasKeyCode(pressedKeys, KeyEvent::KEYCODE_SHIFT_LEFT)
1032         || HasKeyCode(pressedKeys, KeyEvent::KEYCODE_SHIFT_RIGHT);
1033     if (SetNameProperty(jsEnv_, result, "shiftKey", isExists) != napi_ok) {
1034         THROWERR(jsEnv_, "Set shiftKey failed");
1035         return false;
1036     }
1037     isExists = HasKeyCode(pressedKeys, KeyEvent::KEYCODE_META_LEFT)
1038         || HasKeyCode(pressedKeys, KeyEvent::KEYCODE_META_RIGHT);
1039     if (SetNameProperty(jsEnv_, result, "logoKey", isExists) != napi_ok) {
1040         THROWERR(jsEnv_, "Set logoKey failed");
1041         return false;
1042     }
1043     isExists = HasKeyCode(pressedKeys, KeyEvent::KEYCODE_FN);
1044     if (SetNameProperty(jsEnv_, result, "fnKey", isExists) != napi_ok) {
1045         THROWERR(jsEnv_, "Set fnKey failed");
1046         return false;
1047     }
1048     return true;
1049 }
1050 
TransformTsActionValue(int32_t pointerAction)1051 int32_t JsInputMonitor::TransformTsActionValue(int32_t pointerAction)
1052 {
1053     switch (pointerAction) {
1054         case PointerEvent::POINTER_ACTION_CANCEL: {
1055             return CANCEL;
1056         }
1057         case PointerEvent::POINTER_ACTION_MOVE:
1058         case PointerEvent::POINTER_ACTION_PULL_MOVE: {
1059             return MOVE;
1060         }
1061         case PointerEvent::POINTER_ACTION_BUTTON_DOWN:
1062         case PointerEvent::POINTER_ACTION_PULL_DOWN: {
1063             return BUTTON_DOWN;
1064         }
1065         case PointerEvent::POINTER_ACTION_BUTTON_UP:
1066         case PointerEvent::POINTER_ACTION_PULL_UP: {
1067             return BUTTON_UP;
1068         }
1069         case PointerEvent::POINTER_ACTION_AXIS_BEGIN: {
1070             return AXIS_BEGIN;
1071         }
1072         case PointerEvent::POINTER_ACTION_AXIS_UPDATE: {
1073             return AXIS_UPDATE;
1074         }
1075         case PointerEvent::POINTER_ACTION_AXIS_END: {
1076             return AXIS_END;
1077         }
1078         default: {
1079             MMI_HILOGD("Abnormal pointer action");
1080             return RET_ERR;
1081         }
1082     }
1083 }
1084 
TransformMousePointerEvent(std::shared_ptr<PointerEvent> pointerEvent,napi_value result)1085 int32_t JsInputMonitor::TransformMousePointerEvent(std::shared_ptr<PointerEvent> pointerEvent, napi_value result)
1086 {
1087     CALL_DEBUG_ENTER;
1088     CHKPR(pointerEvent, ERROR_NULL_POINTER);
1089     int32_t actionValue = TransformTsActionValue(pointerEvent->GetPointerAction());
1090     if (actionValue == RET_ERR) {
1091         MMI_HILOGD("Transform action value failed");
1092         return RET_ERR;
1093     }
1094     if (SetNameProperty(jsEnv_, result, "action", actionValue) != napi_ok) {
1095         MMI_HILOGE("Set property of action failed");
1096         return RET_ERR;
1097     }
1098     std::vector<int32_t> pressedKeys = pointerEvent->GetPressedKeys();
1099     if (!GetPressedKeys(pressedKeys, result)) {
1100         MMI_HILOGE("Get pressedButtons failed");
1101         return RET_ERR;
1102     }
1103     if (!GetPressedKey(pressedKeys, result)) {
1104         MMI_HILOGE("Get singlePressedKey failed");
1105         return RET_ERR;
1106     }
1107     if (GetMousePointerItem(pointerEvent, result) != RET_OK) {
1108         MMI_HILOGE("Get item of mousePointer failed");
1109         return RET_ERR;
1110     }
1111     std::set<int32_t> pressedButtons = pointerEvent->GetPressedButtons();
1112     if (!GetPressedButtons(pressedButtons, result)) {
1113         MMI_HILOGE("Get pressedKeys failed");
1114         return RET_ERR;
1115     }
1116     return RET_OK;
1117 }
1118 
1119 #ifdef OHOS_BUILD_ENABLE_FINGERPRINT
TransformFingerprintEvent(const std::shared_ptr<PointerEvent> pointerEvent,napi_value result)1120 int32_t JsInputMonitor::TransformFingerprintEvent(const std::shared_ptr<PointerEvent> pointerEvent, napi_value result)
1121 {
1122     CALL_DEBUG_ENTER;
1123     CHKPR(pointerEvent, ERROR_NULL_POINTER);
1124     int32_t actionValue = GetFingerprintAction(pointerEvent->GetPointerAction());
1125     if (actionValue == RET_ERR) {
1126         MMI_HILOGW("Get action value failed");
1127         return RET_ERR;
1128     }
1129     if (SetNameProperty(jsEnv_, result, "action", actionValue) != napi_ok) {
1130         MMI_HILOGW("Set name property failed");
1131         return RET_ERR;
1132     }
1133     if (SetNameProperty(jsEnv_, result, "distanceX", pointerEvent->GetFingerprintDistanceX()) != napi_ok) {
1134         MMI_HILOGW("Set distanceX property failed");
1135         return RET_ERR;
1136     }
1137     if (SetNameProperty(jsEnv_, result, "distanceY", pointerEvent->GetFingerprintDistanceY()) != napi_ok) {
1138         MMI_HILOGW("Set distanceY property failed");
1139         return RET_ERR;
1140     }
1141     MMI_HILOGD("jsfingerprint key:%{public}d, x:%{public}f, y:%{public}f", actionValue,
1142         pointerEvent->GetFingerprintDistanceX(), pointerEvent->GetFingerprintDistanceY());
1143     return RET_OK;
1144 }
1145 #endif // OHOS_BUILD_ENABLE_FINGERPRINT
1146 
Start(const std::string & typeName)1147 int32_t JsInputMonitor::Start(const std::string &typeName)
1148 {
1149     CALL_DEBUG_ENTER;
1150     CHKPF(monitor_);
1151     if (isMonitoring_) {
1152         MMI_HILOGW("Js is monitoring");
1153         return RET_OK;
1154     }
1155     int32_t ret = monitor_->Start(typeName);
1156     if (ret >= 0) {
1157         isMonitoring_ = true;
1158     }
1159     return ret;
1160 }
1161 
~JsInputMonitor()1162 JsInputMonitor::~JsInputMonitor()
1163 {
1164     CALL_DEBUG_ENTER;
1165     if (isMonitoring_) {
1166         isMonitoring_ = false;
1167         if (monitor_ != nullptr) {
1168             monitor_->Stop();
1169         }
1170     }
1171     uint32_t refCount = 0;
1172     auto status = napi_reference_unref(jsEnv_, receiver_, &refCount);
1173     if (status != napi_ok) {
1174         THROWERR(jsEnv_, "napi_reference_unref is failed");
1175         return;
1176     }
1177 }
1178 
Stop()1179 void JsInputMonitor::Stop()
1180 {
1181     CALL_DEBUG_ENTER;
1182     CHKPV(monitor_);
1183     if (isMonitoring_) {
1184         isMonitoring_ = false;
1185         if (monitor_ != nullptr) {
1186             monitor_->Stop();
1187         }
1188     }
1189 }
1190 
GetId() const1191 int32_t JsInputMonitor::GetId() const
1192 {
1193     return monitorId_;
1194 }
1195 
GetFingers() const1196 int32_t JsInputMonitor::GetFingers() const
1197 {
1198     return fingers_;
1199 }
1200 
GetTypeName() const1201 std::string JsInputMonitor::GetTypeName() const
1202 {
1203     return typeName_;
1204 }
1205 
OnPointerEvent(std::shared_ptr<PointerEvent> pointerEvent)1206 void JsInputMonitor::OnPointerEvent(std::shared_ptr<PointerEvent> pointerEvent)
1207 {
1208     CALL_DEBUG_ENTER;
1209     if (!isMonitoring_) {
1210         MMI_HILOGE("Js monitor stop");
1211         return;
1212     }
1213     CHKPV(monitor_);
1214     CHKPV(pointerEvent);
1215     {
1216         std::lock_guard<std::mutex> guard(mutex_);
1217         if (!evQueue_.empty()) {
1218             if (IsBeginAndEnd(pointerEvent)) {
1219                 std::queue<std::shared_ptr<PointerEvent>> tmp;
1220                 std::swap(evQueue_, tmp);
1221             }
1222         }
1223         evQueue_.push(pointerEvent);
1224     }
1225 
1226     if (!evQueue_.empty()) {
1227         uv_work_t *work = new (std::nothrow) uv_work_t;
1228         CHKPV(work);
1229         MonitorInfo *monitorInfo = new (std::nothrow) MonitorInfo();
1230         if (monitorInfo == nullptr) {
1231             MMI_HILOGE("monitorInfo is nullptr");
1232             delete work;
1233             work = nullptr;
1234             return;
1235         }
1236         monitorInfo->monitorId = monitorId_;
1237         monitorInfo->fingers = fingers_;
1238         work->data = monitorInfo;
1239         uv_loop_s *loop = nullptr;
1240         auto status = napi_get_uv_event_loop(jsEnv_, &loop);
1241         if (status != napi_ok) {
1242             THROWERR(jsEnv_, "napi_get_uv_event_loop is failed");
1243             CleanData(&monitorInfo, &work);
1244             return;
1245         }
1246         int32_t ret = uv_queue_work_with_qos(
1247             loop, work,
1248             [](uv_work_t *work) {
1249                 MMI_HILOGD("uv_queue_work callback function is called");
1250             },
1251             &JsInputMonitor::JsCallback, uv_qos_user_initiated);
1252         if (ret != 0) {
1253             MMI_HILOGE("add uv_queue failed, ret is %{public}d", ret);
1254             CleanData(&monitorInfo, &work);
1255         }
1256     }
1257 }
1258 
IsBeginAndEnd(std::shared_ptr<PointerEvent> pointerEvent)1259 bool JsInputMonitor::IsBeginAndEnd(std::shared_ptr<PointerEvent> pointerEvent)
1260 {
1261     CHKPF(pointerEvent);
1262     bool res = pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_DOWN ||
1263         pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_UP ||
1264         pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_SWIPE_BEGIN ||
1265         pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_SWIPE_END;
1266     return res;
1267 }
1268 
JsCallback(uv_work_t * work,int32_t status)1269 void JsInputMonitor::JsCallback(uv_work_t *work, int32_t status)
1270 {
1271     CALL_DEBUG_ENTER;
1272     CHKPV(work);
1273     auto temp = static_cast<MonitorInfo*>(work->data);
1274     delete work;
1275     work = nullptr;
1276     auto jsMonitor { JS_INPUT_MONITOR_MGR.GetMonitor(temp->monitorId, temp->fingers) };
1277     CHKPV(jsMonitor);
1278     jsMonitor->OnPointerEventInJsThread(jsMonitor->GetTypeName(), temp->fingers);
1279     delete temp;
1280     temp = nullptr;
1281 }
1282 
OnPointerEventInJsThread(const std::string & typeName,int32_t fingers)1283 void JsInputMonitor::OnPointerEventInJsThread(const std::string &typeName, int32_t fingers)
1284 {
1285     CALL_DEBUG_ENTER;
1286     {
1287         std::lock_guard<std::mutex> guard(mutex_);
1288         if (!isMonitoring_) {
1289             MMI_HILOGE("Js monitor stop");
1290             return;
1291         }
1292         CHKPV(jsEnv_);
1293         CHKPV(receiver_);
1294         while (!evQueue_.empty()) {
1295             if (!isMonitoring_) {
1296                 MMI_HILOGE("Js monitor stop handle callback");
1297                 break;
1298             }
1299             napi_handle_scope scope = nullptr;
1300             napi_open_handle_scope(jsEnv_, &scope);
1301             CHKPV(scope);
1302             auto pointerEvent = evQueue_.front();
1303             if (pointerEvent == nullptr) {
1304                 MMI_HILOGE("scope is nullptr");
1305                 napi_close_handle_scope(jsEnv_, scope);
1306                 continue;
1307             }
1308             evQueue_.pop();
1309             pointerQueue_.push(pointerEvent);
1310             napi_close_handle_scope(jsEnv_, scope);
1311         }
1312     }
1313 
1314     std::lock_guard<std::mutex> guard(resourcesmutex_);
1315     while (!pointerQueue_.empty()) {
1316         auto pointerEventItem = pointerQueue_.front();
1317         pointerQueue_.pop();
1318         napi_handle_scope scope = nullptr;
1319         napi_open_handle_scope(jsEnv_, &scope);
1320         CHKPV(scope);
1321         LogTracer lt(pointerEventItem->GetId(), pointerEventItem->GetEventType(), pointerEventItem->GetPointerAction());
1322         napi_value napiPointer = nullptr;
1323         auto status = napi_create_object(jsEnv_, &napiPointer);
1324         if (status != napi_ok) {
1325             pointerEventItem->MarkProcessed();
1326             napi_close_handle_scope(jsEnv_, scope);
1327             break;
1328         }
1329         auto ret = RET_ERR;
1330         switch (TO_GESTURE_TYPE[typeName.c_str()]) {
1331             case TypeName::TOUCH: {
1332                 ret = TransformPointerEvent(pointerEventItem, napiPointer);
1333                 break;
1334             }
1335             case TypeName::MOUSE: {
1336                 ret = TransformMousePointerEvent(pointerEventItem, napiPointer);
1337                 break;
1338             }
1339             case TypeName::ROTATE: {
1340                 if (!IsRotate(pointerEventItem)) {
1341                     napi_close_handle_scope(jsEnv_, scope);
1342                     continue;
1343                 }
1344                 ret = TransformRotateEvent(pointerEventItem, napiPointer);
1345                 break;
1346             }
1347             case TypeName::PINCH: {
1348                 if (!IsPinch(pointerEventItem, fingers)) {
1349                     napi_close_handle_scope(jsEnv_, scope);
1350                     continue;
1351                 }
1352                 ret = TransformPinchEvent(pointerEventItem, napiPointer);
1353                 break;
1354             }
1355             case TypeName::THREE_FINGERS_SWIPE: {
1356                 if (!IsThreeFingersSwipe(pointerEventItem)) {
1357                     napi_close_handle_scope(jsEnv_, scope);
1358                     continue;
1359                 }
1360                 ret = TransformSwipeEvent(pointerEventItem, napiPointer);
1361                 break;
1362             }
1363             case TypeName::FOUR_FINGERS_SWIPE: {
1364                 if (!IsFourFingersSwipe(pointerEventItem)) {
1365                     napi_close_handle_scope(jsEnv_, scope);
1366                     continue;
1367                 }
1368                 ret = TransformSwipeEvent(pointerEventItem, napiPointer);
1369                 break;
1370             }
1371             case TypeName::THREE_FINGERS_TAP: {
1372                 if (!IsThreeFingersTap(pointerEventItem)) {
1373                 }
1374                 ret = TransformMultiTapEvent(pointerEventItem, napiPointer);
1375                 break;
1376             }
1377             case TypeName::SWIPE_INWARD: {
1378                 if (!IsSwipeInward(pointerEventItem)) {
1379                     napi_close_handle_scope(jsEnv_, scope);
1380                     continue;
1381                 }
1382                 ret = TransformSwipeInwardEvent(pointerEventItem, napiPointer);
1383                 break;
1384             }
1385 #ifdef OHOS_BUILD_ENABLE_FINGERPRINT
1386             case TypeName::FINGERPRINT: {
1387                 if (!IsFingerprint(pointerEventItem)) {
1388                     napi_close_handle_scope(jsEnv_, scope);
1389                     continue;
1390                 }
1391                 ret = TransformFingerprintEvent(pointerEventItem, napiPointer);
1392                 break;
1393             }
1394 #endif // OHOS_BUILD_ENABLE_FINGERPRINT
1395             default: {
1396                 MMI_HILOGE("This event is invalid");
1397                 break;
1398             }
1399         }
1400         bool checkFlag = ret != RET_OK || napiPointer == nullptr;
1401         if (checkFlag) {
1402             napi_close_handle_scope(jsEnv_, scope);
1403             break;
1404         }
1405         napi_value callback = nullptr;
1406         status = napi_get_reference_value(jsEnv_, receiver_, &callback);
1407         if (status != napi_ok) {
1408             pointerEventItem->MarkProcessed();
1409             napi_close_handle_scope(jsEnv_, scope);
1410             break;
1411         }
1412         napi_value result = nullptr;
1413         if (monitor_->GetRectTotal() == 0
1414             || IsLocaledWithinRect(jsEnv_, napiPointer, monitor_->GetRectTotal(), monitor_->GetHotRectArea())) {
1415             status = napi_call_function(jsEnv_, nullptr, callback, 1, &napiPointer, &result);
1416             if (status != napi_ok) {
1417                 pointerEventItem->MarkProcessed();
1418                 napi_close_handle_scope(jsEnv_, scope);
1419                 break;
1420             }
1421         }
1422         bool typeNameFlag = typeName == "touch" || typeName == "pinch" || typeName == "threeFingersSwipe" ||
1423             typeName == "fourFingersSwipe" || typeName == "rotate" || typeName == "threeFingersTap" ||
1424             typeName == "fingerprint" || typeName == "swipeInward";
1425         if (typeNameFlag) {
1426             if (pointerEventItem->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_UPDATE &&
1427                 pointerEventItem->GetPointerAction() != PointerEvent::POINTER_ACTION_PULL_MOVE) {
1428                 MMI_HILOGI("pointer:%{public}d,pointerAction:%{public}s", pointerEventItem->GetPointerId(),
1429                     pointerEventItem->DumpPointerAction());
1430             }
1431             bool retValue = false;
1432             status = napi_get_value_bool(jsEnv_, result, &retValue);
1433             if (status != napi_ok) {
1434                 napi_close_handle_scope(jsEnv_, scope);
1435                 return;
1436             }
1437             CheckConsumed(retValue, pointerEventItem);
1438         }
1439         napi_close_handle_scope(jsEnv_, scope);
1440     }
1441 }
1442 
IsLocaledWithinRect(napi_env env,napi_value napiPointer,uint32_t rectTotal,std::vector<Rect> hotRectArea)1443 bool JsInputMonitor::IsLocaledWithinRect(napi_env env, napi_value napiPointer,
1444     uint32_t rectTotal, std::vector<Rect> hotRectArea)
1445 {
1446     napi_value xProperty;
1447     CHKRF(napi_get_named_property(env, napiPointer, "screenX", &xProperty), GET_NAMED_PROPERTY);
1448     CHKPF(xProperty);
1449     int32_t xInt { 0 };
1450     CHKRF(napi_get_value_int32(env, xProperty, &xInt), GET_VALUE_INT32);
1451 
1452     napi_value yProperty;
1453     CHKRF(napi_get_named_property(env, napiPointer, "screenY", &yProperty), GET_NAMED_PROPERTY);
1454     CHKPF(yProperty);
1455     int32_t yInt { 0 };
1456     CHKRF(napi_get_value_int32(env, yProperty, &yInt), GET_VALUE_INT32);
1457 
1458     for (uint32_t i = 0; i < rectTotal; i++) {
1459         int32_t hotAreaX = hotRectArea.at(i).x;
1460         int32_t hotAreaY = hotRectArea.at(i).y;
1461         int32_t hotAreaWidth = hotRectArea.at(i).width;
1462         int32_t hotAreaHeight = hotRectArea.at(i).height;
1463         if ((xInt >= hotAreaX) && (xInt <= hotAreaX + hotAreaWidth)
1464             && (yInt >= hotAreaY) && (yInt <= hotAreaY + hotAreaHeight)) {
1465             return true;
1466         }
1467     }
1468     return false;
1469 }
1470 
CheckConsumed(bool retValue,std::shared_ptr<PointerEvent> pointerEvent)1471 void JsInputMonitor::CheckConsumed(bool retValue, std::shared_ptr<PointerEvent> pointerEvent)
1472 {
1473     CALL_DEBUG_ENTER;
1474     CHKPV(pointerEvent);
1475     if (retValue) {
1476         auto eventId = pointerEvent->GetId();
1477         MarkConsumed(eventId);
1478     }
1479 }
1480 
IsPinch(std::shared_ptr<PointerEvent> pointerEvent,const int32_t fingers)1481 bool JsInputMonitor::IsPinch(std::shared_ptr<PointerEvent> pointerEvent, const int32_t fingers)
1482 {
1483     CHKPF(pointerEvent);
1484     if ((fingers > 0 && ((pointerEvent->GetSourceType() != PointerEvent::SOURCE_TYPE_MOUSE &&
1485         pointerEvent->GetSourceType() != PointerEvent::SOURCE_TYPE_TOUCHPAD) ||
1486         pointerEvent->GetFingerCount() != fingers)) ||
1487         (fingers == 0 && (pointerEvent->GetSourceType() != PointerEvent::SOURCE_TYPE_TOUCHPAD ||
1488         pointerEvent->GetFingerCount() < THREE_FINGERS))) {
1489         return false;
1490     }
1491     if ((pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_AXIS_BEGIN &&
1492         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_AXIS_UPDATE &&
1493         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_AXIS_END)) {
1494         return false;
1495     }
1496     return true;
1497 }
1498 
IsRotate(std::shared_ptr<PointerEvent> pointerEvent)1499 bool JsInputMonitor::IsRotate(std::shared_ptr<PointerEvent> pointerEvent)
1500 {
1501     CHKPF(pointerEvent);
1502     if (pointerEvent->GetSourceType() != PointerEvent::SOURCE_TYPE_MOUSE ||
1503         (pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_ROTATE_BEGIN &&
1504         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_ROTATE_UPDATE &&
1505         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_ROTATE_END)) {
1506         return false;
1507     }
1508     return true;
1509 }
1510 
1511 
IsThreeFingersSwipe(std::shared_ptr<PointerEvent> pointerEvent)1512 bool JsInputMonitor::IsThreeFingersSwipe(std::shared_ptr<PointerEvent> pointerEvent)
1513 {
1514     CHKPF(pointerEvent);
1515     if (pointerEvent->GetSourceType() != PointerEvent::SOURCE_TYPE_TOUCHPAD ||
1516         pointerEvent->GetFingerCount() != THREE_FINGERS ||
1517         (pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_BEGIN &&
1518         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_UPDATE &&
1519         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_END)) {
1520         return false;
1521     }
1522     return true;
1523 }
1524 
IsFourFingersSwipe(std::shared_ptr<PointerEvent> pointerEvent)1525 bool JsInputMonitor::IsFourFingersSwipe(std::shared_ptr<PointerEvent> pointerEvent)
1526 {
1527     CHKPF(pointerEvent);
1528     if (pointerEvent->GetSourceType() != PointerEvent::SOURCE_TYPE_TOUCHPAD ||
1529         pointerEvent->GetFingerCount() != FOUR_FINGERS ||
1530         (pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_BEGIN &&
1531         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_UPDATE &&
1532         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_END)) {
1533         return false;
1534     }
1535     return true;
1536 }
1537 
IsThreeFingersTap(std::shared_ptr<PointerEvent> pointerEvent)1538 bool JsInputMonitor::IsThreeFingersTap(std::shared_ptr<PointerEvent> pointerEvent)
1539 {
1540     CHKPR(pointerEvent, ERROR_NULL_POINTER);
1541     if (pointerEvent->GetSourceType() != PointerEvent::SOURCE_TYPE_TOUCHPAD ||
1542         pointerEvent->GetFingerCount() != THREE_FINGERS ||
1543         (pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_TRIPTAP)) {
1544         return false;
1545     }
1546     return true;
1547 }
1548 
IsSwipeInward(std::shared_ptr<PointerEvent> pointerEvent)1549 bool JsInputMonitor::IsSwipeInward(std::shared_ptr<PointerEvent> pointerEvent)
1550 {
1551     CHKPF(pointerEvent);
1552     if (pointerEvent->GetSourceType() != PointerEvent::SOURCE_TYPE_TOUCHPAD) {
1553         MMI_HILOGE("failed to do swipe inward, wrong source: %{public}d ", pointerEvent->GetSourceType());
1554         return false;
1555     } else if (pointerEvent->GetPointerCount() != ONE_FINGERS) {
1556         MMI_HILOGE("failed to do swipe inward, more than one finger");
1557         return false;
1558     } else if (pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_DOWN &&
1559         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_MOVE &&
1560         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_UP &&
1561         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_CANCEL) {
1562         MMI_HILOGE("failed to do swipe inward, wrong action");
1563         return false;
1564     }
1565     return true;
1566 }
1567 
1568 #ifdef OHOS_BUILD_ENABLE_FINGERPRINT
IsFingerprint(std::shared_ptr<PointerEvent> pointerEvent)1569 bool JsInputMonitor::IsFingerprint(std::shared_ptr<PointerEvent> pointerEvent)
1570 {
1571     CHKPR(pointerEvent, ERROR_NULL_POINTER);
1572     if (pointerEvent->GetSourceType() == PointerEvent::SOURCE_TYPE_FINGERPRINT &&
1573         ((PointerEvent::POINTER_ACTION_FINGERPRINT_DOWN <= pointerEvent->GetPointerAction() &&
1574         pointerEvent->GetPointerAction() <= PointerEvent::POINTER_ACTION_FINGERPRINT_CLICK) ||
1575         pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_FINGERPRINT_CANCEL)) {
1576         return true;
1577     }
1578     MMI_HILOGD("not fingerprint event");
1579     return false;
1580 }
1581 #endif // OHOS_BUILD_ENABLE_FINGERPRINT
1582 
OnKeyEvent(const std::shared_ptr<KeyEvent> keyEvent)1583 void JsInputMonitor::OnKeyEvent(const std::shared_ptr<KeyEvent> keyEvent)
1584 {
1585     CALL_DEBUG_ENTER;
1586     if (!isMonitoring_) {
1587         MMI_HILOGE("Js monitor stop");
1588         return;
1589     }
1590     CHKPV(monitor_);
1591     CHKPV(keyEvent);
1592     {
1593         std::lock_guard<std::mutex> guard(mutex_);
1594         preEvQueue_.push(keyEvent);
1595     }
1596     if (!preEvQueue_.empty()) {
1597         uv_work_t *work = new (std::nothrow) uv_work_t;
1598         CHKPV(work);
1599         MonitorInfo *monitorInfo = new (std::nothrow) MonitorInfo();
1600         if (monitorInfo == nullptr) {
1601             MMI_HILOGE("The monitorInfo is nullptr");
1602             delete work;
1603             work = nullptr;
1604             return;
1605         }
1606         monitorInfo->monitorId = monitorId_;
1607         work->data = monitorInfo;
1608         uv_loop_s *loop = nullptr;
1609         auto status = napi_get_uv_event_loop(jsEnv_, &loop);
1610         if (status != napi_ok) {
1611             THROWERR(jsEnv_, "napi_get_uv_event_loop is failed");
1612             CleanData(&monitorInfo, &work);
1613             return;
1614         }
1615         int32_t ret = uv_queue_work_with_qos(
1616             loop,
1617             work,
1618             [](uv_work_t *work) { MMI_HILOGD("uv_queue_work callback function is called"); },
1619             &JsInputMonitor::JsPreCallback,
1620             uv_qos_user_initiated);
1621         if (ret != 0) {
1622             MMI_HILOGE("Add uv_queue failed, ret is %{public}d", ret);
1623             CleanData(&monitorInfo, &work);
1624         }
1625     }
1626 }
1627 
JsPreCallback(uv_work_t * work,int32_t status)1628 void JsInputMonitor::JsPreCallback(uv_work_t *work, int32_t status)
1629 {
1630     CALL_DEBUG_ENTER;
1631     CHKPV(work);
1632     auto temp = static_cast<MonitorInfo*>(work->data);
1633     delete work;
1634     work = nullptr;
1635     auto jsMonitor { JS_INPUT_MONITOR_MGR.GetPreMonitor(temp->monitorId) };
1636     CHKPV(jsMonitor);
1637     jsMonitor->OnKeyEventInJsThread(jsMonitor->GetTypeName());
1638     delete temp;
1639     temp = nullptr;
1640 }
1641 
OnKeyEventInJsThread(const std::string & typeName)1642 void JsInputMonitor::OnKeyEventInJsThread(const std::string &typeName)
1643 {
1644     CALL_DEBUG_ENTER;
1645     std::lock_guard<std::mutex> guard(resourcesmutex_);
1646     if (!isMonitoring_) {
1647         MMI_HILOGE("Js monitor stop");
1648         return;
1649     }
1650     CHKPV(jsEnv_);
1651     CHKPV(receiver_);
1652     while (!preEvQueue_.empty()) {
1653         auto keyEventItem = preEvQueue_.front();
1654         preEvQueue_.pop();
1655         napi_handle_scope scope = nullptr;
1656         napi_open_handle_scope(jsEnv_, &scope);
1657         CHKPV(scope);
1658         napi_value napiKeyEvent = nullptr;
1659         auto status = napi_create_object(jsEnv_, &napiKeyEvent);
1660         if (status != napi_ok) {
1661             napi_close_handle_scope(jsEnv_, scope);
1662             break;
1663         }
1664         auto ret = RET_ERR;
1665         switch (TO_PRE_MONITOR_TYPE[typeName.c_str()]) {
1666             case TypeName::PRE_KEY: {
1667                 ret = TransformKeyEvent(keyEventItem, napiKeyEvent);
1668                 break;
1669             }
1670             default: {
1671                 MMI_HILOGE("This event is invalid");
1672                 break;
1673             }
1674         }
1675         bool checkFlag = ret != RET_OK || napiKeyEvent == nullptr;
1676         if (checkFlag) {
1677             napi_close_handle_scope(jsEnv_, scope);
1678             break;
1679         }
1680         napi_value callback = nullptr;
1681         status = napi_get_reference_value(jsEnv_, receiver_, &callback);
1682         if (status != napi_ok) {
1683             napi_close_handle_scope(jsEnv_, scope);
1684             break;
1685         }
1686         napi_value result = nullptr;
1687         if (napi_call_function(jsEnv_, nullptr, callback, 1, &napiKeyEvent, &result) != napi_ok) {
1688             napi_close_handle_scope(jsEnv_, scope);
1689             return;
1690         }
1691         napi_close_handle_scope(jsEnv_, scope);
1692     }
1693 }
1694 
TransformKeyEvent(const std::shared_ptr<KeyEvent> keyEvent,napi_value result)1695 int32_t JsInputMonitor::TransformKeyEvent(const std::shared_ptr<KeyEvent> keyEvent, napi_value result)
1696 {
1697     CHKPR(keyEvent, ERROR_NULL_POINTER);
1698     // set inputEvent
1699     if (SetInputEventProperty(keyEvent, result) != RET_OK) {
1700         MMI_HILOGE("Set inputEvent property failed");
1701         return RET_ERR;
1702     }
1703 
1704     // set action
1705     if (SetNameProperty(jsEnv_, result, "action", GetKeyEventAction(keyEvent->GetKeyAction())) != napi_ok) {
1706         MMI_HILOGE("Set action property failed");
1707         return RET_ERR;
1708     }
1709 
1710     // set key
1711     napi_value keyObject = nullptr;
1712     CHKRR(napi_create_object(jsEnv_, &keyObject), "napi_create_object is ", RET_ERR);
1713     std::optional<KeyEvent::KeyItem> keyItem = keyEvent->GetKeyItem();
1714     if (!keyItem) {
1715         MMI_HILOGE("The keyItem is nullopt");
1716         return false;
1717     }
1718     GetJsKeyItem(keyItem, keyObject);
1719     if (SetNameProperty(jsEnv_, result, "key", keyObject) != napi_ok) {
1720         MMI_HILOGE("Set key property failed");
1721         return RET_ERR;
1722     }
1723 
1724     // set unicodeChar
1725     if (SetNameProperty(jsEnv_, result, "unicodeChar", keyItem->GetUnicode()) != napi_ok) {
1726         MMI_HILOGE("Set unicodeChar property failed");
1727         return RET_ERR;
1728     }
1729 
1730     std::vector<int32_t> pressedKeys = keyEvent->GetPressedKeys();
1731     // set keys
1732     if (!GetKeys(keyEvent, pressedKeys, result)) {
1733         MMI_HILOGE("Get pressedKeys failed");
1734         return RET_ERR;
1735     }
1736 
1737     if (!GetPressedKey(pressedKeys, result)) {
1738         MMI_HILOGE("Get single pressedKey failed");
1739         return RET_ERR;
1740     }
1741 
1742     if (!GetFunctionKeyState(keyEvent, result)) {
1743         MMI_HILOGE("Get FunctionKey failed");
1744         return RET_ERR;
1745     }
1746 
1747     return RET_OK;
1748 }
1749 
GetKeyEventAction(int32_t action) const1750 int32_t JsInputMonitor::GetKeyEventAction(int32_t action) const
1751 {
1752     if (KeyEvent::KEY_ACTION_CANCEL == action) {
1753         return InputKeyEventAction ::KEY_ACTION_CANCEL;
1754     } else if (KeyEvent::KEY_ACTION_DOWN == action) {
1755         return InputKeyEventAction ::KEY_ACTION_DOWN;
1756     } else if (KeyEvent::KEY_ACTION_UP == action) {
1757         return InputKeyEventAction ::KEY_ACTION_UP;
1758     } else {
1759         return RET_ERR;
1760     }
1761 }
1762 
GetJsKeyItem(const std::optional<MMI::KeyEvent::KeyItem> keyItem,napi_value value) const1763 int32_t JsInputMonitor::GetJsKeyItem(const std::optional<MMI::KeyEvent::KeyItem> keyItem, napi_value value) const
1764 {
1765     CALL_DEBUG_ENTER;
1766     CHKRR(SetNameProperty(jsEnv_, value, "code", keyItem->GetKeyCode()), "Set code", RET_ERR);
1767     CHKRR(SetNameProperty(jsEnv_, value, "pressedTime", keyItem->GetDownTime()), "Set pressedTime", RET_ERR);
1768     CHKRR(SetNameProperty(jsEnv_, value, "deviceId", keyItem->GetDeviceId()), "Set deviceId", RET_ERR);
1769     return RET_OK;
1770 }
1771 
GetFunctionKeyState(const std::shared_ptr<KeyEvent> keyEvent,napi_value result) const1772 bool JsInputMonitor::GetFunctionKeyState(const std::shared_ptr<KeyEvent> keyEvent, napi_value result) const
1773 {
1774     CALL_DEBUG_ENTER;
1775     // set capsLock
1776     napi_value capsLockValue = nullptr;
1777     napi_status status =
1778         napi_get_boolean(jsEnv_, keyEvent->GetFunctionKey(KeyEvent::CAPS_LOCK_FUNCTION_KEY), &capsLockValue);
1779     if (status != napi_ok) {
1780         return false;
1781     }
1782     if (SetNameProperty(jsEnv_, result, "capsLock", capsLockValue) != napi_ok) {
1783         MMI_HILOGE("Set capsLock property failed");
1784         return false;
1785     }
1786 
1787     // set numLock
1788     napi_value numLockValue = nullptr;
1789     if (napi_get_boolean(jsEnv_, keyEvent->GetFunctionKey(KeyEvent::NUM_LOCK_FUNCTION_KEY), &numLockValue) != napi_ok) {
1790         return false;
1791     }
1792     if (SetNameProperty(jsEnv_, result, "numLock", numLockValue) != napi_ok) {
1793         MMI_HILOGE("Set numLock property failed");
1794         return false;
1795     }
1796 
1797     // set scrollLock
1798     napi_value scrollLockValue = nullptr;
1799     if (napi_get_boolean(jsEnv_, keyEvent->GetFunctionKey(KeyEvent::SCROLL_LOCK_FUNCTION_KEY), &scrollLockValue) !=
1800         napi_ok) {
1801         return false;
1802     }
1803     if (SetNameProperty(jsEnv_, result, "scrollLock", scrollLockValue) != napi_ok) {
1804         MMI_HILOGE("Set scrollLock property failed");
1805         return false;
1806     }
1807     return true;
1808 }
1809 
GetKeys(const std::shared_ptr<KeyEvent> keyEvent,const std::vector<int32_t> & pressedKeys,napi_value result) const1810 bool JsInputMonitor::GetKeys(
1811     const std::shared_ptr<KeyEvent> keyEvent, const std::vector<int32_t> &pressedKeys, napi_value result) const
1812 {
1813     CALL_DEBUG_ENTER;
1814     napi_value keysArray = nullptr;
1815     napi_status status = napi_create_array(jsEnv_, &keysArray);
1816     if (status != napi_ok || keysArray == nullptr) {
1817         THROWERR(jsEnv_, "napi_create_array is failed");
1818         return false;
1819     }
1820     uint32_t index = 0;
1821     for (const auto &pressedKeyCode : pressedKeys) {
1822         napi_value element = nullptr;
1823         if (napi_create_object(jsEnv_, &element) != napi_ok) {
1824             THROWERR(jsEnv_, "Napi create element failed");
1825             return false;
1826         }
1827         std::optional<KeyEvent::KeyItem> pressedKeyItem = keyEvent->GetKeyItem(pressedKeyCode);
1828         if (!pressedKeyItem) {
1829             MMI_HILOGE("The pressedKeyItem is nullopt");
1830             return false;
1831         }
1832         GetJsKeyItem(pressedKeyItem, element);
1833 
1834         if (napi_set_element(jsEnv_, keysArray, index, element)) {
1835             THROWERR(jsEnv_, "Napi set element failed");
1836             return false;
1837         }
1838         ++index;
1839     }
1840     if (SetNameProperty(jsEnv_, result, "keys", keysArray) != napi_ok) {
1841         MMI_HILOGE("Set keys property failed");
1842         return false;
1843     }
1844     return true;
1845 }
1846 } // namespace MMI
1847 } // namespace OHOS
1848