1 /* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_PATTERN_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_PATTERN_H 18 19 #include <optional> 20 21 #include "base/geometry/ng/rect_t.h" 22 #include "base/memory/ace_type.h" 23 #include "base/memory/referenced.h" 24 #include "base/utils/noncopyable.h" 25 #include "base/view_data/view_data_wrap.h" 26 #include "core/common/recorder/event_recorder.h" 27 #include "core/components_ng/base/frame_node.h" 28 #include "core/components_ng/event/event_hub.h" 29 #include "core/components_ng/layout/layout_property.h" 30 #include "core/components_ng/property/property.h" 31 #include "core/components_ng/render/node_paint_method.h" 32 #include "core/components_ng/render/paint_property.h" 33 #include "core/event/pointer_event.h" 34 35 namespace OHOS::Accessibility { 36 class AccessibilityElementInfo; 37 class AccessibilityEventInfo; 38 } 39 40 namespace OHOS::Ace::NG { 41 struct DirtySwapConfig { 42 bool frameSizeChange = false; 43 bool frameOffsetChange = false; 44 bool contentSizeChange = false; 45 bool contentOffsetChange = false; 46 bool skipMeasure = false; 47 bool skipLayout = false; 48 }; 49 50 class ScrollingListener : public AceType { 51 DECLARE_ACE_TYPE(ScrollingListener, AceType); 52 53 public: ScrollingListener(std::function<void ()> && callback)54 explicit ScrollingListener(std::function<void()>&& callback) : callback_(std::move(callback)) {} 55 56 ~ScrollingListener() override = default; 57 NotifyScrollingEvent()58 void NotifyScrollingEvent() 59 { 60 if (callback_) { 61 callback_(); 62 } 63 } 64 65 private: 66 std::function<void()> callback_; 67 }; 68 69 // Pattern is the base class for different measure, layout and paint behavior. 70 class Pattern : public virtual AceType { 71 DECLARE_ACE_TYPE(Pattern, AceType); 72 73 public: 74 Pattern() = default; 75 ~Pattern() override = default; 76 77 // atomic node is like button, image, custom node and so on. 78 // In ets UI compiler, the atomic node does not Add Pop function, only have Create function. IsAtomicNode()79 virtual bool IsAtomicNode() const 80 { 81 return true; 82 } 83 StopExpandMark()84 virtual bool StopExpandMark() 85 { 86 return false; 87 } 88 89 // The pattern needs softkeyboard is like search, rich editor, text area, text field pattern. NeedSoftKeyboard()90 virtual bool NeedSoftKeyboard() const 91 { 92 return false; 93 } 94 DefaultSupportDrag()95 virtual bool DefaultSupportDrag() 96 { 97 return false; 98 } 99 GetContextParam()100 virtual std::optional<RenderContext::ContextParam> GetContextParam() const 101 { 102 return std::nullopt; 103 } 104 DetachFromFrameNode(FrameNode * frameNode)105 void DetachFromFrameNode(FrameNode* frameNode) 106 { 107 OnDetachFromFrameNode(frameNode); 108 frameNode_.Reset(); 109 } 110 AttachToFrameNode(const WeakPtr<FrameNode> & frameNode)111 void AttachToFrameNode(const WeakPtr<FrameNode>& frameNode) 112 { 113 if (frameNode_ == frameNode) { 114 return; 115 } 116 frameNode_ = frameNode; 117 OnAttachToFrameNode(); 118 } 119 CreateAccessibilityProperty()120 virtual RefPtr<AccessibilityProperty> CreateAccessibilityProperty() 121 { 122 return MakeRefPtr<AccessibilityProperty>(); 123 } 124 CreatePaintProperty()125 virtual RefPtr<PaintProperty> CreatePaintProperty() 126 { 127 return MakeRefPtr<PaintProperty>(); 128 } 129 CreateLayoutProperty()130 virtual RefPtr<LayoutProperty> CreateLayoutProperty() 131 { 132 return MakeRefPtr<LayoutProperty>(); 133 } 134 CreateLayoutAlgorithm()135 virtual RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() 136 { 137 return MakeRefPtr<BoxLayoutAlgorithm>(); 138 } 139 CreateNodePaintMethod()140 virtual RefPtr<NodePaintMethod> CreateNodePaintMethod() 141 { 142 return nullptr; 143 } 144 GetOverridePaintRect()145 virtual std::optional<RectF> GetOverridePaintRect() const 146 { 147 return std::nullopt; 148 } 149 CreateEventHub()150 virtual RefPtr<EventHub> CreateEventHub() 151 { 152 return MakeRefPtr<EventHub>(); 153 } 154 OnContextAttached()155 virtual void OnContextAttached() {} 156 OnModifyDone()157 virtual void OnModifyDone() 158 { 159 #if (defined(__aarch64__) || defined(__x86_64__)) 160 FrameNode::PostTask( 161 [weak = WeakClaim(this)]() { 162 if (Recorder::EventRecorder::Get().IsComponentRecordEnable()) { 163 auto pattern = weak.Upgrade(); 164 CHECK_NULL_VOID(pattern); 165 pattern->OnAfterModifyDone(); 166 } 167 }, 168 TaskExecutor::TaskType::UI); 169 if (IsNeedInitClickEventRecorder()) { 170 InitClickEventRecorder(); 171 } 172 #endif 173 auto frameNode = frameNode_.Upgrade(); 174 auto children = frameNode->GetChildren(); 175 if (children.empty()) { 176 return; 177 } 178 auto renderContext = frameNode->GetRenderContext(); 179 if (!renderContext->HasForegroundColor() && !renderContext->HasForegroundColorStrategy()) { 180 return; 181 } 182 std::list<RefPtr<FrameNode>> childrenList {}; 183 std::queue<RefPtr<FrameNode>> queue {}; 184 queue.emplace(frameNode); 185 RefPtr<FrameNode> parentNode; 186 while (!queue.empty()) { 187 parentNode = queue.front(); 188 queue.pop(); 189 auto childs = parentNode->GetChildren(); 190 if (childs.empty()) { 191 continue; 192 } 193 for (auto child : childs) { 194 if (!AceType::InstanceOf<NG::FrameNode>(child)) { 195 continue; 196 } 197 auto childFrameNode = AceType::DynamicCast<FrameNode>(child); 198 auto childRenderContext = childFrameNode->GetRenderContext(); 199 if (childRenderContext->HasForegroundColorFlag() && childRenderContext->GetForegroundColorFlagValue()) { 200 continue; 201 } 202 queue.emplace(childFrameNode); 203 childrenList.emplace_back(childFrameNode); 204 } 205 } 206 bool isForegroundColor = renderContext->HasForegroundColor(); 207 for (auto child : childrenList) { 208 auto childRenderContext = child->GetRenderContext(); 209 if (!childRenderContext->HasForegroundColor() && !childRenderContext->HasForegroundColorStrategy()) { 210 if (isForegroundColor) { 211 childRenderContext->UpdateForegroundColor(renderContext->GetForegroundColorValue()); 212 childRenderContext->ResetForegroundColorStrategy(); 213 childRenderContext->UpdateForegroundColorFlag(false); 214 } else { 215 childRenderContext->UpdateForegroundColorStrategy(renderContext->GetForegroundColorStrategyValue()); 216 childRenderContext->ResetForegroundColor(); 217 childRenderContext->UpdateForegroundColorFlag(false); 218 } 219 } else { 220 if (!childRenderContext->HasForegroundColorFlag()) { 221 continue; 222 } 223 if (childRenderContext->GetForegroundColorFlagValue()) { 224 continue; 225 } 226 if (isForegroundColor) { 227 childRenderContext->UpdateForegroundColor(renderContext->GetForegroundColorValue()); 228 childRenderContext->ResetForegroundColorStrategy(); 229 childRenderContext->UpdateForegroundColorFlag(false); 230 } else { 231 childRenderContext->UpdateForegroundColorStrategy(renderContext->GetForegroundColorStrategyValue()); 232 childRenderContext->ResetForegroundColor(); 233 childRenderContext->UpdateForegroundColorFlag(false); 234 } 235 } 236 } 237 } 238 OnAfterModifyDone()239 virtual void OnAfterModifyDone() {} 240 OnMountToParentDone()241 virtual void OnMountToParentDone() {} 242 IsRootPattern()243 virtual bool IsRootPattern() const 244 { 245 return false; 246 } 247 IsMeasureBoundary()248 virtual bool IsMeasureBoundary() const 249 { 250 return false; 251 } 252 IsRenderBoundary()253 virtual bool IsRenderBoundary() const 254 { 255 return true; 256 } 257 UpdateScrollOffset(SizeF)258 virtual void UpdateScrollOffset(SizeF /* frameSize */) {} 259 260 // TODO: for temp use, need to delete this. OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> &,bool,bool)261 virtual bool OnDirtyLayoutWrapperSwap( 262 const RefPtr<LayoutWrapper>& /*dirty*/, bool /*skipMeasure*/, bool /*skipLayout*/) 263 { 264 return false; 265 } 266 267 // Called on main thread to check if need rerender of the content. OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> &,const DirtySwapConfig &)268 virtual bool OnDirtyLayoutWrapperSwap( 269 const RefPtr<LayoutWrapper>& /*dirty*/, const DirtySwapConfig& /*changeConfig*/) 270 { 271 return false; 272 } 273 UsResRegion()274 virtual bool UsResRegion() 275 { 276 return true; 277 } 278 GetHostFrameSize()279 std::optional<SizeF> GetHostFrameSize() const 280 { 281 auto frameNode = frameNode_.Upgrade(); 282 if (!frameNode) { 283 return std::nullopt; 284 } 285 return frameNode->GetGeometryNode()->GetMarginFrameSize(); 286 } 287 GetHostFrameOffset()288 std::optional<OffsetF> GetHostFrameOffset() const 289 { 290 auto frameNode = frameNode_.Upgrade(); 291 if (!frameNode) { 292 return std::nullopt; 293 } 294 return frameNode->GetGeometryNode()->GetFrameOffset(); 295 } 296 GetHostFrameGlobalOffset()297 std::optional<OffsetF> GetHostFrameGlobalOffset() const 298 { 299 auto frameNode = frameNode_.Upgrade(); 300 if (!frameNode) { 301 return std::nullopt; 302 } 303 return frameNode->GetGeometryNode()->GetFrameOffset() + frameNode->GetGeometryNode()->GetParentGlobalOffset(); 304 } 305 GetHostContentSize()306 std::optional<SizeF> GetHostContentSize() const 307 { 308 auto frameNode = frameNode_.Upgrade(); 309 if (!frameNode) { 310 return std::nullopt; 311 } 312 const auto& content = frameNode->GetGeometryNode()->GetContent(); 313 if (!content) { 314 return std::nullopt; 315 } 316 return content->GetRect().GetSize(); 317 } 318 GetHost()319 RefPtr<FrameNode> GetHost() const 320 { 321 return frameNode_.Upgrade(); 322 } 323 DumpInfo()324 virtual void DumpInfo() {} DumpAdvanceInfo()325 virtual void DumpAdvanceInfo() {} DumpViewDataPageNode(RefPtr<ViewDataWrap> viewDataWrap)326 virtual void DumpViewDataPageNode(RefPtr<ViewDataWrap> viewDataWrap) {} NotifyFillRequestSuccess(RefPtr<PageNodeInfoWrap> nodeWrap,AceAutoFillType autoFillType)327 virtual void NotifyFillRequestSuccess(RefPtr<PageNodeInfoWrap> nodeWrap, AceAutoFillType autoFillType) {} NotifyFillRequestFailed(int32_t errCode)328 virtual void NotifyFillRequestFailed(int32_t errCode) {} CheckAutoSave()329 virtual bool CheckAutoSave() 330 { 331 return false; 332 } 333 334 template<typename T> GetLayoutProperty()335 RefPtr<T> GetLayoutProperty() const 336 { 337 auto host = GetHost(); 338 CHECK_NULL_RETURN(host, nullptr); 339 return DynamicCast<T>(host->GetLayoutProperty<T>()); 340 } 341 342 template<typename T> GetPaintProperty()343 RefPtr<T> GetPaintProperty() const 344 { 345 auto host = GetHost(); 346 CHECK_NULL_RETURN(host, nullptr); 347 return DynamicCast<T>(host->GetPaintProperty<T>()); 348 } 349 350 template<typename T> GetEventHub()351 RefPtr<T> GetEventHub() const 352 { 353 auto host = GetHost(); 354 CHECK_NULL_RETURN(host, nullptr); 355 return DynamicCast<T>(host->GetEventHub<T>()); 356 } 357 358 // Called after frameNode RebuildRenderContextTree. OnRebuildFrame()359 virtual void OnRebuildFrame() {} 360 // Called before frameNode CreateLayoutWrapper. BeforeCreateLayoutWrapper()361 virtual void BeforeCreateLayoutWrapper() {} 362 // Called before frameNode CreatePaintWrapper. BeforeCreatePaintWrapper()363 virtual void BeforeCreatePaintWrapper() {} 364 GetFocusPattern()365 virtual FocusPattern GetFocusPattern() const 366 { 367 return { FocusType::DISABLE, false, FocusStyleType::NONE }; 368 } 369 GetScopeFocusAlgorithm()370 virtual ScopeFocusAlgorithm GetScopeFocusAlgorithm() 371 { 372 return ScopeFocusAlgorithm(); 373 } 374 ScrollToNode(const RefPtr<FrameNode> & focusFrameNode)375 virtual bool ScrollToNode(const RefPtr<FrameNode>& focusFrameNode) 376 { 377 return false; 378 } 379 GetFocusNodeIndex(const RefPtr<FocusHub> & focusNode)380 virtual int32_t GetFocusNodeIndex(const RefPtr<FocusHub>& focusNode) 381 { 382 return -1; 383 } 384 ScrollToFocusNodeIndex(int32_t index)385 virtual void ScrollToFocusNodeIndex(int32_t index) {} 386 387 // out of viewport or visible is none or gone. OnInActive()388 virtual void OnInActive() {} OnActive()389 virtual void OnActive() {} 390 391 // called by window life cycle. OnWindowShow()392 virtual void OnWindowShow() {} OnWindowHide()393 virtual void OnWindowHide() {} OnWindowFocused()394 virtual void OnWindowFocused() {} OnWindowUnfocused()395 virtual void OnWindowUnfocused() {} OnPixelRoundFinish(const SizeF & pixelGridRoundSize)396 virtual void OnPixelRoundFinish(const SizeF& pixelGridRoundSize) {} OnWindowSizeChanged(int32_t width,int32_t height,WindowSizeChangeReason type)397 virtual void OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type) {} OnNotifyMemoryLevel(int32_t level)398 virtual void OnNotifyMemoryLevel(int32_t level) {} 399 400 // get XTS inspector value ToJsonValue(std::unique_ptr<JsonValue> & json)401 virtual void ToJsonValue(std::unique_ptr<JsonValue>& json) const {} 402 403 // call by recycle framework. OnRecycle()404 virtual void OnRecycle() {} OnReuse()405 virtual void OnReuse() {} 406 OnAttachToMainTree()407 virtual void OnAttachToMainTree() {} OnAttachToBuilderNode(NodeStatus nodeStatus)408 virtual void OnAttachToBuilderNode(NodeStatus nodeStatus) {} 409 OnDetachFromMainTree()410 virtual void OnDetachFromMainTree() {} 411 FromJson(const std::unique_ptr<JsonValue> & json)412 virtual void FromJson(const std::unique_ptr<JsonValue>& json) {} 413 OnAreaChangedInner()414 virtual void OnAreaChangedInner() {} OnVisibleChange(bool isVisible)415 virtual void OnVisibleChange(bool isVisible) {} ProvideRestoreInfo()416 virtual std::string ProvideRestoreInfo() 417 { 418 return ""; 419 } 420 OnRestoreInfo(const std::string & restoreInfo)421 virtual void OnRestoreInfo(const std::string& restoreInfo) {} 422 IsNeedAdjustByAspectRatio()423 virtual bool IsNeedAdjustByAspectRatio() 424 { 425 auto host = GetHost(); 426 CHECK_NULL_RETURN(host, false); 427 auto layoutProperty = host->GetLayoutProperty(); 428 CHECK_NULL_RETURN(host, false); 429 return layoutProperty->HasAspectRatio(); 430 } 431 OnTouchTestHit(SourceType hitTestType)432 virtual void OnTouchTestHit(SourceType hitTestType) {} 433 GetDragRecordSize()434 virtual int32_t GetDragRecordSize() 435 { 436 return -1; 437 } 438 HandleOnDragStatusCallback(const DragEventType & dragEventType,const RefPtr<NotifyDragEvent> & notifyDragEvent)439 virtual void HandleOnDragStatusCallback( 440 const DragEventType& dragEventType, const RefPtr<NotifyDragEvent>& notifyDragEvent) {}; 441 HandleDragEvent(const PointerEvent & info)442 virtual void HandleDragEvent(const PointerEvent& info) {}; OnLanguageConfigurationUpdate()443 virtual void OnLanguageConfigurationUpdate() {} OnColorConfigurationUpdate()444 virtual void OnColorConfigurationUpdate() {} OnDirectionConfigurationUpdate()445 virtual void OnDirectionConfigurationUpdate() {} OnDpiConfigurationUpdate()446 virtual void OnDpiConfigurationUpdate() {} OnIconConfigurationUpdate()447 virtual void OnIconConfigurationUpdate() {} 448 ShouldDelayChildPressedState()449 virtual bool ShouldDelayChildPressedState() const 450 { 451 return false; 452 } 453 RegisterScrollingListener(const RefPtr<ScrollingListener> listener)454 virtual void RegisterScrollingListener(const RefPtr<ScrollingListener> listener) {} FireAndCleanScrollingListener()455 virtual void FireAndCleanScrollingListener() {} CleanScrollingListener()456 virtual void CleanScrollingListener() {} ResetDragOption()457 virtual void ResetDragOption() {} 458 WrapExtensionAbilityId(int64_t extensionOffset,int64_t abilityId)459 virtual int64_t WrapExtensionAbilityId(int64_t extensionOffset, int64_t abilityId) 460 { 461 return -1; 462 } 463 SearchExtensionElementInfoByAccessibilityId(int64_t elementId,int32_t mode,int64_t baseParent,std::list<Accessibility::AccessibilityElementInfo> & output)464 virtual void SearchExtensionElementInfoByAccessibilityId(int64_t elementId, int32_t mode, 465 int64_t baseParent, std::list<Accessibility::AccessibilityElementInfo>& output) {} SearchElementInfosByText(int64_t elementId,const std::string & text,int64_t baseParent,std::list<Accessibility::AccessibilityElementInfo> & output)466 virtual void SearchElementInfosByText(int64_t elementId, const std::string& text, 467 int64_t baseParent, std::list<Accessibility::AccessibilityElementInfo>& output) {} FindFocusedElementInfo(int64_t elementId,int32_t focusType,int64_t baseParent,Accessibility::AccessibilityElementInfo & output)468 virtual void FindFocusedElementInfo(int64_t elementId, int32_t focusType, 469 int64_t baseParent, Accessibility::AccessibilityElementInfo& output) {} FocusMoveSearch(int64_t elementId,int32_t direction,int64_t baseParent,Accessibility::AccessibilityElementInfo & output)470 virtual void FocusMoveSearch(int64_t elementId, int32_t direction, 471 int64_t baseParent, Accessibility::AccessibilityElementInfo& output) {} TransferExecuteAction(int64_t elementId,const std::map<std::string,std::string> & actionArguments,int32_t action,int64_t offset)472 virtual bool TransferExecuteAction( 473 int64_t elementId, const std::map<std::string, std::string>& actionArguments, int32_t action, int64_t offset) 474 { 475 return false; 476 } 477 GetUiExtensionId()478 virtual int32_t GetUiExtensionId() 479 { 480 return -1; 481 } 482 GetLongPressEventRecorder()483 GestureEventFunc GetLongPressEventRecorder() 484 { 485 auto longPressCallback = [weak = WeakClaim(this)](GestureEvent& info) { 486 if (!Recorder::EventRecorder::Get().IsComponentRecordEnable()) { 487 return; 488 } 489 auto pattern = weak.Upgrade(); 490 CHECK_NULL_VOID(pattern); 491 auto host = pattern->GetHost(); 492 CHECK_NULL_VOID(host); 493 auto inspectorId = host->GetInspectorId().value_or(""); 494 auto text = host->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetAccessibilityText(true); 495 auto desc = host->GetAutoEventParamValue(""); 496 if (inspectorId.empty() && text.empty() && desc.empty()) { 497 return; 498 } 499 500 Recorder::EventParamsBuilder builder; 501 builder.SetId(inspectorId) 502 .SetType(host->GetTag()) 503 .SetEventType(Recorder::LONG_PRESS) 504 .SetText(text) 505 .SetDescription(desc); 506 Recorder::EventRecorder::Get().OnEvent(std::move(builder)); 507 }; 508 return longPressCallback; 509 } 510 511 protected: OnAttachToFrameNode()512 virtual void OnAttachToFrameNode() {} OnDetachFromFrameNode(FrameNode * frameNode)513 virtual void OnDetachFromFrameNode(FrameNode* frameNode) {} 514 IsNeedInitClickEventRecorder()515 virtual bool IsNeedInitClickEventRecorder() const 516 { 517 return false; 518 } 519 InitClickEventRecorder()520 void InitClickEventRecorder() 521 { 522 if (clickCallback_) { 523 return; 524 } 525 526 auto host = GetHost(); 527 CHECK_NULL_VOID(host); 528 auto gesture = host->GetOrCreateGestureEventHub(); 529 CHECK_NULL_VOID(gesture); 530 if (!gesture->IsClickable()) { 531 return; 532 } 533 534 auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) { 535 if (!Recorder::EventRecorder::Get().IsComponentRecordEnable()) { 536 return; 537 } 538 auto pattern = weak.Upgrade(); 539 CHECK_NULL_VOID(pattern); 540 auto host = pattern->GetHost(); 541 CHECK_NULL_VOID(host); 542 auto inspectorId = host->GetInspectorId().value_or(""); 543 auto text = host->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetAccessibilityText(true); 544 auto desc = host->GetAutoEventParamValue(""); 545 if (inspectorId.empty() && text.empty() && desc.empty()) { 546 return; 547 } 548 549 Recorder::EventParamsBuilder builder; 550 builder.SetId(inspectorId).SetType(host->GetTag()).SetText(text).SetDescription(desc); 551 Recorder::EventRecorder::Get().OnClick(std::move(builder)); 552 }; 553 clickCallback_ = MakeRefPtr<ClickEvent>(std::move(clickCallback)); 554 gesture->AddClickEvent(clickCallback_); 555 } 556 557 WeakPtr<FrameNode> frameNode_; 558 RefPtr<ClickEvent> clickCallback_; 559 560 private: 561 ACE_DISALLOW_COPY_AND_MOVE(Pattern); 562 }; 563 } // namespace OHOS::Ace::NG 564 565 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_PATTERN_H 566