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