1 /*
2 * Copyright (c) 2023-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 "core/pipeline_ng/pipeline_context.h"
17
18 #include "base/subwindow/subwindow_manager.h"
19
20 #ifdef ENABLE_ROSEN_BACKEND
21 #include "render_service_client/core/transaction/rs_transaction.h"
22 #include "render_service_client/core/ui/rs_ui_director.h"
23 #endif
24 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
25 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
26 #include "frameworks/core/components_ng/base/inspector.h"
27 #endif
28
29 #include "base/geometry/ng/offset_t.h"
30 #include "base/geometry/ng/rect_t.h"
31 #include "base/log/ace_performance_monitor.h"
32 #include "base/log/ace_trace.h"
33 #include "base/log/ace_tracker.h"
34 #include "base/log/dump_log.h"
35 #include "base/log/event_report.h"
36 #include "base/memory/ace_type.h"
37 #include "base/perfmonitor/perf_monitor.h"
38 #include "base/ressched/ressched_report.h"
39 #include "core/common/ace_engine.h"
40 #include "core/common/font_manager.h"
41 #include "core/common/font_change_observer.h"
42 #include "core/common/ime/input_method_manager.h"
43 #include "core/common/layout_inspector.h"
44 #include "core/common/stylus/stylus_detector_default.h"
45 #include "core/common/stylus/stylus_detector_mgr.h"
46 #include "core/common/text_field_manager.h"
47 #include "core/components_ng/base/view_advanced_register.h"
48 #include "core/components_ng/pattern/container_modal/container_modal_view_factory.h"
49 #include "core/components_ng/pattern/container_modal/enhance/container_modal_pattern_enhance.h"
50 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
51 #include "core/components_ng/pattern/navigation/nav_bar_node.h"
52 #include "core/components_ng/pattern/root/root_pattern.h"
53 #include "core/components_ng/pattern/text_field/text_field_manager.h"
54 #ifdef WINDOW_SCENE_SUPPORTED
55 #include "core/components_ng/pattern/window_scene/scene/window_scene_layout_manager.h"
56 #endif
57 #include "core/image/image_file_cache.h"
58 #include "core/pipeline/pipeline_context.h"
59
60 namespace {
61 constexpr uint64_t ONE_MS_IN_NS = 1 * 1000 * 1000;
62 constexpr uint64_t ONE_S_IN_NS = 1 * 1000 * 1000 * 1000;
63 constexpr uint64_t INTERPOLATION_THRESHOLD = 100 * 1000 * 1000; // 100ms
64 constexpr int32_t INDEX_X = 0;
65 constexpr int32_t INDEX_Y = 1;
66 constexpr int32_t INDEX_TIME = 2;
67 constexpr int32_t INDEX_X_SLOPE = 2;
68 constexpr int32_t INDEX_Y_SLOPE = 3;
69 constexpr int32_t TIME_THRESHOLD = 2 * 1000000; // 3 millisecond
70 constexpr int32_t PLATFORM_VERSION_TEN = 10;
71 constexpr int32_t USED_ID_FIND_FLAG = 3; // if args >3 , it means use id to find
72 constexpr int32_t MILLISECONDS_TO_NANOSECONDS = 1000000; // Milliseconds to nanoseconds
73 constexpr int32_t RESAMPLE_COORD_TIME_THRESHOLD = 20 * 1000 * 1000;
74 constexpr int32_t VSYNC_PERIOD_COUNT = 5;
75 constexpr int32_t MIN_IDLE_TIME = 1000000;
76 constexpr uint8_t SINGLECOLOR_UPDATE_ALPHA = 75;
77 constexpr int8_t RENDERING_SINGLE_COLOR = 1;
78 constexpr int32_t MAX_MISS_COUNT = 3;
79 constexpr int32_t DELAY_TIME = 500;
80
81 } // namespace
82
83 namespace OHOS::Ace::NG {
84
PipelineContext(std::shared_ptr<Window> window,RefPtr<TaskExecutor> taskExecutor,RefPtr<AssetManager> assetManager,RefPtr<PlatformResRegister> platformResRegister,const RefPtr<Frontend> & frontend,int32_t instanceId)85 PipelineContext::PipelineContext(std::shared_ptr<Window> window, RefPtr<TaskExecutor> taskExecutor,
86 RefPtr<AssetManager> assetManager, RefPtr<PlatformResRegister> platformResRegister,
87 const RefPtr<Frontend>& frontend, int32_t instanceId)
88 : PipelineBase(window, std::move(taskExecutor), std::move(assetManager), frontend, instanceId, platformResRegister)
89 {
90 window_->OnHide();
91 }
92
PipelineContext(std::shared_ptr<Window> window,RefPtr<TaskExecutor> taskExecutor,RefPtr<AssetManager> assetManager,const RefPtr<Frontend> & frontend,int32_t instanceId)93 PipelineContext::PipelineContext(std::shared_ptr<Window> window, RefPtr<TaskExecutor> taskExecutor,
94 RefPtr<AssetManager> assetManager, const RefPtr<Frontend>& frontend, int32_t instanceId)
95 : PipelineBase(window, std::move(taskExecutor), std::move(assetManager), frontend, instanceId)
96 {
97 window_->OnHide();
98 }
99
GetCurrentContext()100 RefPtr<PipelineContext> PipelineContext::GetCurrentContext()
101 {
102 auto currentContainer = Container::Current();
103 CHECK_NULL_RETURN(currentContainer, nullptr);
104 return DynamicCast<PipelineContext>(currentContainer->GetPipelineContext());
105 }
106
GetCurrentContextSafely()107 RefPtr<PipelineContext> PipelineContext::GetCurrentContextSafely()
108 {
109 auto currentContainer = Container::CurrentSafely();
110 CHECK_NULL_RETURN(currentContainer, nullptr);
111 return DynamicCast<PipelineContext>(currentContainer->GetPipelineContext());
112 }
113
GetCurrentContextSafelyWithCheck()114 RefPtr<PipelineContext> PipelineContext::GetCurrentContextSafelyWithCheck()
115 {
116 auto currentContainer = Container::CurrentSafelyWithCheck();
117 CHECK_NULL_RETURN(currentContainer, nullptr);
118 return DynamicCast<PipelineContext>(currentContainer->GetPipelineContext());
119 }
120
GetCurrentContextPtrSafely()121 PipelineContext* PipelineContext::GetCurrentContextPtrSafely()
122 {
123 auto currentContainer = Container::CurrentSafely();
124 CHECK_NULL_RETURN(currentContainer, nullptr);
125 const auto& base = currentContainer->GetPipelineContext();
126 CHECK_NULL_RETURN(base, nullptr);
127 return DynamicCast<PipelineContext>(RawPtr(base));
128 }
129
GetCurrentContextPtrSafelyWithCheck()130 PipelineContext* PipelineContext::GetCurrentContextPtrSafelyWithCheck()
131 {
132 auto currentContainer = Container::CurrentSafelyWithCheck();
133 CHECK_NULL_RETURN(currentContainer, nullptr);
134 const auto& base = currentContainer->GetPipelineContext();
135 CHECK_NULL_RETURN(base, nullptr);
136 return DynamicCast<PipelineContext>(RawPtr(base));
137 }
138
GetMainPipelineContext()139 RefPtr<PipelineContext> PipelineContext::GetMainPipelineContext()
140 {
141 auto pipeline = PipelineBase::GetMainPipelineContext();
142 CHECK_NULL_RETURN(pipeline, nullptr);
143 return DynamicCast<PipelineContext>(pipeline);
144 }
145
NeedSoftKeyboard()146 bool PipelineContext::NeedSoftKeyboard()
147 {
148 auto needSoftKeyboard = InputMethodManager::GetInstance()->NeedSoftKeyboard();
149 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "window switch need keyboard %d", needSoftKeyboard);
150 return needSoftKeyboard;
151 }
152
GetContextByContainerId(int32_t containerId)153 RefPtr<PipelineContext> PipelineContext::GetContextByContainerId(int32_t containerId)
154 {
155 auto preContainer = Container::GetContainer(containerId);
156 CHECK_NULL_RETURN(preContainer, nullptr);
157 return DynamicCast<PipelineContext>(preContainer->GetPipelineContext());
158 }
159
GetCurrentRootWidth()160 float PipelineContext::GetCurrentRootWidth()
161 {
162 auto context = GetCurrentContext();
163 CHECK_NULL_RETURN(context, 0.0f);
164 return static_cast<float>(context->rootWidth_);
165 }
166
GetCurrentRootHeight()167 float PipelineContext::GetCurrentRootHeight()
168 {
169 auto context = GetCurrentContext();
170 CHECK_NULL_RETURN(context, 0.0f);
171 return static_cast<float>(context->rootHeight_);
172 }
173
AddDirtyPropertyNode(const RefPtr<FrameNode> & dirtyNode)174 void PipelineContext::AddDirtyPropertyNode(const RefPtr<FrameNode>& dirtyNode)
175 {
176 if (!CheckThreadSafe()) {
177 LOGW("AddDirtyPropertyNode doesn't run on UI thread!");
178 }
179 dirtyPropertyNodes_.emplace(dirtyNode);
180 hasIdleTasks_ = true;
181 RequestFrame();
182 }
183
AddDirtyCustomNode(const RefPtr<UINode> & dirtyNode)184 void PipelineContext::AddDirtyCustomNode(const RefPtr<UINode>& dirtyNode)
185 {
186 CHECK_RUN_ON(UI);
187 CHECK_NULL_VOID(dirtyNode);
188 auto customNode = DynamicCast<CustomNode>(dirtyNode);
189 if (customNode && !dirtyNode->GetInspectorIdValue("").empty()) {
190 ACE_BUILD_TRACE_BEGIN("AddDirtyCustomNode[%s][self:%d][parent:%d][key:%s]",
191 customNode->GetJSViewName().c_str(),
192 dirtyNode->GetId(), dirtyNode->GetParent() ? dirtyNode->GetParent()->GetId() : 0,
193 dirtyNode->GetInspectorIdValue("").c_str());
194 ACE_BUILD_TRACE_END()
195 } else if (customNode) {
196 ACE_BUILD_TRACE_BEGIN("AddDirtyCustomNode[%s][self:%d][parent:%d]",
197 customNode->GetJSViewName().c_str(),
198 dirtyNode->GetId(), dirtyNode->GetParent() ? dirtyNode->GetParent()->GetId() : 0);
199 ACE_BUILD_TRACE_END()
200 }
201 dirtyNodes_.emplace(dirtyNode);
202 hasIdleTasks_ = true;
203 RequestFrame();
204 }
205
AddDirtyLayoutNode(const RefPtr<FrameNode> & dirty)206 void PipelineContext::AddDirtyLayoutNode(const RefPtr<FrameNode>& dirty)
207 {
208 CHECK_RUN_ON(UI);
209 CHECK_NULL_VOID(dirty);
210 if (IsDestroyed()) {
211 LOGW("Cannot add dirty layout node as the pipeline context is destroyed.");
212 return;
213 }
214 if (!dirty->GetInspectorIdValue("").empty()) {
215 ACE_BUILD_TRACE_BEGIN("AddDirtyLayoutNode[%s][self:%d][parent:%d][key:%s]",
216 dirty->GetTag().c_str(),
217 dirty->GetId(), dirty->GetParent() ? dirty->GetParent()->GetId() : 0,
218 dirty->GetInspectorIdValue("").c_str());
219 ACE_BUILD_TRACE_END()
220 } else {
221 ACE_BUILD_TRACE_BEGIN("AddDirtyLayoutNode[%s][self:%d][parent:%d]", dirty->GetTag().c_str(),
222 dirty->GetId(), dirty->GetParent() ? dirty->GetParent()->GetId() : 0);
223 ACE_BUILD_TRACE_END()
224 }
225 if (!dirty->IsOnMainTree() && predictNode_) {
226 predictNode_->AddPredictLayoutNode(dirty);
227 return;
228 }
229 taskScheduler_->AddDirtyLayoutNode(dirty);
230 ForceLayoutForImplicitAnimation();
231 #ifdef UICAST_COMPONENT_SUPPORTED
232 do {
233 auto container = Container::Current();
234 CHECK_NULL_BREAK(container);
235 auto distributedUI = container->GetDistributedUI();
236 CHECK_NULL_BREAK(distributedUI);
237 distributedUI->AddDirtyLayoutNode(dirty->GetId());
238 } while (false);
239 #endif
240 hasIdleTasks_ = true;
241 if (dirty->GetTag() == V2::ROOT_ETS_TAG && isFirstRootLayout_) {
242 isFirstRootLayout_ = false;
243 LOGI("Root node request first frame.");
244 }
245 RequestFrame();
246 }
247
AddLayoutNode(const RefPtr<FrameNode> & layoutNode)248 void PipelineContext::AddLayoutNode(const RefPtr<FrameNode>& layoutNode)
249 {
250 taskScheduler_->AddLayoutNode(layoutNode);
251 }
252
AddDirtyRenderNode(const RefPtr<FrameNode> & dirty)253 void PipelineContext::AddDirtyRenderNode(const RefPtr<FrameNode>& dirty)
254 {
255 CHECK_RUN_ON(UI);
256 CHECK_NULL_VOID(dirty);
257 if (IsDestroyed()) {
258 LOGW("Cannot add dirty render node as the pipeline context is destroyed.");
259 return;
260 }
261 if (!dirty->GetInspectorIdValue("").empty()) {
262 ACE_BUILD_TRACE_BEGIN("AddDirtyRenderNode[%s][self:%d][parent:%d][key:%s]", dirty->GetTag().c_str(),
263 dirty->GetId(), dirty->GetParent() ? dirty->GetParent()->GetId() : 0,
264 dirty->GetInspectorIdValue("").c_str());
265 ACE_BUILD_TRACE_END()
266 } else {
267 ACE_BUILD_TRACE_BEGIN("AddDirtyRenderNode[%s][self:%d][parent:%d]", dirty->GetTag().c_str(),
268 dirty->GetId(), dirty->GetParent() ? dirty->GetParent()->GetId() : 0);
269 ACE_BUILD_TRACE_END()
270 }
271 taskScheduler_->AddDirtyRenderNode(dirty);
272 ForceRenderForImplicitAnimation();
273 #ifdef UICAST_COMPONENT_SUPPORTED
274 do {
275 auto container = Container::Current();
276 CHECK_NULL_BREAK(container);
277 auto distributedUI = container->GetDistributedUI();
278 CHECK_NULL_BREAK(distributedUI);
279 distributedUI->AddDirtyRenderNode(dirty->GetId());
280 } while (false);
281 #endif
282 hasIdleTasks_ = true;
283 RequestFrame();
284 }
285
AddDirtyFreezeNode(FrameNode * node)286 void PipelineContext::AddDirtyFreezeNode(FrameNode* node)
287 {
288 dirtyFreezeNode_.emplace_back(WeakClaim(node));
289 hasIdleTasks_ = true;
290 RequestFrame();
291 }
292
FlushFreezeNode()293 void PipelineContext::FlushFreezeNode()
294 {
295 std::set<RefPtr<FrameNode>, NodeCompare<RefPtr<FrameNode>>> dirtyFreezeNodeSet;
296 auto dirtyFreezeNodes = std::move(dirtyFreezeNode_);
297 dirtyFreezeNode_.clear();
298 for (auto&& weakNode : dirtyFreezeNodes) {
299 auto node = weakNode.Upgrade();
300 if (node) {
301 dirtyFreezeNodeSet.emplace(node);
302 }
303 }
304 // Process parentNode before childNode
305 for (auto&& node : dirtyFreezeNodeSet) {
306 node->ProcessFreezeNode();
307 }
308 }
309
FlushDirtyPropertyNodes()310 void PipelineContext::FlushDirtyPropertyNodes()
311 {
312 // node api property diff before ets update.
313 if (!CheckThreadSafe()) {
314 LOGW("FlushDirtyNodeUpdate doesn't run on UI thread!");
315 }
316 decltype(dirtyPropertyNodes_) dirtyPropertyNodes(std::move(dirtyPropertyNodes_));
317 dirtyPropertyNodes_.clear();
318 for (const auto& node : dirtyPropertyNodes) {
319 node->ProcessPropertyDiff();
320 }
321 }
322
FlushDirtyNodeUpdate()323 void PipelineContext::FlushDirtyNodeUpdate()
324 {
325 CHECK_RUN_ON(UI);
326 ACE_FUNCTION_TRACE();
327 if (FrameReport::GetInstance().GetEnable()) {
328 FrameReport::GetInstance().BeginFlushBuild();
329 }
330
331 // freeze node unlock before build begin.
332 FlushFreezeNode();
333
334 FlushDirtyPropertyNodes();
335
336 if (!ViewStackProcessor::GetInstance()->IsEmpty() && !dirtyNodes_.empty()) {
337 ACE_SCOPED_TRACE("Error update, node stack non-empty");
338 LOGW("stack is not empty when call FlushDirtyNodeUpdate, node may be mounted to incorrect pos!");
339 }
340 // SomeTimes, customNode->Update may add some dirty custom nodes to dirtyNodes_,
341 // use maxFlushTimes to avoid dead cycle.
342 int maxFlushTimes = 3;
343 while (!dirtyNodes_.empty() && maxFlushTimes > 0) {
344 ArkUIPerfMonitor::GetInstance().RecordStateMgmtNode(dirtyNodes_.size());
345 decltype(dirtyNodes_) dirtyNodes(std::move(dirtyNodes_));
346 for (const auto& node : dirtyNodes) {
347 if (AceType::InstanceOf<NG::CustomNodeBase>(node)) {
348 auto customNode = AceType::DynamicCast<NG::CustomNodeBase>(node);
349 ACE_SCOPED_TRACE("CustomNodeUpdate %s", customNode->GetJSViewName().c_str());
350 customNode->Update();
351 }
352 }
353 --maxFlushTimes;
354 }
355
356 if (FrameReport::GetInstance().GetEnable()) {
357 FrameReport::GetInstance().EndFlushBuild();
358 }
359 }
360
AddScheduleTask(const RefPtr<ScheduleTask> & task)361 uint32_t PipelineContext::AddScheduleTask(const RefPtr<ScheduleTask>& task)
362 {
363 CHECK_RUN_ON(UI);
364 scheduleTasks_.try_emplace(++nextScheduleTaskId_, task);
365 RequestFrame();
366 return nextScheduleTaskId_;
367 }
368
RemoveScheduleTask(uint32_t id)369 void PipelineContext::RemoveScheduleTask(uint32_t id)
370 {
371 CHECK_RUN_ON(UI);
372 scheduleTasks_.erase(id);
373 }
374
LinearInterpolation(const std::tuple<float,float,uint64_t> & history,const std::tuple<float,float,uint64_t> & current,const uint64_t nanoTimeStamp)375 std::tuple<float, float, float, float> PipelineContext::LinearInterpolation(
376 const std::tuple<float, float, uint64_t>& history, const std::tuple<float, float, uint64_t>& current,
377 const uint64_t nanoTimeStamp)
378 {
379 if (nanoTimeStamp == std::get<INDEX_TIME>(history) || nanoTimeStamp == std::get<INDEX_TIME>(current)) {
380 return std::make_tuple(0.0f, 0.0f, 0.0f, 0.0f);
381 }
382 if (std::get<INDEX_TIME>(current) <= std::get<INDEX_TIME>(history)) {
383 return std::make_tuple(0.0f, 0.0f, 0.0f, 0.0f);
384 }
385 if (std::get<INDEX_TIME>(current) - std::get<INDEX_TIME>(history) > INTERPOLATION_THRESHOLD) {
386 return std::make_tuple(0.0f, 0.0f, 0.0f, 0.0f);
387 }
388 if (nanoTimeStamp < std::get<INDEX_TIME>(history)) {
389 return std::make_tuple(0.0f, 0.0f, 0.0f, 0.0f);
390 }
391 auto inputXDeltaSlope = (std::get<INDEX_X>(current) - std::get<INDEX_X>(history)) * ONE_S_IN_NS /
392 (float)(std::get<INDEX_TIME>(current) - std::get<INDEX_TIME>(history));
393 auto inputYDeltaSlope = (std::get<INDEX_Y>(current) - std::get<INDEX_Y>(history)) * ONE_S_IN_NS /
394 (float)(std::get<INDEX_TIME>(current) - std::get<INDEX_TIME>(history));
395 if (nanoTimeStamp < std::get<INDEX_TIME>(current)) {
396 float alpha = (float)(nanoTimeStamp - std::get<INDEX_TIME>(history)) /
397 (float)(std::get<INDEX_TIME>(current) - std::get<INDEX_TIME>(history));
398 float x = std::get<INDEX_X>(history) + alpha * (std::get<INDEX_X>(current) - std::get<INDEX_X>(history));
399 float y = std::get<INDEX_Y>(history) + alpha * (std::get<INDEX_Y>(current) - std::get<INDEX_Y>(history));
400 return std::make_tuple(x, y, inputXDeltaSlope, inputYDeltaSlope);
401 } else if (nanoTimeStamp > std::get<INDEX_TIME>(current)) {
402 float alpha = (float)(nanoTimeStamp - std::get<INDEX_TIME>(current)) /
403 (float)(std::get<INDEX_TIME>(current) - std::get<INDEX_TIME>(history));
404 float x = std::get<INDEX_X>(current) + alpha * (std::get<INDEX_X>(current) - std::get<INDEX_X>(history));
405 float y = std::get<INDEX_Y>(current) + alpha * (std::get<INDEX_Y>(current) - std::get<INDEX_Y>(history));
406 return std::make_tuple(x, y, inputXDeltaSlope, inputYDeltaSlope);
407 }
408 return std::make_tuple(0.0f, 0.0f, 0.0f, 0.0f);
409 }
410
GetAvgPoint(const std::vector<TouchEvent> & events,const bool isScreen)411 std::tuple<float, float, uint64_t> PipelineContext::GetAvgPoint(
412 const std::vector<TouchEvent>& events, const bool isScreen)
413 {
414 float avgX = 0.0f;
415 float avgY = 0.0f;
416 uint64_t avgTime = 0;
417 int32_t i = 0;
418 uint64_t lastTime = 0;
419 for (auto iter = events.begin(); iter != events.end(); iter++) {
420 if (lastTime == 0 || static_cast<uint64_t>(iter->time.time_since_epoch().count()) != lastTime) {
421 if (!isScreen) {
422 avgX += iter->x;
423 avgY += iter->y;
424 } else {
425 avgX += iter->screenX;
426 avgY += iter->screenY;
427 }
428 avgTime += static_cast<uint64_t>(iter->time.time_since_epoch().count());
429 i++;
430 lastTime = static_cast<uint64_t>(iter->time.time_since_epoch().count());
431 }
432 }
433 if (i > 0) {
434 avgX /= i;
435 avgY /= i;
436 avgTime /= static_cast<uint64_t>(i);
437 }
438 return std::make_tuple(avgX, avgY, avgTime);
439 }
440
GetResampleCoord(const std::vector<TouchEvent> & history,const std::vector<TouchEvent> & current,const uint64_t nanoTimeStamp,const bool isScreen)441 std::tuple<float, float, float, float> PipelineContext::GetResampleCoord(const std::vector<TouchEvent>& history,
442 const std::vector<TouchEvent>& current, const uint64_t nanoTimeStamp, const bool isScreen)
443 {
444 if (history.empty() || current.empty()) {
445 return std::make_tuple(0.0f, 0.0f, 0.0f, 0.0f);
446 }
447 uint64_t lastNanoTime = 0;
448 float x = 0.0f;
449 float y = 0.0f;
450 for (const auto& item : current) {
451 uint64_t currentNanoTime = static_cast<uint64_t>(item.time.time_since_epoch().count());
452 if (lastNanoTime < currentNanoTime) {
453 lastNanoTime = currentNanoTime;
454 x = item.x;
455 y = item.y;
456 }
457 }
458 if (nanoTimeStamp > RESAMPLE_COORD_TIME_THRESHOLD + lastNanoTime) {
459 return std::make_tuple(x, y, 0.0f, 0.0f);
460 }
461 auto historyPoint = GetAvgPoint(history, isScreen);
462 auto currentPoint = GetAvgPoint(current, isScreen);
463
464 if (SystemProperties::GetDebugEnabled()) {
465 TAG_LOGD(AceLogTag::ACE_UIEVENT, "input time is %{public}" PRIu64 "", nanoTimeStamp);
466 for (auto iter : history) {
467 TAG_LOGD(AceLogTag::ACE_UIEVENT, "history point x %{public}f, y %{public}f, time %{public}" PRIu64 "",
468 iter.x, iter.y, static_cast<uint64_t>(iter.time.time_since_epoch().count()));
469 }
470 TAG_LOGD(AceLogTag::ACE_UIEVENT, "historyAvgPoint is x %{public}f, y %{public}f, time %{public}" PRIu64 "",
471 std::get<INDEX_X>(historyPoint), std::get<INDEX_Y>(historyPoint), std::get<INDEX_TIME>(historyPoint));
472 for (auto iter : current) {
473 TAG_LOGD(AceLogTag::ACE_UIEVENT, "current point x %{public}f, y %{public}f, time %{public}" PRIu64 "",
474 iter.x, iter.y, static_cast<uint64_t>(iter.time.time_since_epoch().count()));
475 }
476 TAG_LOGD(AceLogTag::ACE_UIEVENT, "currentAvgPoint is x %{public}f, y %{public}f, time %{public}" PRIu64 "",
477 std::get<INDEX_X>(currentPoint), std::get<INDEX_Y>(currentPoint), std::get<INDEX_TIME>(currentPoint));
478 }
479 return LinearInterpolation(historyPoint, currentPoint, nanoTimeStamp);
480 }
481
GetResampleTouchEvent(const std::vector<TouchEvent> & history,const std::vector<TouchEvent> & current,const uint64_t nanoTimeStamp,TouchEvent & newTouchEvent)482 bool PipelineContext::GetResampleTouchEvent(const std::vector<TouchEvent>& history,
483 const std::vector<TouchEvent>& current, const uint64_t nanoTimeStamp, TouchEvent& newTouchEvent)
484 {
485 auto newXy = GetResampleCoord(history, current, nanoTimeStamp, false);
486 auto newScreenXy = GetResampleCoord(history, current, nanoTimeStamp, true);
487 newTouchEvent = GetLatestPoint(current, nanoTimeStamp);
488 bool ret = false;
489 if (std::get<INDEX_X>(newXy) != 0 && std::get<INDEX_Y>(newXy) != 0) {
490 newTouchEvent.x = std::get<INDEX_X>(newXy);
491 newTouchEvent.y = std::get<INDEX_Y>(newXy);
492 newTouchEvent.screenX = std::get<INDEX_X>(newScreenXy);
493 newTouchEvent.screenY = std::get<INDEX_Y>(newScreenXy);
494 std::chrono::nanoseconds nanoseconds(nanoTimeStamp);
495 newTouchEvent.time = TimeStamp(nanoseconds);
496 newTouchEvent.history = current;
497 newTouchEvent.isInterpolated = true;
498 newTouchEvent.inputXDeltaSlope = std::get<INDEX_X_SLOPE>(newXy);
499 newTouchEvent.inputYDeltaSlope = std::get<INDEX_Y_SLOPE>(newXy);
500 ret = true;
501 }
502 if (SystemProperties::GetDebugEnabled()) {
503 TAG_LOGD(AceLogTag::ACE_UIEVENT,
504 "Interpolate point is %{public}d, %{public}f, %{public}f, %{public}f, %{public}f, %{public}" PRIu64 "",
505 newTouchEvent.id, newTouchEvent.x, newTouchEvent.y, newTouchEvent.screenX, newTouchEvent.screenY,
506 static_cast<uint64_t>(newTouchEvent.time.time_since_epoch().count()));
507 }
508 return ret;
509 }
510
GetLatestPoint(const std::vector<TouchEvent> & current,const uint64_t nanoTimeStamp)511 TouchEvent PipelineContext::GetLatestPoint(const std::vector<TouchEvent>& current, const uint64_t nanoTimeStamp)
512 {
513 TouchEvent result;
514 uint64_t gap = UINT64_MAX;
515 for (auto iter = current.begin(); iter != current.end(); iter++) {
516 uint64_t timeStamp = static_cast<uint64_t>(iter->time.time_since_epoch().count());
517 if (timeStamp == nanoTimeStamp) {
518 result = *iter;
519 return result;
520 } else if (timeStamp > nanoTimeStamp) {
521 if (timeStamp - nanoTimeStamp < gap) {
522 gap = timeStamp - nanoTimeStamp;
523 result = *iter;
524 }
525 } else {
526 if (nanoTimeStamp - timeStamp < gap) {
527 gap = nanoTimeStamp - timeStamp;
528 result = *iter;
529 }
530 }
531 }
532 return result;
533 }
534
FlushOnceVsyncTask()535 void PipelineContext::FlushOnceVsyncTask()
536 {
537 if (onceVsyncListener_ != nullptr) {
538 onceVsyncListener_();
539 onceVsyncListener_ = nullptr;
540 }
541 }
542
FlushVsync(uint64_t nanoTimestamp,uint32_t frameCount)543 void PipelineContext::FlushVsync(uint64_t nanoTimestamp, uint32_t frameCount)
544 {
545 CHECK_RUN_ON(UI);
546 if (IsDestroyed()) {
547 LOGW("Cannot flush vsync as the pipeline context is destroyed.");
548 return;
549 }
550 ACE_SCOPED_TRACE_COMMERCIAL("UIVsyncTask[timestamp:%" PRIu64 "][vsyncID:%" PRIu64 "][instanceID:%d]", nanoTimestamp,
551 static_cast<uint64_t>(frameCount), instanceId_);
552 window_->Lock();
553 static const std::string abilityName = AceApplicationInfo::GetInstance().GetProcessName().empty()
554 ? AceApplicationInfo::GetInstance().GetPackageName()
555 : AceApplicationInfo::GetInstance().GetProcessName();
556 window_->RecordFrameTime(nanoTimestamp, abilityName);
557 resampleTimeStamp_ = nanoTimestamp - static_cast<uint64_t>(window_->GetVSyncPeriod()) + ONE_MS_IN_NS -\
558 compensationValue_;
559 #ifdef UICAST_COMPONENT_SUPPORTED
560 do {
561 auto container = Container::Current();
562 CHECK_NULL_BREAK(container);
563 auto distributedUI = container->GetDistributedUI();
564 CHECK_NULL_BREAK(distributedUI);
565 distributedUI->ApplyOneUpdate();
566 } while (false);
567 #endif
568 ProcessDelayTasks();
569 DispatchDisplaySync(nanoTimestamp);
570 FlushAnimation(nanoTimestamp);
571 FlushFrameCallback(nanoTimestamp);
572 SetVsyncTime(nanoTimestamp);
573 auto hasRunningAnimation = FlushModifierAnimation(nanoTimestamp);
574 FlushTouchEvents();
575 FlushBuild();
576 if (isFormRender_ && drawDelegate_ && rootNode_) {
577 auto renderContext = AceType::DynamicCast<NG::RenderContext>(rootNode_->GetRenderContext());
578 drawDelegate_->DrawRSFrame(renderContext);
579 drawDelegate_ = nullptr;
580 }
581 if (!taskScheduler_->isEmpty()) {
582 #if !defined(PREVIEW)
583 LayoutInspector::SupportInspector();
584 #endif
585 }
586
587 taskScheduler_->StartRecordFrameInfo(GetCurrentFrameInfo(recvTime_, nanoTimestamp));
588 taskScheduler_->FlushTask();
589 UIObserverHandler::GetInstance().HandleLayoutDoneCallBack();
590 // flush correct rect again
591 taskScheduler_->FlushPersistAfterLayoutTask();
592 taskScheduler_->FlushLatestFrameLayoutFinishTask();
593 taskScheduler_->FinishRecordFrameInfo();
594 FlushNodeChangeFlag();
595 FlushAnimationClosure();
596 TryCallNextFrameLayoutCallback();
597
598 #ifdef UICAST_COMPONENT_SUPPORTED
599 do {
600 auto container = Container::Current();
601 CHECK_NULL_BREAK(container);
602 auto distributedUI = container->GetDistributedUI();
603 CHECK_NULL_BREAK(distributedUI);
604 distributedUI->OnTreeUpdate();
605 } while (false);
606 #endif
607
608 if (hasRunningAnimation || window_->HasUIRunningAnimation()) {
609 RequestFrame();
610 }
611 window_->FlushModifier();
612 FlushFrameRate();
613 if (dragWindowVisibleCallback_) {
614 dragWindowVisibleCallback_();
615 dragWindowVisibleCallback_ = nullptr;
616 }
617 if (isFirstFlushMessages_) {
618 isFirstFlushMessages_ = false;
619 LOGI("ArkUi flush first frame messages.");
620 }
621 FlushMessages();
622 InspectDrew();
623 UIObserverHandler::GetInstance().HandleDrawCommandSendCallBack();
624 FlushWindowPatternInfo();
625 if (onShow_ && onFocus_ && isWindowHasFocused_) {
626 auto isDynamicRender = Container::Current() == nullptr ? false : Container::Current()->IsDynamicRender();
627 if ((!isFormRender_) || isDynamicRender) {
628 FlushFocusView();
629 FlushFocus();
630 FlushFocusScroll();
631 }
632 }
633 HandleOnAreaChangeEvent(nanoTimestamp);
634 HandleVisibleAreaChangeEvent(nanoTimestamp);
635 if (isNeedFlushMouseEvent_) {
636 FlushMouseEvent();
637 isNeedFlushMouseEvent_ = false;
638 }
639 if (isNeedFlushAnimationStartTime_) {
640 window_->FlushAnimationStartTime(animationTimeStamp_);
641 isNeedFlushAnimationStartTime_ = false;
642 }
643 needRenderNode_.clear();
644 taskScheduler_->FlushAfterRenderTask();
645 FireAccessibilityEvents();
646 // Keep the call sent at the end of the function
647 ResSchedReport::GetInstance().LoadPageEvent(ResDefine::LOAD_PAGE_COMPLETE_EVENT);
648 window_->Unlock();
649 }
650
FlushWindowPatternInfo()651 void PipelineContext::FlushWindowPatternInfo()
652 {
653 #ifdef WINDOW_SCENE_SUPPORTED
654 auto container = Container::Current();
655 CHECK_NULL_VOID(container);
656 if (!container->IsScenceBoardWindow()) {
657 return;
658 }
659 auto screenNode = screenNode_.Upgrade();
660 if (!screenNode) {
661 return;
662 }
663 ACE_SCOPED_TRACE("FlushWindowPatternInfo");
664 auto instance = WindowSceneLayoutManager::GetInstance();
665 if (instance != nullptr) {
666 instance->FlushWindowPatternInfo(screenNode);
667 }
668 #endif
669 }
670
InspectDrew()671 void PipelineContext::InspectDrew()
672 {
673 CHECK_RUN_ON(UI);
674 if (!needRenderNode_.empty()) {
675 auto needRenderNode = std::move(needRenderNode_);
676 for (auto&& nodeWeak : needRenderNode) {
677 auto node = nodeWeak.Upgrade();
678 if (node) {
679 OnDrawCompleted(node->GetInspectorId()->c_str());
680 }
681 }
682 }
683 }
684
ProcessDelayTasks()685 void PipelineContext::ProcessDelayTasks()
686 {
687 if (delayedTasks_.empty()) {
688 return;
689 }
690 auto currentTimeStamp = GetSysTimestamp();
691 auto delayedTasks = std::move(delayedTasks_);
692 auto result = std::remove_if(delayedTasks.begin(), delayedTasks.end(), [this, currentTimeStamp](const auto& task) {
693 if (task.timeStamp + static_cast<int64_t>(task.time) * MILLISECONDS_TO_NANOSECONDS > currentTimeStamp) {
694 delayedTasks_.emplace_back(task);
695 return true;
696 }
697 return false;
698 });
699 delayedTasks.erase(result, delayedTasks.end());
700 std::for_each(delayedTasks.begin(), delayedTasks.end(), [this](auto& delayedTask) {
701 if (delayedTask.task) {
702 delayedTask.task();
703 }
704 });
705 }
706
DispatchDisplaySync(uint64_t nanoTimestamp)707 void PipelineContext::DispatchDisplaySync(uint64_t nanoTimestamp)
708 {
709 CHECK_RUN_ON(UI);
710 ACE_FUNCTION_TRACE();
711
712 GetOrCreateUIDisplaySyncManager()->SetRefreshRateMode(window_->GetCurrentRefreshRateMode());
713 GetOrCreateUIDisplaySyncManager()->SetVsyncPeriod(window_->GetVSyncPeriod());
714
715 if (FrameReport::GetInstance().GetEnable()) {
716 FrameReport::GetInstance().BeginFlushAnimation();
717 }
718
719 scheduleTasks_.clear();
720 GetOrCreateUIDisplaySyncManager()->DispatchFunc(nanoTimestamp);
721
722 if (FrameReport::GetInstance().GetEnable()) {
723 FrameReport::GetInstance().EndFlushAnimation();
724 }
725
726 int32_t displaySyncRate = GetOrCreateUIDisplaySyncManager()->GetDisplaySyncRate();
727 frameRateManager_->SetDisplaySyncRate(displaySyncRate);
728 ArkUIPerfMonitor::GetInstance().RecordDisplaySyncRate(displaySyncRate);
729 }
730
FlushAnimation(uint64_t nanoTimestamp)731 void PipelineContext::FlushAnimation(uint64_t nanoTimestamp)
732 {
733 CHECK_RUN_ON(UI);
734 ACE_FUNCTION_TRACE();
735 if (scheduleTasks_.empty()) {
736 return;
737 }
738 }
739
FlushModifier()740 void PipelineContext::FlushModifier()
741 {
742 window_->FlushModifier();
743 }
744
FlushMessages()745 void PipelineContext::FlushMessages()
746 {
747 ACE_FUNCTION_TRACE();
748 if (IsFreezeFlushMessage()) {
749 SetIsFreezeFlushMessage(false);
750 LOGI("Flush message is freezed.");
751 return;
752 }
753 window_->FlushTasks();
754 }
755
FlushUITasks(bool triggeredByImplicitAnimation)756 void PipelineContext::FlushUITasks(bool triggeredByImplicitAnimation)
757 {
758 window_->Lock();
759 if (!CheckThreadSafe()) {
760 LOGW("FlushUITasks doesn't run on UI thread!");
761 }
762 decltype(dirtyPropertyNodes_) dirtyPropertyNodes(std::move(dirtyPropertyNodes_));
763 dirtyPropertyNodes_.clear();
764 for (const auto& dirtyNode : dirtyPropertyNodes) {
765 dirtyNode->ProcessPropertyDiff();
766 }
767 taskScheduler_->FlushTask(triggeredByImplicitAnimation);
768 window_->Unlock();
769 }
770
FlushUITaskWithSingleDirtyNode(const RefPtr<FrameNode> & node)771 void PipelineContext::FlushUITaskWithSingleDirtyNode(const RefPtr<FrameNode>& node)
772 {
773 CHECK_NULL_VOID(node);
774 auto layoutProperty = node->GetLayoutProperty();
775 CHECK_NULL_VOID(layoutProperty);
776 auto layoutConstraint = node->GetLayoutConstraint();
777 auto originLayoutingFlag = IsLayouting();
778 SetIsLayouting(true);
779 if (layoutProperty->GetLayoutRect()) {
780 node->SetActive(true, true);
781 node->Measure(std::nullopt);
782 node->Layout();
783 } else {
784 auto ancestorNodeOfFrame = node->GetAncestorNodeOfFrame();
785 {
786 ACE_SCOPED_TRACE("FlushUITaskWithSingleDirtyNodeMeasure[%s][self:%d][parent:%d][layoutConstraint:%s]"
787 "[pageId:%d][depth:%d]",
788 node->GetTag().c_str(), node->GetId(), ancestorNodeOfFrame ? ancestorNodeOfFrame->GetId() : 0,
789 layoutConstraint.ToString().c_str(), node->GetPageId(), node->GetDepth());
790 node->Measure(layoutConstraint);
791 }
792 {
793 ACE_SCOPED_TRACE("FlushUITaskWithSingleDirtyNodeLayout[%s][self:%d][parent:%d][pageId:%d][depth:%d]",
794 node->GetTag().c_str(), node->GetId(), ancestorNodeOfFrame ? ancestorNodeOfFrame->GetId() : 0,
795 node->GetPageId(), node->GetDepth());
796 node->Layout();
797 }
798 }
799 SetIsLayouting(originLayoutingFlag);
800 }
801
FlushAfterLayoutCallbackInImplicitAnimationTask()802 void PipelineContext::FlushAfterLayoutCallbackInImplicitAnimationTask()
803 {
804 if (AnimationUtils::IsImplicitAnimationOpen()) {
805 TAG_LOGI(AceLogTag::ACE_ANIMATION,
806 "Can not flush implicit animation task after layout because implicit animation is open.");
807 return;
808 }
809 window_->Lock();
810 taskScheduler_->FlushAfterLayoutCallbackInImplicitAnimationTask();
811 window_->Unlock();
812 }
813
SetNeedRenderNode(const WeakPtr<FrameNode> & node)814 void PipelineContext::SetNeedRenderNode(const WeakPtr<FrameNode>& node)
815 {
816 CHECK_RUN_ON(UI);
817 needRenderNode_.insert(node);
818 }
819
FlushFocus()820 void PipelineContext::FlushFocus()
821 {
822 CHECK_RUN_ON(UI);
823 ACE_FUNCTION_TRACK();
824 ACE_FUNCTION_TRACE();
825
826 FlushRequestFocus();
827
828 auto focusNode = dirtyFocusNode_.Upgrade();
829 if (!focusNode || focusNode->GetFocusType() != FocusType::NODE) {
830 dirtyFocusNode_.Reset();
831 } else {
832 FlushFocusWithNode(focusNode, false);
833 return;
834 }
835 auto focusScope = dirtyFocusScope_.Upgrade();
836 if (!focusScope || focusScope->GetFocusType() != FocusType::SCOPE) {
837 dirtyFocusScope_.Reset();
838 } else {
839 FlushFocusWithNode(focusScope, true);
840 return;
841 }
842 GetOrCreateFocusManager()->WindowFocusMoveEnd();
843 }
844
FlushFocusWithNode(RefPtr<FrameNode> focusNode,bool isScope)845 void PipelineContext::FlushFocusWithNode(RefPtr<FrameNode> focusNode, bool isScope)
846 {
847 auto focusNodeHub = focusNode->GetFocusHub();
848 if (focusNodeHub && !focusNodeHub->RequestFocusImmediately()) {
849 auto unfocusableParentFocusNode = focusNodeHub->GetUnfocusableParentFocusNode().Upgrade();
850 if (unfocusableParentFocusNode) {
851 TAG_LOGI(AceLogTag::ACE_FOCUS,
852 "Request focus on %{public}s: %{public}s/%{public}d return false, unfocusable node: "
853 "%{public}s/%{public}d, focusable = %{public}d, shown = %{public}d, enabled = %{public}d",
854 isScope ? "scope" : "node", focusNode->GetTag().c_str(), focusNode->GetId(),
855 unfocusableParentFocusNode->GetFrameName().c_str(), unfocusableParentFocusNode->GetFrameId(),
856 unfocusableParentFocusNode->GetFocusable(), unfocusableParentFocusNode->IsShow(),
857 unfocusableParentFocusNode->IsEnabled());
858 unfocusableParentFocusNode = nullptr;
859 } else {
860 TAG_LOGI(AceLogTag::ACE_FOCUS, "Request focus on %{public}s: %{public}s/%{public}d return false",
861 isScope ? "scope" : "node", focusNode->GetTag().c_str(), focusNode->GetId());
862 }
863 }
864 dirtyFocusNode_.Reset();
865 dirtyFocusScope_.Reset();
866 dirtyRequestFocusNode_.Reset();
867 GetOrCreateFocusManager()->WindowFocusMoveEnd();
868 }
869
FlushRequestFocus()870 void PipelineContext::FlushRequestFocus()
871 {
872 CHECK_RUN_ON(UI);
873
874 auto requestFocusNode = dirtyRequestFocusNode_.Upgrade();
875 if (!requestFocusNode) {
876 dirtyRequestFocusNode_.Reset();
877 } else {
878 auto focusNodeHub = requestFocusNode->GetFocusHub();
879 if (focusNodeHub && !focusNodeHub->RequestFocusImmediately()) {
880 auto unfocusableParentFocusNode = focusNodeHub->GetUnfocusableParentFocusNode().Upgrade();
881 if (unfocusableParentFocusNode) {
882 TAG_LOGI(AceLogTag::ACE_FOCUS,
883 "Request focus by id on node: %{public}s/%{public}d return false, unfocusable node: "
884 "%{public}s/%{public}d, focusable = %{public}d, shown = %{public}d, enabled = %{public}d",
885 requestFocusNode->GetTag().c_str(), requestFocusNode->GetId(),
886 unfocusableParentFocusNode->GetFrameName().c_str(), unfocusableParentFocusNode->GetFrameId(),
887 unfocusableParentFocusNode->GetFocusable(), unfocusableParentFocusNode->IsShow(),
888 unfocusableParentFocusNode->IsEnabled());
889 unfocusableParentFocusNode = nullptr;
890 }
891 }
892 dirtyFocusNode_.Reset();
893 dirtyFocusScope_.Reset();
894 dirtyRequestFocusNode_.Reset();
895 return;
896 }
897 }
898
FlushFocusView()899 void PipelineContext::FlushFocusView()
900 {
901 CHECK_NULL_VOID(focusManager_);
902 auto lastFocusView = (focusManager_->GetLastFocusView()).Upgrade();
903 CHECK_NULL_VOID(lastFocusView);
904 auto lastFocusViewHub = lastFocusView->GetFocusHub();
905 CHECK_NULL_VOID(lastFocusViewHub);
906 auto container = Container::Current();
907 if (container && (container->IsUIExtensionWindow() || container->IsDynamicRender()) &&
908 (!lastFocusView->IsRootScopeCurrentFocus())) {
909 lastFocusView->SetIsViewRootScopeFocused(false);
910 }
911 if (lastFocusView && (!lastFocusView->IsRootScopeCurrentFocus() || !lastFocusView->GetIsViewHasFocused()) &&
912 lastFocusViewHub->IsFocusableNode()) {
913 lastFocusView->RequestDefaultFocus();
914 }
915 }
916
FlushFocusScroll()917 void PipelineContext::FlushFocusScroll()
918 {
919 CHECK_NULL_VOID(focusManager_);
920 if (!focusManager_->GetNeedTriggerScroll()) {
921 return;
922 }
923 auto lastFocusStateNode = focusManager_->GetLastFocusStateNode();
924 CHECK_NULL_VOID(lastFocusStateNode);
925 if (!lastFocusStateNode->TriggerFocusScroll()) {
926 focusManager_->SetNeedTriggerScroll(false);
927 }
928 }
929
FlushPipelineImmediately()930 void PipelineContext::FlushPipelineImmediately()
931 {
932 CHECK_RUN_ON(UI);
933 ACE_FUNCTION_TRACE();
934 FlushPipelineWithoutAnimation();
935 }
936
RebuildFontNode()937 void PipelineContext::RebuildFontNode()
938 {
939 if (fontManager_) {
940 fontManager_->RebuildFontNodeNG();
941 }
942 }
943
FlushPipelineWithoutAnimation()944 void PipelineContext::FlushPipelineWithoutAnimation()
945 {
946 ACE_FUNCTION_TRACE();
947 window_->Lock();
948 FlushBuild();
949 FlushTouchEvents();
950 taskScheduler_->FlushTask();
951 FlushAnimationClosure();
952 window_->FlushModifier();
953 FlushMessages();
954 FlushFocus();
955 window_->Unlock();
956 }
957
FlushFrameRate()958 void PipelineContext::FlushFrameRate()
959 {
960 frameRateManager_->SetAnimateRate(window_->GetAnimateExpectedRate());
961 int32_t currAnimatorExpectedFrameRate = GetOrCreateUIDisplaySyncManager()->GetAnimatorRate();
962 if (frameRateManager_->IsRateChanged() || currAnimatorExpectedFrameRate != lastAnimatorExpectedFrameRate_) {
963 auto [rate, rateType] = frameRateManager_->GetExpectedRate();
964 ACE_SCOPED_TRACE("FlushFrameRate Expected frameRate = %d frameRateType = %d "
965 "currAnimatorExpectedFrameRate = %d, lastAnimatorExpectedFrameRate = %d",
966 rate, rateType, currAnimatorExpectedFrameRate, lastAnimatorExpectedFrameRate_);
967 TAG_LOGD(AceLogTag::ACE_DISPLAY_SYNC, "FlushFrameRate Expected frameRate = %{public}d "
968 "frameRateType = %{public}d currAnimatorExpectedFrameRate = %{public}d, lastRate = %{public}d",
969 rate, rateType, currAnimatorExpectedFrameRate, lastAnimatorExpectedFrameRate_);
970 window_->FlushFrameRate(rate, currAnimatorExpectedFrameRate, rateType);
971 frameRateManager_->SetIsRateChanged(false);
972 lastAnimatorExpectedFrameRate_ = currAnimatorExpectedFrameRate;
973 }
974 }
975
FlushBuild()976 void PipelineContext::FlushBuild()
977 {
978 if (vsyncListener_ != nullptr) {
979 ACE_SCOPED_TRACE("arkoala build");
980 vsyncListener_();
981 }
982 FlushOnceVsyncTask();
983 isRebuildFinished_ = false;
984 FlushDirtyNodeUpdate();
985 isRebuildFinished_ = true;
986 FlushBuildFinishCallbacks();
987 }
988
AddAnimationClosure(std::function<void ()> && animation)989 void PipelineContext::AddAnimationClosure(std::function<void()>&& animation)
990 {
991 animationClosuresList_.emplace_back(std::move(animation));
992 }
993
FlushAnimationClosure()994 void PipelineContext::FlushAnimationClosure()
995 {
996 if (animationClosuresList_.empty()) {
997 return;
998 }
999 window_->Lock();
1000 taskScheduler_->FlushTask();
1001
1002 decltype(animationClosuresList_) temp(std::move(animationClosuresList_));
1003 for (const auto& animation : temp) {
1004 animation();
1005 }
1006 window_->Unlock();
1007 }
1008
FlushBuildFinishCallbacks()1009 void PipelineContext::FlushBuildFinishCallbacks()
1010 {
1011 decltype(buildFinishCallbacks_) buildFinishCallbacks(std::move(buildFinishCallbacks_));
1012 for (const auto& func : buildFinishCallbacks) {
1013 if (func) {
1014 func();
1015 }
1016 }
1017 }
1018
RegisterRootEvent()1019 void PipelineContext::RegisterRootEvent()
1020 {
1021 if (!IsFormRender()) {
1022 return;
1023 }
1024 auto accessibilityProperty = rootNode_->GetAccessibilityProperty<AccessibilityProperty>();
1025 if (accessibilityProperty != nullptr) {
1026 accessibilityProperty->SetAccessibilityLevel(AccessibilityProperty::Level::NO_STR);
1027 }
1028
1029 // To avoid conflicts between longPress and click events on the card,
1030 // use an empty longPress event placeholder in the EtsCard scenario
1031 auto hub = rootNode_->GetOrCreateGestureEventHub();
1032 CHECK_NULL_VOID(hub);
1033 auto event = [](const GestureEvent& info) mutable {};
1034 auto longPress = AceType::MakeRefPtr<NG::LongPressEvent>(std::move(event));
1035 hub->SetLongPressEvent(longPress, false, true);
1036 }
1037
SetupRootElement()1038 void PipelineContext::SetupRootElement()
1039 {
1040 CHECK_RUN_ON(UI);
1041 rootNode_ = FrameNode::CreateFrameNodeWithTree(
1042 V2::ROOT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<RootPattern>());
1043 rootNode_->SetHostRootId(GetInstanceId());
1044 rootNode_->SetHostPageId(-1);
1045 rootNode_->SetActive(true);
1046 RegisterRootEvent();
1047 CalcSize idealSize { CalcLength(rootWidth_), CalcLength(rootHeight_) };
1048 MeasureProperty layoutConstraint;
1049 layoutConstraint.selfIdealSize = idealSize;
1050 layoutConstraint.maxSize = idealSize;
1051 rootNode_->UpdateLayoutConstraint(layoutConstraint);
1052 auto rootFocusHub = rootNode_->GetOrCreateFocusHub();
1053 rootFocusHub->SetFocusType(FocusType::SCOPE);
1054 rootFocusHub->SetFocusable(true);
1055 window_->SetRootFrameNode(rootNode_);
1056 rootNode_->AttachToMainTree(false, this);
1057 auto stagePattern = ViewAdvancedRegister::GetInstance()->GeneratePattern(V2::STAGE_ETS_TAG);
1058 if (!stagePattern) {
1059 stagePattern = MakeRefPtr<StagePattern>();
1060 }
1061 auto stageNode = FrameNode::CreateFrameNode(
1062 V2::STAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), stagePattern);
1063 RefPtr<AppBarView> appBar = AceType::MakeRefPtr<AppBarView>();
1064 auto atomicService = installationFree_ ? appBar->Create(stageNode) : nullptr;
1065 auto container = Container::Current();
1066 if (container) {
1067 container->SetAppBar(appBar);
1068 }
1069 if (windowModal_ == WindowModal::CONTAINER_MODAL) {
1070 MaximizeMode maximizeMode = GetWindowManager()->GetWindowMaximizeMode();
1071 rootNode_->AddChild(
1072 ContainerModalViewFactory::GetView(atomicService ? atomicService : stageNode, maximizeMode));
1073 } else {
1074 rootNode_->AddChild(atomicService ? atomicService : stageNode);
1075 }
1076 #ifdef ENABLE_ROSEN_BACKEND
1077 if (!IsJsCard() && !isFormRender_) {
1078 auto window = GetWindow();
1079 if (window) {
1080 auto rsUIDirector = window->GetRSUIDirector();
1081 if (rsUIDirector) {
1082 rsUIDirector->SetAbilityBGAlpha(appBgColor_.GetAlpha());
1083 }
1084 }
1085 }
1086 #endif
1087 #ifdef WINDOW_SCENE_SUPPORTED
1088 uiExtensionManager_ = MakeRefPtr<UIExtensionManager>();
1089 #endif
1090 accessibilityManagerNG_ = MakeRefPtr<AccessibilityManagerNG>();
1091 stageManager_ = ViewAdvancedRegister::GetInstance()->GenerateStageManager(stageNode);
1092 if (!stageManager_) {
1093 stageManager_ = MakeRefPtr<StageManager>(stageNode);
1094 }
1095 overlayManager_ = MakeRefPtr<OverlayManager>(
1096 DynamicCast<FrameNode>(installationFree_ ? stageNode->GetParent()->GetParent() : stageNode->GetParent()));
1097 fullScreenManager_ = MakeRefPtr<FullScreenManager>(rootNode_);
1098 selectOverlayManager_ = MakeRefPtr<SelectOverlayManager>(rootNode_);
1099 fontManager_->AddFontObserver(selectOverlayManager_);
1100 if (!privacySensitiveManager_) {
1101 privacySensitiveManager_ = MakeRefPtr<PrivacySensitiveManager>();
1102 }
1103 postEventManager_ = MakeRefPtr<PostEventManager>();
1104 dragDropManager_ = MakeRefPtr<DragDropManager>();
1105 focusManager_ = GetOrCreateFocusManager();
1106 sharedTransitionManager_ = MakeRefPtr<SharedOverlayManager>(
1107 DynamicCast<FrameNode>(installationFree_ ? stageNode->GetParent()->GetParent() : stageNode->GetParent()));
1108
1109 OnAreaChangedFunc onAreaChangedFunc = [weakOverlayManger = AceType::WeakClaim(AceType::RawPtr(overlayManager_))](
1110 const RectF& /* oldRect */, const OffsetF& /* oldOrigin */,
1111 const RectF& /* rect */, const OffsetF& /* origin */) {
1112 TAG_LOGD(AceLogTag::ACE_OVERLAY, "start OnAreaChangedFunc");
1113 auto overlay = weakOverlayManger.Upgrade();
1114 CHECK_NULL_VOID(overlay);
1115 overlay->HideAllMenus();
1116 SubwindowManager::GetInstance()->HideMenuNG(false);
1117 overlay->HideCustomPopups();
1118 SubwindowManager::GetInstance()->ClearToastInSubwindow();
1119 SubwindowManager::GetInstance()->ClearToastInSystemSubwindow();
1120 overlay->UpdateCustomKeyboardPosition();
1121 };
1122 rootNode_->SetOnAreaChangeCallback(std::move(onAreaChangedFunc));
1123 AddOnAreaChangeNode(rootNode_->GetId());
1124 }
1125
SetupSubRootElement()1126 void PipelineContext::SetupSubRootElement()
1127 {
1128 CHECK_RUN_ON(UI);
1129 appBgColor_ = Color::TRANSPARENT;
1130 rootNode_ = FrameNode::CreateFrameNodeWithTree(
1131 V2::ROOT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<RootPattern>());
1132 rootNode_->SetHostRootId(GetInstanceId());
1133 rootNode_->SetHostPageId(-1);
1134 rootNode_->SetActive(true);
1135 CalcSize idealSize { CalcLength(rootWidth_), CalcLength(rootHeight_) };
1136 MeasureProperty layoutConstraint;
1137 layoutConstraint.selfIdealSize = idealSize;
1138 layoutConstraint.maxSize = idealSize;
1139 rootNode_->UpdateLayoutConstraint(layoutConstraint);
1140 auto rootFocusHub = rootNode_->GetOrCreateFocusHub();
1141 rootFocusHub->SetFocusType(FocusType::SCOPE);
1142 rootFocusHub->SetFocusable(true);
1143 window_->SetRootFrameNode(rootNode_);
1144 rootNode_->AttachToMainTree(false, this);
1145
1146 #ifdef ENABLE_ROSEN_BACKEND
1147 if (!IsJsCard()) {
1148 auto window = GetWindow();
1149 if (window) {
1150 auto rsUIDirector = window->GetRSUIDirector();
1151 if (rsUIDirector) {
1152 rsUIDirector->SetAbilityBGAlpha(appBgColor_.GetAlpha());
1153 }
1154 }
1155 }
1156 #endif
1157 #ifdef WINDOW_SCENE_SUPPORTED
1158 uiExtensionManager_ = MakeRefPtr<UIExtensionManager>();
1159 #endif
1160 accessibilityManagerNG_ = MakeRefPtr<AccessibilityManagerNG>();
1161 // the subwindow for overlay not need stage
1162 stageManager_ = ViewAdvancedRegister::GetInstance()->GenerateStageManager(nullptr);
1163 if (!stageManager_) {
1164 stageManager_ = MakeRefPtr<StageManager>(nullptr);
1165 }
1166 overlayManager_ = MakeRefPtr<OverlayManager>(rootNode_);
1167 fullScreenManager_ = MakeRefPtr<FullScreenManager>(rootNode_);
1168 selectOverlayManager_ = MakeRefPtr<SelectOverlayManager>(rootNode_);
1169 fontManager_->AddFontObserver(selectOverlayManager_);
1170 dragDropManager_ = MakeRefPtr<DragDropManager>();
1171 focusManager_ = GetOrCreateFocusManager();
1172 postEventManager_ = MakeRefPtr<PostEventManager>();
1173 }
1174
GetAccessibilityManagerNG()1175 RefPtr<AccessibilityManagerNG> PipelineContext::GetAccessibilityManagerNG()
1176 {
1177 return accessibilityManagerNG_;
1178 }
1179
SendEventToAccessibilityWithNode(const AccessibilityEvent & accessibilityEvent,const RefPtr<FrameNode> & node)1180 void PipelineContext::SendEventToAccessibilityWithNode(
1181 const AccessibilityEvent& accessibilityEvent, const RefPtr<FrameNode>& node)
1182 {
1183 auto accessibilityManager = GetAccessibilityManager();
1184 if (!accessibilityManager || !AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
1185 return;
1186 }
1187 accessibilityManager->SendEventToAccessibilityWithNode(accessibilityEvent, node, Claim(this));
1188 }
1189
GetStageManager()1190 const RefPtr<StageManager>& PipelineContext::GetStageManager()
1191 {
1192 return stageManager_;
1193 }
1194
GetDragDropManager()1195 const RefPtr<DragDropManager>& PipelineContext::GetDragDropManager()
1196 {
1197 return dragDropManager_;
1198 }
1199
GetFocusManager() const1200 const RefPtr<FocusManager>& PipelineContext::GetFocusManager() const
1201 {
1202 return focusManager_;
1203 }
1204
GetOrCreateFocusManager()1205 const RefPtr<FocusManager>& PipelineContext::GetOrCreateFocusManager()
1206 {
1207 if (!focusManager_) {
1208 focusManager_ = MakeRefPtr<FocusManager>(AceType::Claim(this));
1209 RegisterFocusCallback();
1210 }
1211 return focusManager_;
1212 }
1213
GetSelectOverlayManager()1214 const RefPtr<SelectOverlayManager>& PipelineContext::GetSelectOverlayManager()
1215 {
1216 return selectOverlayManager_;
1217 }
1218
GetOverlayManager()1219 const RefPtr<OverlayManager>& PipelineContext::GetOverlayManager()
1220 {
1221 return overlayManager_;
1222 }
1223
GetFullScreenManager()1224 const RefPtr<FullScreenManager>& PipelineContext::GetFullScreenManager()
1225 {
1226 return fullScreenManager_;
1227 }
1228
OnSurfaceChanged(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)1229 void PipelineContext::OnSurfaceChanged(int32_t width, int32_t height, WindowSizeChangeReason type,
1230 const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
1231 {
1232 CHECK_RUN_ON(UI);
1233 if (NearEqual(rootWidth_, width) && NearEqual(rootHeight_, height) &&
1234 type == WindowSizeChangeReason::CUSTOM_ANIMATION && !isDensityChanged_) {
1235 TryCallNextFrameLayoutCallback();
1236 return;
1237 }
1238 ExecuteSurfaceChangedCallbacks(width, height, type);
1239 auto callback = [weakFrontend = weakFrontend_, width, height]() {
1240 auto frontend = weakFrontend.Upgrade();
1241 if (frontend) {
1242 frontend->OnSurfaceChanged(width, height);
1243 }
1244 };
1245 auto container = Container::Current();
1246 if (!container) {
1247 return;
1248 }
1249 if (container->IsUseStageModel()) {
1250 callback();
1251 FlushBuild();
1252 } else {
1253 taskExecutor_->PostTask(callback, TaskExecutor::TaskType::JS, "ArkUISurfaceChanged");
1254 }
1255
1256 FlushWindowSizeChangeCallback(width, height, type);
1257 UpdateHalfFoldHoverProperty(width, height);
1258 UpdateSizeChangeReason(type, rsTransaction);
1259
1260 #ifdef ENABLE_ROSEN_BACKEND
1261 StartWindowSizeChangeAnimate(width, height, type, rsTransaction);
1262 #else
1263 SetRootRect(width, height, 0.0);
1264 #endif
1265 }
1266
UpdateHalfFoldHoverProperty(int32_t windowWidth,int32_t windowHeight)1267 void PipelineContext::UpdateHalfFoldHoverProperty(int32_t windowWidth, int32_t windowHeight)
1268 {
1269 isHoverModeChanged_ = false;
1270 preIsHalfFoldHoverStatus_ = isHalfFoldHoverStatus_;
1271 UpdateHalfFoldHoverStatus(windowWidth, windowHeight);
1272 if (preIsHalfFoldHoverStatus_ != isHalfFoldHoverStatus_) {
1273 isHoverModeChanged_ = true;
1274 }
1275 }
1276
OnLayoutCompleted(const std::string & componentId)1277 void PipelineContext::OnLayoutCompleted(const std::string& componentId)
1278 {
1279 CHECK_RUN_ON(UI);
1280 auto frontend = weakFrontend_.Upgrade();
1281 if (frontend) {
1282 frontend->OnLayoutCompleted(componentId);
1283 }
1284 }
1285
OnDrawCompleted(const std::string & componentId)1286 void PipelineContext::OnDrawCompleted(const std::string& componentId)
1287 {
1288 CHECK_RUN_ON(UI);
1289 auto frontend = weakFrontend_.Upgrade();
1290 if (frontend) {
1291 frontend->OnDrawCompleted(componentId);
1292 }
1293 }
1294
ExecuteSurfaceChangedCallbacks(int32_t newWidth,int32_t newHeight,WindowSizeChangeReason type)1295 void PipelineContext::ExecuteSurfaceChangedCallbacks(int32_t newWidth, int32_t newHeight, WindowSizeChangeReason type)
1296 {
1297 for (auto&& [id, callback] : surfaceChangedCallbackMap_) {
1298 if (callback) {
1299 callback(newWidth, newHeight, rootWidth_, rootHeight_, type);
1300 }
1301 }
1302 }
1303
OnSurfacePositionChanged(int32_t posX,int32_t posY)1304 void PipelineContext::OnSurfacePositionChanged(int32_t posX, int32_t posY)
1305 {
1306 for (auto&& [id, callback] : surfacePositionChangedCallbackMap_) {
1307 if (callback) {
1308 callback(posX, posY);
1309 }
1310 }
1311 }
1312
OnFoldStatusChange(FoldStatus foldStatus)1313 void PipelineContext::OnFoldStatusChange(FoldStatus foldStatus)
1314 {
1315 for (auto&& [id, callback] : foldStatusChangedCallbackMap_) {
1316 if (callback) {
1317 callback(foldStatus);
1318 }
1319 }
1320 StartFoldStatusDelayTask(foldStatus);
1321 }
1322
OnFoldDisplayModeChange(FoldDisplayMode foldDisplayMode)1323 void PipelineContext::OnFoldDisplayModeChange(FoldDisplayMode foldDisplayMode)
1324 {
1325 for (auto&& [id, callback] : foldDisplayModeChangedCallbackMap_) {
1326 if (callback) {
1327 callback(foldDisplayMode);
1328 }
1329 }
1330 }
1331
OnTransformHintChanged(uint32_t transform)1332 void PipelineContext::OnTransformHintChanged(uint32_t transform)
1333 {
1334 for (auto&& [id, callback] : transformHintChangedCallbackMap_) {
1335 if (callback) {
1336 callback(transform);
1337 }
1338 }
1339 transform_ = transform;
1340 }
1341
StartWindowSizeChangeAnimate(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)1342 void PipelineContext::StartWindowSizeChangeAnimate(int32_t width, int32_t height, WindowSizeChangeReason type,
1343 const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
1344 {
1345 static const bool IsWindowSizeAnimationEnabled = SystemProperties::IsWindowSizeAnimationEnabled();
1346 if (!IsWindowSizeAnimationEnabled) {
1347 SetRootRect(width, height, 0.0);
1348 return;
1349 }
1350 switch (type) {
1351 case WindowSizeChangeReason::FULL_TO_SPLIT:
1352 case WindowSizeChangeReason::FULL_TO_FLOATING: {
1353 StartFullToMultWindowAnimation(width, height, type, rsTransaction);
1354 break;
1355 }
1356 case WindowSizeChangeReason::RECOVER:
1357 case WindowSizeChangeReason::MAXIMIZE: {
1358 StartWindowMaximizeAnimation(width, height, rsTransaction);
1359 break;
1360 }
1361 case WindowSizeChangeReason::ROTATION: {
1362 safeAreaManager_->UpdateKeyboardOffset(0.0);
1363 SetRootRect(width, height, 0.0);
1364 FlushUITasks();
1365 if (textFieldManager_) {
1366 DynamicCast<TextFieldManagerNG>(textFieldManager_)->ScrollTextFieldToSafeArea();
1367 }
1368 FlushUITasks();
1369 if (!textFieldManager_) {
1370 break;
1371 }
1372 PostKeyboardAvoidTask();
1373 break;
1374 }
1375 case WindowSizeChangeReason::DRAG_START:
1376 case WindowSizeChangeReason::DRAG:
1377 case WindowSizeChangeReason::DRAG_END:
1378 case WindowSizeChangeReason::RESIZE:
1379 case WindowSizeChangeReason::UNDEFINED:
1380 default: {
1381 SetRootRect(width, height, 0.0f);
1382 }
1383 }
1384 }
1385
PostKeyboardAvoidTask()1386 void PipelineContext::PostKeyboardAvoidTask()
1387 {
1388 auto textFieldManager = DynamicCast<TextFieldManagerNG>(textFieldManager_);
1389 CHECK_NULL_VOID(textFieldManager);
1390 CHECK_NULL_VOID(textFieldManager->GetLaterAvoid());
1391 auto container = Container::Current();
1392 if (container) {
1393 auto displayInfo = container->GetDisplayInfo();
1394 if (displayInfo && textFieldManager->GetLaterOrientation() != (int32_t)displayInfo->GetRotation()) {
1395 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "orientation not match, clear laterAvoid");
1396 textFieldManager->SetLaterAvoid(false);
1397 return;
1398 }
1399 }
1400 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "after rotation set root, trigger avoid now");
1401 taskExecutor_->PostTask(
1402 [weakContext = WeakClaim(this), keyboardRect = textFieldManager->GetLaterAvoidKeyboardRect(),
1403 positionY = textFieldManager->GetLaterAvoidPositionY(),
1404 height = textFieldManager->GetLaterAvoidHeight(),
1405 weakManager = WeakPtr<TextFieldManagerNG>(textFieldManager)] {
1406 auto context = weakContext.Upgrade();
1407 CHECK_NULL_VOID(context);
1408 context->OnVirtualKeyboardAreaChange(keyboardRect, positionY, height);
1409 auto manager = weakManager.Upgrade();
1410 CHECK_NULL_VOID(manager);
1411 manager->SetLaterAvoid(false);
1412 },
1413 TaskExecutor::TaskType::UI, "ArkUIVirtualKeyboardAreaChange");
1414 }
1415
StartWindowMaximizeAnimation(int32_t width,int32_t height,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)1416 void PipelineContext::StartWindowMaximizeAnimation(
1417 int32_t width, int32_t height, const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
1418 {
1419 TAG_LOGI(AceLogTag::ACE_ANIMATION,
1420 "Root node start RECOVER/MAXIMIZE animation, width = %{public}d, height = %{public}d", width, height);
1421 #ifdef ENABLE_ROSEN_BACKEND
1422 if (rsTransaction) {
1423 FlushMessages();
1424 rsTransaction->Begin();
1425 }
1426 #endif
1427 AnimationOption option;
1428 int32_t duration = 400;
1429 MaximizeMode maximizeMode = GetWindowManager()->GetWindowMaximizeMode();
1430 bool freeMultiWindowModeEnabled = GetWindowManager()->GetFreeMultiWindowModeEnabledState();
1431 if (maximizeMode == MaximizeMode::MODE_FULL_FILL || maximizeMode == MaximizeMode::MODE_AVOID_SYSTEM_BAR ||
1432 freeMultiWindowModeEnabled) {
1433 int32_t preWidth = GetRootRect().Width();
1434 int32_t preHeight = GetRootRect().Height();
1435 if (width > preWidth && height > preHeight) {
1436 duration = 0;
1437 }
1438 }
1439 option.SetDuration(duration);
1440 auto curve = Curves::EASE_OUT;
1441 option.SetCurve(curve);
1442 auto weak = WeakClaim(this);
1443 Animate(option, curve, [width, height, weak]() {
1444 auto pipeline = weak.Upgrade();
1445 CHECK_NULL_VOID(pipeline);
1446 pipeline->SetRootRect(width, height, 0.0);
1447 pipeline->FlushUITasks();
1448 });
1449 #ifdef ENABLE_ROSEN_BACKEND
1450 if (rsTransaction) {
1451 rsTransaction->Commit();
1452 }
1453 #endif
1454 }
1455
StartFullToMultWindowAnimation(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)1456 void PipelineContext::StartFullToMultWindowAnimation(int32_t width, int32_t height,
1457 WindowSizeChangeReason type, const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
1458 {
1459 TAG_LOGI(AceLogTag::ACE_ANIMATION,
1460 "Root node start multiple window animation, type = %{public}d, width = %{public}d, height = %{public}d", type,
1461 width, height);
1462 #ifdef ENABLE_ROSEN_BACKEND
1463 if (rsTransaction) {
1464 FlushMessages();
1465 rsTransaction->Begin();
1466 }
1467 #endif
1468 float response = 0.5f;
1469 float dampingFraction = 1.0f;
1470 AnimationOption option;
1471 if (type == WindowSizeChangeReason::FULL_TO_FLOATING) {
1472 response = 0.45f;
1473 dampingFraction = 0.75f;
1474 }
1475 auto springMotion = AceType::MakeRefPtr<ResponsiveSpringMotion>(response, dampingFraction, 0);
1476 option.SetCurve(springMotion);
1477 auto weak = WeakClaim(this);
1478 Animate(option, springMotion, [width, height, weak]() {
1479 auto pipeline = weak.Upgrade();
1480 CHECK_NULL_VOID(pipeline);
1481 pipeline->SetRootRect(width, height, 0.0);
1482 pipeline->FlushUITasks();
1483 });
1484 #ifdef ENABLE_ROSEN_BACKEND
1485 if (rsTransaction) {
1486 rsTransaction->Commit();
1487 }
1488 #endif
1489 }
1490
SetRootRect(double width,double height,double offset)1491 void PipelineContext::SetRootRect(double width, double height, double offset)
1492 {
1493 CHECK_RUN_ON(UI);
1494 UpdateRootSizeAndScale(width, height);
1495 CHECK_NULL_VOID(rootNode_);
1496 if (Container::CurrentId() < MIN_SUBCONTAINER_ID) {
1497 ScreenSystemManager::GetInstance().SetWindowInfo(rootWidth_, density_, dipScale_);
1498 ScreenSystemManager::GetInstance().OnSurfaceChanged(width);
1499 } else {
1500 ScreenSystemManager::GetInstance().SetWindowInfo(density_, dipScale_);
1501 }
1502 SizeF sizeF { static_cast<float>(width), static_cast<float>(height) };
1503 if (rootNode_->GetGeometryNode()->GetFrameSize() != sizeF || rootNode_->IsLayoutDirtyMarked()) {
1504 CalcSize idealSize { CalcLength(width), CalcLength(height) };
1505 MeasureProperty layoutConstraint;
1506 layoutConstraint.selfIdealSize = idealSize;
1507 layoutConstraint.maxSize = idealSize;
1508 rootNode_->UpdateLayoutConstraint(layoutConstraint);
1509 // reset parentLayoutConstraint to update itself when next measure task
1510 rootNode_->GetGeometryNode()->ResetParentLayoutConstraint();
1511 rootNode_->MarkDirtyNode();
1512 }
1513 if (rootNode_->GetGeometryNode()->GetFrameOffset().GetY() != offset) {
1514 OffsetF newOffset = rootNode_->GetGeometryNode()->GetFrameOffset();
1515 newOffset.SetY(static_cast<float>(offset));
1516 rootNode_->GetGeometryNode()->SetMarginFrameOffset(newOffset);
1517 auto rootContext = rootNode_->GetRenderContext();
1518 rootContext->SyncGeometryProperties(RawPtr(rootNode_->GetGeometryNode()));
1519 RequestFrame();
1520 }
1521 if (isDensityChanged_) {
1522 rootNode_->GetGeometryNode()->ResetParentLayoutConstraint();
1523 rootNode_->MarkForceMeasure();
1524 isDensityChanged_ = false;
1525 }
1526 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
1527 // For cross-platform build, flush tasks when first resize, speed up for fisrt frame.
1528 if (window_ && rootNode_->GetRenderContext() && !NearZero(width) && !NearZero(height)) {
1529 rootNode_->GetRenderContext()->SetBounds(0.0, 0.0, width, height);
1530 window_->FlushTasks();
1531 FlushVsync(GetTimeFromExternalTimer(), 0);
1532 }
1533 #endif
1534 }
1535
UpdateSystemSafeArea(const SafeAreaInsets & systemSafeArea)1536 void PipelineContext::UpdateSystemSafeArea(const SafeAreaInsets& systemSafeArea)
1537 {
1538 CHECK_NULL_VOID(minPlatformVersion_ >= PLATFORM_VERSION_TEN);
1539 if (safeAreaManager_->UpdateSystemSafeArea(systemSafeArea)) {
1540 AnimateOnSafeAreaUpdate();
1541 }
1542 }
1543
UpdateCutoutSafeArea(const SafeAreaInsets & cutoutSafeArea)1544 void PipelineContext::UpdateCutoutSafeArea(const SafeAreaInsets& cutoutSafeArea)
1545 {
1546 CHECK_NULL_VOID(minPlatformVersion_ >= PLATFORM_VERSION_TEN);
1547 if (safeAreaManager_->UpdateCutoutSafeArea(cutoutSafeArea)) {
1548 AnimateOnSafeAreaUpdate();
1549 }
1550 }
1551
UpdateNavSafeArea(const SafeAreaInsets & navSafeArea)1552 void PipelineContext::UpdateNavSafeArea(const SafeAreaInsets& navSafeArea)
1553 {
1554 CHECK_NULL_VOID(minPlatformVersion_ >= PLATFORM_VERSION_TEN);
1555 if (safeAreaManager_->UpdateNavArea(navSafeArea)) {
1556 AnimateOnSafeAreaUpdate();
1557 }
1558 }
1559
CheckAndUpdateKeyboardInset(float keyboardHeight)1560 void PipelineContext::CheckAndUpdateKeyboardInset(float keyboardHeight)
1561 {
1562 safeAreaManager_->UpdateKeyboardSafeArea(keyboardHeight);
1563 }
1564
UpdateOriginAvoidArea(const Rosen::AvoidArea & avoidArea,uint32_t type)1565 void PipelineContext::UpdateOriginAvoidArea(const Rosen::AvoidArea& avoidArea, uint32_t type)
1566 {
1567 #ifdef WINDOW_SCENE_SUPPORTED
1568 CHECK_NULL_VOID(uiExtensionManager_);
1569 uiExtensionManager_->TransferOriginAvoidArea(avoidArea, type);
1570 #endif
1571 }
1572
UpdateSizeChangeReason(WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)1573 void PipelineContext::UpdateSizeChangeReason(
1574 WindowSizeChangeReason type, const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
1575 {
1576 #ifdef WINDOW_SCENE_SUPPORTED
1577 CHECK_NULL_VOID(uiExtensionManager_);
1578 uiExtensionManager_->NotifySizeChangeReason(type, rsTransaction);
1579 #endif
1580 }
1581
SetEnableKeyBoardAvoidMode(bool value)1582 void PipelineContext::SetEnableKeyBoardAvoidMode(bool value)
1583 {
1584 safeAreaManager_->SetKeyBoardAvoidMode(value);
1585 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "keyboardAvoid Mode update:%{public}d", value);
1586 }
1587
IsEnableKeyBoardAvoidMode()1588 bool PipelineContext::IsEnableKeyBoardAvoidMode()
1589 {
1590 return safeAreaManager_->KeyboardSafeAreaEnabled();
1591 }
1592
SetIgnoreViewSafeArea(bool value)1593 void PipelineContext::SetIgnoreViewSafeArea(bool value)
1594 {
1595 if (safeAreaManager_->SetIgnoreSafeArea(value)) {
1596 SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_WINDOW_IGNORE);
1597 }
1598 }
1599
SetIsLayoutFullScreen(bool value)1600 void PipelineContext::SetIsLayoutFullScreen(bool value)
1601 {
1602 if (safeAreaManager_->SetIsFullScreen(value)) {
1603 SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_WINDOW_IGNORE);
1604 }
1605 }
1606
SetIsNeedAvoidWindow(bool value)1607 void PipelineContext::SetIsNeedAvoidWindow(bool value)
1608 {
1609 if (safeAreaManager_->SetIsNeedAvoidWindow(value)) {
1610 SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_WINDOW_IGNORE);
1611 }
1612 }
1613
GetSafeArea() const1614 PipelineBase::SafeAreaInsets PipelineContext::GetSafeArea() const
1615 {
1616 return safeAreaManager_->GetSafeArea();
1617 }
1618
GetSafeAreaWithoutProcess() const1619 PipelineBase::SafeAreaInsets PipelineContext::GetSafeAreaWithoutProcess() const
1620 {
1621 return safeAreaManager_->GetSafeAreaWithoutProcess();
1622 }
1623
GetPageAvoidOffset()1624 float PipelineContext::GetPageAvoidOffset()
1625 {
1626 return safeAreaManager_->GetKeyboardOffset();
1627 }
1628
CheckNeedAvoidInSubWindow()1629 bool PipelineContext::CheckNeedAvoidInSubWindow()
1630 {
1631 CHECK_NULL_RETURN(NearZero(GetPageAvoidOffset()), true);
1632 CHECK_NULL_RETURN(safeAreaManager_->KeyboardSafeAreaEnabled(), false);
1633 auto KeyboardInsetLength = safeAreaManager_->GetKeyboardInset().Length();
1634 return GreatNotEqual(KeyboardInsetLength, 0.0f);
1635 }
1636
SyncSafeArea(SafeAreaSyncType syncType)1637 void PipelineContext::SyncSafeArea(SafeAreaSyncType syncType)
1638 {
1639 bool keyboardSafeArea =
1640 syncType == SafeAreaSyncType::SYNC_TYPE_KEYBOARD && !safeAreaManager_->KeyboardSafeAreaEnabled();
1641 CHECK_NULL_VOID(stageManager_);
1642 stageManager_->SyncPageSafeArea(keyboardSafeArea);
1643 SubwindowManager::GetInstance()->MarkDirtyDialogSafeArea();
1644 if (overlayManager_) {
1645 overlayManager_->MarkDirty(PROPERTY_UPDATE_MEASURE);
1646 }
1647 if (selectOverlayManager_) {
1648 selectOverlayManager_->MarkDirty(PROPERTY_UPDATE_MEASURE);
1649 }
1650 auto&& restoreNodes = safeAreaManager_->GetGeoRestoreNodes();
1651 for (auto&& wk : restoreNodes) {
1652 auto node = wk.Upgrade();
1653 if (node) {
1654 bool needMeasure = (syncType == SafeAreaSyncType::SYNC_TYPE_KEYBOARD && node->SelfExpansiveToKeyboard()) ||
1655 (syncType == SafeAreaSyncType::SYNC_TYPE_AVOID_AREA ||
1656 syncType == SafeAreaSyncType::SYNC_TYPE_WINDOW_IGNORE);
1657 node->MarkDirtyNode(needMeasure ? PROPERTY_UPDATE_MEASURE : PROPERTY_UPDATE_LAYOUT);
1658 }
1659 }
1660 }
1661
DetachNode(RefPtr<UINode> uiNode)1662 void PipelineContext::DetachNode(RefPtr<UINode> uiNode)
1663 {
1664 auto frameNode = DynamicCast<FrameNode>(uiNode);
1665
1666 CHECK_NULL_VOID(frameNode);
1667
1668 RemoveStoredNode(frameNode->GetRestoreId());
1669 if (frameNode->IsPrivacySensitive()) {
1670 auto privacyManager = GetPrivacySensitiveManager();
1671 privacyManager->RemoveNode(AceType::WeakClaim(AceType::RawPtr(frameNode)));
1672 }
1673
1674 if (!CheckThreadSafe()) {
1675 LOGW("DetachNode doesn't run on UI thread!");
1676 }
1677 dirtyPropertyNodes_.erase(frameNode);
1678 needRenderNode_.erase(WeakPtr<FrameNode>(frameNode));
1679
1680 if (dirtyFocusNode_ == frameNode) {
1681 dirtyFocusNode_.Reset();
1682 }
1683
1684 if (dirtyFocusScope_ == frameNode) {
1685 dirtyFocusScope_.Reset();
1686 }
1687
1688 if (dirtyRequestFocusNode_ == frameNode) {
1689 dirtyRequestFocusNode_.Reset();
1690 }
1691
1692 if (activeNode_ == frameNode) {
1693 activeNode_.Reset();
1694 }
1695
1696 if (focusNode_ == frameNode) {
1697 focusNode_.Reset();
1698 }
1699 }
1700
OnVirtualKeyboardHeightChange(float keyboardHeight,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,const float safeHeight,const bool supportAvoidance,bool forceChange)1701 void PipelineContext::OnVirtualKeyboardHeightChange(float keyboardHeight,
1702 const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, const float safeHeight, const bool supportAvoidance,
1703 bool forceChange)
1704 {
1705 CHECK_RUN_ON(UI);
1706 // prevent repeated trigger with same keyboardHeight
1707 if (!forceChange && NearEqual(keyboardHeight, safeAreaManager_->GetKeyboardInset().Length())) {
1708 return;
1709 }
1710
1711 ACE_FUNCTION_TRACE();
1712 #ifdef ENABLE_ROSEN_BACKEND
1713 if (rsTransaction) {
1714 FlushMessages();
1715 rsTransaction->Begin();
1716 }
1717 #endif
1718
1719 if (supportAvoidance) {
1720 AvoidanceLogic(keyboardHeight, rsTransaction, safeHeight, supportAvoidance);
1721 } else {
1722 OriginalAvoidanceLogic(keyboardHeight, rsTransaction);
1723 }
1724
1725 #ifdef ENABLE_ROSEN_BACKEND
1726 if (rsTransaction) {
1727 rsTransaction->Commit();
1728 }
1729 #endif
1730 }
1731
AvoidanceLogic(float keyboardHeight,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,const float safeHeight,const bool supportAvoidance)1732 void PipelineContext::AvoidanceLogic(float keyboardHeight, const std::shared_ptr<Rosen::RSTransaction>& rsTransaction,
1733 const float safeHeight, const bool supportAvoidance)
1734 {
1735 auto func = [this, keyboardHeight, safeHeight, supportAvoidance]() mutable {
1736 safeAreaManager_->UpdateKeyboardSafeArea(keyboardHeight);
1737 keyboardHeight += safeAreaManager_->GetSafeHeight();
1738 float positionY = 0.0f;
1739 float textfieldHeight = 0.0f;
1740 float keyboardPosition = rootHeight_ - keyboardHeight;
1741 auto manager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
1742 float keyboardOffset = manager ? manager->GetClickPositionOffset() : safeAreaManager_->GetKeyboardOffset();
1743 if (manager) {
1744 positionY = static_cast<float>(manager->GetClickPosition().GetY()) - keyboardOffset;
1745 textfieldHeight = manager->GetHeight();
1746 }
1747 if (!NearZero(keyboardOffset)) {
1748 auto offsetY = keyboardPosition - safeAreaManager_->GetLastKeyboardPoistion();
1749 safeAreaManager_->UpdateKeyboardOffset(keyboardOffset + offsetY);
1750 } else {
1751 if (NearZero(keyboardHeight)) {
1752 safeAreaManager_->UpdateKeyboardOffset(0.0f);
1753 } else if (LessOrEqual(positionY + safeHeight + textfieldHeight, rootHeight_ - keyboardHeight)) {
1754 safeAreaManager_->UpdateKeyboardOffset(0.0f);
1755 } else if (positionY + safeHeight + textfieldHeight > rootHeight_ - keyboardHeight) {
1756 safeAreaManager_->UpdateKeyboardOffset(
1757 -(positionY - rootHeight_ + keyboardHeight)- safeHeight - textfieldHeight);
1758 } else {
1759 safeAreaManager_->UpdateKeyboardOffset(0.0f);
1760 }
1761 }
1762 safeAreaManager_->SetLastKeyboardPoistion(keyboardPosition);
1763 SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_KEYBOARD);
1764 CHECK_NULL_VOID(manager);
1765 manager->AvoidKeyBoardInNavigation();
1766 // layout before scrolling textfield to safeArea, because of getting correct position
1767 FlushUITasks();
1768 bool scrollResult = manager->ScrollTextFieldToSafeArea();
1769 if (scrollResult) {
1770 FlushUITasks();
1771 }
1772
1773 TAG_LOGI(AceLogTag::ACE_KEYBOARD,
1774 "AvoidanceLogic keyboardHeight: %{public}f, positionY: %{public}f, safeHeight: %{public}f, "
1775 "rootHeight_ %{public}f final calculate keyboard offset is %{public}f",
1776 keyboardHeight, positionY, safeHeight, rootHeight_, safeAreaManager_->GetKeyboardOffset());
1777 };
1778 FlushUITasks();
1779 DoKeyboardAvoidAnimate(keyboardAnimationConfig_, keyboardHeight, func);
1780 }
1781
OriginalAvoidanceLogic(float keyboardHeight,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)1782 void PipelineContext::OriginalAvoidanceLogic(
1783 float keyboardHeight, const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
1784 {
1785 auto func = [this, keyboardHeight]() mutable {
1786 safeAreaManager_->UpdateKeyboardSafeArea(keyboardHeight);
1787 if (keyboardHeight > 0) {
1788 // add height of navigation bar
1789 keyboardHeight += safeAreaManager_->GetSystemSafeArea().bottom_.Length();
1790 }
1791 float positionY = 0.0f;
1792 auto manager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
1793 float height = 0.0f;
1794 if (manager) {
1795 height = manager->GetHeight();
1796 positionY = static_cast<float>(manager->GetClickPosition().GetY());
1797 }
1798 SizeF rootSize { static_cast<float>(rootWidth_), static_cast<float>(rootHeight_) };
1799 float keyboardOffset = manager ? manager->GetClickPositionOffset() : safeAreaManager_->GetKeyboardOffset();
1800 float positionYWithOffset = positionY - keyboardOffset;
1801 float offsetFix = (rootSize.Height() - positionYWithOffset) > 100.0f
1802 ? keyboardHeight - (rootSize.Height() - positionYWithOffset) / 2.0f
1803 : keyboardHeight;
1804 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
1805 if (offsetFix > 0.0f && positionYWithOffset < offsetFix) {
1806 offsetFix = keyboardHeight - (rootSize.Height() - positionYWithOffset - height);
1807 }
1808 #endif
1809 if (NearZero(keyboardHeight)) {
1810 safeAreaManager_->UpdateKeyboardOffset(0.0f);
1811 } else if (LessOrEqual(rootSize.Height() - positionYWithOffset - height, height) &&
1812 LessOrEqual(rootSize.Height() - positionYWithOffset, keyboardHeight)) {
1813 safeAreaManager_->UpdateKeyboardOffset(-keyboardHeight);
1814 } else if (positionYWithOffset + height > (rootSize.Height() - keyboardHeight) && offsetFix > 0.0f) {
1815 safeAreaManager_->UpdateKeyboardOffset(-offsetFix);
1816 } else if ((positionYWithOffset + height > rootSize.Height() - keyboardHeight &&
1817 positionYWithOffset < rootSize.Height() - keyboardHeight && height < keyboardHeight / 2.0f) &&
1818 NearZero(rootNode_->GetGeometryNode()->GetFrameOffset().GetY())) {
1819 safeAreaManager_->UpdateKeyboardOffset(-height - offsetFix / 2.0f);
1820 } else {
1821 safeAreaManager_->UpdateKeyboardOffset(0.0f);
1822 }
1823 SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_KEYBOARD);
1824 CHECK_NULL_VOID(manager);
1825 manager->AvoidKeyBoardInNavigation();
1826 // layout before scrolling textfield to safeArea, because of getting correct position
1827 FlushUITasks();
1828 bool scrollResult = manager->ScrollTextFieldToSafeArea();
1829 if (scrollResult) {
1830 FlushUITasks();
1831 }
1832 };
1833 FlushUITasks();
1834 DoKeyboardAvoidAnimate(keyboardAnimationConfig_, keyboardHeight, func);
1835 }
1836
OnVirtualKeyboardHeightChange(float keyboardHeight,double positionY,double height,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,bool forceChange)1837 void PipelineContext::OnVirtualKeyboardHeightChange(float keyboardHeight, double positionY, double height,
1838 const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, bool forceChange)
1839 {
1840 CHECK_RUN_ON(UI);
1841 // prevent repeated trigger with same keyboardHeight
1842 CHECK_NULL_VOID(safeAreaManager_);
1843 auto manager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
1844 CHECK_NULL_VOID(manager);
1845 if (!forceChange && NearEqual(keyboardHeight, safeAreaManager_->GetKeyboardInset().Length()) &&
1846 prevKeyboardAvoidMode_ == safeAreaManager_->KeyboardSafeAreaEnabled() && manager->PrevHasTextFieldPattern()) {
1847 TAG_LOGD(
1848 AceLogTag::ACE_KEYBOARD, "KeyboardHeight as same as last time, don't need to calculate keyboardOffset");
1849 return;
1850 }
1851
1852 if (!forceChange && (NearEqual(keyboardHeight + 1, safeAreaManager_->GetKeyboardInset().Length()) ||
1853 NearEqual(keyboardHeight - 1, safeAreaManager_->GetKeyboardInset().Length())) &&
1854 prevKeyboardAvoidMode_ == safeAreaManager_->KeyboardSafeAreaEnabled() && manager->PrevHasTextFieldPattern()) {
1855 TAG_LOGI(
1856 AceLogTag::ACE_KEYBOARD, "Ignore ileagal keyboard height change");
1857 return;
1858 }
1859
1860 if (keyboardHeight > rootHeight_) {
1861 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Keyboard higher than whole rootrect, no need to avoid");
1862 return;
1863 }
1864
1865 if (manager->UsingCustomKeyboardAvoid()) {
1866 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Using Custom Avoid Instead");
1867 return;
1868 }
1869
1870 manager->UpdatePrevHasTextFieldPattern();
1871 prevKeyboardAvoidMode_ = safeAreaManager_->KeyboardSafeAreaEnabled();
1872
1873 ACE_FUNCTION_TRACE();
1874 #ifdef ENABLE_ROSEN_BACKEND
1875 if (rsTransaction) {
1876 FlushMessages();
1877 rsTransaction->Begin();
1878 }
1879 #endif
1880
1881 auto weak = WeakClaim(this);
1882 auto func = [weak, keyboardHeight, positionY, height, manager]() mutable {
1883 auto context = weak.Upgrade();
1884 CHECK_NULL_VOID(context);
1885 context->SetIsLayouting(false);
1886 context->safeAreaManager_->UpdateKeyboardSafeArea(keyboardHeight);
1887 context->SetKeyboardAction(NearZero(keyboardHeight) ? KeyboardAction::CLOSING : KeyboardAction::OPENING);
1888 if (keyboardHeight > 0) {
1889 // add height of navigation bar
1890 keyboardHeight += context->safeAreaManager_->GetSystemSafeArea().bottom_.Length();
1891 }
1892
1893 SizeF rootSize { static_cast<float>(context->rootWidth_), static_cast<float>(context->rootHeight_) };
1894
1895 TAG_LOGI(AceLogTag::ACE_KEYBOARD,
1896 "origin positionY: %{public}f, height %{public}f", positionY, height);
1897
1898 float positionYWithOffset = positionY;
1899 float keyboardOffset = manager ? manager->GetClickPositionOffset() :
1900 context->safeAreaManager_->GetKeyboardOffset();
1901 float currentPos = manager->GetClickPosition().GetY() - context->GetRootRect().GetOffset().GetY() -
1902 keyboardOffset;
1903
1904 auto onFocusField = manager->GetOnFocusTextField().Upgrade();
1905 float adjust = 0.0f;
1906 if (onFocusField && onFocusField->GetHost() && onFocusField->GetHost()->GetGeometryNode()) {
1907 auto adjustRect = onFocusField->GetHost()->GetGeometryNode()->GetParentAdjust();
1908 adjust = adjustRect.Top();
1909 }
1910 currentPos += adjust;
1911
1912 if (!onFocusField) {
1913 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "use origin arg from the window");
1914 } else if (manager->GetIfFocusTextFieldIsInline()) {
1915 manager->GetInlineTextFieldAvoidPositionYAndHeight(positionY, height);
1916 positionYWithOffset = positionY;
1917 } else if (!NearEqual(positionY, currentPos) && !context->IsEnableKeyBoardAvoidMode()) {
1918 positionY = currentPos;
1919 positionYWithOffset = currentPos;
1920 height = manager->GetHeight();
1921 }
1922
1923 if (rootSize.Height() - positionY - height < 0) {
1924 height = rootSize.Height() - positionY;
1925 }
1926 float offsetFix = (rootSize.Height() - positionY - height) < keyboardHeight
1927 ? keyboardHeight - (rootSize.Height() - positionY - height)
1928 : keyboardHeight;
1929 auto lastKeyboardOffset = context->safeAreaManager_->GetKeyboardOffset();
1930 float newKeyboardOffset = 0.0f;
1931 if (NearZero(keyboardHeight)) {
1932 newKeyboardOffset = 0.0f;
1933 } else if (positionYWithOffset + height > (rootSize.Height() - keyboardHeight) && offsetFix > 0.0f) {
1934 newKeyboardOffset = -offsetFix;
1935 } else if (LessOrEqual(rootSize.Height() - positionYWithOffset - height, height) &&
1936 LessOrEqual(rootSize.Height() - positionYWithOffset, keyboardHeight)) {
1937 newKeyboardOffset = -keyboardHeight;
1938 } else if ((positionYWithOffset + height > rootSize.Height() - keyboardHeight &&
1939 positionYWithOffset < rootSize.Height() - keyboardHeight && height < keyboardHeight / 2.0f) &&
1940 NearZero(context->rootNode_->GetGeometryNode()->GetFrameOffset().GetY())) {
1941 newKeyboardOffset = -height - offsetFix / 2.0f;
1942 } else {
1943 newKeyboardOffset = 0.0f;
1944 }
1945
1946 if (NearZero(keyboardHeight) || LessOrEqual(newKeyboardOffset, lastKeyboardOffset) ||
1947 manager->GetOnFocusTextFieldId() == manager->GetLastAvoidFieldId()) {
1948 context->safeAreaManager_->UpdateKeyboardOffset(newKeyboardOffset);
1949 } else {
1950 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Different field, Calculated offfset %{public}f is smaller than current"
1951 "keyboardOffset, so keep current keyboardOffset", newKeyboardOffset);
1952 }
1953 manager->SetLastAvoidFieldId(manager->GetOnFocusTextFieldId());
1954
1955 TAG_LOGI(AceLogTag::ACE_KEYBOARD,
1956 "keyboardHeight: %{public}f, positionY: %{public}f, textHeight: %{public}f, "
1957 "rootSize.Height() %{public}f final calculate keyboard offset is %{public}f",
1958 keyboardHeight, positionY, height, rootSize.Height(), context->safeAreaManager_->GetKeyboardOffset());
1959 context->SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_KEYBOARD);
1960 manager->AvoidKeyBoardInNavigation();
1961 // layout before scrolling textfield to safeArea, because of getting correct position
1962 context->FlushUITasks();
1963 bool scrollResult = manager->ScrollTextFieldToSafeArea();
1964 if (scrollResult) {
1965 context->FlushUITasks();
1966 }
1967 context->SetKeyboardAction(KeyboardAction::NONE);
1968 };
1969 FlushUITasks();
1970 SetIsLayouting(true);
1971 DoKeyboardAvoidAnimate(keyboardAnimationConfig_, keyboardHeight, func);
1972
1973 #ifdef ENABLE_ROSEN_BACKEND
1974 if (rsTransaction) {
1975 rsTransaction->Commit();
1976 }
1977 #endif
1978 }
1979
OnBackPressed()1980 bool PipelineContext::OnBackPressed()
1981 {
1982 CHECK_RUN_ON(PLATFORM);
1983 auto frontend = weakFrontend_.Upgrade();
1984 if (!frontend) {
1985 // return back.
1986 return false;
1987 }
1988
1989 // If the tag of the last child of the rootnode is video, exit full screen.
1990 if (fullScreenManager_->OnBackPressed()) {
1991 LOGI("fullscreen component: video or web consumed backpressed event");
1992 return true;
1993 }
1994
1995 // if has sharedTransition, back press will stop the sharedTransition
1996 if (sharedTransitionManager_ && sharedTransitionManager_->OnBackPressed()) {
1997 LOGI("sharedTransition consumed backpressed event");
1998 return true;
1999 }
2000
2001 // if has popup, back press would hide popup and not trigger page back
2002 auto textfieldMgr = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
2003 if (textfieldMgr) {
2004 auto lastRequestKeyboardNodeId = textfieldMgr->GetLastRequestKeyboardId();
2005 auto lastRequestKeyboardNode = DynamicCast<FrameNode>(
2006 ElementRegister::GetInstance()->GetUINodeById(lastRequestKeyboardNodeId));
2007 if (lastRequestKeyboardNode && lastRequestKeyboardNode->GetPageId() == -1 &&
2008 textfieldMgr->OnBackPressed()) {
2009 LOGI("textfield consumed backpressed event");
2010 return true;
2011 }
2012 }
2013
2014 auto hasOverlay = false;
2015 taskExecutor_->PostSyncTask(
2016 [weakOverlay = AceType::WeakClaim(AceType::RawPtr(overlayManager_)),
2017 weakSelectOverlay = AceType::WeakClaim(AceType::RawPtr(selectOverlayManager_)), &hasOverlay]() {
2018 // Destroy behaviour of Select Overlay shouble be adjusted.
2019 auto overlay = weakOverlay.Upgrade();
2020 CHECK_NULL_VOID(overlay);
2021 auto selectOverlay = weakSelectOverlay.Upgrade();
2022 CHECK_NULL_VOID(selectOverlay);
2023 hasOverlay = selectOverlay->ResetSelectionAndDestroySelectOverlay(true);
2024 hasOverlay |= overlay->RemoveOverlay(true);
2025 },
2026 TaskExecutor::TaskType::UI, "ArkUIBackPressedRemoveOverlay");
2027 if (hasOverlay) {
2028 LOGI("Overlay consumed backpressed event");
2029 return true;
2030 }
2031
2032 auto textfieldManager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
2033 if (textfieldManager && textfieldManager->OnBackPressed()) {
2034 LOGI("textfield consumed backpressed event");
2035 return true;
2036 }
2037
2038 auto result = false;
2039 taskExecutor_->PostSyncTask(
2040 [weakFrontend = weakFrontend_, weakPipelineContext = WeakClaim(this), stageManager = stageManager_, &result]() {
2041 auto frontend = weakFrontend.Upgrade();
2042 if (!frontend) {
2043 result = false;
2044 return;
2045 }
2046 auto context = weakPipelineContext.Upgrade();
2047 if (!context) {
2048 result = false;
2049 return;
2050 }
2051 CHECK_NULL_VOID(stageManager);
2052 auto lastPage = stageManager->GetLastPage();
2053 CHECK_NULL_VOID(lastPage);
2054 bool isEntry = false;
2055 auto navigationGroupNode =
2056 AceType::DynamicCast<NavigationGroupNode>(context->FindNavigationNodeToHandleBack(lastPage, isEntry));
2057 if (navigationGroupNode) {
2058 result = true;
2059 }
2060 },
2061 TaskExecutor::TaskType::UI, "ArkUIBackPressedFindNavigationGroup");
2062
2063 if (result) {
2064 // user accept
2065 LOGI("Navigation consumed backpressed event");
2066 return true;
2067 }
2068
2069 taskExecutor_->PostSyncTask(
2070 [weakFrontend = weakFrontend_, weakPipelineContext = WeakClaim(this), &result]() {
2071 auto frontend = weakFrontend.Upgrade();
2072 if (!frontend) {
2073 result = false;
2074 return;
2075 }
2076 result = frontend->OnBackPressed();
2077 },
2078 TaskExecutor::TaskType::JS, "ArkUIBackPressed");
2079
2080 if (result) {
2081 // user accept
2082 LOGI("router consumed backpressed event");
2083 return true;
2084 }
2085 return false;
2086 }
2087
FindNavigationNodeToHandleBack(const RefPtr<UINode> & node,bool & isEntry)2088 RefPtr<FrameNode> PipelineContext::FindNavigationNodeToHandleBack(const RefPtr<UINode>& node, bool& isEntry)
2089 {
2090 CHECK_NULL_RETURN(node, nullptr);
2091 const auto& children = node->GetChildren();
2092 for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
2093 auto& child = *iter;
2094 auto childNode = AceType::DynamicCast<FrameNode>(child);
2095 if (childNode && childNode->GetLayoutProperty()) {
2096 auto property = childNode->GetLayoutProperty();
2097 if (property->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE ||
2098 !childNode->IsActive()) {
2099 continue;
2100 }
2101 }
2102 if (childNode && childNode->GetTag() == V2::NAVIGATION_VIEW_ETS_TAG) {
2103 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(childNode);
2104 auto topChild = navigationGroupNode->GetTopDestination();
2105 // find navigation from top destination
2106 auto targetNodeFromDestination = FindNavigationNodeToHandleBack(topChild, isEntry);
2107 if (targetNodeFromDestination) {
2108 return targetNodeFromDestination;
2109 }
2110 if (isEntry) {
2111 return nullptr;
2112 }
2113 targetNodeFromDestination = childNode;
2114 auto targetNavigation = AceType::DynamicCast<NavigationGroupNode>(targetNodeFromDestination);
2115 // check if the destination responds
2116 if (targetNavigation && targetNavigation->CheckCanHandleBack(isEntry)) {
2117 return targetNavigation;
2118 }
2119 if (isEntry) {
2120 return nullptr;
2121 }
2122 // if the destination does not responds, find navigation from navbar
2123 auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationGroupNode->GetNavBarNode());
2124 auto navigationLayoutProperty = navigationGroupNode->GetLayoutProperty<NavigationLayoutProperty>();
2125 CHECK_NULL_RETURN(navigationLayoutProperty, nullptr);
2126 if (navigationLayoutProperty->GetHideNavBarValue(false)) {
2127 return nullptr;
2128 }
2129 auto targetNodeFromNavbar = FindNavigationNodeToHandleBack(navBarNode, isEntry);
2130 if (targetNodeFromNavbar) {
2131 return targetNodeFromNavbar;
2132 }
2133 return nullptr;
2134 }
2135 auto target = FindNavigationNodeToHandleBack(child, isEntry);
2136 if (target) {
2137 return target;
2138 }
2139 if (isEntry) {
2140 return nullptr;
2141 }
2142 }
2143 return nullptr;
2144 }
2145
SetIsFocusActive(bool isFocusActive)2146 bool PipelineContext::SetIsFocusActive(bool isFocusActive)
2147 {
2148 if (isFocusActive_ == isFocusActive) {
2149 return false;
2150 }
2151 TAG_LOGI(AceLogTag::ACE_FOCUS, "Pipeline focus turns to %{public}s", isFocusActive ? "active" : "inactive");
2152 isFocusActive_ = isFocusActive;
2153 for (auto& pair : isFocusActiveUpdateEvents_) {
2154 if (pair.second) {
2155 pair.second(isFocusActive_);
2156 }
2157 }
2158 CHECK_NULL_RETURN(rootNode_, false);
2159 auto rootFocusHub = rootNode_->GetFocusHub();
2160 CHECK_NULL_RETURN(rootFocusHub, false);
2161 if (isFocusActive_) {
2162 return rootFocusHub->PaintAllFocusState();
2163 }
2164 rootFocusHub->ClearAllFocusState();
2165 return true;
2166 }
2167
OnTouchEvent(const TouchEvent & point,bool isSubPipe)2168 void PipelineContext::OnTouchEvent(const TouchEvent& point, bool isSubPipe)
2169 {
2170 OnTouchEvent(point, rootNode_, isSubPipe);
2171 }
2172
OnMouseEvent(const MouseEvent & event)2173 void PipelineContext::OnMouseEvent(const MouseEvent& event)
2174 {
2175 OnMouseEvent(event, rootNode_);
2176 }
2177
OnAxisEvent(const AxisEvent & event)2178 void PipelineContext::OnAxisEvent(const AxisEvent& event)
2179 {
2180 OnAxisEvent(event, rootNode_);
2181 }
2182
OnTouchEvent(const TouchEvent & point,const RefPtr<FrameNode> & node,bool isSubPipe)2183 void PipelineContext::OnTouchEvent(const TouchEvent& point, const RefPtr<FrameNode>& node, bool isSubPipe)
2184 {
2185 CHECK_RUN_ON(UI);
2186
2187 HandlePenHoverOut(point);
2188
2189 #ifdef UICAST_COMPONENT_SUPPORTED
2190 do {
2191 auto container = Container::Current();
2192 CHECK_NULL_BREAK(container);
2193 auto distributedUI = container->GetDistributedUI();
2194 CHECK_NULL_BREAK(distributedUI);
2195 if (distributedUI->IsSinkMode()) {
2196 distributedUI->BypassEvent(point, isSubPipe);
2197 return;
2198 }
2199 } while (false);
2200 #endif
2201
2202 SerializedGesture etsSerializedGesture;
2203 if (point.type != TouchType::DOWN) {
2204 HandleEtsCardTouchEvent(point, etsSerializedGesture);
2205 }
2206
2207 auto oriPoint = point;
2208 auto scalePoint = point.CreateScalePoint(GetViewScale());
2209 eventManager_->CheckDownEvent(scalePoint);
2210 ResSchedReport::GetInstance().OnTouchEvent(scalePoint);
2211
2212 if (scalePoint.type != TouchType::MOVE && scalePoint.type != TouchType::PULL_MOVE &&
2213 scalePoint.type != TouchType::HOVER_MOVE) {
2214 eventManager_->GetEventTreeRecord(EventTreeType::TOUCH).AddTouchPoint(scalePoint);
2215 if (SystemProperties::GetAceCommercialLogEnabled() || scalePoint.isPrivacyMode) {
2216 TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW,
2217 "InputTracking id:%{public}d, fingerId:%{public}d, type=%{public}d, inject=%{public}d, "
2218 "isPrivacyMode=%{public}d",
2219 scalePoint.touchEventId, scalePoint.id, (int)scalePoint.type, scalePoint.isInjected,
2220 scalePoint.isPrivacyMode);
2221 } else {
2222 TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW,
2223 "InputTracking id:%{public}d, fingerId:%{public}d, x=%{public}.3f, y=%{public}.3f type=%{public}d, "
2224 "inject=%{public}d",
2225 scalePoint.touchEventId, scalePoint.id, scalePoint.x, scalePoint.y, (int)scalePoint.type,
2226 scalePoint.isInjected);
2227 }
2228 }
2229
2230 if (scalePoint.type == TouchType::MOVE) {
2231 for (auto listenerItem : listenerVector_) {
2232 if (listenerItem) {
2233 listenerItem->OnTouchEvent();
2234 }
2235 }
2236 }
2237
2238 eventManager_->SetInstanceId(GetInstanceId());
2239 if (scalePoint.type != TouchType::MOVE && historyPointsById_.find(scalePoint.id) != historyPointsById_.end()) {
2240 historyPointsById_.erase(scalePoint.id);
2241 }
2242 if (scalePoint.type == TouchType::DOWN) {
2243 // Set focus state inactive while touch down event received
2244 SetIsFocusActive(false);
2245 TouchRestrict touchRestrict { TouchRestrict::NONE };
2246 touchRestrict.sourceType = point.sourceType;
2247 touchRestrict.touchEvent = point;
2248 touchRestrict.inputEventType = InputEventType::TOUCH_SCREEN;
2249
2250 eventManager_->TouchTest(scalePoint, node, touchRestrict, GetPluginEventOffset(), viewScale_, isSubPipe);
2251 if (!touchRestrict.childTouchTestList.empty()) {
2252 scalePoint.childTouchTestList = touchRestrict.childTouchTestList;
2253 }
2254 touchTestResults_ = eventManager_->touchTestResults_;
2255 if (StylusDetectorMgr::GetInstance()->IsNeedInterceptedTouchEvent(scalePoint, touchTestResults_)) {
2256 eventManager_->ClearTouchTestTargetForPenStylus(scalePoint);
2257 return;
2258 }
2259
2260 HandleEtsCardTouchEvent(oriPoint, etsSerializedGesture);
2261
2262 if (etsSerializedGesture.data.size() != 0) {
2263 GestureGroup rebirth(GestureMode::Exclusive);
2264 rebirth.Deserialize(etsSerializedGesture.data.data());
2265 auto recognizer = rebirth.CreateRecognizer();
2266 if (recognizer) {
2267 recognizer->SetInnerFlag(true);
2268 recognizer->BeginReferee(scalePoint.id, true);
2269 std::list<RefPtr<NGGestureRecognizer>> combined;
2270 combined.emplace_back(recognizer);
2271 for (auto iter = touchTestResults_[point.id].begin();
2272 iter != touchTestResults_[point.id].end(); iter++) {
2273 auto outRecognizer = AceType::DynamicCast<NGGestureRecognizer>(*iter);
2274 if (outRecognizer) {
2275 combined.emplace_back(outRecognizer);
2276 touchTestResults_[point.id].erase(iter);
2277 break;
2278 }
2279 }
2280 auto exclusiveRecognizer = AceType::MakeRefPtr<ExclusiveRecognizer>(std::move(combined));
2281 exclusiveRecognizer->AttachFrameNode(node);
2282 exclusiveRecognizer->BeginReferee(scalePoint.id);
2283 touchTestResults_[point.id].emplace_back(exclusiveRecognizer);
2284 eventManager_->touchTestResults_ = touchTestResults_;
2285 eventManager_->SetInnerFlag(true);
2286 }
2287 }
2288 if (IsFormRender() && touchTestResults_.find(point.id) != touchTestResults_.end()) {
2289 for (const auto& touchResult : touchTestResults_[point.id]) {
2290 auto recognizer = AceType::DynamicCast<NG::RecognizerGroup>(touchResult);
2291 if (recognizer) {
2292 auto gesture = recognizer->CreateGestureFromRecognizer();
2293 if (gesture) {
2294 serializedGesture_.data = std::vector<char>(gesture->SizeofMe());
2295 gesture->Serialize(serializedGesture_.data.data());
2296 }
2297 break;
2298 }
2299 }
2300 }
2301 for (const auto& weakContext : touchPluginPipelineContext_) {
2302 auto pipelineContext = DynamicCast<OHOS::Ace::PipelineBase>(weakContext.Upgrade());
2303 if (!pipelineContext) {
2304 continue;
2305 }
2306 auto pluginPoint =
2307 point.UpdateScalePoint(viewScale_, static_cast<float>(pipelineContext->GetPluginEventOffset().GetX()),
2308 static_cast<float>(pipelineContext->GetPluginEventOffset().GetY()), point.id);
2309 // eventManager_ instance Id may changed.
2310 pipelineContext->OnTouchEvent(pluginPoint, true);
2311 }
2312
2313 // restore instance Id.
2314 eventManager_->SetInstanceId(GetInstanceId());
2315 }
2316 auto rootOffset = GetRootRect().GetOffset();
2317 eventManager_->HandleGlobalEventNG(scalePoint, selectOverlayManager_, rootOffset);
2318
2319 if (isSubPipe) {
2320 return;
2321 }
2322
2323 // Currently, SetupRootElement is executed later than InitializeCallback in AceContainer.
2324 // We need to check whether accessibilityManagerNG_ is created.
2325 if (accessibilityManagerNG_ != nullptr) {
2326 accessibilityManagerNG_->HandleAccessibilityHoverEvent(node, scalePoint);
2327 }
2328
2329 if (scalePoint.type == TouchType::MOVE) {
2330 if (!eventManager_->GetInnerFlag()) {
2331 auto mockPoint = point;
2332 mockPoint.type = TouchType::CANCEL;
2333 HandleEtsCardTouchEvent(mockPoint, etsSerializedGesture);
2334 RemoveEtsCardTouchEventCallback(mockPoint.id);
2335 }
2336 touchEvents_.emplace_back(point);
2337 hasIdleTasks_ = true;
2338 RequestFrame();
2339 return;
2340 }
2341
2342 if (scalePoint.type == TouchType::UP) {
2343 lastTouchTime_ = GetTimeFromExternalTimer();
2344 CompensateTouchMoveEvent(scalePoint);
2345 if (thpExtraMgr_ != nullptr) {
2346 const uint32_t delay = 800; // 800: ms
2347 taskExecutor_->RemoveTask(TaskExecutor::TaskType::UI, "NotifyResponseRegionChanged");
2348 auto task = [weak = WeakClaim(this)]() {
2349 auto pipeline = weak.Upgrade();
2350 CHECK_NULL_VOID(pipeline);
2351 pipeline->NotifyResponseRegionChanged(pipeline->GetRootElement());
2352 };
2353 taskExecutor_->PostDelayedTask(task, TaskExecutor::TaskType::UI, delay, "NotifyResponseRegionChanged");
2354 }
2355 }
2356
2357 eventManager_->DispatchTouchEvent(scalePoint);
2358
2359 if ((scalePoint.type == TouchType::UP) || (scalePoint.type == TouchType::CANCEL)) {
2360 // need to reset touchPluginPipelineContext_ for next touch down event.
2361 touchPluginPipelineContext_.clear();
2362 RemoveEtsCardTouchEventCallback(point.id);
2363 ResetDraggingStatus(scalePoint, node);
2364 }
2365 if (scalePoint.type != TouchType::MOVE) {
2366 lastDispatchTime_.erase(scalePoint.id);
2367 idToTouchPoints_.erase(scalePoint.id);
2368 }
2369
2370 hasIdleTasks_ = true;
2371 RequestFrame();
2372 }
2373
CompensateTouchMoveEventFromUnhandledEvents(const TouchEvent & event)2374 bool PipelineContext::CompensateTouchMoveEventFromUnhandledEvents(const TouchEvent& event)
2375 {
2376 std::vector<TouchEvent> history;
2377 if (!touchEvents_.empty()) {
2378 for (auto iter = touchEvents_.begin(); iter != touchEvents_.end();) {
2379 auto movePoint = (*iter).CreateScalePoint(GetViewScale());
2380 if (event.id == movePoint.id) {
2381 history.emplace_back(movePoint);
2382 iter = touchEvents_.erase(iter);
2383 } else {
2384 auto& pointers = iter->pointers;
2385 for (auto pointerIter = pointers.begin(); pointerIter != pointers.end();) {
2386 if (pointerIter->id == event.id) {
2387 pointerIter = pointers.erase(pointerIter);
2388 } else {
2389 ++pointerIter;
2390 }
2391 }
2392 ++iter;
2393 }
2394 }
2395 if (!history.empty()) {
2396 TouchEvent lastMoveEvent(history.back());
2397 lastMoveEvent.history.swap(history);
2398 eventManager_->SetLastMoveBeforeUp(event.sourceType == SourceType::MOUSE);
2399 eventManager_->DispatchTouchEvent(lastMoveEvent);
2400 eventManager_->SetLastMoveBeforeUp(false);
2401 } else {
2402 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING,
2403 "Finger id: %{public}d, not found unhandled move event, compensate failed.", event.id);
2404 }
2405 return true;
2406 }
2407 return false;
2408 }
2409
CompensateTouchMoveEvent(const TouchEvent & event)2410 void PipelineContext::CompensateTouchMoveEvent(const TouchEvent& event)
2411 {
2412 if (event.type != TouchType::UP) {
2413 // If not up, no need to compensate touch move event.
2414 return;
2415 }
2416 if (!CompensateTouchMoveEventFromUnhandledEvents(event)) {
2417 // Compensate touch move event with all touch move Event before up has been handled.
2418 auto lastEventIter = idToTouchPoints_.find(event.id);
2419 if (lastEventIter != idToTouchPoints_.end()) {
2420 auto iter = lastDispatchTime_.find(lastEventIter->first);
2421 if (iter != lastDispatchTime_.end()) {
2422 ACE_SCOPED_TRACE("CompensateTouchMoveEvent last move event time: %s last dispatch time: %s",
2423 std::to_string(static_cast<uint64_t>(lastEventIter->second.time.time_since_epoch().count()))
2424 .c_str(),
2425 std::to_string(iter->second).c_str());
2426 if (static_cast<uint64_t>(lastEventIter->second.time.time_since_epoch().count()) > iter->second) {
2427 eventManager_->SetLastMoveBeforeUp(event.sourceType == SourceType::MOUSE);
2428 eventManager_->DispatchTouchEvent(lastEventIter->second);
2429 eventManager_->SetLastMoveBeforeUp(false);
2430 }
2431 }
2432 }
2433 }
2434
2435 auto lastEventIter = idToTouchPoints_.find(event.id);
2436 if (lastEventIter != idToTouchPoints_.end()) {
2437 ACE_SCOPED_TRACE("Finger id: %d process last move event eventId: %d", lastEventIter->first,
2438 lastEventIter->second.touchEventId);
2439 }
2440 }
2441
ResetDraggingStatus(const TouchEvent & touchPoint,const RefPtr<FrameNode> & node)2442 void PipelineContext::ResetDraggingStatus(const TouchEvent& touchPoint, const RefPtr<FrameNode>& node)
2443 {
2444 auto manager = GetDragDropManager();
2445 CHECK_NULL_VOID(manager);
2446 manager->ResetDraggingStatus(touchPoint);
2447 }
2448
OnSurfaceDensityChanged(double density)2449 void PipelineContext::OnSurfaceDensityChanged(double density)
2450 {
2451 CHECK_RUN_ON(UI);
2452 if (!NearEqual(density, density_)) {
2453 isDensityChanged_ = true;
2454 }
2455 density_ = density;
2456 if (!NearZero(viewScale_)) {
2457 dipScale_ = density_ / viewScale_;
2458 }
2459 if (isDensityChanged_) {
2460 UIObserverHandler::GetInstance().NotifyDensityChange(density_);
2461 PipelineBase::OnSurfaceDensityChanged(density);
2462 }
2463 }
2464
DumpPageViewData(const RefPtr<FrameNode> & node,RefPtr<ViewDataWrap> viewDataWrap,bool skipSubAutoFillContainer,bool needsRecordData)2465 bool PipelineContext::DumpPageViewData(const RefPtr<FrameNode>& node, RefPtr<ViewDataWrap> viewDataWrap,
2466 bool skipSubAutoFillContainer, bool needsRecordData)
2467 {
2468 CHECK_NULL_RETURN(viewDataWrap, false);
2469 RefPtr<FrameNode> pageNode = nullptr;
2470 RefPtr<FrameNode> dumpNode = nullptr;
2471 if (node == nullptr) {
2472 if (stageManager_) {
2473 pageNode = stageManager_->GetLastPage();
2474 dumpNode = pageNode;
2475 }
2476 } else {
2477 pageNode = node->GetPageNode();
2478 dumpNode = node;
2479 }
2480 CHECK_NULL_RETURN(dumpNode, false);
2481 dumpNode->DumpViewDataPageNodes(viewDataWrap, skipSubAutoFillContainer, needsRecordData);
2482 if (node && node->GetTag() == V2::DIALOG_ETS_TAG) {
2483 viewDataWrap->SetPageUrl(node->GetTag());
2484 return true;
2485 }
2486 CHECK_NULL_RETURN(pageNode, false);
2487 auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
2488 CHECK_NULL_RETURN(pagePattern, false);
2489 auto pageInfo = pagePattern->GetPageInfo();
2490 CHECK_NULL_RETURN(pageInfo, false);
2491 viewDataWrap->SetPageUrl(pageInfo->GetPageUrl());
2492 return true;
2493 }
2494
CheckNeedAutoSave()2495 bool PipelineContext::CheckNeedAutoSave()
2496 {
2497 CHECK_NULL_RETURN(stageManager_, false);
2498 auto pageNode = stageManager_->GetLastPage();
2499 CHECK_NULL_RETURN(pageNode, false);
2500 return pageNode->NeedRequestAutoSave();
2501 }
2502
CheckOverlayFocus()2503 bool PipelineContext::CheckOverlayFocus()
2504 {
2505 CHECK_NULL_RETURN(overlayManager_, false);
2506 auto overlayNode = overlayManager_->GetOverlayNode();
2507 CHECK_NULL_RETURN(overlayNode, false);
2508 return overlayNode->GetFocusHub() && overlayNode->GetFocusHub()->IsCurrentFocus();
2509 }
2510
NotifyFillRequestSuccess(AceAutoFillType autoFillType,RefPtr<ViewDataWrap> viewDataWrap)2511 void PipelineContext::NotifyFillRequestSuccess(AceAutoFillType autoFillType, RefPtr<ViewDataWrap> viewDataWrap)
2512 {
2513 CHECK_NULL_VOID(viewDataWrap);
2514 auto pageNodeInfoWraps = viewDataWrap->GetPageNodeInfoWraps();
2515 for (const auto& item : pageNodeInfoWraps) {
2516 if (item == nullptr) {
2517 continue;
2518 }
2519 auto frameNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetUINodeById(item->GetId()));
2520 if (frameNode == nullptr) {
2521 TAG_LOGW(AceLogTag::ACE_AUTO_FILL, "frameNode is not found, id=%{public}d", item->GetId());
2522 continue;
2523 }
2524 frameNode->NotifyFillRequestSuccess(viewDataWrap, item, autoFillType);
2525 }
2526 }
2527
NotifyFillRequestFailed(RefPtr<FrameNode> node,int32_t errCode,const std::string & fillContent,bool isPopup)2528 void PipelineContext::NotifyFillRequestFailed(RefPtr<FrameNode> node, int32_t errCode,
2529 const std::string& fillContent, bool isPopup)
2530 {
2531 CHECK_NULL_VOID(node);
2532 node->NotifyFillRequestFailed(errCode, fillContent, isPopup);
2533 }
2534
OnDumpInfo(const std::vector<std::string> & params) const2535 bool PipelineContext::OnDumpInfo(const std::vector<std::string>& params) const
2536 {
2537 ACE_DCHECK(!params.empty());
2538 if (window_) {
2539 DumpLog::GetInstance().Print(1, "LastRequestVsyncTime: " + std::to_string(window_->GetLastRequestVsyncTime()));
2540 #ifdef ENABLE_ROSEN_BACKEND
2541 auto rsUIDirector = window_->GetRSUIDirector();
2542 if (rsUIDirector) {
2543 DumpLog::GetInstance().Print(1, "transactionFlags: [" + std::to_string(getpid()) + "," +
2544 std::to_string(rsUIDirector->GetIndex()) + "]");
2545 }
2546 #endif
2547 }
2548 DumpLog::GetInstance().Print(1, "last vsyncId: " + std::to_string(GetFrameCount()));
2549 if (params[0] == "-element") {
2550 if (params.size() > 1 && params[1] == "-lastpage") {
2551 auto lastPage = stageManager_->GetLastPage();
2552 if (params.size() < USED_ID_FIND_FLAG && lastPage) {
2553 lastPage->DumpTree(0);
2554 DumpLog::GetInstance().OutPutBySize();
2555 }
2556 if (params.size() == USED_ID_FIND_FLAG && lastPage && !lastPage->DumpTreeById(0, params[2])) {
2557 DumpLog::GetInstance().Print(
2558 "There is no id matching the ID in the parameter,please check whether the id is correct");
2559 }
2560 } else {
2561 if (params.size() == USED_ID_FIND_FLAG && !rootNode_->DumpTreeById(0, params[2])) {
2562 DumpLog::GetInstance().Print(
2563 "There is no id matching the ID in the parameter,please check whether the id is correct");
2564 }
2565 if (params.size() < USED_ID_FIND_FLAG) {
2566 rootNode_->DumpTree(0);
2567 DumpLog::GetInstance().OutPutBySize();
2568 }
2569 }
2570 } else if (params[0] == "-navigation") {
2571 auto navigationDumpMgr = GetNavigationManager();
2572 if (navigationDumpMgr) {
2573 navigationDumpMgr->OnDumpInfo();
2574 }
2575 } else if (params[0] == "-focus") {
2576 if (rootNode_->GetFocusHub()) {
2577 rootNode_->GetFocusHub()->DumpFocusTree(0);
2578 }
2579 } else if (params[0] == "-focuswindowscene") {
2580 auto windowSceneNode = GetFocusedWindowSceneNode();
2581 auto windowSceneFocusHub = windowSceneNode ? windowSceneNode->GetFocusHub() : nullptr;
2582 if (windowSceneFocusHub) {
2583 windowSceneFocusHub->DumpFocusTree(0);
2584 }
2585 } else if (params[0] == "-focusmanager") {
2586 if (focusManager_) {
2587 focusManager_->DumpFocusManager();
2588 }
2589 } else if (params[0] == "-accessibility" || params[0] == "-inspector") {
2590 auto accessibilityManager = GetAccessibilityManager();
2591 if (accessibilityManager) {
2592 accessibilityManager->OnDumpInfoNG(params, windowId_);
2593 }
2594 } else if (params[0] == "-rotation" && params.size() >= 2) {
2595 } else if (params[0] == "-animationscale" && params.size() >= 2) {
2596 } else if (params[0] == "-velocityscale" && params.size() >= 2) {
2597 } else if (params[0] == "-scrollfriction" && params.size() >= 2) {
2598 } else if (params[0] == "-threadstuck" && params.size() >= 3) {
2599 } else if (params[0] == "-pipeline") {
2600 DumpPipelineInfo();
2601 } else if (params[0] == "-jsdump") {
2602 std::vector<std::string> jsParams;
2603 if (params.begin() != params.end()) {
2604 jsParams = std::vector<std::string>(params.begin() + 1, params.end());
2605 }
2606
2607 auto stageNode = stageManager_->GetStageNode();
2608 CHECK_NULL_RETURN(stageNode, false);
2609 auto children = stageNode->GetChildren();
2610 for (const auto& pageNode : children) {
2611 auto frameNode = AceType::DynamicCast<FrameNode>(pageNode);
2612 CHECK_NULL_RETURN(frameNode, false);
2613 auto pagePattern = frameNode->GetPattern<PagePattern>();
2614 CHECK_NULL_RETURN(pagePattern, false);
2615 pagePattern->FireDumpListener(jsParams);
2616 }
2617 } else if (params[0] == "-event") {
2618 if (eventManager_) {
2619 eventManager_->DumpEvent(EventTreeType::TOUCH);
2620 }
2621 } else if (params[0] == "-postevent") {
2622 if (eventManager_) {
2623 eventManager_->DumpEvent(EventTreeType::POST_EVENT);
2624 }
2625 } else if (params[0] == "-imagecache") {
2626 if (imageCache_) {
2627 imageCache_->DumpCacheInfo();
2628 }
2629 } else if (params[0] == "-imagefilecache") {
2630 ImageFileCache::GetInstance().DumpCacheInfo();
2631 } else if (params[0] == "-allelements") {
2632 AceEngine::Get().NotifyContainers([](const RefPtr<Container>& container) {
2633 auto pipeline = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
2634 auto rootNode = pipeline->GetRootElement();
2635 if (rootNode) {
2636 DumpLog::GetInstance().Print(0, "ContainerId: " + std::to_string(Container::CurrentId()));
2637 rootNode->DumpTree(0);
2638 DumpLog::GetInstance().OutPutBySize();
2639 }
2640 });
2641 } else if (params[0] == "-default") {
2642 rootNode_->DumpTree(0);
2643 DumpLog::GetInstance().OutPutDefault();
2644 } else if (params[0] == "--stylus") {
2645 StylusDetectorDefault::GetInstance()->ExecuteCommand(params);
2646 } else if (params[0] == "-overlay") {
2647 if (overlayManager_) {
2648 overlayManager_->DumpOverlayInfo();
2649 }
2650 } else if (params[0] == "-simplify") {
2651 auto root = JsonUtil::Create(true);
2652 rootNode_->DumpSimplifyTree(0, root);
2653 auto json = root->ToString();
2654 json.erase(std::remove(json.begin(), json.end(), ' '), json.end());
2655 DumpLog::GetInstance().Print(json);
2656 }
2657 return true;
2658 }
2659
GetCurrentFrameInfo(uint64_t recvTime,uint64_t timeStamp)2660 FrameInfo* PipelineContext::GetCurrentFrameInfo(uint64_t recvTime, uint64_t timeStamp)
2661 {
2662 if (SystemProperties::GetDumpFrameCount() == 0) {
2663 return nullptr;
2664 }
2665 if (dumpFrameInfos_.size() >= SystemProperties::GetDumpFrameCount()) {
2666 dumpFrameInfos_.pop_front();
2667 }
2668
2669 dumpFrameInfos_.push_back({ .frameRecvTime_ = recvTime, .frameTimeStamp_ = timeStamp });
2670 return &dumpFrameInfos_.back();
2671 }
2672
DumpPipelineInfo() const2673 void PipelineContext::DumpPipelineInfo() const
2674 {
2675 DumpLog::GetInstance().Print("PipelineInfo:");
2676 if (window_) {
2677 DumpLog::GetInstance().Print(1, "DisplayRefreshRate: " + std::to_string(window_->GetRefreshRate()));
2678 DumpLog::GetInstance().Print(1, "LastRequestVsyncTime: " + std::to_string(window_->GetLastRequestVsyncTime()));
2679 DumpLog::GetInstance().Print(1, "NowTime: " + std::to_string(GetSysTimestamp()));
2680 }
2681 if (!dumpFrameInfos_.empty()) {
2682 DumpLog::GetInstance().Print("==================================FrameTask==================================");
2683 for (const auto& info : dumpFrameInfos_) {
2684 DumpLog::GetInstance().Print("Task: " + info.GetTimeInfo());
2685 DumpLog::GetInstance().Print(1, "LayoutTask:");
2686 for (const auto& layout : info.layoutInfos_) {
2687 DumpLog::GetInstance().Print(2, layout.ToString());
2688 }
2689 DumpLog::GetInstance().Print(1, "RenderTask:");
2690 for (const auto& layout : info.renderInfos_) {
2691 DumpLog::GetInstance().Print(2, layout.ToString());
2692 }
2693 DumpLog::GetInstance().Print(
2694 "==================================FrameTask==================================");
2695 }
2696 }
2697 }
2698
CollectTouchEventsBeforeVsync(std::list<TouchEvent> & touchEvents)2699 void PipelineContext::CollectTouchEventsBeforeVsync(std::list<TouchEvent>& touchEvents)
2700 {
2701 auto targetTimeStamp = GetVsyncTime() - compensationValue_;
2702 for (auto iter = touchEvents_.begin(); iter != touchEvents_.end();) {
2703 auto timeStamp = std::chrono::duration_cast<std::chrono::nanoseconds>(iter->time.time_since_epoch()).count();
2704 if (targetTimeStamp < static_cast<uint64_t>(timeStamp)) {
2705 iter++;
2706 continue;
2707 }
2708 touchEvents.emplace_back(*iter);
2709 iter = touchEvents_.erase(iter);
2710 }
2711 }
2712
FlushTouchEvents()2713 void PipelineContext::FlushTouchEvents()
2714 {
2715 CHECK_RUN_ON(UI);
2716 CHECK_NULL_VOID(rootNode_);
2717 {
2718 std::unordered_set<int32_t> moveEventIds;
2719 std::list<TouchEvent> touchEvents;
2720 CollectTouchEventsBeforeVsync(touchEvents);
2721 if (touchEvents.empty()) {
2722 canUseLongPredictTask_ = true;
2723 return;
2724 }
2725 canUseLongPredictTask_ = false;
2726 eventManager_->FlushTouchEventsBegin(touchEvents_);
2727 std::unordered_map<int, TouchEvent> idToTouchPoints;
2728 bool needInterpolation = true;
2729 std::unordered_map<int32_t, TouchEvent> newIdTouchPoints;
2730 for (auto iter = touchEvents.rbegin(); iter != touchEvents.rend(); ++iter) {
2731 auto scalePoint = (*iter).CreateScalePoint(GetViewScale());
2732 idToTouchPoints.emplace(scalePoint.id, scalePoint);
2733 idToTouchPoints[scalePoint.id].history.insert(idToTouchPoints[scalePoint.id].history.begin(), scalePoint);
2734 needInterpolation = iter->type != TouchType::MOVE ? false : true;
2735 }
2736 if (focusWindowId_.has_value()) {
2737 needInterpolation = false;
2738 }
2739 if (needInterpolation) {
2740 auto targetTimeStamp = resampleTimeStamp_;
2741 for (const auto& idIter : idToTouchPoints) {
2742 auto stamp =
2743 std::chrono::duration_cast<std::chrono::nanoseconds>(idIter.second.time.time_since_epoch()).count();
2744 if (targetTimeStamp > static_cast<uint64_t>(stamp)) {
2745 continue;
2746 }
2747 TouchEvent newTouchEvent;
2748 if (GetResampleTouchEvent(
2749 historyPointsById_[idIter.first], idIter.second.history, targetTimeStamp, newTouchEvent)) {
2750 newIdTouchPoints[idIter.first] = newTouchEvent;
2751 }
2752 historyPointsById_[idIter.first] = idIter.second.history;
2753 }
2754 }
2755 std::list<TouchEvent> touchPoints;
2756 for (const auto& iter : idToTouchPoints) {
2757 lastDispatchTime_[iter.first] = GetVsyncTime() - compensationValue_;
2758 auto it = newIdTouchPoints.find(iter.first);
2759 if (it != newIdTouchPoints.end()) {
2760 touchPoints.emplace_back(it->second);
2761 } else {
2762 touchPoints.emplace_back(iter.second);
2763 }
2764 }
2765 auto maxSize = touchPoints.size();
2766 for (auto iter = touchPoints.rbegin(); iter != touchPoints.rend(); ++iter) {
2767 maxSize--;
2768 if (maxSize == 0) {
2769 eventManager_->FlushTouchEventsEnd(touchPoints);
2770 }
2771 eventManager_->DispatchTouchEvent(*iter);
2772 }
2773 idToTouchPoints_ = std::move(idToTouchPoints);
2774 }
2775 }
2776
OnAccessibilityHoverEvent(const TouchEvent & point,const RefPtr<NG::FrameNode> & node)2777 void PipelineContext::OnAccessibilityHoverEvent(const TouchEvent& point, const RefPtr<NG::FrameNode>& node)
2778 {
2779 CHECK_RUN_ON(UI);
2780 auto scaleEvent = point.CreateScalePoint(viewScale_);
2781 if (scaleEvent.type != TouchType::HOVER_MOVE) {
2782 #ifdef IS_RELEASE_VERSION
2783 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING,
2784 "OnAccessibilityHoverEvent event id:%{public}d, fingerId:%{public}d,"
2785 "type=%{public}d, "
2786 "inject=%{public}d",
2787 scaleEvent.touchEventId, scaleEvent.id, (int)scaleEvent.type, scaleEvent.isInjected);
2788 #else
2789 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING,
2790 "OnAccessibilityHoverEvent event id:%{public}d, fingerId:%{public}d, x=%{public}f y=%{public}f "
2791 "type=%{public}d, "
2792 "inject=%{public}d",
2793 scaleEvent.touchEventId, scaleEvent.id, scaleEvent.x, scaleEvent.y, (int)scaleEvent.type,
2794 scaleEvent.isInjected);
2795 #endif
2796 }
2797 auto targerNode = node ? node : rootNode_;
2798 if (accessibilityManagerNG_ != nullptr) {
2799 accessibilityManagerNG_->HandleAccessibilityHoverEvent(targerNode, scaleEvent);
2800 }
2801 TouchRestrict touchRestrict { TouchRestrict::NONE };
2802 touchRestrict.sourceType = scaleEvent.sourceType;
2803 // use mouse to collect accessibility hover target
2804 touchRestrict.hitTestType = SourceType::MOUSE;
2805 touchRestrict.inputEventType = InputEventType::TOUCH_SCREEN;
2806 eventManager_->AccessibilityHoverTest(scaleEvent, targerNode, touchRestrict);
2807 eventManager_->DispatchAccessibilityHoverEventNG(scaleEvent);
2808 RequestFrame();
2809 }
2810
OnPenHoverEvent(const TouchEvent & point,const RefPtr<NG::FrameNode> & node)2811 void PipelineContext::OnPenHoverEvent(const TouchEvent& point, const RefPtr<NG::FrameNode>& node)
2812 {
2813 CHECK_RUN_ON(UI);
2814 auto scaleEvent = point.CreateScalePoint(viewScale_);
2815 if (scaleEvent.type != TouchType::MOVE) {
2816 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING,
2817 "OnPenHoverEvent event id:%{public}d, fingerId:%{public}d "
2818 "type=%{public}d, "
2819 "inject=%{public}d",
2820 scaleEvent.touchEventId, scaleEvent.id, (int)scaleEvent.type,
2821 scaleEvent.isInjected);
2822 }
2823
2824 auto targerNode = node ? node : rootNode_;
2825 TouchRestrict touchRestrict { TouchRestrict::NONE };
2826 touchRestrict.sourceType = scaleEvent.sourceType;
2827 touchRestrict.touchEvent.sourceTool = scaleEvent.sourceTool;
2828 touchRestrict.touchEvent.type = scaleEvent.type;
2829 touchRestrict.touchEvent.force = scaleEvent.force;
2830
2831 // use mouse to collect pen hover target
2832 touchRestrict.hitTestType = SourceType::MOUSE;
2833 touchRestrict.inputEventType = InputEventType::TOUCH_SCREEN;
2834 eventManager_->PenHoverTest(scaleEvent, targerNode, touchRestrict);
2835 eventManager_->DispatchPenHoverEventNG(scaleEvent);
2836 RequestFrame();
2837 }
2838
HandlePenHoverOut(const TouchEvent & point)2839 void PipelineContext::HandlePenHoverOut(const TouchEvent& point)
2840 {
2841 if (point.sourceTool != SourceTool::PEN || point.type != TouchType::DOWN || NearZero(point.force)) {
2842 return;
2843 }
2844
2845 CHECK_RUN_ON(UI);
2846 auto oriPoint = point;
2847 oriPoint.type = TouchType::PROXIMITY_OUT;
2848
2849 TouchTestResult testResult;
2850 eventManager_->UpdatePenHoverNode(oriPoint, testResult);
2851 eventManager_->DispatchPenHoverEventNG(oriPoint);
2852 }
2853
OnMouseEvent(const MouseEvent & event,const RefPtr<FrameNode> & node)2854 void PipelineContext::OnMouseEvent(const MouseEvent& event, const RefPtr<FrameNode>& node)
2855 {
2856 CHECK_RUN_ON(UI);
2857 if (!lastMouseEvent_) {
2858 lastMouseEvent_ = std::make_unique<MouseEvent>();
2859 }
2860 lastMouseEvent_->x = event.x;
2861 lastMouseEvent_->y = event.y;
2862 lastMouseEvent_->button = event.button;
2863 lastMouseEvent_->action = event.action;
2864 lastMouseEvent_->sourceType = event.sourceType;
2865 lastMouseEvent_->time = event.time;
2866 lastMouseEvent_->touchEventId = event.touchEventId;
2867
2868 if (event.button == MouseButton::RIGHT_BUTTON && event.action == MouseAction::PRESS) {
2869 // Mouse right button press event set focus inactive here.
2870 // Mouse left button press event will set focus inactive in touch process.
2871 SetIsFocusActive(false);
2872 }
2873
2874 auto manager = GetDragDropManager();
2875 if (manager) {
2876 if (event.button == MouseButton::RIGHT_BUTTON &&
2877 (event.action == MouseAction::PRESS || event.action == MouseAction::PULL_UP)) {
2878 manager->SetIsDragCancel(true);
2879 } else {
2880 manager->SetIsDragCancel(false);
2881 }
2882 } else {
2883 TAG_LOGW(AceLogTag::ACE_INPUTTRACKING, "InputTracking id:%{public}d, OnMouseEvent GetDragDropManager is null",
2884 event.touchEventId);
2885 }
2886
2887 auto container = Container::Current();
2888 if ((event.action == MouseAction::RELEASE || event.action == MouseAction::PRESS ||
2889 event.action == MouseAction::MOVE) &&
2890 (event.button == MouseButton::LEFT_BUTTON || event.pressedButtons == MOUSE_PRESS_LEFT)) {
2891 auto touchPoint = event.CreateTouchPoint();
2892 if (event.pullAction == MouseAction::PULL_MOVE) {
2893 touchPoint.pullType = TouchType::PULL_MOVE;
2894 }
2895 OnTouchEvent(touchPoint, node);
2896 } else {
2897 auto touchPoint = event.CreateTouchPoint();
2898 auto scalePoint = touchPoint.CreateScalePoint(GetViewScale());
2899 auto rootOffset = GetRootRect().GetOffset();
2900 eventManager_->HandleGlobalEventNG(scalePoint, selectOverlayManager_, rootOffset);
2901 }
2902
2903 CHECK_NULL_VOID(node);
2904 auto scaleEvent = event.CreateScaleEvent(viewScale_);
2905 TouchRestrict touchRestrict { TouchRestrict::NONE };
2906 touchRestrict.sourceType = event.sourceType;
2907 touchRestrict.hitTestType = SourceType::MOUSE;
2908 touchRestrict.inputEventType = InputEventType::MOUSE_BUTTON;
2909 eventManager_->MouseTest(scaleEvent, node, touchRestrict);
2910 eventManager_->DispatchMouseEventNG(scaleEvent);
2911 eventManager_->DispatchMouseHoverEventNG(scaleEvent);
2912 eventManager_->DispatchMouseHoverAnimationNG(scaleEvent);
2913 accessibilityManagerNG_->HandleAccessibilityHoverEvent(node, scaleEvent);
2914 RequestFrame();
2915 }
2916
FlushMouseEvent()2917 void PipelineContext::FlushMouseEvent()
2918 {
2919 if (!lastMouseEvent_ || lastMouseEvent_->action == MouseAction::WINDOW_LEAVE) {
2920 return;
2921 }
2922 auto container = Container::Current();
2923 if (container) {
2924 int32_t sourceType = 0;
2925 auto result = container->GetCurPointerEventSourceType(sourceType);
2926 if (result) {
2927 TAG_LOGI(AceLogTag::ACE_MOUSE,
2928 "FlushMouseEvent: last pointer event id %{public}d sourceType:%{public}d last mouse event "
2929 "time:%{public}" PRId64 " current time %{public}" PRId64 "",
2930 lastMouseEvent_->touchEventId, sourceType,
2931 static_cast<int64_t>(lastMouseEvent_->time.time_since_epoch().count()), GetSysTimestamp());
2932 }
2933 }
2934 MouseEvent event;
2935 event.x = lastMouseEvent_->x;
2936 event.y = lastMouseEvent_->y;
2937 event.time = lastMouseEvent_->time;
2938 event.action = MouseAction::MOVE;
2939 event.button = MouseButton::NONE_BUTTON;
2940 event.sourceType = SourceType::MOUSE;
2941
2942 CHECK_RUN_ON(UI);
2943 CHECK_NULL_VOID(rootNode_);
2944 auto scaleEvent = event.CreateScaleEvent(viewScale_);
2945 TouchRestrict touchRestrict { TouchRestrict::NONE };
2946 touchRestrict.sourceType = event.sourceType;
2947 touchRestrict.hitTestType = SourceType::MOUSE;
2948 touchRestrict.inputEventType = InputEventType::MOUSE_BUTTON;
2949 eventManager_->MouseTest(scaleEvent, rootNode_, touchRestrict);
2950 eventManager_->DispatchMouseEventNG(scaleEvent);
2951 eventManager_->DispatchMouseHoverEventNG(scaleEvent);
2952 eventManager_->DispatchMouseHoverAnimationNG(scaleEvent);
2953 }
2954
ChangeMouseStyle(int32_t nodeId,MouseFormat format,int32_t windowId,bool isByPass)2955 bool PipelineContext::ChangeMouseStyle(int32_t nodeId, MouseFormat format, int32_t windowId, bool isByPass)
2956 {
2957 auto window = GetWindow();
2958 if (window && window->IsUserSetCursor()) {
2959 return false;
2960 }
2961 if (mouseStyleNodeId_ != nodeId || isByPass) {
2962 return false;
2963 }
2964 auto mouseStyle = MouseStyle::CreateMouseStyle();
2965 CHECK_NULL_RETURN(mouseStyle, false);
2966 if (windowId) {
2967 return mouseStyle->ChangePointerStyle(windowId, format);
2968 }
2969 return mouseStyle->ChangePointerStyle(GetFocusWindowId(), format);
2970 }
2971
TriggerKeyEventDispatch(const KeyEvent & event)2972 bool PipelineContext::TriggerKeyEventDispatch(const KeyEvent& event)
2973 {
2974 auto curFocusView = focusManager_ ? focusManager_->GetLastFocusView().Upgrade() : nullptr;
2975 auto curEntryFocusView = curFocusView ? curFocusView->GetEntryFocusView() : nullptr;
2976 auto curEntryFocusViewFrame = curEntryFocusView ? curEntryFocusView->GetFrameNode() : nullptr;
2977 if (event.isPreIme) {
2978 return eventManager_->DispatchKeyEventNG(event, curEntryFocusViewFrame);
2979 }
2980
2981 if (!IsSkipShortcutAndFocusMove() && DispatchTabKey(event, curFocusView)) {
2982 return true;
2983 }
2984 return eventManager_->DispatchKeyEventNG(event, curEntryFocusViewFrame);
2985 }
2986
IsSkipShortcutAndFocusMove()2987 bool PipelineContext::IsSkipShortcutAndFocusMove()
2988 {
2989 // Web component will NOT dispatch shortcut during the first event dispatch process.
2990 // Web component will NOT trigger focus move during the third event dispatch process.
2991 auto focusHub = focusManager_ ? focusManager_->GetCurrentFocus() : nullptr;
2992 RefPtr<FrameNode> curFrameNode = focusHub ? focusHub->GetFrameNode() : nullptr;
2993 return EventManager::IsSkipEventNode(curFrameNode);
2994 }
2995
DispatchTabKey(const KeyEvent & event,const RefPtr<FocusView> & curFocusView)2996 bool PipelineContext::DispatchTabKey(const KeyEvent& event, const RefPtr<FocusView>& curFocusView)
2997 {
2998 auto curEntryFocusView = curFocusView ? curFocusView->GetEntryFocusView() : nullptr;
2999 auto curEntryFocusViewFrame = curEntryFocusView ? curEntryFocusView->GetFrameNode() : nullptr;
3000 auto isKeyTabDown = event.action == KeyAction::DOWN && event.IsKey({ KeyCode::KEY_TAB });
3001 auto isViewRootScopeFocused = curFocusView ? curFocusView->GetIsViewRootScopeFocused() : true;
3002 isTabJustTriggerOnKeyEvent_ = false;
3003
3004 if (isKeyTabDown && isViewRootScopeFocused && curFocusView) {
3005 // Current focused on the view root scope. Tab key used to extend focus.
3006 // If return true. This tab key will just trigger onKeyEvent process.
3007 isTabJustTriggerOnKeyEvent_ = curFocusView->TriggerFocusMove();
3008 }
3009
3010 // Tab key set focus state from inactive to active.
3011 // If return true. This tab key will just trigger onKeyEvent process.
3012 bool isHandleFocusActive = isKeyTabDown && SetIsFocusActive(true);
3013 isTabJustTriggerOnKeyEvent_ = isTabJustTriggerOnKeyEvent_ || isHandleFocusActive;
3014 if (eventManager_->DispatchTabIndexEventNG(event, curEntryFocusViewFrame)) {
3015 return true;
3016 }
3017 return false;
3018 }
3019
ReDispatch(KeyEvent & keyEvent)3020 void PipelineContext::ReDispatch(KeyEvent& keyEvent)
3021 {
3022 CHECK_NULL_VOID(eventManager_);
3023 TAG_LOGD(AceLogTag::ACE_WEB, "Web ReDispach key event: code:%{public}d/action:%{public}d.", keyEvent.code,
3024 keyEvent.action);
3025 // Set keyEvent coming from Redispatch
3026 keyEvent.isRedispatch = true;
3027
3028 if (eventManager_->DispatchKeyboardShortcut(keyEvent)) {
3029 return;
3030 }
3031
3032 auto curFocusView = focusManager_ ? focusManager_->GetLastFocusView().Upgrade() : nullptr;
3033 auto curEntryFocusView = curFocusView ? curFocusView->GetEntryFocusView() : nullptr;
3034 auto curEntryFocusViewFrame = curEntryFocusView ? curEntryFocusView->GetFrameNode() : nullptr;
3035 if (DispatchTabKey(keyEvent, curFocusView)) {
3036 return;
3037 }
3038 eventManager_->DispatchKeyEventNG(keyEvent, curEntryFocusViewFrame);
3039 }
3040
OnKeyEvent(const KeyEvent & event)3041 bool PipelineContext::OnKeyEvent(const KeyEvent& event)
3042 {
3043 CHECK_NULL_RETURN(eventManager_, false);
3044 eventManager_->SetPressedKeyCodes(event.pressedCodes);
3045
3046 // onKeyPreIme
3047 if (event.isPreIme) {
3048 if (TriggerKeyEventDispatch(event)) {
3049 return true;
3050 }
3051 if (!IsSkipShortcutAndFocusMove()) {
3052 return eventManager_->DispatchKeyboardShortcut(event);
3053 }
3054 return false;
3055 }
3056
3057 // process drag cancel
3058 if (event.code == KeyCode::KEY_ESCAPE) {
3059 auto manager = GetDragDropManager();
3060 if (manager && manager->IsMSDPDragging()) {
3061 manager->SetIsDragCancel(true);
3062 manager->OnDragEnd(PointerEvent(0, 0), "");
3063 manager->SetIsDragCancel(false);
3064 return true;
3065 }
3066 }
3067
3068 // OnKeyEvent
3069 if (TriggerKeyEventDispatch(event)) {
3070 return true;
3071 }
3072
3073 // process exit overlay
3074 if (event.code == KeyCode::KEY_ESCAPE && event.action == KeyAction::DOWN) {
3075 CHECK_NULL_RETURN(overlayManager_, false);
3076 auto currentContainer = Container::Current();
3077 if (currentContainer->IsSubContainer() || currentContainer->IsDialogContainer()) {
3078 return overlayManager_->RemoveOverlayInSubwindow();
3079 } else {
3080 return overlayManager_->RemoveOverlay(false);
3081 }
3082 }
3083 return false;
3084 }
3085
RequestFocus(const std::string & targetNodeId,bool isSyncRequest)3086 bool PipelineContext::RequestFocus(const std::string& targetNodeId, bool isSyncRequest)
3087 {
3088 auto rootNode = GetFocusedWindowSceneNode();
3089 if (!rootNode) {
3090 rootNode = rootNode_;
3091 }
3092 CHECK_NULL_RETURN(rootNode, false);
3093 auto focusHub = rootNode->GetFocusHub();
3094 CHECK_NULL_RETURN(focusHub, false);
3095 auto currentFocusChecked = focusHub->RequestFocusImmediatelyById(targetNodeId, isSyncRequest);
3096 if (!isSubPipeline_ || currentFocusChecked) {
3097 return currentFocusChecked;
3098 }
3099 auto parentPipelineBase = parentPipeline_.Upgrade();
3100 CHECK_NULL_RETURN(parentPipelineBase, false);
3101 auto parentPipelineContext = AceType::DynamicCast<NG::PipelineContext>(parentPipelineBase);
3102 CHECK_NULL_RETURN(parentPipelineContext, false);
3103 return parentPipelineContext->RequestFocus(targetNodeId, isSyncRequest);
3104 }
3105
AddDirtyFocus(const RefPtr<FrameNode> & node)3106 void PipelineContext::AddDirtyFocus(const RefPtr<FrameNode>& node)
3107 {
3108 CHECK_RUN_ON(UI);
3109 CHECK_NULL_VOID(node);
3110 if (node->GetFocusType() == FocusType::NODE) {
3111 dirtyFocusNode_ = WeakClaim(RawPtr(node));
3112 } else {
3113 dirtyFocusScope_ = WeakClaim(RawPtr(node));
3114 }
3115 RequestFrame();
3116 }
3117
AddDirtyRequestFocus(const RefPtr<FrameNode> & node)3118 void PipelineContext::AddDirtyRequestFocus(const RefPtr<FrameNode>& node)
3119 {
3120 CHECK_RUN_ON(UI);
3121 CHECK_NULL_VOID(node);
3122 dirtyRequestFocusNode_ = WeakPtr<FrameNode>(node);
3123 RequestFrame();
3124 }
3125
RootLostFocus(BlurReason reason) const3126 void PipelineContext::RootLostFocus(BlurReason reason) const
3127 {
3128 CHECK_NULL_VOID(rootNode_);
3129 auto focusHub = rootNode_->GetFocusHub();
3130 CHECK_NULL_VOID(focusHub);
3131 focusHub->LostFocus(reason);
3132 CHECK_NULL_VOID(overlayManager_);
3133 overlayManager_->HideAllMenus();
3134 }
3135
ConvertAxisToMouse(const AxisEvent & event)3136 MouseEvent ConvertAxisToMouse(const AxisEvent& event)
3137 {
3138 MouseEvent result;
3139 result.x = event.x;
3140 result.y = event.y;
3141 result.action = MouseAction::MOVE;
3142 result.button = MouseButton::NONE_BUTTON;
3143 result.time = event.time;
3144 result.deviceId = event.deviceId;
3145 result.sourceType = event.sourceType;
3146 result.sourceTool = event.sourceTool;
3147 result.touchEventId = event.touchEventId;
3148 result.pointerEvent = event.pointerEvent;
3149 result.screenX = event.screenX;
3150 result.screenY = event.screenY;
3151 return result;
3152 }
3153
OnAxisEvent(const AxisEvent & event,const RefPtr<FrameNode> & node)3154 void PipelineContext::OnAxisEvent(const AxisEvent& event, const RefPtr<FrameNode>& node)
3155 {
3156 auto scaleEvent = event.CreateScaleEvent(viewScale_);
3157
3158 auto dragManager = GetDragDropManager();
3159 if (dragManager && !dragManager->IsDragged()) {
3160 if (event.action == AxisAction::BEGIN) {
3161 isBeforeDragHandleAxis_ = true;
3162 TouchRestrict touchRestrict { TouchRestrict::NONE };
3163 touchRestrict.sourceType = event.sourceType;
3164 touchRestrict.hitTestType = SourceType::TOUCH;
3165 touchRestrict.inputEventType = InputEventType::AXIS;
3166 // If received rotate event, no need to touchtest.
3167 if (!event.isRotationEvent) {
3168 eventManager_->TouchTest(scaleEvent, node, touchRestrict);
3169 }
3170 }
3171 eventManager_->DispatchTouchEvent(scaleEvent);
3172 } else if (isBeforeDragHandleAxis_ && event.action == AxisAction::END) {
3173 eventManager_->DispatchTouchEvent(scaleEvent);
3174 isBeforeDragHandleAxis_ = false;
3175 }
3176
3177 if (event.action == AxisAction::BEGIN || event.action == AxisAction::UPDATE) {
3178 eventManager_->AxisTest(scaleEvent, node);
3179 eventManager_->DispatchAxisEventNG(scaleEvent);
3180 }
3181
3182 auto mouseEvent = ConvertAxisToMouse(event);
3183 OnMouseEvent(mouseEvent, node);
3184 }
3185
HasDifferentDirectionGesture() const3186 bool PipelineContext::HasDifferentDirectionGesture() const
3187 {
3188 CHECK_NULL_RETURN(eventManager_, false);
3189 return eventManager_->HasDifferentDirectionGesture();
3190 }
3191
AddVisibleAreaChangeNode(const int32_t nodeId)3192 void PipelineContext::AddVisibleAreaChangeNode(const int32_t nodeId)
3193 {
3194 onVisibleAreaChangeNodeIds_.emplace(nodeId);
3195 }
3196
AddVisibleAreaChangeNode(const RefPtr<FrameNode> & node,const std::vector<double> & ratios,const VisibleRatioCallback & callback,bool isUserCallback,bool isCalculateInnerClip)3197 void PipelineContext::AddVisibleAreaChangeNode(const RefPtr<FrameNode>& node,
3198 const std::vector<double>& ratios, const VisibleRatioCallback& callback, bool isUserCallback,
3199 bool isCalculateInnerClip)
3200 {
3201 CHECK_NULL_VOID(node);
3202 VisibleCallbackInfo addInfo;
3203 addInfo.callback = callback;
3204 addInfo.isCurrentVisible = false;
3205 onVisibleAreaChangeNodeIds_.emplace(node->GetId());
3206 if (isUserCallback) {
3207 node->SetVisibleAreaUserCallback(ratios, addInfo);
3208 } else {
3209 node->SetVisibleAreaInnerCallback(ratios, addInfo, isCalculateInnerClip);
3210 }
3211 }
3212
RemoveVisibleAreaChangeNode(int32_t nodeId)3213 void PipelineContext::RemoveVisibleAreaChangeNode(int32_t nodeId)
3214 {
3215 onVisibleAreaChangeNodeIds_.erase(nodeId);
3216 }
3217
HandleVisibleAreaChangeEvent(uint64_t nanoTimestamp)3218 void PipelineContext::HandleVisibleAreaChangeEvent(uint64_t nanoTimestamp)
3219 {
3220 ACE_FUNCTION_TRACE();
3221 if (onVisibleAreaChangeNodeIds_.empty()) {
3222 return;
3223 }
3224 auto nodes = FrameNode::GetNodesById(onVisibleAreaChangeNodeIds_);
3225 for (auto&& frameNode : nodes) {
3226 frameNode->TriggerVisibleAreaChangeCallback(nanoTimestamp);
3227 }
3228 }
3229
AddOnAreaChangeNode(int32_t nodeId)3230 void PipelineContext::AddOnAreaChangeNode(int32_t nodeId)
3231 {
3232 onAreaChangeNodeIds_.emplace(nodeId);
3233 isOnAreaChangeNodesCacheVaild_ = false;
3234 }
3235
RemoveOnAreaChangeNode(int32_t nodeId)3236 void PipelineContext::RemoveOnAreaChangeNode(int32_t nodeId)
3237 {
3238 onAreaChangeNodeIds_.erase(nodeId);
3239 isOnAreaChangeNodesCacheVaild_ = false;
3240 }
3241
HasOnAreaChangeNode(int32_t nodeId)3242 bool PipelineContext::HasOnAreaChangeNode(int32_t nodeId)
3243 {
3244 return onAreaChangeNodeIds_.find(nodeId) != onAreaChangeNodeIds_.end();
3245 }
3246
HandleOnAreaChangeEvent(uint64_t nanoTimestamp)3247 void PipelineContext::HandleOnAreaChangeEvent(uint64_t nanoTimestamp)
3248 {
3249 ACE_FUNCTION_TRACE();
3250 if (onAreaChangeNodeIds_.empty()) {
3251 return;
3252 }
3253 auto nodes = FrameNode::GetNodesById(onAreaChangeNodeIds_);
3254 for (auto&& frameNode : nodes) {
3255 frameNode->TriggerOnAreaChangeCallback(nanoTimestamp);
3256 }
3257 UpdateFormLinkInfos();
3258 }
3259
UpdateFormLinkInfos()3260 void PipelineContext::UpdateFormLinkInfos()
3261 {
3262 if (formLinkInfoUpdateHandler_ && !formLinkInfoMap_.empty()) {
3263 std::vector<std::string> formLinkInfos;
3264 for (auto iter = formLinkInfoMap_.rbegin(); iter != formLinkInfoMap_.rend(); ++iter) {
3265 auto info = iter->second;
3266 formLinkInfos.push_back(info);
3267 }
3268 formLinkInfoUpdateHandler_(formLinkInfos);
3269 }
3270 }
3271
OnShow()3272 void PipelineContext::OnShow()
3273 {
3274 CHECK_RUN_ON(UI);
3275 onShow_ = true;
3276 window_->OnShow();
3277 PerfMonitor::GetPerfMonitor()->SetAppForeground(true);
3278 RequestFrame();
3279 FlushWindowStateChangedCallback(true);
3280 AccessibilityEvent event;
3281 event.windowChangeTypes = WindowUpdateType::WINDOW_UPDATE_ACTIVE;
3282 event.type = AccessibilityEventType::PAGE_CHANGE;
3283 SendEventToAccessibility(event);
3284 }
3285
OnHide()3286 void PipelineContext::OnHide()
3287 {
3288 CHECK_RUN_ON(UI);
3289 auto dragDropManager = GetDragDropManager();
3290 if (dragDropManager && dragDropManager->IsItemDragging()) {
3291 dragDropManager->CancelItemDrag();
3292 }
3293 onShow_ = false;
3294 window_->OnHide();
3295 PerfMonitor::GetPerfMonitor()->SetAppForeground(false);
3296 RequestFrame();
3297 OnVirtualKeyboardAreaChange(Rect());
3298 FlushWindowStateChangedCallback(false);
3299 auto rootNode = GetRootElement();
3300 CHECK_NULL_VOID(rootNode);
3301 rootNode->OnAccessibilityEvent(AccessibilityEventType::PAGE_CLOSE);
3302 }
3303
WindowFocus(bool isFocus)3304 void PipelineContext::WindowFocus(bool isFocus)
3305 {
3306 CHECK_RUN_ON(UI);
3307 onFocus_ = isFocus;
3308 if (!isFocus) {
3309 TAG_LOGI(AceLogTag::ACE_FOCUS, "Window id: %{public}d lost focus.", windowId_);
3310 RestoreDefault();
3311 RootLostFocus(BlurReason::WINDOW_BLUR);
3312 NotifyPopupDismiss();
3313 } else {
3314 TAG_LOGI(AceLogTag::ACE_FOCUS, "Window id: %{public}d get focus.", windowId_);
3315 isWindowHasFocused_ = true;
3316 InputMethodManager::GetInstance()->SetWindowFocus(true);
3317 }
3318 GetOrCreateFocusManager()->WindowFocus(isFocus);
3319 FlushWindowFocusChangedCallback(isFocus);
3320 }
3321
ContainerModalUnFocus()3322 void PipelineContext::ContainerModalUnFocus()
3323 {
3324 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
3325 return;
3326 }
3327 CHECK_NULL_VOID(rootNode_);
3328 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
3329 CHECK_NULL_VOID(containerNode);
3330 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
3331 CHECK_NULL_VOID(containerPattern);
3332 containerPattern->OnWindowForceUnfocused();
3333 }
3334
ShowContainerTitle(bool isShow,bool hasDeco,bool needUpdate)3335 void PipelineContext::ShowContainerTitle(bool isShow, bool hasDeco, bool needUpdate)
3336 {
3337 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
3338 return;
3339 }
3340 CHECK_NULL_VOID(rootNode_);
3341 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
3342 CHECK_NULL_VOID(containerNode);
3343 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
3344 CHECK_NULL_VOID(containerPattern);
3345 containerPattern->ShowTitle(isShow, hasDeco, needUpdate);
3346 isShowTitle_ = isShow && hasDeco;
3347 }
3348
UpdateTitleInTargetPos(bool isShow,int32_t height)3349 void PipelineContext::UpdateTitleInTargetPos(bool isShow, int32_t height)
3350 {
3351 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
3352 return;
3353 }
3354 CHECK_NULL_VOID(rootNode_);
3355 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
3356 CHECK_NULL_VOID(containerNode);
3357 auto containerPattern = containerNode->GetPattern<ContainerModalPatternEnhance>();
3358 CHECK_NULL_VOID(containerPattern);
3359 containerPattern->UpdateTitleInTargetPos(isShow, height);
3360 }
3361
SetContainerWindow(bool isShow)3362 void PipelineContext::SetContainerWindow(bool isShow)
3363 {
3364 #ifdef ENABLE_ROSEN_BACKEND
3365 if (!IsJsCard()) {
3366 auto window = GetWindow();
3367 if (window) {
3368 auto rsUIDirector = window->GetRSUIDirector();
3369 if (rsUIDirector) {
3370 // set container window show state to render service
3371 rsUIDirector->SetContainerWindow(isShow, density_);
3372 }
3373 }
3374 }
3375 #endif
3376 }
3377
SetAppBgColor(const Color & color)3378 void PipelineContext::SetAppBgColor(const Color& color)
3379 {
3380 appBgColor_ = color;
3381 #ifdef ENABLE_ROSEN_BACKEND
3382 if (!IsJsCard()) {
3383 auto window = GetWindow();
3384 if (window) {
3385 auto rsUIDirector = window->GetRSUIDirector();
3386 if (rsUIDirector) {
3387 rsUIDirector->SetAbilityBGAlpha(appBgColor_.GetAlpha());
3388 }
3389 }
3390 }
3391 #endif
3392 CHECK_NULL_VOID(stageManager_);
3393 auto stage = stageManager_->GetStageNode();
3394 CHECK_NULL_VOID(stage);
3395 auto renderContext = stage->GetRenderContext();
3396 CHECK_NULL_VOID(renderContext);
3397 renderContext->UpdateBackgroundColor(color);
3398 }
3399
SetAppTitle(const std::string & title)3400 void PipelineContext::SetAppTitle(const std::string& title)
3401 {
3402 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
3403 return;
3404 }
3405 CHECK_NULL_VOID(rootNode_);
3406 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
3407 CHECK_NULL_VOID(containerNode);
3408 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
3409 CHECK_NULL_VOID(containerPattern);
3410 containerPattern->SetAppTitle(title);
3411 }
3412
SetAppIcon(const RefPtr<PixelMap> & icon)3413 void PipelineContext::SetAppIcon(const RefPtr<PixelMap>& icon)
3414 {
3415 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
3416 return;
3417 }
3418 CHECK_NULL_VOID(rootNode_);
3419 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
3420 CHECK_NULL_VOID(containerNode);
3421 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
3422 CHECK_NULL_VOID(containerPattern);
3423 containerPattern->SetAppIcon(icon);
3424 }
3425
FlushReload(const ConfigurationChange & configurationChange,bool fullUpdate)3426 void PipelineContext::FlushReload(const ConfigurationChange& configurationChange, bool fullUpdate)
3427 {
3428 AnimationOption option;
3429 const int32_t duration = 400;
3430 option.SetDuration(duration);
3431 option.SetCurve(Curves::FRICTION);
3432 RecycleManager::Notify(configurationChange);
3433 AnimationUtils::Animate(option, [weak = WeakClaim(this), configurationChange,
3434 weakOverlayManager = AceType::WeakClaim(AceType::RawPtr(overlayManager_)), fullUpdate]() {
3435 auto pipeline = weak.Upgrade();
3436 CHECK_NULL_VOID(pipeline);
3437 if (configurationChange.IsNeedUpdate()) {
3438 auto rootNode = pipeline->GetRootElement();
3439 rootNode->UpdateConfigurationUpdate(configurationChange);
3440 auto overlay = weakOverlayManager.Upgrade();
3441 if (overlay) {
3442 overlay->ReloadBuilderNodeConfig();
3443 }
3444 }
3445 if (fullUpdate) {
3446 CHECK_NULL_VOID(pipeline->stageManager_);
3447 pipeline->SetIsReloading(true);
3448 pipeline->stageManager_->ReloadStage();
3449 pipeline->SetIsReloading(false);
3450 pipeline->FlushUITasks();
3451 }
3452 });
3453 }
3454
Destroy()3455 void PipelineContext::Destroy()
3456 {
3457 CHECK_RUN_ON(UI);
3458 SetDestroyed();
3459 rootNode_->DetachFromMainTree();
3460 rootNode_->FireCustomDisappear();
3461 taskScheduler_->CleanUp();
3462 scheduleTasks_.clear();
3463 dirtyNodes_.clear();
3464 rootNode_.Reset();
3465 accessibilityManagerNG_.Reset();
3466 stageManager_.Reset();
3467 if (overlayManager_) {
3468 overlayManager_->ClearUIExtensionNode();
3469 }
3470 overlayManager_.Reset();
3471 sharedTransitionManager_.Reset();
3472 dragDropManager_.Reset();
3473 TAG_LOGI(AceLogTag::ACE_DRAG, "PipelineContext::Destroy Reset dragDropManager_");
3474 focusManager_.Reset();
3475 selectOverlayManager_.Reset();
3476 fullScreenManager_.Reset();
3477 touchEvents_.clear();
3478 buildFinishCallbacks_.clear();
3479 onWindowStateChangedCallbacks_.clear();
3480 onWindowFocusChangedCallbacks_.clear();
3481 nodesToNotifyMemoryLevel_.clear();
3482 dirtyFocusNode_.Reset();
3483 dirtyFocusScope_.Reset();
3484 needRenderNode_.clear();
3485 dirtyRequestFocusNode_.Reset();
3486 if (textFieldManager_ && textFieldManager_->GetImeShow()) {
3487 InputMethodManager::GetInstance()->CloseKeyboardInPipelineDestroy();
3488 }
3489 #ifdef WINDOW_SCENE_SUPPORTED
3490 uiExtensionManager_.Reset();
3491 #endif
3492 PipelineBase::Destroy();
3493 }
3494
AddBuildFinishCallBack(std::function<void ()> && callback)3495 void PipelineContext::AddBuildFinishCallBack(std::function<void()>&& callback)
3496 {
3497 buildFinishCallbacks_.emplace_back(std::move(callback));
3498 }
3499
AddWindowStateChangedCallback(int32_t nodeId)3500 void PipelineContext::AddWindowStateChangedCallback(int32_t nodeId)
3501 {
3502 if (!CheckThreadSafe()) {
3503 LOGW("AddWindowStateChangedCallback doesn't run on UI thread!");
3504 }
3505 onWindowStateChangedCallbacks_.emplace(nodeId);
3506 }
3507
RemoveWindowStateChangedCallback(int32_t nodeId)3508 void PipelineContext::RemoveWindowStateChangedCallback(int32_t nodeId)
3509 {
3510 if (!CheckThreadSafe()) {
3511 LOGW("RemoveWindowStateChangedCallback doesn't run on UI thread!");
3512 }
3513 onWindowStateChangedCallbacks_.erase(nodeId);
3514 }
3515
FlushWindowStateChangedCallback(bool isShow)3516 void PipelineContext::FlushWindowStateChangedCallback(bool isShow)
3517 {
3518 if (!CheckThreadSafe()) {
3519 LOGW("FlushWindowStateChangedCallback doesn't run on UI thread!");
3520 }
3521 auto iter = onWindowStateChangedCallbacks_.begin();
3522 while (iter != onWindowStateChangedCallbacks_.end()) {
3523 auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
3524 if (!node) {
3525 iter = onWindowStateChangedCallbacks_.erase(iter);
3526 } else {
3527 if (isShow) {
3528 node->OnWindowShow();
3529 } else {
3530 node->OnWindowHide();
3531 }
3532 ++iter;
3533 }
3534 }
3535 HandleVisibleAreaChangeEvent(GetTimeFromExternalTimer());
3536 HandleSubwindow(isShow);
3537 }
3538
AddWindowFocusChangedCallback(int32_t nodeId)3539 void PipelineContext::AddWindowFocusChangedCallback(int32_t nodeId)
3540 {
3541 onWindowFocusChangedCallbacks_.emplace_back(nodeId);
3542 }
3543
RemoveWindowFocusChangedCallback(int32_t nodeId)3544 void PipelineContext::RemoveWindowFocusChangedCallback(int32_t nodeId)
3545 {
3546 onWindowFocusChangedCallbacks_.remove(nodeId);
3547 }
3548
FlushWindowFocusChangedCallback(bool isFocus)3549 void PipelineContext::FlushWindowFocusChangedCallback(bool isFocus)
3550 {
3551 auto iter = onWindowFocusChangedCallbacks_.begin();
3552 while (iter != onWindowFocusChangedCallbacks_.end()) {
3553 auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
3554 if (!node) {
3555 iter = onWindowFocusChangedCallbacks_.erase(iter);
3556 } else {
3557 if (isFocus) {
3558 node->OnWindowFocused();
3559 } else {
3560 node->OnWindowUnfocused();
3561 }
3562 ++iter;
3563 }
3564 }
3565 }
3566
AddWindowSizeChangeCallback(int32_t nodeId)3567 void PipelineContext::AddWindowSizeChangeCallback(int32_t nodeId)
3568 {
3569 onWindowSizeChangeCallbacks_.emplace_back(nodeId);
3570 }
3571
RemoveWindowSizeChangeCallback(int32_t nodeId)3572 void PipelineContext::RemoveWindowSizeChangeCallback(int32_t nodeId)
3573 {
3574 onWindowSizeChangeCallbacks_.remove(nodeId);
3575 }
3576
AddNavigationNode(int32_t pageId,WeakPtr<UINode> navigationNode)3577 void PipelineContext::AddNavigationNode(int32_t pageId, WeakPtr<UINode> navigationNode)
3578 {
3579 CHECK_RUN_ON(UI);
3580 pageToNavigationNodes_[pageId].push_back(navigationNode);
3581 }
3582
RemoveNavigationNode(int32_t pageId,int32_t nodeId)3583 void PipelineContext::RemoveNavigationNode(int32_t pageId, int32_t nodeId)
3584 {
3585 CHECK_RUN_ON(UI);
3586 auto it = pageToNavigationNodes_.find(pageId);
3587 if (it != pageToNavigationNodes_.end() && !it->second.empty()) {
3588 for (auto iter = it->second.begin(); iter != it->second.end();) {
3589 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>((*iter).Upgrade());
3590 if (navigationNode && navigationNode->GetId() == nodeId) {
3591 iter = it->second.erase(iter);
3592 } else {
3593 iter++;
3594 }
3595 }
3596 }
3597 }
3598
FirePageChanged(int32_t pageId,bool isOnShow)3599 void PipelineContext::FirePageChanged(int32_t pageId, bool isOnShow)
3600 {
3601 CHECK_RUN_ON(UI);
3602 for (auto navigationNode : pageToNavigationNodes_[pageId]) {
3603 NavigationPattern::FireNavigationChange(navigationNode.Upgrade(), isOnShow, true);
3604 }
3605 }
3606
FlushWindowSizeChangeCallback(int32_t width,int32_t height,WindowSizeChangeReason type)3607 void PipelineContext::FlushWindowSizeChangeCallback(int32_t width, int32_t height, WindowSizeChangeReason type)
3608 {
3609 auto iter = onWindowSizeChangeCallbacks_.begin();
3610 while (iter != onWindowSizeChangeCallbacks_.end()) {
3611 auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
3612 if (!node) {
3613 iter = onWindowSizeChangeCallbacks_.erase(iter);
3614 } else {
3615 node->OnWindowSizeChanged(width, height, type);
3616 ++iter;
3617 }
3618 }
3619 }
3620
RequireSummary()3621 void PipelineContext::RequireSummary()
3622 {
3623 auto manager = GetDragDropManager();
3624 if (!manager) {
3625 TAG_LOGW(AceLogTag::ACE_DRAG, "require summary, dragDropManager is null");
3626 return;
3627 }
3628 manager->RequireSummary();
3629 }
3630
OnDragEvent(const PointerEvent & pointerEvent,DragEventAction action,const RefPtr<NG::FrameNode> & node)3631 void PipelineContext::OnDragEvent(const PointerEvent& pointerEvent, DragEventAction action,
3632 const RefPtr<NG::FrameNode>& node)
3633 {
3634 auto manager = GetDragDropManager();
3635 CHECK_NULL_VOID(manager);
3636 std::string extraInfo;
3637 auto container = Container::Current();
3638 if (container && container->IsScenceBoardWindow()) {
3639 if (!manager->IsDragged() && manager->IsWindowConsumed()) {
3640 manager->SetIsWindowConsumed(false);
3641 return;
3642 }
3643 }
3644 if (action == DragEventAction::DRAG_EVENT_START_FOR_CONTROLLER) {
3645 manager->RequireSummary();
3646 manager->OnDragStart(pointerEvent.GetPoint());
3647 return;
3648 }
3649 if (action == DragEventAction::DRAG_EVENT_OUT) {
3650 manager->OnDragMoveOut(pointerEvent);
3651 manager->ClearSummary();
3652 manager->ClearExtraInfo();
3653 manager->SetDragCursorStyleCore(DragCursorStyleCore::DEFAULT);
3654 return;
3655 }
3656
3657 if (action == DragEventAction::DRAG_EVENT_START) {
3658 manager->ResetPreTargetFrameNode(GetInstanceId());
3659 manager->RequireSummaryIfNecessary(pointerEvent);
3660 manager->SetDragCursorStyleCore(DragCursorStyleCore::DEFAULT);
3661 TAG_LOGI(AceLogTag::ACE_DRAG, "start drag, current windowId is %{public}d", container->GetWindowId());
3662 }
3663 extraInfo = manager->GetExtraInfo();
3664 if (action == DragEventAction::DRAG_EVENT_END) {
3665 manager->OnDragEnd(pointerEvent, extraInfo, node);
3666 return;
3667 }
3668 if (action == DragEventAction::DRAG_EVENT_MOVE) {
3669 manager->DoDragMoveAnimate(pointerEvent);
3670 }
3671 manager->OnDragMove(pointerEvent, extraInfo, node);
3672 }
3673
AddNodesToNotifyMemoryLevel(int32_t nodeId)3674 void PipelineContext::AddNodesToNotifyMemoryLevel(int32_t nodeId)
3675 {
3676 nodesToNotifyMemoryLevel_.emplace_back(nodeId);
3677 }
3678
RemoveNodesToNotifyMemoryLevel(int32_t nodeId)3679 void PipelineContext::RemoveNodesToNotifyMemoryLevel(int32_t nodeId)
3680 {
3681 nodesToNotifyMemoryLevel_.remove(nodeId);
3682 }
3683
NotifyMemoryLevel(int32_t level)3684 void PipelineContext::NotifyMemoryLevel(int32_t level)
3685 {
3686 auto iter = nodesToNotifyMemoryLevel_.begin();
3687 while (iter != nodesToNotifyMemoryLevel_.end()) {
3688 auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
3689 if (!node) {
3690 iter = nodesToNotifyMemoryLevel_.erase(iter);
3691 } else {
3692 node->OnNotifyMemoryLevel(level);
3693 ++iter;
3694 }
3695 }
3696 }
AddPredictTask(PredictTask && task)3697 void PipelineContext::AddPredictTask(PredictTask&& task)
3698 {
3699 taskScheduler_->AddPredictTask(std::move(task));
3700 RequestFrame();
3701 }
3702
AddFrameCallback(FrameCallbackFunc && frameCallbackFunc,FrameCallbackFunc && idleCallbackFunc,int64_t delayMillis)3703 void PipelineContext::AddFrameCallback(FrameCallbackFunc&& frameCallbackFunc, FrameCallbackFunc&& idleCallbackFunc,
3704 int64_t delayMillis)
3705 {
3706 if (delayMillis <= 0) {
3707 if (frameCallbackFunc != nullptr) {
3708 frameCallbackFuncs_.emplace_back(std::move(frameCallbackFunc));
3709 }
3710 if (idleCallbackFunc != nullptr) {
3711 idleCallbackFuncs_.emplace_back(std::move(idleCallbackFunc));
3712 }
3713 RequestFrame();
3714 return;
3715 }
3716 auto taskScheduler = GetTaskExecutor();
3717 CHECK_NULL_VOID(taskScheduler);
3718 if (frameCallbackFunc != nullptr) {
3719 taskScheduler->PostDelayedTask(
3720 [weak = WeakClaim(this), callbackFunc = std::move(frameCallbackFunc)]() -> void {
3721 auto pipeline = weak.Upgrade();
3722 CHECK_NULL_VOID(pipeline);
3723 auto callback = const_cast<FrameCallbackFunc&>(callbackFunc);
3724 pipeline->frameCallbackFuncs_.emplace_back(std::move(callback));
3725 pipeline->RequestFrame();
3726 },
3727 TaskExecutor::TaskType::UI, delayMillis, "ArkUIPostFrameCallbackFuncDelayed");
3728 }
3729 if (idleCallbackFunc != nullptr) {
3730 taskScheduler->PostDelayedTask(
3731 [weak = WeakClaim(this), callbackFunc = std::move(idleCallbackFunc)]() -> void {
3732 auto pipeline = weak.Upgrade();
3733 CHECK_NULL_VOID(pipeline);
3734 auto callback = const_cast<FrameCallbackFunc&>(callbackFunc);
3735 pipeline->idleCallbackFuncs_.emplace_back(std::move(callback));
3736 pipeline->RequestFrame();
3737 },
3738 TaskExecutor::TaskType::UI, delayMillis, "ArkUIPostIdleCallbackFuncDelayed");
3739 }
3740 }
3741
TriggerIdleCallback(int64_t deadline)3742 void PipelineContext::TriggerIdleCallback(int64_t deadline)
3743 {
3744 if (idleCallbackFuncs_.empty()) {
3745 return;
3746 }
3747 int64_t currentTime = GetSysTimestamp();
3748 if (deadline - currentTime < MIN_IDLE_TIME) {
3749 RequestFrame();
3750 return;
3751 }
3752 decltype(idleCallbackFuncs_) tasks(std::move(idleCallbackFuncs_));
3753 for (const auto& idleCallbackFunc : tasks) {
3754 idleCallbackFunc(deadline - currentTime);
3755 currentTime = GetSysTimestamp();
3756 }
3757 }
3758
OnIdle(int64_t deadline)3759 void PipelineContext::OnIdle(int64_t deadline)
3760 {
3761 int64_t currentTime = GetSysTimestamp();
3762 if (deadline == 0) {
3763 int64_t lastTaskEndTimestamp = window_->GetLastVsyncEndTimestamp();
3764 if (eventManager_) {
3765 lastTaskEndTimestamp = std::max(lastTaskEndTimestamp, eventManager_->GetLastTouchEventEndTimestamp());
3766 }
3767 if (lastTaskEndTimestamp > 0 && currentTime > lastTaskEndTimestamp
3768 && currentTime - lastTaskEndTimestamp > VSYNC_PERIOD_COUNT * window_->GetVSyncPeriod()) {
3769 auto frontend = weakFrontend_.Upgrade();
3770 if (frontend) {
3771 frontend->NotifyUIIdle();
3772 }
3773 }
3774 }
3775 if (deadline == 0 || isWindowAnimation_) {
3776 canUseLongPredictTask_ = false;
3777 return;
3778 }
3779 if (canUseLongPredictTask_) {
3780 // check new incoming event after vsync.
3781 if (!touchEvents_.empty()) {
3782 canUseLongPredictTask_ = false;
3783 }
3784 }
3785 CHECK_RUN_ON(UI);
3786 ACE_SCOPED_TRACE("OnIdle, targettime:%" PRId64 "", deadline);
3787 taskScheduler_->FlushPredictTask(deadline - TIME_THRESHOLD, canUseLongPredictTask_);
3788 canUseLongPredictTask_ = false;
3789 if (currentTime < deadline) {
3790 ElementRegister::GetInstance()->CallJSCleanUpIdleTaskFunc();
3791 }
3792 TriggerIdleCallback(deadline);
3793 }
3794
Finish(bool) const3795 void PipelineContext::Finish(bool /* autoFinish */) const
3796 {
3797 CHECK_RUN_ON(UI);
3798 if (finishEventHandler_) {
3799 finishEventHandler_();
3800 }
3801 }
3802
AddAfterLayoutTask(std::function<void ()> && task,bool isFlushInImplicitAnimationTask)3803 void PipelineContext::AddAfterLayoutTask(std::function<void()>&& task, bool isFlushInImplicitAnimationTask)
3804 {
3805 taskScheduler_->AddAfterLayoutTask(std::move(task), isFlushInImplicitAnimationTask);
3806 }
3807
AddPersistAfterLayoutTask(std::function<void ()> && task)3808 void PipelineContext::AddPersistAfterLayoutTask(std::function<void()>&& task)
3809 {
3810 taskScheduler_->AddPersistAfterLayoutTask(std::move(task));
3811 }
3812
AddLatestFrameLayoutFinishTask(std::function<void ()> && task)3813 void PipelineContext::AddLatestFrameLayoutFinishTask(std::function<void()>&& task)
3814 {
3815 taskScheduler_->AddLatestFrameLayoutFinishTask(std::move(task));
3816 }
3817
AddAfterRenderTask(std::function<void ()> && task)3818 void PipelineContext::AddAfterRenderTask(std::function<void()>&& task)
3819 {
3820 taskScheduler_->AddAfterRenderTask(std::move(task));
3821 }
3822
RestoreNodeInfo(std::unique_ptr<JsonValue> nodeInfo)3823 void PipelineContext::RestoreNodeInfo(std::unique_ptr<JsonValue> nodeInfo)
3824 {
3825 auto child = nodeInfo->GetChild();
3826 while (child->IsValid()) {
3827 auto key = child->GetKey();
3828 auto value = child->GetString();
3829 restoreNodeInfo_.try_emplace(StringUtils::StringToInt(key), value);
3830 child = child->GetNext();
3831 }
3832 }
3833
GetStoredNodeInfo()3834 std::unique_ptr<JsonValue> PipelineContext::GetStoredNodeInfo()
3835 {
3836 auto jsonNodeInfo = JsonUtil::Create(true);
3837 auto iter = storeNode_.begin();
3838 while (iter != storeNode_.end()) {
3839 auto node = (iter->second).Upgrade();
3840 if (node) {
3841 std::string info = node->ProvideRestoreInfo();
3842 if (!info.empty()) {
3843 jsonNodeInfo->Put(std::to_string(iter->first).c_str(), info.c_str());
3844 }
3845 }
3846 ++iter;
3847 }
3848 return jsonNodeInfo;
3849 }
3850
StoreNode(int32_t restoreId,const WeakPtr<FrameNode> & node)3851 void PipelineContext::StoreNode(int32_t restoreId, const WeakPtr<FrameNode>& node)
3852 {
3853 auto ret = storeNode_.try_emplace(restoreId, node);
3854 if (!ret.second) {
3855 storeNode_[restoreId] = node;
3856 }
3857 }
3858
GetRestoreInfo(int32_t restoreId,std::string & restoreInfo)3859 bool PipelineContext::GetRestoreInfo(int32_t restoreId, std::string& restoreInfo)
3860 {
3861 auto iter = restoreNodeInfo_.find(restoreId);
3862 if (iter != restoreNodeInfo_.end()) {
3863 restoreInfo = iter->second;
3864 restoreNodeInfo_.erase(iter);
3865 return true;
3866 }
3867 return false;
3868 }
3869
SetContainerButtonHide(bool hideSplit,bool hideMaximize,bool hideMinimize)3870 void PipelineContext::SetContainerButtonHide(bool hideSplit, bool hideMaximize, bool hideMinimize)
3871 {
3872 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
3873 LOGW("Set app icon failed, Window modal is not container.");
3874 return;
3875 }
3876 CHECK_NULL_VOID(rootNode_);
3877 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
3878 CHECK_NULL_VOID(containerNode);
3879 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
3880 CHECK_NULL_VOID(containerPattern);
3881 containerPattern->SetContainerButtonHide(hideSplit, hideMaximize, hideMinimize);
3882 }
3883
AddFontNodeNG(const WeakPtr<UINode> & node)3884 void PipelineContext::AddFontNodeNG(const WeakPtr<UINode>& node)
3885 {
3886 if (fontManager_) {
3887 fontManager_->AddFontNodeNG(node);
3888 }
3889 }
3890
RemoveFontNodeNG(const WeakPtr<UINode> & node)3891 void PipelineContext::RemoveFontNodeNG(const WeakPtr<UINode>& node)
3892 {
3893 if (fontManager_) {
3894 fontManager_->RemoveFontNodeNG(node);
3895 }
3896 }
3897
SetWindowSceneConsumed(bool isConsumed)3898 void PipelineContext::SetWindowSceneConsumed(bool isConsumed)
3899 {
3900 isWindowSceneConsumed_ = isConsumed;
3901 }
3902
IsWindowSceneConsumed()3903 bool PipelineContext::IsWindowSceneConsumed()
3904 {
3905 return isWindowSceneConsumed_;
3906 }
3907
SetCloseButtonStatus(bool isEnabled)3908 void PipelineContext::SetCloseButtonStatus(bool isEnabled)
3909 {
3910 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
3911 return;
3912 }
3913 CHECK_NULL_VOID(rootNode_);
3914 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
3915 CHECK_NULL_VOID(containerNode);
3916 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
3917 CHECK_NULL_VOID(containerPattern);
3918 containerPattern->SetCloseButtonStatus(isEnabled);
3919 }
3920
AnimateOnSafeAreaUpdate()3921 void PipelineContext::AnimateOnSafeAreaUpdate()
3922 {
3923 // complete other layout tasks before animation
3924 FlushUITasks();
3925 AnimationOption option;
3926 option.SetCurve(safeAreaManager_->GetSafeAreaCurve());
3927 AnimationUtils::Animate(option, [weak = WeakClaim(this)]() {
3928 auto self = weak.Upgrade();
3929 CHECK_NULL_VOID(self);
3930 self->SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_AVOID_AREA);
3931 self->FlushUITasks();
3932 });
3933 }
3934
HandleSubwindow(bool isShow)3935 void PipelineContext::HandleSubwindow(bool isShow)
3936 {
3937 // When the main window is applied to the background,
3938 // there are sub windows that do not immediately hide, such as Toast floating window
3939 if (!isShow) {
3940 overlayManager_->ClearToastInSubwindow();
3941 }
3942 }
3943
AddIsFocusActiveUpdateEvent(const RefPtr<FrameNode> & node,const std::function<void (bool)> & eventCallback)3944 void PipelineContext::AddIsFocusActiveUpdateEvent(
3945 const RefPtr<FrameNode>& node, const std::function<void(bool)>& eventCallback)
3946 {
3947 CHECK_NULL_VOID(node);
3948 isFocusActiveUpdateEvents_.insert_or_assign(node->GetId(), eventCallback);
3949 }
3950
RemoveIsFocusActiveUpdateEvent(const RefPtr<FrameNode> & node)3951 void PipelineContext::RemoveIsFocusActiveUpdateEvent(const RefPtr<FrameNode>& node)
3952 {
3953 CHECK_NULL_VOID(node);
3954 auto iter = isFocusActiveUpdateEvents_.find(node->GetId());
3955 if (iter != isFocusActiveUpdateEvents_.end()) {
3956 isFocusActiveUpdateEvents_.erase(iter);
3957 }
3958 }
3959
GetNavigationController(const std::string & id)3960 std::shared_ptr<NavigationController> PipelineContext::GetNavigationController(const std::string& id)
3961 {
3962 std::lock_guard lock(navigationMutex_);
3963 auto iter = navigationNodes_.find(id);
3964 if (iter == navigationNodes_.end()) {
3965 return nullptr;
3966 }
3967
3968 auto navigationGroupNode = iter->second.Upgrade();
3969 CHECK_NULL_RETURN(navigationGroupNode, nullptr);
3970
3971 auto navigationPattern = navigationGroupNode->GetPattern<NavigationPattern>();
3972 CHECK_NULL_RETURN(navigationPattern, nullptr);
3973 return navigationPattern->GetNavigationController();
3974 }
3975
AddOrReplaceNavigationNode(const std::string & id,const WeakPtr<FrameNode> & node)3976 void PipelineContext::AddOrReplaceNavigationNode(const std::string& id, const WeakPtr<FrameNode>& node)
3977 {
3978 std::lock_guard lock(navigationMutex_);
3979 auto frameNode = node.Upgrade();
3980 CHECK_NULL_VOID(frameNode);
3981 auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
3982 CHECK_NULL_VOID(navigationGroupNode);
3983 auto oldId = navigationGroupNode->GetCurId();
3984 if (!oldId.empty() && navigationNodes_.find(oldId) != navigationNodes_.end()) {
3985 navigationNodes_.erase(oldId);
3986 }
3987
3988 if (!id.empty()) {
3989 navigationNodes_[id] = node;
3990 }
3991 }
3992
DeleteNavigationNode(const std::string & id)3993 void PipelineContext::DeleteNavigationNode(const std::string& id)
3994 {
3995 std::lock_guard lock(navigationMutex_);
3996 if (!id.empty() && navigationNodes_.find(id) != navigationNodes_.end()) {
3997 navigationNodes_.erase(id);
3998 }
3999 }
4000
SetCursor(int32_t cursorValue)4001 void PipelineContext::SetCursor(int32_t cursorValue)
4002 {
4003 if (cursorValue >= 0 && cursorValue <= static_cast<int32_t>(MouseFormat::RUNNING)) {
4004 auto window = GetWindow();
4005 CHECK_NULL_VOID(window);
4006 auto mouseStyle = MouseStyle::CreateMouseStyle();
4007 CHECK_NULL_VOID(mouseStyle);
4008 auto cursor = static_cast<MouseFormat>(cursorValue);
4009 window->SetCursor(cursor);
4010 window->SetUserSetCursor(true);
4011 mouseStyle->ChangePointerStyle(GetFocusWindowId(), cursor);
4012 }
4013 }
4014
RestoreDefault(int32_t windowId)4015 void PipelineContext::RestoreDefault(int32_t windowId)
4016 {
4017 auto window = GetWindow();
4018 CHECK_NULL_VOID(window);
4019 auto mouseStyle = MouseStyle::CreateMouseStyle();
4020 CHECK_NULL_VOID(mouseStyle);
4021 window->SetCursor(MouseFormat::DEFAULT);
4022 window->SetUserSetCursor(false);
4023 mouseStyle->ChangePointerStyle(windowId > 0 ? windowId : GetFocusWindowId(), MouseFormat::DEFAULT);
4024 }
4025
GetCurrentExtraInfo()4026 std::string PipelineContext::GetCurrentExtraInfo()
4027 {
4028 auto node = activeNode_.Upgrade();
4029 return node ? node->GetCurrentCustomNodeInfo() : std::string();
4030 }
4031
OpenFrontendAnimation(const AnimationOption & option,const RefPtr<Curve> & curve,const std::function<void ()> & finishCallback)4032 void PipelineContext::OpenFrontendAnimation(
4033 const AnimationOption& option, const RefPtr<Curve>& curve, const std::function<void()>& finishCallback)
4034 {
4035 // push false to show we already open a animation closure.
4036 pendingFrontendAnimation_.push(false);
4037
4038 // flush ui tasks before open animation closure.
4039 if (!isReloading_ && !IsLayouting()) {
4040 FlushUITasks();
4041 }
4042 auto wrapFinishCallback = GetWrappedAnimationCallback(finishCallback);
4043 if (IsFormRender()) {
4044 SetIsFormAnimation(true);
4045 if (!IsFormAnimationFinishCallback()) {
4046 SetFormAnimationStartTime(GetMicroTickCount());
4047 }
4048 }
4049 AnimationUtils::OpenImplicitAnimation(option, curve, wrapFinishCallback);
4050 }
4051
CloseFrontendAnimation()4052 void PipelineContext::CloseFrontendAnimation()
4053 {
4054 if (pendingFrontendAnimation_.empty()) {
4055 return;
4056 }
4057
4058 if (pendingFrontendAnimation_.top()) {
4059 if (!isReloading_ && !IsLayouting()) {
4060 FlushUITasks();
4061 } else if (IsLayouting()) {
4062 TAG_LOGW(AceLogTag::ACE_ANIMATION,
4063 "IsLayouting, CloseFrontendAnimation has tasks not flushed, maybe some layout animation not generated");
4064 }
4065 }
4066 if (!pendingFrontendAnimation_.empty()) {
4067 pendingFrontendAnimation_.pop();
4068 }
4069 AnimationUtils::CloseImplicitAnimation();
4070 }
4071
SetContainerModalTitleVisible(bool customTitleSettedShow,bool floatingTitleSettedShow)4072 void PipelineContext::SetContainerModalTitleVisible(bool customTitleSettedShow, bool floatingTitleSettedShow)
4073 {
4074 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4075 return;
4076 }
4077 CHECK_NULL_VOID(rootNode_);
4078 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
4079 CHECK_NULL_VOID(containerNode);
4080 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4081 CHECK_NULL_VOID(containerPattern);
4082 containerPattern->SetContainerModalTitleVisible(customTitleSettedShow, floatingTitleSettedShow);
4083 customTitleSettedShow_ = customTitleSettedShow;
4084 }
4085
SetContainerModalTitleHeight(int32_t height)4086 void PipelineContext::SetContainerModalTitleHeight(int32_t height)
4087 {
4088 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4089 return;
4090 }
4091 CHECK_NULL_VOID(rootNode_);
4092 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
4093 CHECK_NULL_VOID(containerNode);
4094 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4095 CHECK_NULL_VOID(containerPattern);
4096 containerPattern->SetContainerModalTitleHeight(height);
4097 }
4098
GetContainerModalTitleHeight()4099 int32_t PipelineContext::GetContainerModalTitleHeight()
4100 {
4101 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4102 return -1;
4103 }
4104 CHECK_NULL_RETURN(rootNode_, -1);
4105 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
4106 CHECK_NULL_RETURN(containerNode, -1);
4107 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4108 CHECK_NULL_RETURN(containerPattern, -1);
4109 return containerPattern->GetContainerModalTitleHeight();
4110 }
4111
GetContainerModalNode()4112 RefPtr<FrameNode> PipelineContext::GetContainerModalNode()
4113 {
4114 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4115 return nullptr;
4116 }
4117 CHECK_NULL_RETURN(rootNode_, nullptr);
4118 return AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
4119 }
4120
DoKeyboardAvoidAnimate(const KeyboardAnimationConfig & keyboardAnimationConfig,float keyboardHeight,const std::function<void ()> & func)4121 void PipelineContext::DoKeyboardAvoidAnimate(const KeyboardAnimationConfig& keyboardAnimationConfig,
4122 float keyboardHeight, const std::function<void()>& func)
4123 {
4124 if (isDoKeyboardAvoidAnimate_) {
4125 AnimationOption option = AnimationUtil::CreateKeyboardAnimationOption(keyboardAnimationConfig, keyboardHeight);
4126 Animate(option, option.GetCurve(), func);
4127 } else {
4128 func();
4129 }
4130 }
4131
GetCustomTitleHeight()4132 Dimension PipelineContext::GetCustomTitleHeight()
4133 {
4134 auto containerModal = GetContainerModalNode();
4135 CHECK_NULL_RETURN(containerModal, Dimension());
4136 return containerModal->GetPattern<ContainerModalPattern>()->GetCustomTitleHeight();
4137 }
4138
GetContainerModalButtonsRect(RectF & containerModal,RectF & buttons)4139 bool PipelineContext::GetContainerModalButtonsRect(RectF& containerModal, RectF& buttons)
4140 {
4141 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4142 return false;
4143 }
4144 CHECK_NULL_RETURN(rootNode_, false);
4145 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
4146 CHECK_NULL_RETURN(containerNode, false);
4147 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4148 CHECK_NULL_RETURN(containerPattern, false);
4149 return containerPattern->GetContainerModalButtonsRect(containerModal, buttons);
4150 }
4151
SubscribeContainerModalButtonsRectChange(std::function<void (RectF & containerModal,RectF & buttons)> && callback)4152 void PipelineContext::SubscribeContainerModalButtonsRectChange(
4153 std::function<void(RectF& containerModal, RectF& buttons)>&& callback)
4154 {
4155 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4156 return;
4157 }
4158 CHECK_NULL_VOID(rootNode_);
4159 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
4160 CHECK_NULL_VOID(containerNode);
4161 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4162 CHECK_NULL_VOID(containerPattern);
4163 containerPattern->SubscribeContainerModalButtonsRectChange(std::move(callback));
4164 }
4165
GetWindowPaintRectWithoutMeasureAndLayout(RectInt & rect)4166 void PipelineContext::GetWindowPaintRectWithoutMeasureAndLayout(RectInt& rect)
4167 {
4168 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4169 return;
4170 }
4171 CHECK_NULL_VOID(rootNode_);
4172 auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
4173 CHECK_NULL_VOID(containerNode);
4174 auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4175 CHECK_NULL_VOID(containerPattern);
4176 containerPattern->GetWindowPaintRectWithoutMeasureAndLayout(rect);
4177 }
4178
IsDragging() const4179 bool PipelineContext::IsDragging() const
4180 {
4181 if (!dragDropManager_) {
4182 return false;
4183 }
4184 bool isDragging = dragDropManager_->IsDragging();
4185 isDragging = (isDragging || dragDropManager_->IsMSDPDragging());
4186 return isDragging;
4187 }
4188
SetIsDragging(bool isDragging)4189 void PipelineContext::SetIsDragging(bool isDragging)
4190 {
4191 if (!eventManager_) {
4192 return;
4193 }
4194 eventManager_->SetIsDragging(isDragging);
4195 }
4196
ResetDragging()4197 void PipelineContext::ResetDragging()
4198 {
4199 CHECK_NULL_VOID(dragDropManager_);
4200 dragDropManager_->ResetDragging();
4201 }
4202
GetPostEventManager()4203 const RefPtr<PostEventManager>& PipelineContext::GetPostEventManager()
4204 {
4205 return postEventManager_;
4206 }
4207
GetSerializedGesture() const4208 const SerializedGesture& PipelineContext::GetSerializedGesture() const
4209 {
4210 return serializedGesture_;
4211 }
4212
PrintVsyncInfoIfNeed() const4213 bool PipelineContext::PrintVsyncInfoIfNeed() const
4214 {
4215 if (dumpFrameInfos_.empty()) {
4216 return false;
4217 }
4218 auto lastFrameInfo = dumpFrameInfos_.back();
4219 const uint64_t timeout = 1000000000; // unit is ns, 1s
4220 if (lastFrameInfo.frameRecvTime_ < window_->GetLastRequestVsyncTime() &&
4221 static_cast<uint64_t>(GetSysTimestamp()) - window_->GetLastRequestVsyncTime() >= timeout) {
4222 LOGW("lastRequestVsyncTime is %{public}" PRIu64 ", now time is %{public}" PRId64
4223 ", timeout, window foreground:%{public}d, lastReceiveVsync info:%{public}s",
4224 window_->GetLastRequestVsyncTime(), GetSysTimestamp(), onShow_, lastFrameInfo.GetTimeInfo().c_str());
4225 return true;
4226 }
4227 return false;
4228 }
4229
AddSyncGeometryNodeTask(std::function<void ()> && task)4230 void PipelineContext::AddSyncGeometryNodeTask(std::function<void()>&& task)
4231 {
4232 taskScheduler_->AddSyncGeometryNodeTask(std::move(task));
4233 }
4234
FlushSyncGeometryNodeTasks()4235 void PipelineContext::FlushSyncGeometryNodeTasks()
4236 {
4237 taskScheduler_->FlushSyncGeometryNodeTasks();
4238 }
4239
SetUIExtensionImeShow(bool imeShow)4240 void PipelineContext::SetUIExtensionImeShow(bool imeShow)
4241 {
4242 textFieldManager_->SetUIExtensionImeShow(imeShow);
4243 }
4244
SetOverlayNodePositions(std::vector<Ace::RectF> rects)4245 void PipelineContext::SetOverlayNodePositions(std::vector<Ace::RectF> rects)
4246 {
4247 overlayNodePositions_ = rects;
4248 }
4249
SetCallBackNode(const WeakPtr<NG::FrameNode> & node)4250 void PipelineContext::SetCallBackNode(const WeakPtr<NG::FrameNode>& node)
4251 {
4252 auto frameNode = node.Upgrade();
4253 CHECK_NULL_VOID(frameNode);
4254 auto pipelineContext = frameNode->GetContext();
4255 CHECK_NULL_VOID(pipelineContext);
4256 pipelineContext->UpdateCurrentActiveNode(node);
4257 }
4258
GetOverlayNodePositions()4259 std::vector<Ace::RectF> PipelineContext::GetOverlayNodePositions()
4260 {
4261 return overlayNodePositions_;
4262 }
4263
RegisterOverlayNodePositionsUpdateCallback(const std::function<void (std::vector<Ace::RectF>)> && callback)4264 void PipelineContext::RegisterOverlayNodePositionsUpdateCallback(
4265 const std::function<void(std::vector<Ace::RectF>)>&& callback)
4266 {
4267 overlayNodePositionUpdateCallback_ = std::move(callback);
4268 }
4269
TriggerOverlayNodePositionsUpdateCallback(std::vector<Ace::RectF> rects)4270 void PipelineContext::TriggerOverlayNodePositionsUpdateCallback(std::vector<Ace::RectF> rects)
4271 {
4272 if (overlayNodePositionUpdateCallback_) {
4273 overlayNodePositionUpdateCallback_(rects);
4274 }
4275 }
4276
IsContainerModalVisible()4277 bool PipelineContext::IsContainerModalVisible()
4278 {
4279 if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4280 return false;
4281 }
4282 auto windowManager = GetWindowManager();
4283 bool isFloatingWindow = windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
4284 return isShowTitle_ && isFloatingWindow && customTitleSettedShow_;
4285 }
4286
CheckNeedUpdateBackgroundColor(Color & color)4287 void PipelineContext::CheckNeedUpdateBackgroundColor(Color& color)
4288 {
4289 if (!isFormRender_ || (renderingMode_ != RENDERING_SINGLE_COLOR)) {
4290 return;
4291 }
4292 Color replaceColor = color.ChangeAlpha(SINGLECOLOR_UPDATE_ALPHA);
4293 color = replaceColor;
4294 }
4295
CheckNeedDisableUpdateBackgroundImage()4296 bool PipelineContext::CheckNeedDisableUpdateBackgroundImage()
4297 {
4298 if (!isFormRender_ || (renderingMode_ != RENDERING_SINGLE_COLOR)) {
4299 return false;
4300 }
4301 return true;
4302 }
4303
ChangeDarkModeBrightness()4304 void PipelineContext::ChangeDarkModeBrightness()
4305 {
4306 auto windowManager = GetWindowManager();
4307 CHECK_NULL_VOID(windowManager);
4308 auto mode = windowManager->GetWindowMode();
4309 auto container = Container::CurrentSafely();
4310 CHECK_NULL_VOID(container);
4311 auto percent = SystemProperties::GetDarkModeBrightnessPercent();
4312 auto stage = stageManager_->GetStageNode();
4313 CHECK_NULL_VOID(stage);
4314 auto renderContext = stage->GetRenderContext();
4315 CHECK_NULL_VOID(renderContext);
4316 CalcDimension dimension;
4317 dimension.SetValue(1);
4318 if (SystemProperties::GetColorMode() == ColorMode::DARK && appBgColor_.ColorToString().compare("#FF000000") == 0 &&
4319 mode != WindowMode::WINDOW_MODE_FULLSCREEN && !container->IsUIExtensionWindow() &&
4320 !container->IsDynamicRender() && !container->IsFormRender() && !IsJsCard()) {
4321 if (!onFocus_ && mode == WindowMode::WINDOW_MODE_FLOATING) {
4322 dimension.SetValue(1 + percent.second);
4323 } else {
4324 dimension.SetValue(1 + percent.first);
4325 }
4326 }
4327 renderContext->UpdateFrontBrightness(dimension);
4328 }
4329
PreLayout(uint64_t nanoTimestamp,uint32_t frameCount)4330 void PipelineContext::PreLayout(uint64_t nanoTimestamp, uint32_t frameCount)
4331 {
4332 FlushVsync(nanoTimestamp, frameCount);
4333 }
4334
CheckAndLogLastReceivedTouchEventInfo(int32_t eventId,TouchType type)4335 void PipelineContext::CheckAndLogLastReceivedTouchEventInfo(int32_t eventId, TouchType type)
4336 {
4337 eventManager_->CheckAndLogLastReceivedTouchEventInfo(eventId, type);
4338 }
4339
CheckAndLogLastConsumedTouchEventInfo(int32_t eventId,TouchType type)4340 void PipelineContext::CheckAndLogLastConsumedTouchEventInfo(int32_t eventId, TouchType type)
4341 {
4342 eventManager_->CheckAndLogLastConsumedTouchEventInfo(eventId, type);
4343 }
4344
CheckAndLogLastReceivedMouseEventInfo(int32_t eventId,MouseAction action)4345 void PipelineContext::CheckAndLogLastReceivedMouseEventInfo(int32_t eventId, MouseAction action)
4346 {
4347 eventManager_->CheckAndLogLastReceivedMouseEventInfo(eventId, action);
4348 }
4349
CheckAndLogLastConsumedMouseEventInfo(int32_t eventId,MouseAction action)4350 void PipelineContext::CheckAndLogLastConsumedMouseEventInfo(int32_t eventId, MouseAction action)
4351 {
4352 eventManager_->CheckAndLogLastConsumedMouseEventInfo(eventId, action);
4353 }
4354
CheckAndLogLastReceivedAxisEventInfo(int32_t eventId,AxisAction action)4355 void PipelineContext::CheckAndLogLastReceivedAxisEventInfo(int32_t eventId, AxisAction action)
4356 {
4357 eventManager_->CheckAndLogLastReceivedAxisEventInfo(eventId, action);
4358 }
4359
CheckAndLogLastConsumedAxisEventInfo(int32_t eventId,AxisAction action)4360 void PipelineContext::CheckAndLogLastConsumedAxisEventInfo(int32_t eventId, AxisAction action)
4361 {
4362 eventManager_->CheckAndLogLastConsumedAxisEventInfo(eventId, action);
4363 }
4364
RegisterTouchEventListener(const std::shared_ptr<ITouchEventCallback> & listener)4365 void PipelineContext::RegisterTouchEventListener(const std::shared_ptr<ITouchEventCallback>& listener)
4366 {
4367 if (!listener) {
4368 return;
4369 }
4370 listenerVector_.emplace_back(listener);
4371 }
4372
UnregisterTouchEventListener(const WeakPtr<NG::Pattern> & pattern)4373 void PipelineContext::UnregisterTouchEventListener(const WeakPtr<NG::Pattern>& pattern)
4374 {
4375 for (auto iter = listenerVector_.begin(); iter != listenerVector_.end();) {
4376 auto patternPtr = (*iter)->GetPatternFromListener();
4377 if (patternPtr.Invalid() || patternPtr == pattern) {
4378 iter = listenerVector_.erase(iter);
4379 } else {
4380 iter++;
4381 }
4382 }
4383 }
4384
FlushFrameCallback(uint64_t nanoTimestamp)4385 void PipelineContext::FlushFrameCallback(uint64_t nanoTimestamp)
4386 {
4387 if (!frameCallbackFuncs_.empty()) {
4388 decltype(frameCallbackFuncs_) tasks(std::move(frameCallbackFuncs_));
4389 for (const auto& frameCallbackFunc : tasks) {
4390 frameCallbackFunc(nanoTimestamp);
4391 }
4392 }
4393 }
4394
RegisterFocusCallback()4395 void PipelineContext::RegisterFocusCallback()
4396 {
4397 focusManager_->AddFocusListener([](const WeakPtr<FocusHub>& last, const RefPtr<FocusHub>& current) {
4398 CHECK_NULL_VOID(current);
4399 auto node = current->GetFrameNode();
4400 CHECK_NULL_VOID(node);
4401 InputMethodManager::GetInstance()->OnFocusNodeChange(node);
4402 });
4403 }
4404
AddFrameNodeChangeListener(const WeakPtr<FrameNode> & node)4405 void PipelineContext::AddFrameNodeChangeListener(const WeakPtr<FrameNode>& node)
4406 {
4407 CHECK_NULL_VOID(node.Upgrade());
4408 if (std::find(changeInfoListeners_.begin(), changeInfoListeners_.end(), node) == changeInfoListeners_.end()) {
4409 changeInfoListeners_.push_back(node);
4410 }
4411 }
4412
RemoveFrameNodeChangeListener(int32_t nodeId)4413 void PipelineContext::RemoveFrameNodeChangeListener(int32_t nodeId)
4414 {
4415 if (changeInfoListeners_.empty()) {
4416 return;
4417 }
4418 changeInfoListeners_.remove_if([nodeId](const WeakPtr<FrameNode>& node) {
4419 return !node.Upgrade() || nodeId == node.Upgrade()->GetId();
4420 });
4421 }
4422
AddChangedFrameNode(const WeakPtr<FrameNode> & node)4423 bool PipelineContext::AddChangedFrameNode(const WeakPtr<FrameNode>& node)
4424 {
4425 CHECK_NULL_RETURN(node.Upgrade(), false);
4426 if (changeInfoListeners_.empty()) {
4427 return false;
4428 }
4429 if (std::find(changedNodes_.begin(), changedNodes_.end(), node) == changedNodes_.end()) {
4430 changedNodes_.push_back(node);
4431 }
4432 return true;
4433 }
4434
RemoveChangedFrameNode(int32_t nodeId)4435 void PipelineContext::RemoveChangedFrameNode(int32_t nodeId)
4436 {
4437 if (changedNodes_.empty()) {
4438 return;
4439 }
4440 changedNodes_.remove_if([nodeId](const WeakPtr<FrameNode>& node) {
4441 return !node.Upgrade() || nodeId == node.Upgrade()->GetId();
4442 });
4443 }
4444
FlushNodeChangeFlag()4445 void PipelineContext::FlushNodeChangeFlag()
4446 {
4447 ACE_FUNCTION_TRACE();
4448 if (!changeInfoListeners_.empty()) {
4449 for (const auto& it : changeInfoListeners_) {
4450 auto listener = it.Upgrade();
4451 if (listener) {
4452 listener->ProcessFrameNodeChangeFlag();
4453 }
4454 }
4455 }
4456 CleanNodeChangeFlag();
4457 }
4458
CleanNodeChangeFlag()4459 void PipelineContext::CleanNodeChangeFlag()
4460 {
4461 auto cleanNodes = std::move(changedNodes_);
4462 changedNodes_.clear();
4463 for (const auto& it : cleanNodes) {
4464 auto changeNode = it.Upgrade();
4465 if (changeNode) {
4466 changeNode->ClearChangeInfoFlag();
4467 }
4468 }
4469 }
4470
GetInspectorTree()4471 void PipelineContext::GetInspectorTree()
4472 {
4473 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
4474 bool needThrow = false;
4475 NG::InspectorFilter filter;
4476 filter.AddFilterAttr("content");
4477 auto nodeInfos = NG::Inspector::GetInspector(false, filter, needThrow);
4478 UiSessionManager::GetInstance().AddValueForTree(0, nodeInfos);
4479 #endif
4480 rootNode_->GetInspectorValue();
4481 }
4482
NotifyAllWebPattern(bool isRegister)4483 void PipelineContext::NotifyAllWebPattern(bool isRegister)
4484 {
4485 rootNode_->NotifyWebPattern(isRegister);
4486 }
4487
4488 #if defined(SUPPORT_TOUCH_TARGET_TEST)
4489
OnTouchTargetHitTest(const TouchEvent & point,bool isSubPipe,const std::string & target)4490 bool PipelineContext::OnTouchTargetHitTest(const TouchEvent& point, bool isSubPipe, const std::string& target)
4491 {
4492 auto scalePoint = point.CreateScalePoint(GetViewScale());
4493 if (scalePoint.type == TouchType::DOWN) {
4494 TouchRestrict touchRestrict { TouchRestrict::NONE };
4495 touchRestrict.sourceType = point.sourceType;
4496 touchRestrict.touchEvent = point;
4497 bool isTouchTarget = eventManager_->TouchTargetHitTest(
4498 scalePoint, rootNode_, touchRestrict, GetPluginEventOffset(), viewScale_, isSubPipe, target);
4499 return isTouchTarget;
4500 }
4501 return false;
4502 }
4503 #endif
4504
UpdateHalfFoldHoverStatus(int32_t windowWidth,int32_t windowHeight)4505 void PipelineContext::UpdateHalfFoldHoverStatus(int32_t windowWidth, int32_t windowHeight)
4506 {
4507 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_THIRTEEN)) {
4508 isHalfFoldHoverStatus_ = false;
4509 return;
4510 }
4511 auto container = Container::Current();
4512 CHECK_NULL_VOID(container);
4513 bool isFoldable = container->IsFoldable();
4514 if (!isFoldable && !SystemProperties::IsSmallFoldProduct()) {
4515 isHalfFoldHoverStatus_ = false;
4516 return;
4517 }
4518 auto displayInfo = container->GetDisplayInfo();
4519 CHECK_NULL_VOID(displayInfo);
4520 auto windowManager = GetWindowManager();
4521 auto windowMode = windowManager->GetWindowMode();
4522 auto isHalfFolded = displayInfo->GetFoldStatus() == FoldStatus::HALF_FOLD;
4523 auto displayWidth = displayInfo->GetWidth();
4524 auto displayHeight = displayInfo->GetHeight();
4525 auto isFullScreen = windowMode == WindowMode::WINDOW_MODE_FULLSCREEN ||
4526 (NearEqual(displayWidth, windowWidth) && NearEqual(displayHeight, windowHeight));
4527 if (!isFullScreen || !isHalfFolded) {
4528 isHalfFoldHoverStatus_ = false;
4529 return;
4530 }
4531 auto rotation = displayInfo->GetRotation();
4532 if (SystemProperties::IsSmallFoldProduct()) {
4533 isHalfFoldHoverStatus_ = rotation == Rotation::ROTATION_0 || rotation == Rotation::ROTATION_180;
4534 } else {
4535 isHalfFoldHoverStatus_ = rotation == Rotation::ROTATION_90 || rotation == Rotation::ROTATION_270;
4536 }
4537 }
4538
OnHalfFoldHoverChangedCallback()4539 void PipelineContext::OnHalfFoldHoverChangedCallback()
4540 {
4541 for (auto&& [id, callback] : halfFoldHoverChangedCallbackMap_) {
4542 if (callback) {
4543 callback(isHalfFoldHoverStatus_);
4544 }
4545 }
4546 }
4547
StartFoldStatusDelayTask(FoldStatus foldStatus)4548 void PipelineContext::StartFoldStatusDelayTask(FoldStatus foldStatus)
4549 {
4550 if (foldStatusDelayTask_) {
4551 foldStatusDelayTask_.Cancel();
4552 }
4553 foldStatusDelayTask_.Reset([weak = WeakClaim(this)]() {
4554 auto context = weak.Upgrade();
4555 CHECK_NULL_VOID(context);
4556 context->UpdateHalfFoldHoverProperty(context->GetRootWidth(), context->GetRootHeight());
4557 context->OnHalfFoldHoverChangedCallback();
4558 });
4559 taskExecutor_->PostDelayedTask(
4560 foldStatusDelayTask_, TaskExecutor::TaskType::UI, DELAY_TIME, "ArkUIHalfFoldHoverStatusChange");
4561 }
4562
CatchInteractiveAnimations(const std::function<void ()> & animationCallback)4563 bool PipelineContext::CatchInteractiveAnimations(const std::function<void()>& animationCallback)
4564 {
4565 CHECK_NULL_RETURN(navigationMgr_, false);
4566 if (navigationMgr_->IsInteractive()) {
4567 return navigationMgr_->AddInteractiveAnimation(animationCallback);
4568 }
4569 return false;
4570 }
4571
GetResponseRegion(const RefPtr<FrameNode> & rootNode)4572 std::string PipelineContext::GetResponseRegion(const RefPtr<FrameNode>& rootNode)
4573 {
4574 CHECK_NULL_RETURN(rootNode, "");
4575 std::vector<RectF> responseRegionList;
4576 rootNode->GetResponseRegionListByTraversal(responseRegionList);
4577 std::string responseRegionStrOrigin;
4578 std::string responseRegionStrFilter;
4579 for (const auto& rect : responseRegionList) {
4580 int32_t left = static_cast<int32_t>(rect.Left());
4581 int32_t top = static_cast<int32_t>(rect.Top());
4582 int32_t width = static_cast<int32_t>(rect.Width());
4583 int32_t height = static_cast<int32_t>(rect.Height());
4584 int32_t right = static_cast<int32_t>(rect.Right());
4585 int32_t bottom = static_cast<int32_t>(rect.Bottom());
4586 std::string rectStr = std::to_string(left) + "," +
4587 std::to_string(top) + "," +
4588 std::to_string(right) + "," +
4589 std::to_string(bottom);
4590
4591 responseRegionStrOrigin += rectStr + "#";
4592 if (thpExtraMgr_ && width <= thpExtraMgr_->GetWidth() && height <= thpExtraMgr_->GetHeight()) {
4593 responseRegionStrFilter += rectStr + "#";
4594 }
4595 }
4596 if (!responseRegionStrFilter.empty()) {
4597 responseRegionStrFilter.pop_back();
4598 }
4599 LOGD("THP_UpdateViewsLocation origin responseRegion = %{public}s", responseRegionStrOrigin.c_str());
4600 return responseRegionStrFilter;
4601 }
4602
NotifyResponseRegionChanged(const RefPtr<FrameNode> & rootNode)4603 void PipelineContext::NotifyResponseRegionChanged(const RefPtr<FrameNode>& rootNode)
4604 {
4605 ACE_FUNCTION_TRACE();
4606 if (!thpExtraMgr_) {
4607 return;
4608 }
4609 std::string responseRegion = GetResponseRegion(rootNode);
4610 std::string parameters = "thp#Location#" + responseRegion;
4611 LOGD("THP_UpdateViewsLocation responseRegion = %{public}s", parameters.c_str());
4612 thpExtraMgr_->ThpExtraRunCommand("THP_UpdateViewsLocation", parameters.c_str());
4613 }
4614
CheckThreadSafe() const4615 bool PipelineContext::CheckThreadSafe() const
4616 {
4617 CHECK_NULL_RETURN(taskExecutor_, true);
4618 if (!isFormRender_ && !taskExecutor_->WillRunOnCurrentThread(OHOS::Ace::TaskExecutor::TaskType::UI)) {
4619 OHOS::Ace::LogBacktrace();
4620 return false;
4621 }
4622 return true;
4623 }
4624
AdjustVsyncTimeStamp(uint64_t nanoTimestamp)4625 uint64_t PipelineContext::AdjustVsyncTimeStamp(uint64_t nanoTimestamp)
4626 {
4627 auto period = window_->GetVSyncPeriod();
4628 if (period > 0 && recvTime_ > static_cast<int64_t>(nanoTimestamp) + MAX_MISS_COUNT * period) {
4629 return static_cast<uint64_t>(recvTime_ - ((recvTime_ - static_cast<int64_t>(nanoTimestamp)) % period));
4630 }
4631 return nanoTimestamp;
4632 }
4633
FlushModifierAnimation(uint64_t nanoTimestamp)4634 bool PipelineContext::FlushModifierAnimation(uint64_t nanoTimestamp)
4635 {
4636 auto animationTimeStamp = AdjustVsyncTimeStamp(nanoTimestamp);
4637 if (animationTimeStamp < animationTimeStamp_) {
4638 ACE_SCOPED_TRACE("skip ModifierAnimation");
4639 TAG_LOGW(AceLogTag::ACE_ANIMATION,
4640 "Time decreases, skip ModifierAnimation, lastTime:%{public}" PRIu64 ", nowTime:%{public}" PRIu64,
4641 animationTimeStamp_, animationTimeStamp);
4642 return true;
4643 }
4644 animationTimeStamp_ = animationTimeStamp;
4645 return window_->FlushAnimation(animationTimeStamp);
4646 }
4647
ScopedLayout(PipelineContext * pipeline)4648 ScopedLayout::ScopedLayout(PipelineContext* pipeline)
4649 {
4650 if (!pipeline) {
4651 return;
4652 }
4653 // save flag before measure
4654 pipeline_ = pipeline;
4655 isLayouting_ = pipeline_->IsLayouting();
4656 pipeline_->SetIsLayouting(true);
4657 }
4658
~ScopedLayout()4659 ScopedLayout::~ScopedLayout()
4660 {
4661 if (!pipeline_) {
4662 return;
4663 }
4664 // set layout flag back
4665 pipeline_->SetIsLayouting(isLayouting_);
4666 }
4667 } // namespace OHOS::Ace::NG
4668