Files
Hippy/renderer/native/ios/renderer/NativeRenderManager.mm

323 lines
11 KiB
Plaintext

/*!
* iOS SDK
*
* Tencent is pleased to support the open source community by making
* Hippy available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "HippyUIManager.h"
#import "HippyUIManager+Private.h"
#import "NativeRenderManager.h"
#import "HippyShadowText.h"
#import "HippyVsyncManager.h"
#import "HippyAssert.h"
#include "dom/dom_manager.h"
#include "dom/layout_node.h"
#include "dom/root_node.h"
using HippyValue = footstone::value::HippyValue;
using RenderManager = hippy::RenderManager;
using DomNode = hippy::DomNode;
using DomManager = hippy::DomManager;
using DomEvent = hippy::DomEvent;
using LayoutResult = hippy::LayoutResult;
using CallFunctionCallback = hippy::CallFunctionCallback;
using RootNode = hippy::RootNode;
NativeRenderManager::NativeRenderManager(const std::string& name): hippy::RenderManager(name) {}
void NativeRenderManager::CreateRenderNode(std::weak_ptr<hippy::RootNode> root_node,
std::vector<std::shared_ptr<DomNode>> &&nodes) {
auto rootNode = root_node.lock();
if (rootNode) {
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
[uiManager createRenderNodes:std::move(nodes) onRootNode:root_node];
}
}
}
void NativeRenderManager::UpdateRenderNode(std::weak_ptr<hippy::RootNode> root_node,
std::vector<std::shared_ptr<DomNode>>&& nodes) {
auto rootNode = root_node.lock();
if (rootNode) {
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
[uiManager updateRenderNodes:std::move(nodes) onRootNode:root_node];
}
}
}
void NativeRenderManager::DeleteRenderNode(std::weak_ptr<hippy::RootNode> root_node,
std::vector<std::shared_ptr<DomNode>>&& nodes) {
auto rootNode = root_node.lock();
if (rootNode) {
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
[uiManager deleteRenderNodesIds:std::move(nodes) onRootNode:root_node];
}
}
}
void NativeRenderManager::UpdateLayout(std::weak_ptr<hippy::RootNode> root_node,
const std::vector<std::shared_ptr<DomNode>>& nodes) {
auto rootNode = root_node.lock();
if (!rootNode) {
return;
}
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
using DomNodeUpdateInfoTuple = std::tuple<int32_t, hippy::LayoutResult>;
std::vector<DomNodeUpdateInfoTuple> nodes_infos;
nodes_infos.reserve(nodes.size());
for (auto node : nodes) {
int32_t tag = node->GetId();
hippy::LayoutResult layoutResult = node->GetRenderLayoutResult();
DomNodeUpdateInfoTuple nodeUpdateInfo = std::make_tuple(tag, layoutResult);
nodes_infos.push_back(nodeUpdateInfo);
}
[uiManager updateNodesLayout:nodes_infos onRootNode:root_node];
}
}
void NativeRenderManager::MoveRenderNode(std::weak_ptr<hippy::RootNode> root_node,
std::vector<int32_t>&& moved_ids,
int32_t from_pid,
int32_t to_pid,
int32_t index) {
auto rootNode = root_node.lock();
if (!rootNode) {
return;
}
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
[uiManager renderMoveViews:std::move(moved_ids)
fromContainer:from_pid
toContainer:to_pid
index:index
onRootNode:root_node];
}
}
void NativeRenderManager::MoveRenderNode(std::weak_ptr<hippy::RootNode> root_node,
std::vector<std::shared_ptr<DomNode>>&& nodes) {
auto rootNode = root_node.lock();
if (!rootNode) {
return;
}
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
// Check whether all nodes have the same pid
uint32_t firstPid = nodes[0]->GetPid();
bool allSamePid = std::all_of(nodes.begin(), nodes.end(),
[firstPid](const std::shared_ptr<DomNode>& node) {
return node->GetPid() == firstPid;
});
if (allSamePid) {
// If all nodes have the same pid, call directly
[uiManager renderMoveNodes:std::move(nodes) onRootNode:root_node];
} else {
// If not, group them by pid and then call for each group
std::map<int, std::vector<std::shared_ptr<DomNode>>> pidNodeMap;
for (auto& node : nodes) {
pidNodeMap[node->GetPid()].push_back(node);
}
for (auto& pair : pidNodeMap) {
[uiManager renderMoveNodes:std::move(pair.second) onRootNode:root_node];
}
}
}
}
void NativeRenderManager::EndBatch(std::weak_ptr<hippy::RootNode> root_node) {
TDF_PERF_LOG("NativeRenderManager::EndBatch Begin");
auto rootNode = root_node.lock();
if (!rootNode) {
return;
}
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
[uiManager batchOnRootNode:root_node];
}
TDF_PERF_LOG("NativeRenderManager::EndBatch End");
}
void NativeRenderManager::BeforeLayout(std::weak_ptr<hippy::RootNode> root_node) {
// Implementation if needed
}
void NativeRenderManager::AfterLayout(std::weak_ptr<hippy::RootNode> root_node) {
// Implementation if needed
}
void NativeRenderManager::AddEventListener(std::weak_ptr<hippy::RootNode> root_node,
std::weak_ptr<DomNode> dom_node,
const std::string& name) {
auto rootNode = root_node.lock();
if (!rootNode) {
return;
}
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
auto node = dom_node.lock();
if (node) {
int32_t tag = node->GetId();
[uiManager addEventName:name forDomNodeId:tag onRootNode:root_node];
}
}
}
void NativeRenderManager::RemoveEventListener(std::weak_ptr<hippy::RootNode> root_node,
std::weak_ptr<DomNode> dom_node,
const std::string &name) {
auto rootNode = root_node.lock();
if (!rootNode) {
return;
}
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
auto node = dom_node.lock();
if (node) {
int32_t node_id = node->GetId();
[uiManager removeEventName:name forDomNodeId:node_id onRootNode:root_node];
}
}
}
void NativeRenderManager::RemoveVSyncEventListener(std::weak_ptr<hippy::RootNode> root_node) {
auto rootNode = root_node.lock();
if (!rootNode) {
return;
}
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
[uiManager removeVSyncEventOnRootNode:root_node];
}
}
void NativeRenderManager::CallFunction(std::weak_ptr<hippy::RootNode> root_node,
std::weak_ptr<DomNode> dom_node,
const std::string &name,
const DomArgument& param,
uint32_t cb) {
auto rootNode = root_node.lock();
if (!rootNode) {
return;
}
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
std::shared_ptr<DomNode> node = dom_node.lock();
if (node) {
HippyValue hippy_value;
param.ToObject(hippy_value);
[uiManager dispatchFunction:name
viewName:node->GetViewName()
viewTag:node->GetId()
onRootNode:root_node
params:hippy_value
callback:node->GetCallback(name, cb)];
}
EndBatch(root_node);
}
}
void NativeRenderManager::RegisterRootView(UIView *view,
std::weak_ptr<hippy::RootNode> root_node,
HippyUIManager *uiManager) {
auto rootNode = root_node.lock();
if (!rootNode) {
return;
}
HippyAssertParam(uiManager);
{
std::unique_lock<std::shared_mutex> lock(_mutex);
_uiManagerMap[rootNode->GetId()] = uiManager;
}
[uiManager registerRootView:view asRootNode:root_node];
}
void NativeRenderManager::UnregisterRootView(uint32_t rootId) {
HippyUIManager *uiManager = nil;
{
std::unique_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootId];
HippyAssertParam(uiManager);
_uiManagerMap.erase(rootId);
}
if (uiManager) {
[uiManager unregisterRootViewFromTag:@(rootId)];
}
}
NativeRenderManager::~NativeRenderManager() {
std::unique_lock<std::shared_mutex> lock(_mutex);
for (auto &pair : _uiManagerMap) {
[pair.second invalidate];
}
_uiManagerMap.clear();
FOOTSTONE_LOG(INFO) << "~NativeRenderManager";
}