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