|
| 1 | +#include "RNGestureHandlerRootViewComponentInstance.h" |
| 2 | + |
| 3 | +namespace rnoh { |
| 4 | + |
| 5 | +RNGestureHandlerRootViewComponentInstance::RNGestureHandlerRootViewComponentInstance(Context context) |
| 6 | + : CppComponentInstance(std::move(context)), |
| 7 | + m_touchHandler(std::make_unique<RNGestureHandlerRootViewTouchHandler>(this)) { |
| 8 | + auto rnInstance = m_deps->rnInstance.lock(); |
| 9 | + if (rnInstance) { |
| 10 | + rnInstance->postMessageToArkTS("RNGH::ROOT_CREATED", m_tag); |
| 11 | + } |
| 12 | +} |
| 13 | + |
| 14 | +RNGestureHandlerRootViewComponentInstance::RNGestureHandlerRootViewTouchHandler::RNGestureHandlerRootViewTouchHandler( |
| 15 | + RNGestureHandlerRootViewComponentInstance *rootView) |
| 16 | + : UIInputEventHandler(rootView->getLocalRootArkUINode()), m_rootView(rootView) {} |
| 17 | + |
| 18 | +TouchTarget::Shared |
| 19 | +RNGestureHandlerRootViewComponentInstance::findTargetForTouchPoint(Point const &point, |
| 20 | + TouchTarget::Shared const &target) { |
| 21 | + bool canHandleTouch = |
| 22 | + target->canHandleTouch() && target->containsPoint(point) && (target->getTouchEventEmitter() != nullptr); |
| 23 | + bool canChildrenHandleTouch = target->canChildrenHandleTouch() && target->containsPointInBoundingBox(point); |
| 24 | + |
| 25 | + if (canChildrenHandleTouch) { |
| 26 | + auto children = target->getTouchTargetChildren(); |
| 27 | + // we want to check the children in reverse order, since the last child is the topmost one |
| 28 | + std::reverse(children.begin(), children.end()); |
| 29 | + for (auto const &child : children) { |
| 30 | + auto childPoint = target->computeChildPoint(point, child); |
| 31 | + auto result = findTargetForTouchPoint(childPoint, child); |
| 32 | + if (result != nullptr) { |
| 33 | + return result; |
| 34 | + } |
| 35 | + } |
| 36 | + } |
| 37 | + if (canHandleTouch) { |
| 38 | + return target; |
| 39 | + } |
| 40 | + return nullptr; |
| 41 | +} |
| 42 | + |
| 43 | +void RNGestureHandlerRootViewComponentInstance::RNGestureHandlerRootViewTouchHandler::onTouchEvent( |
| 44 | + ArkUI_UIInputEvent *e) { |
| 45 | + auto ancestor = m_rootView->getParent().lock(); |
| 46 | + while (ancestor != nullptr) { |
| 47 | + auto ancestorRNGHRootView = std::dynamic_pointer_cast<RNGestureHandlerRootViewComponentInstance>(ancestor); |
| 48 | + if (ancestorRNGHRootView != nullptr) { |
| 49 | + return; |
| 50 | + } |
| 51 | + ancestor = ancestor->getParent().lock(); |
| 52 | + } |
| 53 | + |
| 54 | + auto ancestorTouchTarget = m_rootView->getTouchTargetParent(); |
| 55 | + auto rnInstance = m_rootView->m_deps->rnInstance.lock(); |
| 56 | + while (ancestorTouchTarget != nullptr) { |
| 57 | + if (ancestorTouchTarget->isHandlingTouches()) { |
| 58 | + rnInstance->postMessageToArkTS("RNGH::CANCEL_TOUCHES", m_rootView->getTag()); |
| 59 | + return; |
| 60 | + } |
| 61 | + ancestorTouchTarget = ancestorTouchTarget->getTouchTargetParent(); |
| 62 | + } |
| 63 | + |
| 64 | + folly::dynamic payload = folly::dynamic::object; |
| 65 | + folly::dynamic touchPoints = folly::dynamic::array(); |
| 66 | + std::vector<TouchableView> touchableViews; |
| 67 | + |
| 68 | + auto action = OH_ArkUI_UIInputEvent_GetAction(e); |
| 69 | + auto actionType = static_cast<ActionType>(action); |
| 70 | + |
| 71 | + if (actionType != ActionType::Move) { |
| 72 | + auto componentX = OH_ArkUI_PointerEvent_GetX(e); |
| 73 | + auto componentY = OH_ArkUI_PointerEvent_GetY(e); |
| 74 | + touchableViews = m_rootView->findTouchableViews(componentX, componentY); |
| 75 | + } |
| 76 | + |
| 77 | + auto activeWindowX = OH_ArkUI_PointerEvent_GetWindowX(e); |
| 78 | + auto activeWindowY = OH_ArkUI_PointerEvent_GetWindowY(e); |
| 79 | + int32_t pointerCount = OH_ArkUI_PointerEvent_GetPointerCount(e); |
| 80 | + int activePointerIdx = 0; |
| 81 | + for (int i = 0; i < pointerCount; i++) { |
| 82 | + auto touchPoint = m_rootView->convertNodeTouchPointToDynamic(e, i); |
| 83 | + touchPoints.push_back(touchPoint); |
| 84 | + if (activeWindowX == touchPoint["windowX"].asDouble() && activeWindowY == touchPoint["windowY"].asDouble()) { |
| 85 | + activePointerIdx = i; |
| 86 | + } |
| 87 | + } |
| 88 | + payload["actionTouch"] = touchPoints[activePointerIdx]; |
| 89 | + payload["touchPoints"] = touchPoints; |
| 90 | + payload["sourceType"] = OH_ArkUI_UIInputEvent_GetSourceType(e); |
| 91 | + payload["timestamp"] = OH_ArkUI_UIInputEvent_GetEventTime(e); |
| 92 | + payload["touchableViews"] = m_rootView->dynamicFromTouchableViews(touchableViews); |
| 93 | + payload["rootTag"] = m_rootView->getTag(); |
| 94 | + payload["action"] = action; |
| 95 | + if (rnInstance) { |
| 96 | + rnInstance->postMessageToArkTS("RNGH::TOUCH_EVENT", payload); |
| 97 | + } |
| 98 | +} |
| 99 | + |
| 100 | +StackNode &RNGestureHandlerRootViewComponentInstance::getLocalRootArkUINode() { return m_stackNode; } |
| 101 | + |
| 102 | +void RNGestureHandlerRootViewComponentInstance::setIsHandlingTouches(bool isHandlingTouches) { |
| 103 | + m_isHandlingTouches = isHandlingTouches; |
| 104 | +} |
| 105 | + |
| 106 | +bool RNGestureHandlerRootViewComponentInstance::isHandlingTouches() const { return m_isHandlingTouches; } |
| 107 | + |
| 108 | +void RNGestureHandlerRootViewComponentInstance::onChildInserted(ComponentInstance::Shared const &childComponentInstance, |
| 109 | + std::size_t index) { |
| 110 | + CppComponentInstance::onChildInserted(childComponentInstance, index); |
| 111 | + m_stackNode.insertChild(childComponentInstance->getLocalRootArkUINode(), index); |
| 112 | +} |
| 113 | + |
| 114 | +void RNGestureHandlerRootViewComponentInstance::onChildRemoved( |
| 115 | + ComponentInstance::Shared const &childComponentInstance) { |
| 116 | + CppComponentInstance::onChildRemoved(childComponentInstance); |
| 117 | + m_stackNode.removeChild(childComponentInstance->getLocalRootArkUINode()); |
| 118 | +} |
| 119 | + |
| 120 | +std::vector<RNGestureHandlerRootViewComponentInstance::TouchableView> |
| 121 | +RNGestureHandlerRootViewComponentInstance::findTouchableViews(float componentX, float componentY) { |
| 122 | + auto touchTarget = findTargetForTouchPoint({.x = componentX, .y = componentY}, this->shared_from_this()); |
| 123 | + std::vector<TouchTarget::Shared> touchTargets{}; |
| 124 | + auto tmp = touchTarget; |
| 125 | + while (tmp != nullptr) { |
| 126 | + touchTargets.push_back(tmp); |
| 127 | + tmp = tmp->getTouchTargetParent(); |
| 128 | + } |
| 129 | + std::reverse(touchTargets.begin(), touchTargets.end()); |
| 130 | + |
| 131 | + std::vector<TouchableView> touchableViews{}; |
| 132 | + float offsetX = 0; |
| 133 | + float offsetY = 0; |
| 134 | + auto surface = this->getSurface().lock(); |
| 135 | + if (surface != nullptr) { |
| 136 | + offsetX = surface->getLayoutContext().viewportOffset.x; |
| 137 | + offsetY = surface->getLayoutContext().viewportOffset.y; |
| 138 | + } else { |
| 139 | + LOG(WARNING) << "Surface is nullptr"; |
| 140 | + } |
| 141 | + for (auto &touchTarget : touchTargets) { |
| 142 | + auto buttonRole = dynamic_cast<RNGestureHandlerButtonComponentInstance *>(touchTarget.get()) != nullptr; |
| 143 | + auto frame = touchTarget->getLayoutMetrics().frame; |
| 144 | + auto transform = touchTarget->getTransform(); |
| 145 | + auto transformedFrame = frame * transform; |
| 146 | + touchableViews.push_back({ |
| 147 | + .tag = touchTarget->getTouchTargetTag(), |
| 148 | + .width = transformedFrame.size.width, |
| 149 | + .height = transformedFrame.size.height, |
| 150 | + .x = transformedFrame.origin.x + offsetX, |
| 151 | + .y = transformedFrame.origin.y + offsetY, |
| 152 | + .buttonRole = buttonRole, |
| 153 | + }); |
| 154 | + offsetX += transformedFrame.origin.x; |
| 155 | + offsetY += transformedFrame.origin.y; |
| 156 | + offsetX -= touchTarget->getCurrentOffset().x; |
| 157 | + offsetY -= touchTarget->getCurrentOffset().y; |
| 158 | + } |
| 159 | + |
| 160 | + return touchableViews; |
| 161 | +} |
| 162 | + |
| 163 | +folly::dynamic |
| 164 | +RNGestureHandlerRootViewComponentInstance::dynamicFromTouchableViews(const std::vector<TouchableView> &touchableViews) { |
| 165 | + folly::dynamic d_touchableViews = folly::dynamic::array(); |
| 166 | + for (auto touchableView : touchableViews) { |
| 167 | + folly::dynamic d_touchableView = folly::dynamic::object; |
| 168 | + d_touchableView["tag"] = touchableView.tag; |
| 169 | + d_touchableView["x"] = touchableView.x; |
| 170 | + d_touchableView["y"] = touchableView.y; |
| 171 | + d_touchableView["width"] = touchableView.width; |
| 172 | + d_touchableView["height"] = touchableView.height; |
| 173 | + d_touchableView["buttonRole"] = touchableView.buttonRole; |
| 174 | + d_touchableViews.push_back(d_touchableView); |
| 175 | + } |
| 176 | + return d_touchableViews; |
| 177 | +} |
| 178 | + |
| 179 | +folly::dynamic RNGestureHandlerRootViewComponentInstance::convertNodeTouchPointToDynamic(ArkUI_UIInputEvent *e, |
| 180 | + int32_t index) { |
| 181 | + folly::dynamic result = folly::dynamic::object; |
| 182 | + result["pointerId"] = OH_ArkUI_PointerEvent_GetPointerId(e, index); |
| 183 | + result["windowX"] = OH_ArkUI_PointerEvent_GetWindowXByIndex(e, index); |
| 184 | + result["windowY"] = OH_ArkUI_PointerEvent_GetWindowYByIndex(e, index); |
| 185 | + return result; |
| 186 | +} |
| 187 | + |
| 188 | +Surface::Weak RNGestureHandlerRootViewComponentInstance::getSurface() { |
| 189 | + if (m_surface.lock() != nullptr) { |
| 190 | + return m_surface; |
| 191 | + } |
| 192 | + auto rnInstance = m_deps->rnInstance.lock(); |
| 193 | + if (rnInstance == nullptr) { |
| 194 | + m_surface.reset(); |
| 195 | + return m_surface; |
| 196 | + } |
| 197 | + ComponentInstance::Shared currentRoot = shared_from_this(); |
| 198 | + while (true) { |
| 199 | + auto maybeNewCurrentRoot = currentRoot->getParent().lock(); |
| 200 | + if (maybeNewCurrentRoot == nullptr) { |
| 201 | + break; |
| 202 | + } |
| 203 | + currentRoot = maybeNewCurrentRoot; |
| 204 | + } |
| 205 | + auto maybeSurface = rnInstance->getSurfaceByRootTag(currentRoot->getTag()); |
| 206 | + if (!maybeSurface.has_value()) { |
| 207 | + m_surface.reset(); |
| 208 | + return m_surface; |
| 209 | + } |
| 210 | + m_surface = maybeSurface.value(); |
| 211 | + return m_surface; |
| 212 | +} |
| 213 | + |
| 214 | +} // namespace rnoh |
0 commit comments