1 /*
2 * Copyright (c) 2021 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 "event_util.h"
17 #include "ace_log.h"
18 #include "async_task_manager.h"
19
20 namespace OHOS {
21 namespace ACELite {
22 constexpr char ATTR_TYPE[] = "type";
23 constexpr char ATTR_TARGET[] = "target";
24 constexpr char ATTR_CURRENT_TARGET[] = "currentTarget";
25 constexpr char ATTR_TIMESTAMP[] = "timestamp";
26 constexpr char ATTR_GLOBAL_X[] = "globalX";
27 constexpr char ATTR_GLOBAL_Y[] = "globalY";
28 constexpr char ATTR_DIRECTION[] = "direction";
29 constexpr char ATTR_DISTANCE[] = "distance";
30 constexpr char ATTR_DIRECTION_RIGHT[] = "right";
31 constexpr char ATTR_DIRECTION_LEFT[] = "left";
32 constexpr char ATTR_DIRECTION_UP[] = "up";
33 constexpr char ATTR_DIRECTION_DOWN[] = "down";
34 const char *EventUtil::EVENT_CLICK = "click";
35 const char *EventUtil::EVENT_LONGPRESS = "longpress";
36 const char *EventUtil::EVENT_SWIPE = "swipe";
37 const char *EventUtil::EVENT_TOUCH = "touch";
38
CallbackExecutor(void * data)39 void CallbackExecutor(void *data)
40 {
41 if (data == nullptr) {
42 HILOG_ERROR(HILOG_MODULE_ACE, "failed to execute the callback function of event.");
43 return;
44 }
45
46 auto *params = static_cast<CallbackParams *>(data);
47 if (!JSFunction::Is(params->fn)) {
48 HILOG_ERROR(HILOG_MODULE_ACE, "failed to execute the callback function of event.");
49 delete params;
50 params = nullptr;
51 return;
52 }
53 constexpr uint8_t argsLength = 1;
54 JSValue args[argsLength] = {params->arg};
55 JSRelease(JSFunction::Call(params->fn, params->vm, args, argsLength));
56 if (params->arg) {
57 JSRelease(params->arg);
58 }
59 delete params;
60 params = nullptr;
61 }
62
CreateEvent(const char * type,UIView & view,const Event & event)63 JSValue EventUtil::CreateEvent(const char *type, UIView &view, const Event &event)
64 {
65 // create a JAVASCRIPT plain object that is used as the input parameter of
66 // the callback function for click or longpress event.
67 JSValue arg = JSObject::Create();
68 // set the 'type' attribute value
69 JSObject::SetString(arg, ATTR_TYPE, type);
70 // set the 'target' attribute value
71 UIView *target = nullptr;
72 UIView *currentTarget = nullptr;
73 Point point = event.GetCurrentPos();
74 view.GetTargetView(point, ¤tTarget, &target);
75 JSObject::Set(arg, ATTR_TARGET, GetElementByUIView(target));
76 // set the 'currentTarget' attribute value
77 JSObject::Set(arg, ATTR_CURRENT_TARGET, GetElementByUIView(currentTarget));
78 // set the 'timestamp' attribute value
79 JSObject::SetNumber(arg, ATTR_TIMESTAMP, event.GetTimeStamp());
80 // set the 'globalX' attribute
81 JSObject::SetNumber(arg, ATTR_GLOBAL_X, point.x);
82 // set the 'globalY' attribute
83 JSObject::SetNumber(arg, ATTR_GLOBAL_Y, point.y);
84 return arg;
85 }
CreateSwipeEvent(UIView & view,const DragEvent & event)86 JSValue EventUtil::CreateSwipeEvent(UIView &view, const DragEvent &event)
87 {
88 // create a JAVASCRIPT plain object that is used as the input parameter of
89 // the event callback function.
90 JSValue arg = EventUtil::CreateEvent(EVENT_SWIPE, view, event);
91 int32_t distance = 0;
92 // set the 'direction' attribute for the input parameter of the swipe event callback function.
93 switch (event.GetDragDirection()) {
94 case DragEvent::DIRECTION_LEFT_TO_RIGHT: {
95 JSObject::SetString(arg, ATTR_DIRECTION, ATTR_DIRECTION_RIGHT);
96 distance = event.GetLastPoint().x - event.GetStartPoint().x;
97 break;
98 }
99 case DragEvent::DIRECTION_RIGHT_TO_LEFT: {
100 JSObject::SetString(arg, ATTR_DIRECTION, ATTR_DIRECTION_LEFT);
101 distance = event.GetStartPoint().x - event.GetLastPoint().x;
102 break;
103 }
104 case DragEvent::DIRECTION_TOP_TO_BOTTOM: {
105 JSObject::SetString(arg, ATTR_DIRECTION, ATTR_DIRECTION_DOWN);
106 distance = event.GetLastPoint().y - event.GetStartPoint().y;
107 break;
108 }
109 case DragEvent::DIRECTION_BOTTOM_TO_TOP: {
110 JSObject::SetString(arg, ATTR_DIRECTION, ATTR_DIRECTION_UP);
111 distance = event.GetStartPoint().y - event.GetLastPoint().y;
112 break;
113 }
114 default: {
115 HILOG_ERROR(HILOG_MODULE_ACE, "failed to set direction attribute for event argument.");
116 break;
117 }
118 }
119 JSObject::SetNumber(arg, ATTR_DISTANCE, distance);
120 return arg;
121 }
CreateTouchEvent(UIView & view,const DragEvent & event)122 JSValue EventUtil::CreateTouchEvent(UIView &view, const DragEvent &event)
123 {
124 // create a JAVASCRIPT plain object that is used as the input parameter of
125 // the event callback function.
126 JSValue arg = EventUtil::CreateEvent(EVENT_TOUCH, view, event);
127
128 return arg;
129 }
InvokeCallback(JSValue vm,JSValue callback,JSValue event,const void * context)130 void EventUtil::InvokeCallback(JSValue vm, JSValue callback, JSValue event, const void *context)
131 {
132 auto *params = new CallbackParams();
133 if (params == nullptr) {
134 HILOG_ERROR(HILOG_MODULE_ACE, "fail to invoke event callback.");
135 return;
136 }
137 params->vm = vm;
138 params->fn = callback;
139 params->arg = event;
140 // The views may be destroyed or recreated in conditional or list rendering.
141 // If we directly call the event callback function, the program will crash.
142 if (DISPATCH_FAILURE ==
143 AsyncTaskManager::GetInstance().Dispatch(CallbackExecutor, static_cast<void *>(params), context)) {
144 HILOG_ERROR(HILOG_MODULE_ACE, "EventUtil::InvokeCallback failed: Async task dispatch failure.");
145 delete params;
146 params = nullptr;
147 JSRelease(event);
148 }
149 }
GetElementByUIView(UIView * view)150 JSValue EventUtil::GetElementByUIView(UIView *view)
151 {
152 if (view == nullptr) {
153 HILOG_ERROR(HILOG_MODULE_ACE, "fail to get element by UI view.");
154 return JSUndefined::Create();
155 }
156 UIView::ViewExtraMsg *extraMsg = view->GetExtraMsg();
157 if (extraMsg == nullptr) {
158 HILOG_ERROR(HILOG_MODULE_ACE, "fail to get element by UI view.");
159 return JSUndefined::Create();
160 }
161 JSValue *elementPtr = reinterpret_cast<JSValue *>(extraMsg->elementPtr);
162 if (elementPtr == nullptr) {
163 HILOG_ERROR(HILOG_MODULE_ACE, "fail to get element by UI view.");
164 return JSUndefined::Create();
165 }
166 return *elementPtr;
167 }
168 } // namespace ACELite
169 } // namespace OHOS
170