From cdc0b4a5e10fe892aa9b1478c0fe4b5e0a58384e Mon Sep 17 00:00:00 2001 From: duanaoqi Date: Fri, 12 Jul 2024 18:38:11 +0800 Subject: [PATCH] openHarmony mouseAdapt --- .../src/main/cpp/types/libflutter/index.d.ets | 10 +++ .../main/ets/embedding/engine/FlutterNapi.ets | 27 ++++++ .../main/ets/embedding/ohos/FlutterPage.ets | 13 +++ .../flutter/src/main/ets/view/FlutterView.ets | 4 + shell/platform/ohos/library_loader.cpp | 3 + .../ohos/napi/platform_view_ohos_napi.cpp | 85 ++++++++++++++++++ .../ohos/napi/platform_view_ohos_napi.h | 13 +++ shell/platform/ohos/ohos_touch_processor.cpp | 82 +++++++++++++++++ shell/platform/ohos/ohos_touch_processor.h | 8 ++ .../platform/ohos/ohos_xcomponent_adapter.cpp | 90 +++++++++++++++++++ shell/platform/ohos/ohos_xcomponent_adapter.h | 5 ++ 11 files changed, 340 insertions(+) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets index ce5ef18b90..d38b7a0e4c 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets @@ -94,6 +94,16 @@ export const nativeXComponentAttachFlutterEngine: (xcomponentId: string, nativeS export const nativeXComponentDetachFlutterEngine: (xcomponentId: string, nativeShellHolderId: number) => void; +export const nativeXComponentDispatchMouseWheel: (nativeShellHolderId: number, + xcomponentId: string, + eventType: string, + fingerId: number, + globalX: number, + globalY: number, + offsetY: number, + timestamp: number + ) => void; + /** * Detaches flutterNapi和engine之间的关联 * 这个方法执行前提是flutterNapi已经和engine关联 diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets index b74c2d4c63..c97363ffc9 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets @@ -377,6 +377,33 @@ export default class FlutterNapi { flutter.nativeXComponentDetachFlutterEngine(xcomponentId, this.nativeShellHolderId!); } + /** + * xcomponent send mouseWheel event to flutterEngine + * @param xcomponentId + * @param eventType + * @param event + */ + xComponentDisPatchMouseWheel(xcomponentId: string, eventType: string, event: PanGestureEvent) { + // only mouse + if (event.source !== SourceType.Mouse) { + return; + } + const vaildFinger = event.fingerList?.find(item => item.globalX && item.globalY); + if (!vaildFinger) { + return; + } + flutter.nativeXComponentDispatchMouseWheel( + this.nativeShellHolderId!!, + xcomponentId, + eventType, + vaildFinger?.id, + vaildFinger?.localX, + vaildFinger?.localY, + event.offsetY, + event.timestamp + ); + } + detachFromNativeAndReleaseResources() { flutter.nativeDestroy(this.nativeShellHolderId!!); } diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets index df00af2cf2..7b4ab6b37f 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets @@ -42,6 +42,7 @@ export struct FlutterPage { private flutterView?: FlutterView | null private nodeController: EmbeddingNodeController | undefined = undefined private lastArea?: Area; + private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.Up | PanDirection.Down }); aboutToAppear() { this.flutterView = FlutterManager.getInstance().getFlutterView(this.viewId); @@ -102,5 +103,17 @@ export struct FlutterPage { Log.d(TAG, "onKeyEvent " + event.type); this.flutterView?.onKeyEvent(event) }) + .gesture( + PanGesture(this.panOption) + .onActionStart((event: GestureEvent) => { + this.flutterView?.onMouseWheel("actionStart", event); + }) + .onActionUpdate((event: GestureEvent) => { + this.flutterView?.onMouseWheel("actionUpdate", event); + }) + .onActionEnd((event: GestureEvent) => { + this.flutterView?.onMouseWheel("actionEnd", event); + }) + ) } } diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets index 6198536c35..3f23984aee 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets @@ -336,6 +336,10 @@ export class FlutterView { this.keyboardManager?.handleKeyEvent(event) } + onMouseWheel(eventType: string, event: PanGestureEvent) { + this.flutterEngine?.getFlutterNapi()?.xComponentDisPatchMouseWheel(this.id, eventType, event); + } + addFirstFrameListener(listener: FirstFrameListener) { this.mFirstFrameListeners.add(listener); } diff --git a/shell/platform/ohos/library_loader.cpp b/shell/platform/ohos/library_loader.cpp index 415bf46a65..231723d337 100644 --- a/shell/platform/ohos/library_loader.cpp +++ b/shell/platform/ohos/library_loader.cpp @@ -107,6 +107,9 @@ static napi_value Init(napi_env env, napi_value exports) { DECLARE_NAPI_FUNCTION( "nativeXComponentDetachFlutterEngine", flutter::PlatformViewOHOSNapi::nativeXComponentDetachFlutterEngine), + DECLARE_NAPI_FUNCTION( + "nativeXComponentDispatchMouseWheel", + flutter::PlatformViewOHOSNapi::nativeXComponentDispatchMouseWheel), DECLARE_NAPI_FUNCTION( "nativeInitNativeImage", flutter::PlatformViewOHOSNapi::nativeInitNativeImage), diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index b2ebeb46a3..48b2d20f1d 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -1626,4 +1626,89 @@ napi_value PlatformViewOHOSNapi::nativeXComponentDetachFlutterEngine( return nullptr; } + +/** + * @brief flutterEngine get mouseWheel event from ets + * @note + * @param nativeShellHolderId: number + * @param xcomponentId: number + * @param eventType: string + * @param fingerId: number + * @param globalX: number + * @param globalY: number + * @param offsetY: number + * @param timestamp: number + * @return napi_value + */ +napi_value PlatformViewOHOSNapi::nativeXComponentDispatchMouseWheel( + napi_env env, + napi_callback_info info){ + napi_status ret; + size_t argc = 8; + napi_value args[8] = {nullptr}; + int64_t shell_holder; + std::string xcomponent_id; + std::string event_type; + int64_t finger_id; + double global_x; + double global_y; + double offset_y; + int64_t timestamp; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "nativeXComponentDispatchMouseWheel napi_get_cb_info error:" + << ret; + return nullptr; + } + ret = napi_get_value_int64(env, args[0], &shell_holder); + if (ret != napi_ok) { + LOGE("nativeXComponentDispatchMouseWheel shell_holder napi_get_value_int64 error"); + return nullptr; + } + if (fml::napi::GetString(env, args[1], xcomponent_id) != 0) { + FML_DLOG(ERROR) << "nativeXComponentDispatchMouseWheel xcomponent_id GetString error"; + return nullptr; + } + if (fml::napi::GetString(env, args[2], event_type) != 0) { + FML_DLOG(ERROR) << "nativeXComponentDispatchMouseWheel event_type GetString error"; + return nullptr; + } + ret = napi_get_value_int64(env, args[3], &finger_id); + if (ret != napi_ok) { + LOGE("nativeXComponentDispatchMouseWheel finger_id napi_get_value_int64 error"); + return nullptr; + } + ret = napi_get_value_double(env, args[4], &global_x); + if (ret != napi_ok) { + LOGE("nativeXComponentDispatchMouseWheel global_x napi_get_value_double error"); + return nullptr; + } + ret = napi_get_value_double(env, args[5], &global_y); + if (ret != napi_ok) { + LOGE("nativeXComponentDispatchMouseWheel global_y napi_get_value_double error"); + return nullptr; + } + ret = napi_get_value_double(env, args[6], &offset_y); + if (ret != napi_ok) { + LOGE("nativeXComponentDispatchMouseWheel offset_y napi_get_value_double error"); + return nullptr; + } + ret = napi_get_value_int64(env, args[7], ×tamp); + if (ret != napi_ok) { + LOGE("nativeXComponentDispatchMouseWheel timestamp napi_get_value_int64 error"); + return nullptr; + } + flutter::mouseWheelEvent event { + event_type, + shell_holder, + finger_id, + global_x, + global_y, + offset_y, + timestamp + }; + XComponentAdapter::GetInstance()->OnMouseWheel(xcomponent_id, event); + return nullptr; +} + } // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.h b/shell/platform/ohos/napi/platform_view_ohos_napi.h index 8e3748a6ff..5949a80863 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.h +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.h @@ -37,6 +37,16 @@ struct locale { std::string region; }; +struct mouseWheelEvent { + std::string event_type; + int64_t shell_holder; + int64_t finger_id; + double global_x; + double global_y; + double offset_y; + int64_t timestamp; +}; + class PlatformViewOHOSNapi { public: static napi_value nativeDispatchEmptyPlatformMessage( @@ -181,6 +191,9 @@ class PlatformViewOHOSNapi { static napi_value nativeXComponentDetachFlutterEngine( napi_env env, napi_callback_info info); + static napi_value nativeXComponentDispatchMouseWheel( + napi_env env, + napi_callback_info info); private: static napi_env env_; diff --git a/shell/platform/ohos/ohos_touch_processor.cpp b/shell/platform/ohos/ohos_touch_processor.cpp index 98f02d10ea..55c9ed3f56 100644 --- a/shell/platform/ohos/ohos_touch_processor.cpp +++ b/shell/platform/ohos/ohos_touch_processor.cpp @@ -39,6 +39,38 @@ PointerData::Change OhosTouchProcessor::getPointerChangeForAction( return PointerData::Change::kCancel; } +PointerData::Change OhosTouchProcessor::getPointerChangeForMouseAction( + OH_NativeXComponent_MouseEventAction mouseAction) { + switch (mouseAction) { + case OH_NATIVEXCOMPONENT_MOUSE_PRESS: + return PointerData::Change::kDown; + case OH_NATIVEXCOMPONENT_MOUSE_RELEASE: + return PointerData::Change::kUp; + case OH_NATIVEXCOMPONENT_MOUSE_MOVE: + return PointerData::Change::kMove; + default: + return PointerData::Change::kCancel; + } +} + +PointerButtonMouse OhosTouchProcessor::getPointerButtonFromMouse( + OH_NativeXComponent_MouseEventButton mouseButton) { + switch (mouseButton) { + case OH_NATIVEXCOMPONENT_LEFT_BUTTON: + return kPointerButtonMousePrimary; + case OH_NATIVEXCOMPONENT_RIGHT_BUTTON: + return kPointerButtonMouseSecondary; + case OH_NATIVEXCOMPONENT_MIDDLE_BUTTON: + return kPointerButtonMouseMiddle; + case OH_NATIVEXCOMPONENT_BACK_BUTTON: + return kPointerButtonMouseBack; + case OH_NATIVEXCOMPONENT_FORWARD_BUTTON: + return kPointerButtonMouseForward; + default: + return kPointerButtonMousePrimary; + } +} + PointerData::DeviceKind OhosTouchProcessor::getPointerDeviceTypeForToolType( int toolType) { switch (toolType) { @@ -176,4 +208,54 @@ void OhosTouchProcessor::HandleTouchEvent( return; } +void OhosTouchProcessor::HandleMouseEvent( + int64_t shell_holderID, + OH_NativeXComponent* component, + OH_NativeXComponent_MouseEvent mouseEvent, + double offsetY) { + const int numTouchPoints = 1; + std::unique_ptr packet = std::make_unique(numTouchPoints); + PointerData pointerData; + pointerData.Clear(); + pointerData.embedder_id = mouseEvent.button; + pointerData.time_stamp = mouseEvent.timestamp / MSEC_PER_SECOND; + pointerData.change = getPointerChangeForMouseAction(mouseEvent.action); + pointerData.physical_y = mouseEvent.y; + pointerData.physical_x = mouseEvent.x; + // Delta will be generated in pointer_data_packet_converter.cc. + pointerData.physical_delta_x = 0.0; + pointerData.physical_delta_y = 0.0; + pointerData.device = mouseEvent.button; + // Pointer identifier will be generated in pointer_data_packet_converter.cc. + pointerData.pointer_identifier = 0; + // XComponent not support Scroll + // now it's support + pointerData.signal_kind = offsetY != 0 ? PointerData::SignalKind::kScroll : PointerData::SignalKind::kNone; + pointerData.scroll_delta_x = 0.0; + pointerData.scroll_delta_y = offsetY; + pointerData.pressure = 0.0; + pointerData.pressure_max = 1.0; + pointerData.pressure_min = 0.0; + pointerData.kind = PointerData::DeviceKind::kMouse; + pointerData.buttons = getPointerButtonFromMouse(mouseEvent.button); + // hover support + if (mouseEvent.button == OH_NATIVEXCOMPONENT_NONE_BUTTON && pointerData.change == PointerData::Change::kMove) { + pointerData.change = PointerData::Change::kHover; + pointerData.buttons = 0; + } + pointerData.pan_x = 0.0; + pointerData.pan_y = 0.0; + // Delta will be generated in pointer_data_packet_converter.cc. + pointerData.pan_delta_x = 0.0; + pointerData.pan_delta_y = 0.0; + // The contact area between the fingerpad and the screen + pointerData.size = 0.0; + pointerData.scale = 1.0; + pointerData.rotation = 0.0; + packet->SetPointerData(0, pointerData); + auto ohos_shell_holder = reinterpret_cast(shell_holderID); + ohos_shell_holder->GetPlatformView()->DispatchPointerDataPacket( + std::move(packet)); + return; + } } // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/ohos_touch_processor.h b/shell/platform/ohos/ohos_touch_processor.h index ec70f2b0b5..812d56a81e 100644 --- a/shell/platform/ohos/ohos_touch_processor.h +++ b/shell/platform/ohos/ohos_touch_processor.h @@ -36,9 +36,17 @@ class OhosTouchProcessor { void HandleTouchEvent(int64_t shell_holderID, OH_NativeXComponent* component, OH_NativeXComponent_TouchEvent* touchEvent); + void HandleMouseEvent(int64_t shell_holderID, + OH_NativeXComponent* component, + OH_NativeXComponent_MouseEvent mouseEvent, + double offsetY); flutter::PointerData::Change getPointerChangeForAction(int maskedAction); flutter::PointerData::DeviceKind getPointerDeviceTypeForToolType( int toolType); + flutter::PointerData::Change getPointerChangeForMouseAction( + OH_NativeXComponent_MouseEventAction mouseAction); + PointerButtonMouse getPointerButtonFromMouse( + OH_NativeXComponent_MouseEventButton mouseButton); private: std::shared_ptr packagePacketData(std::unique_ptr touchPacket); diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.cpp b/shell/platform/ohos/ohos_xcomponent_adapter.cpp index d20ac4ab20..0b7ca1e577 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.cpp +++ b/shell/platform/ohos/ohos_xcomponent_adapter.cpp @@ -19,6 +19,9 @@ #include namespace flutter { +bool isMouseLeftActive = false; +double scrollDistance = 0.0; + XComponentAdapter XComponentAdapter::mXComponentAdapter; XComponentAdapter::XComponentAdapter(/* args */) {} @@ -102,6 +105,13 @@ void XComponentAdapter::DetachFlutterEngine(std::string& id) { } } +void XComponentAdapter::OnMouseWheel(std::string& id, mouseWheelEvent event) { + auto iter = xcomponetMap_.find(id); + if (iter != xcomponetMap_.end()) { + iter->second->OnDispatchMouseWheelEvent(event); + } +} + #include using OHOS_SurfaceBufferUsage = enum { BUFFER_USAGE_CPU_READ = (1ULL << 0), /**< CPU read buffer */ @@ -229,11 +239,26 @@ void DispatchTouchEventCB(OH_NativeXComponent* component, void* window) { } } +void DispatchMouseEventCB(OH_NativeXComponent* component, void* window) { + for(auto it: XComponentAdapter::GetInstance()->xcomponetMap_) + { + if(it.second->nativeXComponent_ == component) { + it.second->OnDispatchMouseEvent(component, window); + } + } +} + +void DispatchHoverEventCB(OH_NativeXComponent* component, bool isHover) { + LOGD("XComponentManger::DispatchHoverEventCB"); +} + void XComponentBase::BindXComponentCallback() { callback_.OnSurfaceCreated = OnSurfaceCreatedCB; callback_.OnSurfaceChanged = OnSurfaceChangedCB; callback_.OnSurfaceDestroyed = OnSurfaceDestroyedCB; callback_.DispatchTouchEvent = DispatchTouchEventCB; + mouseCallback_.DispatchMouseEvent = DispatchMouseEventCB; + mouseCallback_.DispatchHoverEvent = DispatchHoverEventCB; } XComponentBase::XComponentBase(std::string id){ @@ -276,6 +301,7 @@ void XComponentBase::SetNativeXComponent(OH_NativeXComponent* nativeXComponent){ if (nativeXComponent_ != nullptr) { BindXComponentCallback(); OH_NativeXComponent_RegisterCallback(nativeXComponent_, &callback_); + OH_NativeXComponent_RegisterMouseEventCallback(nativeXComponent_, &mouseCallback_); } } @@ -342,6 +368,14 @@ void XComponentBase::OnDispatchTouchEvent(OH_NativeXComponent* component, OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent_); if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { if (isEngineAttached_) { + // if this touchEvent triggered by mouse, return + OH_NativeXComponent_EventSourceType sourceType; + int32_t ret2 = OH_NativeXComponent_GetTouchEventSourceType(component, touchEvent_.id, &sourceType); + if (ret2 == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + if (sourceType == OH_NATIVEXCOMPONENT_SOURCE_TYPE_MOUSE) { + return; + } + } ohosTouchProcessor_.HandleTouchEvent(std::stoll(shellholderId_), component, &touchEvent_); } else { @@ -352,4 +386,60 @@ void XComponentBase::OnDispatchTouchEvent(OH_NativeXComponent* component, } } +void XComponentBase::OnDispatchMouseEvent(OH_NativeXComponent* component, + void* window) { + OH_NativeXComponent_MouseEvent mouseEvent_; + int32_t ret = + OH_NativeXComponent_GetMouseEvent(component, window, &mouseEvent_); + if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + if (isEngineAttached_) { + if (mouseEvent_.button == OH_NATIVEXCOMPONENT_LEFT_BUTTON) { + if (mouseEvent_.action == OH_NATIVEXCOMPONENT_MOUSE_PRESS) { + isMouseLeftActive = true; + } else if (mouseEvent_.action == OH_NATIVEXCOMPONENT_MOUSE_RELEASE) { + isMouseLeftActive = false; + } + } + ohosTouchProcessor_.HandleMouseEvent(std::stoll(shellholderId_), + component, mouseEvent_, 0.0); + } else { + LOGE( + "XComponentManger::DispatchMouseEvent XComponentBase is not " + "attached"); + } + } +} + +void XComponentBase::OnDispatchMouseWheelEvent(mouseWheelEvent event) { + std::string shell_holder_str = std::to_string(event.shell_holder); + if (shell_holder_str != shellholderId_) { + return; + } + if (isEngineAttached_) { + if (isMouseLeftActive) { + return; + } + if (event.event_type == "actionUpdate") { + OH_NativeXComponent_MouseEvent mouseEvent_; + double scrollY_ = event.offset_y - scrollDistance; + scrollDistance = event.offset_y; + // resize for flutter + mouseEvent_.x = event.global_x / 0.8; + mouseEvent_.y = event.global_y / 0.8; + scrollY_ = scrollY_ / 0.8; + mouseEvent_.button = OH_NATIVEXCOMPONENT_NONE_BUTTON; + mouseEvent_.action = OH_NATIVEXCOMPONENT_MOUSE_NONE; + mouseEvent_.timestamp = event.timestamp; + ohosTouchProcessor_.HandleMouseEvent(std::stoll(shellholderId_), + nullptr, mouseEvent_, + scrollY_); + } else { + scrollDistance = 0.0; + } + } else { + LOGE( + "XComponentManger::DispatchMouseWheelEvent XComponentBase is not " + "attached"); + } +} } // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.h b/shell/platform/ohos/ohos_xcomponent_adapter.h index 4fd6ff4990..aecea89ded 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.h +++ b/shell/platform/ohos/ohos_xcomponent_adapter.h @@ -18,6 +18,7 @@ #include #include #include "flutter/shell/platform/ohos/ohos_touch_processor.h" +#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" #include "napi/native_api.h" #include "napi_common.h" #include @@ -41,9 +42,12 @@ public: void OnSurfaceChanged(OH_NativeXComponent* component, void* window); void OnSurfaceDestroyed(OH_NativeXComponent* component, void* window); void OnDispatchTouchEvent(OH_NativeXComponent* component, void* window); + void OnDispatchMouseEvent(OH_NativeXComponent* component, void* window); + void OnDispatchMouseWheelEvent(mouseWheelEvent event); OH_NativeXComponent_TouchEvent touchEvent_; OH_NativeXComponent_Callback callback_; + OH_NativeXComponent_MouseEvent_Callback mouseCallback_; std::string id_; std::string shellholderId_; bool isEngineAttached_; @@ -66,6 +70,7 @@ class XComponentAdapter { OH_NativeXComponent* nativeXComponent); void AttachFlutterEngine(std::string& id, std::string& shellholderId); void DetachFlutterEngine(std::string& id); + void OnMouseWheel(std::string& id, mouseWheelEvent event); public: std::map xcomponetMap_; -- Gitee