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 JSRelease(params->arg);
57 delete params;
58 params = nullptr;
59 }
60
CreateEvent(const char * type,UIView & view,const Event & event)61 JSValue EventUtil::CreateEvent(const char *type, UIView &view, const Event &event)
62 {
63 // create a JAVASCRIPT plain object that is used as the input parameter of
64 // the callback function for click or longpress event.
65 JSValue arg = JSObject::Create();
66 // set the 'type' attribute value
67 JSObject::SetString(arg, ATTR_TYPE, type);
68 // set the 'target' attribute value
69 UIView *target = nullptr;
70 UIView *currentTarget = nullptr;
71 Point point = event.GetCurrentPos();
72 view.GetTargetView(point, ¤tTarget, &target);
73 JSObject::Set(arg, ATTR_TARGET, GetElementByUIView(target));
74 // set the 'currentTarget' attribute value
75 JSObject::Set(arg, ATTR_CURRENT_TARGET, GetElementByUIView(currentTarget));
76 // set the 'timestamp' attribute value
77 JSObject::SetNumber(arg, ATTR_TIMESTAMP, event.GetTimeStamp());
78 // set the 'globalX' attribute
79 JSObject::SetNumber(arg, ATTR_GLOBAL_X, point.x);
80 // set the 'globalY' attribute
81 JSObject::SetNumber(arg, ATTR_GLOBAL_Y, point.y);
82 return arg;
83 }
CreateSwipeEvent(UIView & view,const DragEvent & event)84 JSValue EventUtil::CreateSwipeEvent(UIView &view, const DragEvent &event)
85 {
86 // create a JAVASCRIPT plain object that is used as the input parameter of
87 // the event callback function.
88 JSValue arg = EventUtil::CreateEvent(EVENT_SWIPE, view, event);
89 int32_t distance = 0;
90 // set the 'direction' attribute for the input parameter of the swipe event callback function.
91 switch (event.GetDragDirection()) {
92 case DragEvent::DIRECTION_LEFT_TO_RIGHT: {
93 JSObject::SetString(arg, ATTR_DIRECTION, ATTR_DIRECTION_RIGHT);
94 distance = event.GetLastPoint().x - event.GetStartPoint().x;
95 break;
96 }
97 case DragEvent::DIRECTION_RIGHT_TO_LEFT: {
98 JSObject::SetString(arg, ATTR_DIRECTION, ATTR_DIRECTION_LEFT);
99 distance = event.GetStartPoint().x - event.GetLastPoint().x;
100 break;
101 }
102 case DragEvent::DIRECTION_TOP_TO_BOTTOM: {
103 JSObject::SetString(arg, ATTR_DIRECTION, ATTR_DIRECTION_DOWN);
104 distance = event.GetLastPoint().y - event.GetStartPoint().y;
105 break;
106 }
107 case DragEvent::DIRECTION_BOTTOM_TO_TOP: {
108 JSObject::SetString(arg, ATTR_DIRECTION, ATTR_DIRECTION_UP);
109 distance = event.GetStartPoint().y - event.GetLastPoint().y;
110 break;
111 }
112 default: {
113 HILOG_ERROR(HILOG_MODULE_ACE, "failed to set direction attribute for event argument.");
114 break;
115 }
116 }
117 JSObject::SetNumber(arg, ATTR_DISTANCE, distance);
118 return arg;
119 }
CreateTouchEvent(UIView & view,const DragEvent & event)120 JSValue EventUtil::CreateTouchEvent(UIView &view, const DragEvent &event)
121 {
122 // create a JAVASCRIPT plain object that is used as the input parameter of
123 // the event callback function.
124 JSValue arg = EventUtil::CreateEvent(EVENT_TOUCH, view, event);
125
126 return arg;
127 }
InvokeCallback(JSValue vm,JSValue callback,JSValue event,const void * context)128 void EventUtil::InvokeCallback(JSValue vm, JSValue callback, JSValue event, const void *context)
129 {
130 auto *params = new CallbackParams();
131 if (params == nullptr) {
132 HILOG_ERROR(HILOG_MODULE_ACE, "fail to invoke event callback.");
133 return;
134 }
135 params->vm = vm;
136 params->fn = callback;
137 params->arg = event;
138 // The views may be destroyed or recreated in conditional or list rendering.
139 // If we directly call the event callback function, the program will crash.
140 if (DISPATCH_FAILURE ==
141 AsyncTaskManager::GetInstance().Dispatch(CallbackExecutor, static_cast<void *>(params), context)) {
142 HILOG_ERROR(HILOG_MODULE_ACE, "EventUtil::InvokeCallback failed: Async task dispatch failure.");
143 delete params;
144 params = nullptr;
145 JSRelease(event);
146 }
147 }
GetElementByUIView(UIView * view)148 JSValue EventUtil::GetElementByUIView(UIView *view)
149 {
150 if (view == nullptr) {
151 HILOG_ERROR(HILOG_MODULE_ACE, "fail to get element by UI view.");
152 return JSUndefined::Create();
153 }
154 UIView::ViewExtraMsg *extraMsg = view->GetExtraMsg();
155 if (extraMsg == nullptr) {
156 HILOG_ERROR(HILOG_MODULE_ACE, "fail to get element by UI view.");
157 return JSUndefined::Create();
158 }
159 JSValue *elementPtr = reinterpret_cast<JSValue *>(extraMsg->elementPtr);
160 if (elementPtr == nullptr) {
161 HILOG_ERROR(HILOG_MODULE_ACE, "fail to get element by UI view.");
162 return JSUndefined::Create();
163 }
164 return *elementPtr;
165 }
166 } // namespace ACELite
167 } // namespace OHOS
168