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, &currentTarget, &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