diff --git a/cocos/2d/CMakeLists.txt b/cocos/2d/CMakeLists.txt index b1af86e2fb188d895ef304f6a7e8239b3bbe556c..3168fed10211f0b434daa3f600b762219564239e 100644 --- a/cocos/2d/CMakeLists.txt +++ b/cocos/2d/CMakeLists.txt @@ -41,6 +41,7 @@ elseif(OHOS) platform/ohos/napi/modules/RawFileUtils.cpp platform/ohos/napi/modules/TouchesNapi.cpp + platform/ohos/napi/modules/MouseNapi.cpp platform/ohos/napi/modules/InputNapi.cpp platform/ohos/napi/modules/WebViewNapi.cpp platform/ohos/napi/modules/SensorNapi.cpp diff --git a/cocos/2d/platform/ohos/napi/WorkerMessageQueue.h b/cocos/2d/platform/ohos/napi/WorkerMessageQueue.h index 35dece20acc3b545084a2a55eca97cb15c5584de..b8eded03326425e28183e65ed8a867fa1795c7a1 100644 --- a/cocos/2d/platform/ohos/napi/WorkerMessageQueue.h +++ b/cocos/2d/platform/ohos/napi/WorkerMessageQueue.h @@ -34,6 +34,8 @@ enum class MessageType { WM_XCOMPONENT_SURFACE_CREATED = 0, WM_XCOMPONENT_TOUCH_EVENT, WM_XCOMPONENT_KEY_EVENT, + WM_XCOMPONENT_MOUSE_EVENT, + WM_XCOMPONENT_MOUSE_WHEEL_EVENT, WM_XCOMPONENT_SURFACE_CHANGED, WM_XCOMPONENT_SURFACE_DESTROY, WM_APP_SHOW, diff --git a/cocos/2d/platform/ohos/napi/modules/MouseNapi.cpp b/cocos/2d/platform/ohos/napi/modules/MouseNapi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e44a360e4ad29f854eb29d36cacae58cefa82c97 --- /dev/null +++ b/cocos/2d/platform/ohos/napi/modules/MouseNapi.cpp @@ -0,0 +1,49 @@ +// +// Created on 2024/01/05. +// +// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, +// please include "napi/native_api.h". + +#include +#include +#include "MouseNapi.h" +#include "platform/ohos/napi/plugin_manager.h" +#include "../../CCLogOhos.h" +#include "platform/ohos/napi/render/plugin_render.h" +#include + +napi_value MouseNapi::mouseWheelCB(napi_env env, napi_callback_info info) { + napi_status status; + size_t argc = 2; + napi_value args[2]; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); + if (argc != 2) { + napi_throw_type_error(env, NULL, "Wrong number of arguments"); + return nullptr; + } + napi_valuetype valuetype; + status = napi_typeof(env, args[0], &valuetype); + if (status != napi_ok) { + return nullptr; + } + if (valuetype != napi_string) { + napi_throw_type_error(env, NULL, "Wrong arguments"); + return nullptr; + } + + status = napi_typeof(env, args[1], &valuetype); + if (status != napi_ok) { + return nullptr; + } + if (valuetype != napi_number) { + napi_throw_type_error(env, NULL, "Wrong arguments"); + return nullptr; + } + size_t pInt; + char eventType[256]; + NAPI_CALL(env, napi_get_value_string_utf8(env, args[0], eventType, 256, &pInt)); + double scrollY; + NAPI_CALL(env, napi_get_value_double(env, args[1], &scrollY)); + PluginRender::MouseWheelCB(eventType, scrollY); + return nullptr; +} \ No newline at end of file diff --git a/cocos/2d/platform/ohos/napi/modules/MouseNapi.h b/cocos/2d/platform/ohos/napi/modules/MouseNapi.h new file mode 100644 index 0000000000000000000000000000000000000000..59342ce6000584f40c3f47d3f52eeb37fa3433e2 --- /dev/null +++ b/cocos/2d/platform/ohos/napi/modules/MouseNapi.h @@ -0,0 +1,11 @@ +// +// Created on 2024/01/05. +// + +#include +#include + +class MouseNapi { +public: + static napi_value mouseWheelCB(napi_env env, napi_callback_info info); +}; \ No newline at end of file diff --git a/cocos/2d/platform/ohos/napi/plugin_manager.cpp b/cocos/2d/platform/ohos/napi/plugin_manager.cpp index 0db8247b6900ee1763b0f439606ad553f2a5cc6c..a53457461e4704d7ca6bfacf224f6832a1acfe8c 100644 --- a/cocos/2d/platform/ohos/napi/plugin_manager.cpp +++ b/cocos/2d/platform/ohos/napi/plugin_manager.cpp @@ -21,6 +21,7 @@ #include "modules/RawFileUtils.h" #include "modules/InputNapi.h" +#include "modules/MouseNapi.h" #include "modules/WebViewNapi.h" #include "modules/SensorNapi.h" #include "modules/VideoPlayerNapi.h" @@ -41,6 +42,7 @@ enum ContextType { WORKER_INIT, NATIVE_API, INPUT_NAPI, + MOUSE_NAPI, WEBVIEW_NAPI, VIDEOPLAYER_NAPI, SENSOR_API @@ -145,6 +147,15 @@ napi_value NapiManager::GetContext(napi_env env, napi_callback_info info) NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); } break; + case MOUSE_NAPI: + { + OHOS_LOGD("NapiManager::GetContext MOUSE_NAPI"); + napi_property_descriptor desc[] = { + DECLARE_NAPI_FUNCTION("mouseWheelCB", MouseNapi::mouseWheelCB), + }; + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); + } + break; case WEBVIEW_NAPI: { OHOS_LOGD("NapiManager::GetContext WEBVIEW_NAPI"); diff --git a/cocos/2d/platform/ohos/napi/render/plugin_render.cpp b/cocos/2d/platform/ohos/napi/render/plugin_render.cpp index 0b3d9025560fabc9c3cd02e1218170c1af8fc719..17e57024ef4c1a683bb2f388357fe068f174eddf 100644 --- a/cocos/2d/platform/ohos/napi/render/plugin_render.cpp +++ b/cocos/2d/platform/ohos/napi/render/plugin_render.cpp @@ -24,6 +24,7 @@ #include "../helper/NapiHelper.h" #include "2d/platform/ohos/CCLogOhos.h" #include "cocos2d.h" +#include "2d/CCEventMouse.h" using namespace cocos2d; #ifdef __cplusplus @@ -32,10 +33,19 @@ extern "C" { PluginRender* PluginRender::instance_ = nullptr; OH_NativeXComponent_Callback PluginRender::callback_; +OH_NativeXComponent_MouseEvent_Callback PluginRender::mouseCallback_; std::queue PluginRender::touchEventQueue_; std::queue PluginRender::keyEventQueue_; +std::queue PluginRender::mouseEventQueue_; +std::queue PluginRender::mouseWheelEventQueue_; uint64_t PluginRender::animationInterval_ = 16; uint64_t PluginRender::lastTime = 0; +// mouse event +float mousePositionX = -1; +float mousePositionY = -1; +bool isMouseLeftActive = false; +double scrollDistance = 0; +// key event const int keyCodeUnknownInOH = -1; const int keyActionUnknownInOH = -1; @@ -111,6 +121,23 @@ void OnSurfaceDestroyedCB(OH_NativeXComponent* component, void* window) PluginRender::GetInstance()->sendMsgToWorker(MessageType::WM_XCOMPONENT_SURFACE_DESTROY, component, window); } +void DispatchMouseEventCB(OH_NativeXComponent* component, void* window) +{ + OH_NativeXComponent_MouseEvent mouseEvent; + int32_t ret = OH_NativeXComponent_GetMouseEvent(component, window, &mouseEvent); + if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + PluginRender::mouseEventQueue_.push(mouseEvent); + PluginRender::GetInstance()->sendMsgToWorker(MessageType::WM_XCOMPONENT_MOUSE_EVENT, component, window); + } else { + OHOS_LOGE("OpenHarmonyPlatform::getMouseEventError"); + } +} + +void DispatchHoverEventCB(OH_NativeXComponent* component, bool isHover) +{ + OHOS_LOGD("OpenHarmonyPlatform::DispatchHoverEventCB"); +} + void DispatchKeyEventCB(OH_NativeXComponent* component, void* window) { OH_NativeXComponent_KeyEvent* keyEvent; @@ -185,6 +212,10 @@ void PluginRender::onMessageCallback(const uv_async_t* /* req */) { render->DispatchKeyEvent(nativexcomponet, msgData.window); } else if (msgData.type == MessageType::WM_XCOMPONENT_TOUCH_EVENT) { render->DispatchTouchEvent(nativexcomponet, msgData.window); + } else if (msgData.type == MessageType::WM_XCOMPONENT_MOUSE_EVENT) { + render->DispatchMouseEvent(nativexcomponet, msgData.window); + } else if (msgData.type == MessageType::WM_XCOMPONENT_MOUSE_WHEEL_EVENT) { + render->DispatchMouseWheelEvent(); } else if (msgData.type == MessageType::WM_XCOMPONENT_SURFACE_CHANGED) { render->OnSurfaceChanged(nativexcomponet, msgData.window); } else if (msgData.type == MessageType::WM_XCOMPONENT_SURFACE_DESTROY) { @@ -237,6 +268,10 @@ void PluginRender::SetNativeXComponent(OH_NativeXComponent* component) OH_NativeXComponent_RegisterCallback(component_, &PluginRender::callback_); // register keyEvent OH_NativeXComponent_RegisterKeyEventCallback(component_, DispatchKeyEventCB); + // register mouseEvent + PluginRender::mouseCallback_.DispatchMouseEvent = DispatchMouseEventCB; + PluginRender::mouseCallback_.DispatchHoverEvent = DispatchHoverEventCB; + OH_NativeXComponent_RegisterMouseEventCallback(component_, &mouseCallback_); } void PluginRender::workerInit(napi_env env, uv_loop_t* loop) { @@ -324,6 +359,69 @@ void PluginRender::DispatchKeyEvent(OH_NativeXComponent* component, void* window } } +void PluginRender::DispatchMouseEvent(OH_NativeXComponent* component, void* window) +{ + OH_NativeXComponent_MouseEvent mouseEvent; + while (!mouseEventQueue_.empty()) { + mouseEvent = mouseEventQueue_.front(); + mouseEventQueue_.pop(); + EventMouse::MouseEventType mouseAction; + mousePositionX = mouseEvent.x; + mousePositionY = mouseEvent.y; + switch (mouseEvent.action) { + case OH_NATIVEXCOMPONENT_MOUSE_PRESS: + mouseAction = EventMouse::MouseEventType::MOUSE_DOWN; + break; + case OH_NATIVEXCOMPONENT_MOUSE_RELEASE: + mouseAction = EventMouse::MouseEventType::MOUSE_UP; + break; + case OH_NATIVEXCOMPONENT_MOUSE_MOVE: + mouseAction = EventMouse::MouseEventType::MOUSE_MOVE; + break; + default: + mouseAction = EventMouse::MouseEventType::MOUSE_NONE; + break; + } + int mouseButton; + switch (mouseEvent.button) { + case OH_NATIVEXCOMPONENT_LEFT_BUTTON: + mouseButton = MOUSE_BUTTON_LEFT; + break; + case OH_NATIVEXCOMPONENT_RIGHT_BUTTON: + mouseButton = MOUSE_BUTTON_RIGHT; + break; + case OH_NATIVEXCOMPONENT_MIDDLE_BUTTON: + mouseButton = MOUSE_BUTTON_MIDDLE; + break; + default: + break; + } + if (mouseEvent.action == OH_NATIVEXCOMPONENT_MOUSE_PRESS && mouseEvent.button == OH_NATIVEXCOMPONENT_LEFT_BUTTON) { + isMouseLeftActive = true; + } + if (mouseEvent.action == OH_NATIVEXCOMPONENT_MOUSE_RELEASE && mouseEvent.button == OH_NATIVEXCOMPONENT_LEFT_BUTTON) { + isMouseLeftActive = false; + } + EventMouse event(mouseAction); + event.setCursorPosition(mouseEvent.x, mouseEvent.y); + event.setMouseButton(mouseButton); + Director::getInstance()->getEventDispatcher()->dispatchEvent(&event); + } +} + +void PluginRender::DispatchMouseWheelEvent() +{ + EventMouseWheelData mouseWheelData; + while (!mouseWheelEventQueue_.empty()) { + mouseWheelData = mouseWheelEventQueue_.front(); + mouseWheelEventQueue_.pop(); + EventMouse mouseWheelEvent(cocos2d::EventMouse::MouseEventType::MOUSE_SCROLL); + mouseWheelEvent.setScrollData(0, -mouseWheelData.scrollY); + mouseWheelEvent.setCursorPosition(mouseWheelData.positonX, mouseWheelData.positonY); + Director::getInstance()->getEventDispatcher()->dispatchEvent(&mouseWheelEvent); + } +} + void PluginRender::DispatchTouchEvent(OH_NativeXComponent* component, void* window) { OH_NativeXComponent_TouchEvent* touchEvent; @@ -365,6 +463,23 @@ void PluginRender::DispatchTouchEvent(OH_NativeXComponent* component, void* wind } } +void PluginRender::MouseWheelCB(std::string eventType, double scrollY) +{ + if (isMouseLeftActive) { + return; + } + if (eventType == "actionEnd") { + scrollDistance = 0; + } + if (eventType == "actionUpdate") { + double moveScrollY = scrollY - scrollDistance; + scrollDistance = scrollY; + PluginRender::EventMouseWheelData mouseWheelData{mousePositionX, mousePositionY, moveScrollY}; + PluginRender::mouseWheelEventQueue_.push(mouseWheelData); + PluginRender::GetInstance()->sendMsgToWorker(MessageType::WM_XCOMPONENT_MOUSE_WHEEL_EVENT, nullptr, nullptr); + } +} + void PluginRender::OnCreateNative(napi_env env, uv_loop_t* loop) { OHOS_LOGD("PluginRender::OnCreateNative"); } diff --git a/cocos/2d/platform/ohos/napi/render/plugin_render.h b/cocos/2d/platform/ohos/napi/render/plugin_render.h index bf4eb67553523ad573a66661558b07815556f9e2..cd85aed6c0e945cf8b93cf21fcfe023b114c9d5e 100644 --- a/cocos/2d/platform/ohos/napi/render/plugin_render.h +++ b/cocos/2d/platform/ohos/napi/render/plugin_render.h @@ -56,6 +56,8 @@ public: static napi_value NapiChangeColor(napi_env env, napi_callback_info info); static napi_value NapiChangeColorWorker(napi_env env, napi_callback_info info); + static void MouseWheelCB(std::string eventType, double scrollY); + // Callback, called by ACE XComponent void OnSurfaceCreated(OH_NativeXComponent* component, void* window); @@ -63,20 +65,32 @@ public: void OnSurfaceDestroyed(OH_NativeXComponent* component, void* window); + void DispatchMouseEvent(OH_NativeXComponent* component, void* window); + void DispatchKeyEvent(OH_NativeXComponent* component, void* window); void DispatchTouchEvent(OH_NativeXComponent* component, void* window); + void DispatchMouseWheelEvent(); + void OnCreateNative(napi_env env, uv_loop_t* loop); void OnShowNative(); void OnHideNative(); void OnDestroyNative(); public: + struct EventMouseWheelData { + float positonX; + float positonY; + double scrollY; + }; static PluginRender* instance_; static OH_NativeXComponent_Callback callback_; + static OH_NativeXComponent_MouseEvent_Callback mouseCallback_; static std::queue touchEventQueue_; static std::queue keyEventQueue_; + static std::queue mouseEventQueue_; + static std::queue mouseWheelEventQueue_; OH_NativeXComponent* component_{nullptr}; uv_timer_t timerHandle_; diff --git a/tests/cpp-tests/Classes/controller.cpp b/tests/cpp-tests/Classes/controller.cpp index bc41a91c94957a8a2f15953227aac565d01eacea..a765446c67d96269d3d46614233ab71c7611ca9a 100644 --- a/tests/cpp-tests/Classes/controller.cpp +++ b/tests/cpp-tests/Classes/controller.cpp @@ -230,7 +230,12 @@ void TestController::onTouchMoved(Touch* touch, Event *event) void TestController::onMouseScroll(Event *event) { auto mouseEvent = static_cast(event); - float nMoveY = mouseEvent->getScrollY() * 6; + float nMoveY = mouseEvent->getScrollY(); + #if (CC_TARGET_PLATFORM == CC_PLATFORM_OHOS) + nMoveY *= 0.2; + #else + nMoveY *= 6; + #endif auto curPos = _itemMenu->getPosition(); auto nextPos = Point(curPos.x, curPos.y + nMoveY); diff --git a/tests/cpp-tests/proj.ohos/entry/src/main/cpp/types/libentry/index.d.ts b/tests/cpp-tests/proj.ohos/entry/src/main/cpp/types/libentry/index.d.ts index a5bc5c8db63c3b3d3e32a1c715b2752b79f0119a..8c059ca83e8886d1d6a6a10f15ace0532103d009 100644 --- a/tests/cpp-tests/proj.ohos/entry/src/main/cpp/types/libentry/index.d.ts +++ b/tests/cpp-tests/proj.ohos/entry/src/main/cpp/types/libentry/index.d.ts @@ -14,6 +14,7 @@ export interface CPPFunctions { nativeEngineStart: () => void; registerFunction: () => void; initAsyncInfo: () => void; + mouseWheelCB: (eventType: string, scrollY : number) => void; editBoxOnChangeCB: (viewTag: number, text: string) => void; editBoxOnEnterCB: (viewTag: number, text: string) => void; textFieldTTFOnChangeCB: (text: string) => void; diff --git a/tests/cpp-tests/proj.ohos/entry/src/main/ets/pages/Index.ets b/tests/cpp-tests/proj.ohos/entry/src/main/ets/pages/Index.ets index 96759d9166f20aea06adc9fea5ef4bf63dc412bc..16d25eb5f554a03a03ed1847e5bdbb9ebf090931 100644 --- a/tests/cpp-tests/proj.ohos/entry/src/main/ets/pages/Index.ets +++ b/tests/cpp-tests/proj.ohos/entry/src/main/ets/pages/Index.ets @@ -42,6 +42,8 @@ struct Index { alignment: DialogAlignment.Bottom, customStyle: true, }) + // PanGesture + private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.Up | PanDirection.Down }); onPageShow() { console.log('[LIFECYCLE-Page] onPageShow'); @@ -68,6 +70,10 @@ struct Index { return true; } + onMouseWheel(eventType: string, scrollY: number) { + this.cocosWorker.postMessage({ type: "onMouseWheel", eventType: eventType, scrollY: scrollY }); + } + build() { Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { XComponent({ @@ -77,6 +83,21 @@ struct Index { controller: this.xcomponentController }) .focusable(true) + .focusOnTouch(true) + .gesture( + PanGesture(this.panOption) + .onActionStart(() => { + this.onMouseWheel("actionStart", 0); + }) + .onActionUpdate((event: GestureEvent) => { + if (event.source === SourceType.Mouse) { + this.onMouseWheel("actionUpdate", event.offsetY); + } + }) + .onActionEnd(() => { + this.onMouseWheel("actionEnd", 0); + }) + ) .onLoad((context) => { console.log('[cocos] XComponent.onLoad Callback'); this.cocosWorker.postMessage({ type: "onXCLoad", data: "XComponent" }); diff --git a/tests/cpp-tests/proj.ohos/entry/src/main/ets/workers/CocosWorker.ts b/tests/cpp-tests/proj.ohos/entry/src/main/ets/workers/CocosWorker.ts index 327f0f94ad7196dbd6c60b3cb6b2349f6af1ef2b..d8fa6f575898ed90eab89fb5446abf2706ec527e 100644 --- a/tests/cpp-tests/proj.ohos/entry/src/main/ets/workers/CocosWorker.ts +++ b/tests/cpp-tests/proj.ohos/entry/src/main/ets/workers/CocosWorker.ts @@ -28,6 +28,7 @@ import { GlobalContext,GlobalContextConstants} from "@ohos/libSysCapabilities" const appLifecycle: nativeRender.CPPFunctions = nativeRender.getContext(ContextType.APP_LIFECYCLE); const workerContext: nativeRender.CPPFunctions = nativeRender.getContext(ContextType.WORKER_INIT); const inputNapi: nativeRender.CPPFunctions = nativeRender.getContext(ContextType.INPUT_NAPI); +const mouseNapi: nativeRender.CPPFunctions = nativeRender.getContext(ContextType.MOUSE_NAPI); const webViewNapi: nativeRender.CPPFunctions = nativeRender.getContext(ContextType.WEBVIEW_NAPI); const videoPlayNapi: nativeRender.CPPFunctions = nativeRender.getContext(ContextType.VIDEOPLAYER_NAPI); const napiContext: nativeRender.CPPFunctions = nativeRender.getContext(ContextType.NATIVE_API); @@ -63,6 +64,9 @@ workerPort.onmessage = function(e) : void { case "textFieldTTFOnChange": inputNapi.textFieldTTFOnChangeCB(data.data); break; + case "onMouseWheel": + mouseNapi.mouseWheelCB(data.eventType, data.scrollY); + break; case "onPageBegin": webViewNapi.shouldStartLoading(data.viewTag, data.url); break; diff --git a/tests/cpp-tests/proj.ohos/libSysCapabilities/src/main/ets/common/Constants.ts b/tests/cpp-tests/proj.ohos/libSysCapabilities/src/main/ets/common/Constants.ts index f6c4b10f6363c245d0086028b24bf1e3928ac79a..0df8b27ed0595c1ca629a83f4babf639a26b955a 100644 --- a/tests/cpp-tests/proj.ohos/libSysCapabilities/src/main/ets/common/Constants.ts +++ b/tests/cpp-tests/proj.ohos/libSysCapabilities/src/main/ets/common/Constants.ts @@ -19,6 +19,7 @@ export enum ContextType { WORKER_INIT, NATIVE_API, INPUT_NAPI, + MOUSE_NAPI, WEBVIEW_NAPI, VIDEOPLAYER_NAPI, SENSOR_API