1 /*
2 * Copyright (c) 2021-2022 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 "adapter/ohos/entrance/flutter_ace_view.h"
17
18 #include <EGL/egl.h>
19 #include <algorithm>
20 #include <fstream>
21
22 #include "flutter/fml/synchronization/waitable_event.h"
23 #include "flutter/shell/common/shell_io_manager.h"
24 #include "flutter/shell/gpu/gpu_surface_gl_delegate.h"
25 #include "key_event.h"
26 #include "pointer_event.h"
27
28 #include "base/utils/utils.h"
29
30 #if defined(ENABLE_ROSEN_BACKEND) and !defined(UPLOAD_GPU_DISABLED)
31 #include "adapter/ohos/entrance/ace_rosen_sync_task.h"
32 #endif
33
34 #include "adapter/ohos/entrance/ace_container.h"
35 #include "base/log/ace_trace.h"
36 #include "base/log/dump_log.h"
37 #include "base/log/event_report.h"
38 #include "base/log/log.h"
39 #include "base/utils/macros.h"
40 #include "base/utils/system_properties.h"
41 #include "base/utils/utils.h"
42 #include "core/common/ace_engine.h"
43 #include "core/common/container_scope.h"
44 #include "core/components/theme/app_theme.h"
45 #include "core/components/theme/theme_manager.h"
46 #include "core/event/axis_event.h"
47 #include "core/event/key_event.h"
48 #include "core/event/mouse_event.h"
49 #include "core/event/touch_event.h"
50 #include "core/image/image_cache.h"
51 #include "core/pipeline/layers/flutter_scene_builder.h"
52
53 namespace OHOS::Ace::Platform {
54 namespace {
55
56 constexpr int32_t ROTATION_DIVISOR = 64;
57 constexpr double PERMIT_ANGLE_VALUE = 0.5;
58
59 template<typename E>
GetEventDevice(int32_t sourceType,E & event)60 void GetEventDevice(int32_t sourceType, E& event)
61 {
62 switch (sourceType) {
63 case OHOS::MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN:
64 event.sourceType = SourceType::TOUCH;
65 break;
66 case OHOS::MMI::PointerEvent::SOURCE_TYPE_TOUCHPAD:
67 event.sourceType = SourceType::TOUCH_PAD;
68 break;
69 case OHOS::MMI::PointerEvent::SOURCE_TYPE_MOUSE:
70 event.sourceType = SourceType::MOUSE;
71 break;
72 default:
73 event.sourceType = SourceType::NONE;
74 break;
75 }
76 }
77
GetSourceTool(int32_t orgToolType)78 SourceTool GetSourceTool(int32_t orgToolType)
79 {
80 switch (orgToolType) {
81 case OHOS::MMI::PointerEvent::TOOL_TYPE_FINGER:
82 return SourceTool::FINGER;
83 case OHOS::MMI::PointerEvent::TOOL_TYPE_PEN:
84 return SourceTool::PEN;
85 case OHOS::MMI::PointerEvent::TOOL_TYPE_RUBBER:
86 return SourceTool::RUBBER;
87 case OHOS::MMI::PointerEvent::TOOL_TYPE_BRUSH:
88 return SourceTool::BRUSH;
89 case OHOS::MMI::PointerEvent::TOOL_TYPE_PENCIL:
90 return SourceTool::PENCIL;
91 case OHOS::MMI::PointerEvent::TOOL_TYPE_AIRBRUSH:
92 return SourceTool::AIRBRUSH;
93 case OHOS::MMI::PointerEvent::TOOL_TYPE_MOUSE:
94 return SourceTool::MOUSE;
95 case OHOS::MMI::PointerEvent::TOOL_TYPE_LENS:
96 return SourceTool::LENS;
97 default:
98 LOGW("unknown tool type");
99 return SourceTool::UNKNOWN;
100 }
101 }
102
ConvertTouchPoint(const MMI::PointerEvent::PointerItem & pointerItem)103 TouchPoint ConvertTouchPoint(const MMI::PointerEvent::PointerItem& pointerItem)
104 {
105 TouchPoint touchPoint;
106 // just get the max of width and height
107 touchPoint.size = std::max(pointerItem.GetWidth(), pointerItem.GetHeight()) / 2.0;
108 touchPoint.id = pointerItem.GetPointerId();
109 touchPoint.downTime = TimeStamp(std::chrono::microseconds(pointerItem.GetDownTime()));
110 touchPoint.x = pointerItem.GetWindowX();
111 touchPoint.y = pointerItem.GetWindowY();
112 touchPoint.screenX = pointerItem.GetDisplayX();
113 touchPoint.screenY = pointerItem.GetDisplayY();
114 touchPoint.isPressed = pointerItem.IsPressed();
115 touchPoint.force = static_cast<float>(pointerItem.GetPressure());
116 touchPoint.tiltX = pointerItem.GetTiltX();
117 touchPoint.tiltY = pointerItem.GetTiltY();
118 touchPoint.sourceTool = GetSourceTool(pointerItem.GetToolType());
119 return touchPoint;
120 }
121
UpdateTouchEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent,TouchEvent & touchEvent)122 void UpdateTouchEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent, TouchEvent& touchEvent)
123 {
124 auto ids = pointerEvent->GetPointerIds();
125 for (auto&& id : ids) {
126 MMI::PointerEvent::PointerItem item;
127 bool ret = pointerEvent->GetPointerItem(id, item);
128 if (!ret) {
129 LOGE("get pointer item failed.");
130 continue;
131 }
132 auto touchPoint = ConvertTouchPoint(item);
133 touchEvent.pointers.emplace_back(std::move(touchPoint));
134 }
135 }
136
ConvertTouchEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)137 TouchEvent ConvertTouchEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
138 {
139 int32_t pointerID = pointerEvent->GetPointerId();
140 MMI::PointerEvent::PointerItem item;
141 bool ret = pointerEvent->GetPointerItem(pointerID, item);
142 if (!ret) {
143 LOGE("get pointer item failed.");
144 return TouchEvent();
145 }
146 auto touchPoint = ConvertTouchPoint(item);
147 std::chrono::microseconds microseconds(pointerEvent->GetActionTime());
148 TimeStamp time(microseconds);
149 TouchEvent event { touchPoint.id, touchPoint.x, touchPoint.y, touchPoint.screenX, touchPoint.screenY,
150 TouchType::UNKNOWN, time, touchPoint.size, touchPoint.force, touchPoint.tiltX, touchPoint.tiltY,
151 pointerEvent->GetDeviceId(), SourceType::NONE, touchPoint.sourceTool };
152 int32_t orgDevice = pointerEvent->GetSourceType();
153 GetEventDevice(orgDevice, event);
154 int32_t orgAction = pointerEvent->GetPointerAction();
155 switch (orgAction) {
156 case OHOS::MMI::PointerEvent::POINTER_ACTION_CANCEL:
157 event.type = TouchType::CANCEL;
158 break;
159 case OHOS::MMI::PointerEvent::POINTER_ACTION_DOWN:
160 event.type = TouchType::DOWN;
161 break;
162 case OHOS::MMI::PointerEvent::POINTER_ACTION_MOVE:
163 event.type = TouchType::MOVE;
164 break;
165 case OHOS::MMI::PointerEvent::POINTER_ACTION_UP:
166 event.type = TouchType::UP;
167 break;
168 default:
169 LOGW("unknown type");
170 break;
171 }
172 UpdateTouchEvent(pointerEvent, event);
173 return event;
174 }
175
GetMouseEventAction(int32_t action,MouseEvent & events)176 void GetMouseEventAction(int32_t action, MouseEvent& events)
177 {
178 switch (action) {
179 case OHOS::MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN:
180 events.action = MouseAction::PRESS;
181 break;
182 case OHOS::MMI::PointerEvent::POINTER_ACTION_BUTTON_UP:
183 events.action = MouseAction::RELEASE;
184 break;
185 case OHOS::MMI::PointerEvent::POINTER_ACTION_ENTER_WINDOW:
186 events.action = MouseAction::WINDOW_ENTER;
187 break;
188 case OHOS::MMI::PointerEvent::POINTER_ACTION_LEAVE_WINDOW:
189 events.action = MouseAction::WINDOW_LEAVE;
190 break;
191 case OHOS::MMI::PointerEvent::POINTER_ACTION_MOVE:
192 events.action = MouseAction::MOVE;
193 break;
194 default:
195 events.action = MouseAction::NONE;
196 break;
197 }
198 }
199
GetMouseEventButton(int32_t button,MouseEvent & events)200 void GetMouseEventButton(int32_t button, MouseEvent& events)
201 {
202 switch (button) {
203 case OHOS::MMI::PointerEvent::MOUSE_BUTTON_LEFT:
204 events.button = MouseButton::LEFT_BUTTON;
205 break;
206 case OHOS::MMI::PointerEvent::MOUSE_BUTTON_RIGHT:
207 events.button = MouseButton::RIGHT_BUTTON;
208 break;
209 case OHOS::MMI::PointerEvent::MOUSE_BUTTON_MIDDLE:
210 events.button = MouseButton::MIDDLE_BUTTON;
211 break;
212 case OHOS::MMI::PointerEvent::MOUSE_BUTTON_SIDE:
213 events.button = MouseButton::BACK_BUTTON;
214 break;
215 case OHOS::MMI::PointerEvent::MOUSE_BUTTON_EXTRA:
216 events.button = MouseButton::FORWARD_BUTTON;
217 break;
218 default:
219 events.button = MouseButton::NONE_BUTTON;
220 break;
221 }
222 }
223
ConvertMouseEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent,MouseEvent & events)224 void ConvertMouseEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent, MouseEvent& events)
225 {
226 int32_t pointerID = pointerEvent->GetPointerId();
227 MMI::PointerEvent::PointerItem item;
228 bool ret = pointerEvent->GetPointerItem(pointerID, item);
229 if (!ret) {
230 LOGE("get pointer: %{public}d item failed.", pointerID);
231 return;
232 }
233
234 events.x = item.GetWindowX();
235 events.y = item.GetWindowY();
236 events.screenX = item.GetDisplayX();
237 events.screenY = item.GetDisplayY();
238 int32_t orgAction = pointerEvent->GetPointerAction();
239 GetMouseEventAction(orgAction, events);
240 int32_t orgButton = pointerEvent->GetButtonId();
241 GetMouseEventButton(orgButton, events);
242 int32_t orgDevice = pointerEvent->GetSourceType();
243 GetEventDevice(orgDevice, events);
244
245 std::set<int32_t> pressedSet = pointerEvent->GetPressedButtons();
246 uint32_t pressedButtons = 0;
247 if (pressedSet.find(OHOS::MMI::PointerEvent::MOUSE_BUTTON_LEFT) != pressedSet.end()) {
248 pressedButtons &= static_cast<uint32_t>(MouseButton::LEFT_BUTTON);
249 }
250 if (pressedSet.find(OHOS::MMI::PointerEvent::MOUSE_BUTTON_RIGHT) != pressedSet.end()) {
251 pressedButtons &= static_cast<uint32_t>(MouseButton::RIGHT_BUTTON);
252 }
253 if (pressedSet.find(OHOS::MMI::PointerEvent::MOUSE_BUTTON_MIDDLE) != pressedSet.end()) {
254 pressedButtons &= static_cast<uint32_t>(MouseButton::MIDDLE_BUTTON);
255 }
256 events.pressedButtons = static_cast<int32_t>(pressedButtons);
257
258 std::chrono::microseconds microseconds(pointerEvent->GetActionTime());
259 TimeStamp time(microseconds);
260 events.time = time;
261 LOGD("ConvertMouseEvent: (x,y): (%{public}f,%{public}f). Button: %{public}d. Action: %{public}d. "
262 "DeviceType: %{public}d. PressedButton: %{public}d. Time: %{public}lld",
263 events.x, events.y, events.button, events.action, events.sourceType, events.pressedButtons,
264 (long long)pointerEvent->GetActionTime());
265 }
266
GetAxisEventAction(int32_t action,AxisEvent & event)267 void GetAxisEventAction(int32_t action, AxisEvent& event)
268 {
269 switch (action) {
270 case OHOS::MMI::PointerEvent::POINTER_ACTION_AXIS_BEGIN:
271 event.action = AxisAction::BEGIN;
272 break;
273 case OHOS::MMI::PointerEvent::POINTER_ACTION_AXIS_UPDATE:
274 event.action = AxisAction::UPDATE;
275 break;
276 case OHOS::MMI::PointerEvent::POINTER_ACTION_AXIS_END:
277 event.action = AxisAction::END;
278 break;
279 default:
280 event.action = AxisAction::NONE;
281 break;
282 }
283 }
284
ConvertAxisEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent,AxisEvent & event)285 void ConvertAxisEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent, AxisEvent& event)
286 {
287 int32_t pointerID = pointerEvent->GetPointerId();
288 MMI::PointerEvent::PointerItem item;
289 bool ret = pointerEvent->GetPointerItem(pointerID, item);
290 if (!ret) {
291 LOGE("get pointer: %{public}d item failed.", pointerID);
292 return;
293 }
294
295 event.id = item.GetPointerId();
296 event.x = static_cast<float>(item.GetWindowX());
297 event.y = static_cast<float>(item.GetWindowY());
298 event.horizontalAxis = pointerEvent->GetAxisValue(OHOS::MMI::PointerEvent::AxisType::AXIS_TYPE_SCROLL_HORIZONTAL);
299 event.verticalAxis = pointerEvent->GetAxisValue(OHOS::MMI::PointerEvent::AxisType::AXIS_TYPE_SCROLL_VERTICAL);
300 event.pinchAxisScale = pointerEvent->GetAxisValue(OHOS::MMI::PointerEvent::AxisType::AXIS_TYPE_PINCH);
301 int32_t orgAction = pointerEvent->GetPointerAction();
302 GetAxisEventAction(orgAction, event);
303 int32_t orgDevice = pointerEvent->GetSourceType();
304 GetEventDevice(orgDevice, event);
305
306 std::chrono::microseconds microseconds(pointerEvent->GetActionTime());
307 TimeStamp time(microseconds);
308 event.time = time;
309 LOGD("ConvertAxisEvent: id: %{public}d, (x,y): (%{public}f,%{public}f). HorizontalAxis: %{public}f. VerticalAxis: "
310 "%{public}f. "
311 "Action: %{public}d. DeviceType: %{public}d. Time: %{public}lld",
312 event.id, event.x, event.y, event.horizontalAxis, event.verticalAxis, event.action, event.sourceType,
313 (long long)pointerEvent->GetActionTime());
314 }
315
ConvertKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent,KeyEvent & event)316 void ConvertKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent, KeyEvent& event)
317 {
318 event.code = static_cast<KeyCode>(keyEvent->GetKeyCode());
319 if (keyEvent->GetKeyAction() == OHOS::MMI::KeyEvent::KEY_ACTION_UP) {
320 event.action = KeyAction::UP;
321 } else if (keyEvent->GetKeyAction() == OHOS::MMI::KeyEvent::KEY_ACTION_DOWN) {
322 event.action = KeyAction::DOWN;
323 } else {
324 event.action = KeyAction::UNKNOWN;
325 }
326 std::chrono::microseconds microseconds(keyEvent->GetActionTime());
327 TimeStamp time(microseconds);
328 event.timeStamp = time;
329 event.key = MMI::KeyEvent::KeyCodeToString(keyEvent->GetKeyCode());
330 event.deviceId = keyEvent->GetDeviceId();
331 event.sourceType = SourceType::KEYBOARD;
332 std::string pressedKeyStr = "Pressed Keys: ";
333 for (const auto& curCode : keyEvent->GetPressedKeys()) {
334 pressedKeyStr += (std::to_string(curCode) + " ");
335 event.pressedCodes.emplace_back(static_cast<KeyCode>(curCode));
336 }
337 LOGD("ConvertKeyEvent: KeyCode: %{private}d. KeyAction: %{public}d. PressedCodes: %{private}s. Time: %{public}lld",
338 event.code, event.action, pressedKeyStr.c_str(), (long long)(keyEvent->GetActionTime()));
339 }
340
LogPointInfo(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)341 void LogPointInfo(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
342 {
343 LOGD("point source: %{public}d", pointerEvent->GetSourceType());
344 auto actionId = pointerEvent->GetPointerId();
345 MMI::PointerEvent::PointerItem item;
346 if (pointerEvent->GetPointerItem(actionId, item)) {
347 LOGD("action point info: id: %{public}d, x: %{public}d, y: %{public}d, action: %{public}d, pressure: "
348 "%{public}f, tiltX: %{public}f, tiltY: %{public}f",
349 actionId, item.GetWindowX(), item.GetWindowY(), pointerEvent->GetPointerAction(), item.GetPressure(),
350 item.GetTiltX(), item.GetTiltY());
351 }
352 auto ids = pointerEvent->GetPointerIds();
353 for (auto&& id : ids) {
354 MMI::PointerEvent::PointerItem item;
355 if (pointerEvent->GetPointerItem(id, item)) {
356 LOGD("all point info: id: %{public}d, x: %{public}d, y: %{public}d, isPressed: %{public}d, pressure: "
357 "%{public}f, tiltX: %{public}f, tiltY: %{public}f",
358 actionId, item.GetWindowX(), item.GetWindowY(), item.IsPressed(), item.GetPressure(), item.GetTiltX(),
359 item.GetTiltY());
360 }
361 }
362 }
363
364 } // namespace
365
CreateView(int32_t instanceId,bool useCurrentEventRunner,bool usePlatformThread)366 FlutterAceView* FlutterAceView::CreateView(int32_t instanceId, bool useCurrentEventRunner, bool usePlatformThread)
367 {
368 FlutterAceView* aceSurface = new Platform::FlutterAceView(instanceId);
369 if (aceSurface != nullptr) {
370 aceSurface->IncRefCount();
371 }
372 flutter::Settings settings;
373 settings.instanceId = instanceId;
374 settings.platform = flutter::AcePlatform::ACE_PLATFORM_OHOS;
375 #ifndef GPU_DISABLED
376 settings.enable_software_rendering = false;
377 #else
378 settings.enable_software_rendering = true;
379 #endif
380 #ifdef ENABLE_ROSEN_BACKEND
381 settings.use_system_render_thread = SystemProperties::GetRosenBackendEnabled();
382 #endif
383 settings.platform_as_ui_thread = usePlatformThread;
384 settings.use_current_event_runner = useCurrentEventRunner;
385 LOGD("software render: %{public}s", settings.enable_software_rendering ? "true" : "false");
386 LOGD("use platform as ui thread: %{public}s", settings.platform_as_ui_thread ? "true" : "false");
387 settings.idle_notification_callback = [instanceId](int64_t deadline) {
388 ContainerScope scope(instanceId);
389 auto container = Container::Current();
390 CHECK_NULL_VOID_NOLOG(container);
391 auto context = container->GetPipelineContext();
392 CHECK_NULL_VOID_NOLOG(context);
393 context->GetTaskExecutor()->PostTask(
394 [context, deadline]() { context->OnIdle(deadline); }, TaskExecutor::TaskType::UI);
395 };
396 auto shell_holder = std::make_unique<flutter::OhosShellHolder>(settings, false);
397 if (aceSurface != nullptr) {
398 aceSurface->SetShellHolder(std::move(shell_holder));
399 }
400 return aceSurface;
401 }
402
SurfaceCreated(FlutterAceView * view,OHOS::sptr<OHOS::Rosen::Window> window)403 void FlutterAceView::SurfaceCreated(FlutterAceView* view, OHOS::sptr<OHOS::Rosen::Window> window)
404 {
405 CHECK_NULL_VOID(window);
406 CHECK_NULL_VOID(view);
407 LOGD(">>> FlutterAceView::SurfaceCreated, pWnd:%{public}p", &(*window));
408 auto platformView = view->GetShellHolder()->GetPlatformView();
409 LOGD("FlutterAceView::SurfaceCreated, GetPlatformView");
410 if (platformView && !SystemProperties::GetRosenBackendEnabled()) {
411 LOGD("FlutterAceView::SurfaceCreated, call NotifyCreated");
412 platformView->NotifyCreated(window);
413 }
414
415 LOGD("<<< FlutterAceView::SurfaceCreated, end");
416 }
417
SurfaceChanged(FlutterAceView * view,int32_t width,int32_t height,int32_t orientation,WindowSizeChangeReason type)418 void FlutterAceView::SurfaceChanged(
419 FlutterAceView* view, int32_t width, int32_t height, int32_t orientation, WindowSizeChangeReason type)
420 {
421 CHECK_NULL_VOID(view);
422 view->NotifySurfaceChanged(width, height, type);
423 auto platformView = view->GetShellHolder()->GetPlatformView();
424 LOGD("FlutterAceView::SurfaceChanged, GetPlatformView");
425 if (platformView) {
426 LOGD("FlutterAceView::SurfaceChanged, call NotifyChanged");
427 platformView->NotifyChanged(SkISize::Make(width, height));
428 }
429
430 auto instanceId = view->GetInstanceId();
431 auto container = Platform::AceContainer::GetContainer(instanceId);
432 if (container) {
433 auto pipelineContext = AceType::DynamicCast<PipelineContext>(container->GetPipelineContext());
434 CHECK_NULL_VOID(pipelineContext);
435 pipelineContext->CloseContextMenu();
436 auto textOverlayManager = pipelineContext->GetTextOverlayManager();
437 CHECK_NULL_VOID(textOverlayManager);
438 textOverlayManager->PopTextOverlay();
439 }
440
441 LOGD("<<< FlutterAceView::SurfaceChanged, end");
442 }
443
SurfacePositionChanged(FlutterAceView * view,int32_t posX,int32_t posY)444 void FlutterAceView::SurfacePositionChanged(FlutterAceView* view, int32_t posX, int32_t posY)
445 {
446 CHECK_NULL_VOID_NOLOG(view);
447 view->NotifySurfacePositionChanged(posX, posY);
448 }
449
SetViewportMetrics(FlutterAceView * view,const flutter::ViewportMetrics & metrics)450 void FlutterAceView::SetViewportMetrics(FlutterAceView* view, const flutter::ViewportMetrics& metrics)
451 {
452 CHECK_NULL_VOID_NOLOG(view);
453 view->NotifyDensityChanged(metrics.device_pixel_ratio);
454 view->NotifySystemBarHeightChanged(metrics.physical_padding_top, metrics.physical_view_inset_bottom);
455 auto platformView = view->GetShellHolder()->GetPlatformView();
456 CHECK_NULL_VOID_NOLOG(platformView);
457 platformView->SetViewportMetrics(metrics);
458 }
459
DispatchTouchEvent(FlutterAceView * view,const std::shared_ptr<MMI::PointerEvent> & pointerEvent)460 void FlutterAceView::DispatchTouchEvent(FlutterAceView* view, const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
461 {
462 LogPointInfo(pointerEvent);
463 if (pointerEvent->GetSourceType() == MMI::PointerEvent::SOURCE_TYPE_MOUSE) {
464 // mouse event
465 if (pointerEvent->GetPointerAction() >= MMI::PointerEvent::POINTER_ACTION_AXIS_BEGIN &&
466 pointerEvent->GetPointerAction() <= MMI::PointerEvent::POINTER_ACTION_AXIS_END) {
467 LOGD("ProcessAxisEvent");
468 view->ProcessAxisEvent(pointerEvent);
469 } else {
470 LOGD("ProcessMouseEvent");
471 view->ProcessMouseEvent(pointerEvent);
472 }
473 } else {
474 // touch event
475 LOGD("ProcessTouchEvent");
476 view->ProcessTouchEvent(pointerEvent);
477 }
478 }
479
DispatchKeyEvent(FlutterAceView * view,const std::shared_ptr<MMI::KeyEvent> & keyEvent)480 bool FlutterAceView::DispatchKeyEvent(FlutterAceView* view, const std::shared_ptr<MMI::KeyEvent>& keyEvent)
481 {
482 CHECK_NULL_RETURN(view, false);
483 return view->ProcessKeyEvent(keyEvent);
484 }
485
DispatchRotationEvent(FlutterAceView * view,float rotationValue)486 bool FlutterAceView::DispatchRotationEvent(FlutterAceView* view, float rotationValue)
487 {
488 CHECK_NULL_RETURN(view, false);
489 return view->ProcessRotationEvent(rotationValue);
490 }
491
RegisterTouchEventCallback(TouchEventCallback && callback)492 void FlutterAceView::RegisterTouchEventCallback(TouchEventCallback&& callback)
493 {
494 ACE_DCHECK(callback);
495 touchEventCallback_ = std::move(callback);
496 }
497
RegisterDragEventCallback(DragEventCallBack && callback)498 void FlutterAceView::RegisterDragEventCallback(DragEventCallBack&& callback)
499 {
500 ACE_DCHECK(callback);
501 dragEventCallback_ = std::move(callback);
502 }
503
RegisterKeyEventCallback(KeyEventCallback && callback)504 void FlutterAceView::RegisterKeyEventCallback(KeyEventCallback&& callback)
505 {
506 ACE_DCHECK(callback);
507 keyEventCallback_ = std::move(callback);
508 }
509
RegisterMouseEventCallback(MouseEventCallback && callback)510 void FlutterAceView::RegisterMouseEventCallback(MouseEventCallback&& callback)
511 {
512 ACE_DCHECK(callback);
513 mouseEventCallback_ = std::move(callback);
514 }
515
RegisterAxisEventCallback(AxisEventCallback && callback)516 void FlutterAceView::RegisterAxisEventCallback(AxisEventCallback&& callback)
517 {
518 ACE_DCHECK(callback);
519 axisEventCallback_ = std::move(callback);
520 }
521
RegisterRotationEventCallback(RotationEventCallBack && callback)522 void FlutterAceView::RegisterRotationEventCallback(RotationEventCallBack&& callback)
523 {
524 ACE_DCHECK(callback);
525 rotationEventCallBack_ = std::move(callback);
526 }
527
Launch()528 void FlutterAceView::Launch()
529 {
530 LOGD("Launch shell holder.");
531 if (!viewLaunched_) {
532 flutter::RunConfiguration config;
533 shell_holder_->Launch(std::move(config));
534 viewLaunched_ = true;
535 }
536 }
537
SetShellHolder(std::unique_ptr<flutter::OhosShellHolder> holder)538 void FlutterAceView::SetShellHolder(std::unique_ptr<flutter::OhosShellHolder> holder)
539 {
540 shell_holder_ = std::move(holder);
541 }
542
ProcessTouchEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)543 void FlutterAceView::ProcessTouchEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
544 {
545 CHECK_NULL_VOID_NOLOG(pointerEvent);
546 TouchEvent touchPoint = ConvertTouchEvent(pointerEvent);
547 if (SystemProperties::GetDebugEnabled()) {
548 ACE_SCOPED_TRACE("ProcessTouchEvent pointX=%f pointY=%f type=%d timeStamp=%lld id=%d", touchPoint.x,
549 touchPoint.y, (int)touchPoint.type, touchPoint.time.time_since_epoch().count(), touchPoint.id);
550 }
551 auto markProcess = [pointerEvent]() {
552 CHECK_NULL_VOID_NOLOG(pointerEvent);
553 LOGI("Mark %{public}d id Touch Event Processed", pointerEvent->GetPointerId());
554 pointerEvent->MarkProcessed();
555 };
556 if (touchPoint.type != TouchType::UNKNOWN) {
557 if (touchEventCallback_) {
558 touchEventCallback_(touchPoint, markProcess);
559 }
560 } else {
561 LOGW("Unknown event.");
562 }
563 }
564
ProcessDragEvent(int32_t x,int32_t y,const DragEventAction & action)565 void FlutterAceView::ProcessDragEvent(int32_t x, int32_t y, const DragEventAction& action)
566 {
567 LOGD("ProcessDragEvent");
568 CHECK_NULL_VOID_NOLOG(dragEventCallback_);
569 dragEventCallback_(x, y, action);
570 }
571
ProcessMouseEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)572 void FlutterAceView::ProcessMouseEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
573 {
574 MouseEvent event;
575 if (pointerEvent) {
576 ConvertMouseEvent(pointerEvent, event);
577 }
578 auto markProcess = [pointerEvent]() {
579 CHECK_NULL_VOID_NOLOG(pointerEvent);
580 LOGI("Mark %{public}d id Mouse Event Processed", pointerEvent->GetPointerId());
581 pointerEvent->MarkProcessed();
582 };
583
584 CHECK_NULL_VOID_NOLOG(mouseEventCallback_);
585 mouseEventCallback_(event, markProcess);
586 }
587
ProcessAxisEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)588 void FlutterAceView::ProcessAxisEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
589 {
590 AxisEvent event;
591 if (pointerEvent) {
592 ConvertAxisEvent(pointerEvent, event);
593 }
594 auto markProcess = [pointerEvent]() {
595 CHECK_NULL_VOID_NOLOG(pointerEvent);
596 LOGI("Mark %{public}d id Axis Event Processed", pointerEvent->GetPointerId());
597 pointerEvent->MarkProcessed();
598 };
599
600 CHECK_NULL_VOID_NOLOG(axisEventCallback_);
601 axisEventCallback_(event, markProcess);
602 }
603
ProcessKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent)604 bool FlutterAceView::ProcessKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
605 {
606 CHECK_NULL_RETURN_NOLOG(keyEventCallback_, false);
607 KeyEvent event;
608 ConvertKeyEvent(keyEvent, event);
609 return keyEventCallback_(event);
610 }
611
GetNativeWindowById(uint64_t textureId)612 const void* FlutterAceView::GetNativeWindowById(uint64_t textureId)
613 {
614 return nullptr;
615 }
616
ProcessRotationEvent(float rotationValue)617 bool FlutterAceView::ProcessRotationEvent(float rotationValue)
618 {
619 CHECK_NULL_RETURN_NOLOG(rotationEventCallBack_, false);
620 RotationEvent event { .value = rotationValue * ROTATION_DIVISOR };
621 return rotationEventCallBack_(event);
622 }
623
Dump(const std::vector<std::string> & params)624 bool FlutterAceView::Dump(const std::vector<std::string>& params)
625 {
626 if (params.empty() || params[0] != "-drawcmd") {
627 LOGE("Unsupported parameters.");
628 return false;
629 }
630 #ifdef DUMP_DRAW_CMD
631 if (shell_holder_) {
632 auto screenShot = shell_holder_->Screenshot(flutter::Rasterizer::ScreenshotType::SkiaPicture, false);
633 if (screenShot.data->data() != nullptr) {
634 auto byteData = screenShot.data;
635 static int32_t count = 0;
636 auto path = ImageCache::GetImageCacheFilePath() + "/picture_" + std::to_string(count++) + ".mskp";
637 if (DumpLog::GetInstance().GetDumpFile()) {
638 DumpLog::GetInstance().AddDesc("Dump draw command to path: " + path);
639 DumpLog::GetInstance().Print(0, "Info:", 0);
640 }
641 std::ofstream outFile(path, std::fstream::out | std::fstream::binary);
642 if (!outFile.is_open()) {
643 LOGE("Open file %{private}s failed.", path.c_str());
644 return false;
645 }
646 outFile.write(reinterpret_cast<const char*>(byteData->data()), byteData->size());
647 outFile.close();
648 return true;
649 }
650 }
651 #else
652 if (DumpLog::GetInstance().GetDumpFile()) {
653 DumpLog::GetInstance().AddDesc("Dump draw command not support on this version.");
654 DumpLog::GetInstance().Print(0, "Info:", 0);
655 return true;
656 }
657 #endif
658 return false;
659 }
660
InitCacheFilePath(const std::string & path)661 void FlutterAceView::InitCacheFilePath(const std::string& path)
662 {
663 if (!path.empty()) {
664 ImageCache::SetImageCacheFilePath(path);
665 ImageCache::SetCacheFileInfo();
666 } else {
667 LOGW("image cache path empty");
668 }
669 }
670
IsLastPage() const671 bool FlutterAceView::IsLastPage() const
672 {
673 auto container = AceEngine::Get().GetContainer(instanceId_);
674 CHECK_NULL_RETURN_NOLOG(container, false);
675 ContainerScope scope(instanceId_);
676 auto context = container->GetPipelineContext();
677 CHECK_NULL_RETURN_NOLOG(context, false);
678 auto taskExecutor = context->GetTaskExecutor();
679
680 bool isLastPage = false;
681 CHECK_NULL_RETURN_NOLOG(taskExecutor, isLastPage);
682 taskExecutor->PostSyncTask(
683 [context, &isLastPage]() { isLastPage = context->IsLastPage(); }, TaskExecutor::TaskType::UI);
684 return isLastPage;
685 }
686
GetBackgroundColor()687 uint32_t FlutterAceView::GetBackgroundColor()
688 {
689 return Color::WHITE.GetValue();
690 }
691
692 // On watch device, it's probable to quit the application unexpectedly when we slide our finger diagonally upward on the
693 // screen, so we do restrictions here.
IsNeedForbidToPlatform(TouchEvent point)694 bool FlutterAceView::IsNeedForbidToPlatform(TouchEvent point)
695 {
696 if (point.type == TouchType::DOWN) {
697 auto result = touchPointInfoMap_.try_emplace(point.id, TouchPointInfo(point.GetOffset()));
698 if (!result.second) {
699 result.first->second = TouchPointInfo(point.GetOffset());
700 }
701
702 return false;
703 }
704
705 auto iter = touchPointInfoMap_.find(point.id);
706 if (iter == touchPointInfoMap_.end()) {
707 return false;
708 }
709 if (iter->second.eventState_ == EventState::HORIZONTAL_STATE) {
710 return false;
711 } else if (iter->second.eventState_ == EventState::VERTICAL_STATE) {
712 return true;
713 }
714
715 Offset offset = point.GetOffset() - iter->second.offset_;
716 double deltaX = offset.GetX();
717 double deltaY = std::abs(offset.GetY());
718
719 if (point.type == TouchType::MOVE) {
720 if (deltaX > 0.0) {
721 if (deltaY / deltaX > PERMIT_ANGLE_VALUE) {
722 iter->second.eventState_ = EventState::VERTICAL_STATE;
723 return true;
724 } else {
725 iter->second.eventState_ = EventState::HORIZONTAL_STATE;
726 }
727 }
728
729 return false;
730 }
731
732 touchPointInfoMap_.erase(point.id);
733 return deltaX > 0.0 && deltaY / deltaX > PERMIT_ANGLE_VALUE;
734 }
735
GetDrawDelegate()736 std::unique_ptr<DrawDelegate> FlutterAceView::GetDrawDelegate()
737 {
738 auto drawDelegate = std::make_unique<DrawDelegate>();
739
740 drawDelegate->SetDrawFrameCallback([this](RefPtr<Flutter::Layer>& layer, const Rect& dirty) {
741 CHECK_NULL_VOID(layer);
742 RefPtr<Flutter::FlutterSceneBuilder> flutterSceneBuilder = AceType::MakeRefPtr<Flutter::FlutterSceneBuilder>();
743 layer->AddToScene(*flutterSceneBuilder, 0.0, 0.0);
744 auto scene = flutterSceneBuilder->Build();
745 CHECK_NULL_VOID(flutter::UIDartState::Current());
746 auto window = flutter::UIDartState::Current()->window();
747 if (window != nullptr && window->client() != nullptr) {
748 window->client()->Render(scene.get());
749 } else {
750 LOGE("window is nullptr");
751 }
752 });
753
754 return drawDelegate;
755 }
756
GetPlatformWindow()757 std::unique_ptr<PlatformWindow> FlutterAceView::GetPlatformWindow()
758 {
759 return nullptr;
760 }
761
InitIOManager(RefPtr<TaskExecutor> taskExecutor)762 void FlutterAceView::InitIOManager(RefPtr<TaskExecutor> taskExecutor)
763 {
764 if (!SystemProperties::GetGpuUploadEnabled()) {
765 return;
766 }
767 #if defined(ENABLE_ROSEN_BACKEND) and !defined(UPLOAD_GPU_DISABLED)
768 ACE_SCOPED_TRACE("InitIOManager");
769 EGLContext shareContext = nullptr;
770 EGLSurface surface = nullptr;
771 auto callback = [&shareContext, &surface]() {
772 ACE_SCOPED_TRACE("create egl ");
773 EGLContext context = eglGetCurrentContext();
774 if (context == EGL_NO_CONTEXT) {
775 LOGE("eglGetCurrentContext failed errorCode = [%{public}d]", eglGetError());
776 return;
777 }
778 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
779 if (display == EGL_NO_DISPLAY) {
780 LOGE("eglGetDisplay failed errorCode = [%{public}d]", eglGetError());
781 return;
782 }
783 EGLint attributes[] = {
784 // clang-format off
785 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
786 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
787 EGL_RED_SIZE, 8,
788 EGL_GREEN_SIZE, 8,
789 EGL_BLUE_SIZE, 8,
790 EGL_ALPHA_SIZE, 8,
791 EGL_DEPTH_SIZE, 0,
792 EGL_STENCIL_SIZE, 0,
793 EGL_NONE, // termination sentinel
794 // clang-format on
795 };
796 EGLint config_count = 0;
797 EGLConfig egl_config = nullptr;
798 if (eglChooseConfig(display, attributes, &egl_config, 1, &config_count) != EGL_TRUE) {
799 LOGE("Get EGLConfig failed errorCode = [%{public}d]", eglGetError());
800 return;
801 }
802 EGLint contextAttr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
803 shareContext = eglCreateContext(display, egl_config, context, contextAttr);
804 if (shareContext == EGL_NO_CONTEXT) {
805 LOGE("eglCreateContext failed errorCode = [%{public}d]", eglGetError());
806 return;
807 }
808 const EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
809 surface = eglCreatePbufferSurface(display, egl_config, attribs);
810 if (surface == EGL_NO_SURFACE) {
811 LOGE("eglCreatePbufferSurface failed errorCode = [%{public}d]", eglGetError());
812 return;
813 }
814 LOGI("create egl success");
815 };
816 auto task = std::make_shared<AceRosenSyncTask>(std::move(callback));
817 Rosen::RSTransactionProxy::GetInstance()->ExecuteSynchronousTask(task);
818
819 if (shareContext == EGL_NO_CONTEXT || surface == EGL_NO_SURFACE) {
820 LOGW("create egl env failed, image should not upload to gpu.");
821 return;
822 }
823 auto state = flutter::UIDartState::Current()->GetStateById(instanceId_);
824 CHECK_NULL_VOID(state);
825 fml::WeakPtr<flutter::ShellIOManager> ioManager = state->GetIOManager();
826 taskExecutor->PostSyncTask(
827 [surface, shareContext, ioManager]() {
828 ACE_SCOPED_TRACE("create resource_context ");
829 if (eglMakeCurrent(eglGetDisplay(EGL_DEFAULT_DISPLAY), surface, surface, shareContext) == EGL_TRUE) {
830 sk_sp<GrContext> resource_context = flutter::ShellIOManager::CreateCompatibleResourceLoadingContext(
831 GrBackend::kOpenGL_GrBackend, flutter::GPUSurfaceGLDelegate::GetDefaultPlatformGLInterface());
832
833 ioManager->NotifyResourceContextAvailable(resource_context);
834 }
835 },
836 TaskExecutor::TaskType::IO);
837 #endif
838 }
839
840 } // namespace OHOS::Ace::Platform