diff --git a/dom/include/dom/root_node.h b/dom/include/dom/root_node.h index 2b8f50556..850c0d57c 100644 --- a/dom/include/dom/root_node.h +++ b/dom/include/dom/root_node.h @@ -53,6 +53,11 @@ class DomNodeStyleDiffer { std::unordered_map>> node_ext_style_map_; }; +enum VSyncEventNeedSource { + VSyncEventNeedByAnimation = 1, + VSyncEventNeedByFrame = 1<<1 +}; + class RootNode : public DomNode { public: using TaskRunner = footstone::runner::TaskRunner; @@ -99,6 +104,10 @@ class RootNode : public DomNode { return persistent_map_; } + void SetVSyncEventNeedSource(VSyncEventNeedSource source) { vSyncEventNeedSourceBits_ |= source; } + void UnsetVSyncEventNeedSource(VSyncEventNeedSource source) { vSyncEventNeedSourceBits_ &= (~source); } + bool HasVSyncEventNeedSource() { return vSyncEventNeedSourceBits_ != 0; } + private: static void MarkLayoutNodeDirty(const std::vector>& nodes); @@ -128,6 +137,8 @@ class RootNode : public DomNode { std::shared_ptr animation_manager_; std::unique_ptr style_differ_; + int32_t vSyncEventNeedSourceBits_ = 0; + static footstone::utils::PersistentObjectMap> persistent_map_; }; diff --git a/dom/src/dom/animation/animation_manager.cc b/dom/src/dom/animation/animation_manager.cc index 04aa8fdd3..f17187c64 100644 --- a/dom/src/dom/animation/animation_manager.cc +++ b/dom/src/dom/animation/animation_manager.cc @@ -236,6 +236,7 @@ void AnimationManager::AddActiveAnimation(const std::shared_ptr& anim if (!dom_manager) { return; } + root_node->SetVSyncEventNeedSource(VSyncEventNeedByAnimation); listener_id_ = hippy::dom::FetchListenerId(); auto weak_animation_manager = weak_from_this(); dom_manager->AddEventListener(root_node, @@ -379,6 +380,7 @@ void AnimationManager::RemoveVSyncEventListener() { return; } if (dom_manager) { + root_node->UnsetVSyncEventNeedSource(VSyncEventNeedByAnimation); dom_manager->RemoveEventListener(root_node, root_node->GetId(), kVSyncKey, listener_id_); dom_manager->EndBatch(root_node_); } diff --git a/dom/src/dom/root_node.cc b/dom/src/dom/root_node.cc index 0c660158a..abd0027ae 100644 --- a/dom/src/dom/root_node.cc +++ b/dom/src/dom/root_node.cc @@ -27,6 +27,8 @@ #include "footstone/deserializer.h" #include "footstone/hippy_value.h" +constexpr char kVSyncKey[] = "frameupdate"; + namespace hippy { inline namespace dom { @@ -118,7 +120,13 @@ void RootNode::AddEventListener(const std::string& name, uint64_t listener_id, b void RootNode::RemoveEventListener(const std::string& name, uint64_t listener_id) { DomNode::RemoveEventListener(name, listener_id); - RemoveEvent(GetId(), name); + if (name == kVSyncKey) { + if (!HasVSyncEventNeedSource()) { + RemoveEvent(GetId(), name); + } + } else { + RemoveEvent(GetId(), name); + } } void RootNode::ReleaseResources() {} diff --git a/driver/js/src/modules/animation_frame_module.cc b/driver/js/src/modules/animation_frame_module.cc index 8f92b8214..aab2a1ed7 100644 --- a/driver/js/src/modules/animation_frame_module.cc +++ b/driver/js/src/modules/animation_frame_module.cc @@ -73,6 +73,7 @@ void AnimationFrameModule::RequestAnimationFrame(hippy::napi::CallbackInfo &info } has_event_listener_ = true; + root_node->SetVSyncEventNeedSource(VSyncEventNeedByFrame); listener_id_ = hippy::dom::FetchListenerId(); auto weak_this = weak_from_this(); std::weak_ptr weak_scope = scope; @@ -112,6 +113,7 @@ void AnimationFrameModule::CancelAnimationFrame(hippy::napi::CallbackInfo &info, return; } + root_node->UnsetVSyncEventNeedSource(VSyncEventNeedByFrame); dom_manager->RemoveEventListener(root_node, root_node->GetId(), kVSyncKey, listener_id_); dom_manager->EndBatch(root_node);