From d7416f7d4f26439cf4d2eec78d5c06c36bd8cfaf Mon Sep 17 00:00:00 2001 From: chyyy0213 Date: Thu, 3 Mar 2022 19:00:01 +0800 Subject: [PATCH] =?UTF-8?q?js=20callback=20=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: chyyy0213 Change-Id: I2d2b734fff3a4081517606535513ba767d96c5ce --- interfaces/innerkits/wm/window.h | 2 +- .../wm/window_life_cycle_interface.h | 2 +- .../window_manager_napi/js_window_manager.cpp | 31 +-- .../window_manager_napi/js_window_manager.h | 2 +- .../window_runtime/window_napi/js_window.cpp | 195 +++++++++++------- .../window_runtime/window_napi/js_window.h | 3 +- .../window_napi/js_window_listener.cpp | 104 ++++++---- .../window_napi/js_window_listener.h | 26 ++- .../window_stage_napi/js_window_stage.cpp | 160 +++++++------- .../window_stage_napi/js_window_stage.h | 22 +- wm/include/window_impl.h | 4 +- wm/src/window_impl.cpp | 28 +-- 12 files changed, 322 insertions(+), 257 deletions(-) diff --git a/interfaces/innerkits/wm/window.h b/interfaces/innerkits/wm/window.h index b6315719..0139dcd4 100644 --- a/interfaces/innerkits/wm/window.h +++ b/interfaces/innerkits/wm/window.h @@ -121,7 +121,7 @@ public: virtual void UnregisterLifeCycleListener(sptr& listener) = 0; virtual void UnregisterWindowChangeListener(sptr& listener) = 0; virtual void RegisterAvoidAreaChangeListener(sptr& listener) = 0; - virtual void UnregisterAvoidAreaChangeListener() = 0; + virtual void UnregisterAvoidAreaChangeListener(sptr& listener) = 0; virtual void RegisterDragListener(sptr& listener) = 0; virtual void UnregisterDragListener(sptr& listener) = 0; virtual void RegisterDisplayMoveListener(sptr& listener) = 0; diff --git a/interfaces/innerkits/wm/window_life_cycle_interface.h b/interfaces/innerkits/wm/window_life_cycle_interface.h index fdd3e8be..9f6ffd8e 100644 --- a/interfaces/innerkits/wm/window_life_cycle_interface.h +++ b/interfaces/innerkits/wm/window_life_cycle_interface.h @@ -20,7 +20,7 @@ namespace OHOS { namespace Rosen { -class IWindowLifeCycle : public RefBase { +class IWindowLifeCycle : virtual public RefBase { public: virtual void AfterForeground() = 0; virtual void AfterBackground() = 0; diff --git a/interfaces/kits/napi/window_runtime/window_manager_napi/js_window_manager.cpp b/interfaces/kits/napi/window_runtime/window_manager_napi/js_window_manager.cpp index 218b6b2b..5fb8063b 100644 --- a/interfaces/kits/napi/window_runtime/window_manager_napi/js_window_manager.cpp +++ b/interfaces/kits/napi/window_runtime/window_manager_napi/js_window_manager.cpp @@ -118,7 +118,6 @@ static void GetNativeContext(NativeValue* nativeContext, void*& contextPtr, WMEr } contextPtr = objContext->GetNativePointer(); } - return; } static bool GetWindowTypeAndParentName(NativeEngine& engine, std::string& parentName, WindowType& winType, @@ -204,7 +203,6 @@ static void CreateSystemWindowTask(void* contextPtr, std::string windowName, Win task.Reject(engine, CreateJsError(engine, static_cast(WMError::WM_ERROR_NULLPTR), "JsWindowManager::OnCreateWindow failed.")); } - return; } static void CreateSubWindowTask(std::string parentWinName, std::string windowName, WindowType winType, @@ -229,7 +227,6 @@ static void CreateSubWindowTask(std::string parentWinName, std::string windowNam task.Reject(engine, CreateJsError(engine, static_cast(WMError::WM_ERROR_NULLPTR), "JsWindowManager::OnCreateWindow failed.")); } - return; } NativeValue* JsWindowManager::OnCreateWindow(NativeEngine& engine, NativeCallbackInfo& info) @@ -378,10 +375,9 @@ void JsWindowManager::RegisterWmListenerWithType(NativeEngine& engine, std::stri WLOGFE("JsWindowManager::RegisterWmListenerWithType callback already registered!"); return; } - std::unique_ptr callbackRef; + std::shared_ptr callbackRef; callbackRef.reset(engine.CreateReference(value, 1)); - - sptr windowManagerListener = new(std::nothrow) JsWindowListener(&engine); + sptr windowManagerListener = new(std::nothrow) JsWindowListener(&engine, callbackRef); if (windowManagerListener == nullptr) { WLOGFE("JsWindowManager::RegisterWmListenerWithType windowManagerListener malloc failed"); return; @@ -395,9 +391,7 @@ void JsWindowManager::RegisterWmListenerWithType(NativeEngine& engine, std::stri type.c_str()); return; } - windowManagerListener->AddCallback(value); - jsCbMap_[type][std::move(callbackRef)] = windowManagerListener; - return; + jsCbMap_[type][callbackRef] = windowManagerListener; } void JsWindowManager::UnregisterAllWmListenerWithType(std::string type) @@ -408,16 +402,16 @@ void JsWindowManager::UnregisterAllWmListenerWithType(std::string type) return; } for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) { - it->second->RemoveAllCallback(); if (type.compare(SYSTEM_BAR_TINT_CHANGE_CB) == 0) { + // it->second.jsCallBack_ = nullptr sptr thisListener(it->second); SingletonContainer::Get().UnregisterSystemBarChangedListener(thisListener); WLOGFI("JsWindowManager::UnregisterAllWmListenerWithType systemBarTintChange success"); } jsCbMap_[type].erase(it++); } + WLOGFI("JsWindow::UnregisterWindowListenerWithType callback map size: %{public}u success", jsCbMap_[type].size()); jsCbMap_.erase(type); - return; } void JsWindowManager::UnregisterWmListenerWithType(std::string type, NativeValue* value) @@ -427,11 +421,8 @@ void JsWindowManager::UnregisterWmListenerWithType(std::string type, NativeValue type.c_str()); return; } - bool findFlag = false; - for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) { + for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();it++) { if (value->StrictEquals(it->first->Get())) { - findFlag = true; - it->second->RemoveCallback(value); if (type.compare(SYSTEM_BAR_TINT_CHANGE_CB) == 0) { sptr thisListener(it->second); SingletonContainer::Get().UnregisterSystemBarChangedListener(thisListener); @@ -439,25 +430,19 @@ void JsWindowManager::UnregisterWmListenerWithType(std::string type, NativeValue } jsCbMap_[type].erase(it++); break; - } else { - it++; } } - if (!findFlag) { - WLOGFE("JsWindowManager::UnregisterWmListenerWithType can't find callback!"); - return; - } + WLOGFI("JsWindow::UnregisterWindowListenerWithType callback map size: %{public}u success", jsCbMap_[type].size()); // one type with multi jscallback, erase type when there is no callback in one type if (jsCbMap_[type].empty()) { jsCbMap_.erase(type); } - return; } NativeValue* JsWindowManager::OnRegisterWindowMangerCallback(NativeEngine& engine, NativeCallbackInfo& info) { WLOGFI("JsWindowManager::OnRegisterWindowMangerCallback is called"); - if (info.argc != ARGC_TWO) { + if (info.argc != 2) { // 2 is num of argc WLOGFE("Params not match"); return engine.CreateUndefined(); } diff --git a/interfaces/kits/napi/window_runtime/window_manager_napi/js_window_manager.h b/interfaces/kits/napi/window_runtime/window_manager_napi/js_window_manager.h index f7468aeb..53d407f3 100644 --- a/interfaces/kits/napi/window_runtime/window_manager_napi/js_window_manager.h +++ b/interfaces/kits/napi/window_runtime/window_manager_napi/js_window_manager.h @@ -52,7 +52,7 @@ private: NativeValue* OnGetTopWindow(NativeEngine& engine, NativeCallbackInfo& info); NativeValue* OnSetWindowLayoutMode(NativeEngine& engine, NativeCallbackInfo& info); std::weak_ptr context_; - std::map, sptr>> jsCbMap_; + std::map, sptr>> jsCbMap_; std::mutex mtx_; }; } // namespace Rosen diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp b/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp index e0d46235..4e85f055 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp @@ -28,6 +28,14 @@ namespace { static std::map> g_jsWindowMap; std::recursive_mutex g_mutex; +// std::map, sptr)>> JsWindow::g_registerMap = +// { +// {WINDOW_SIZE_CHANGE_CB, add}, +// {SYSTEM_BAR_TINT_CHANGE_CB, std::minus()},//标准库的函数,参数为两个整数,可以参考前一篇博客 +// {SYSTEM_AVOID_AREA_CHANGE_CB, divide()},//类成员函数 +// {LIFECYCLE_EVENT_CB, [](sptr listener, sptr window){sptr thisListener(listener); + // window->UnregisterAvoidAreaChangeListener(thisListener);}},//lambda表达式 +// }; JsWindow::JsWindow(const sptr& window) : windowToken_(window) { } @@ -162,7 +170,7 @@ NativeValue* JsWindow::SetSystemBarEnable(NativeEngine* engine, NativeCallbackIn NativeValue* JsWindow::SetSystemBarProperties(NativeEngine* engine, NativeCallbackInfo* info) { - WLOGFI("JsWindow::SetBarProperties is called"); + WLOGFI("JsWindow::SetSystemBarProperties is called"); JsWindow* me = CheckParamsAndGetThis(engine, info); return (me != nullptr) ? me->OnSetSystemBarProperties(*engine, *info) : nullptr; } @@ -514,13 +522,13 @@ NativeValue* JsWindow::OnGetProperties(NativeEngine& engine, NativeCallbackInfo& bool JsWindow::IsCallbackRegistered(std::string type, NativeValue* jsListenerObject) { - if (jsCallbackMap_.empty() || jsCallbackMap_.find(type) == jsCallbackMap_.end()) { + if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { WLOGFI("JsWindow::IsCallbackRegistered methodName %{public}s not registertd!", type.c_str()); return false; } - for (auto iter = jsCallbackMap_[type].begin(); iter != jsCallbackMap_[type].end(); iter++) { - if (jsListenerObject->StrictEquals((*iter)->Get())) { + for (auto iter = jsCbMap_[type].begin(); iter != jsCbMap_[type].end(); iter++) { + if (jsListenerObject->StrictEquals(iter->first->Get())) { WLOGFE("JsWindow::IsCallbackRegistered callback already registered!"); return true; } @@ -528,95 +536,142 @@ bool JsWindow::IsCallbackRegistered(std::string type, NativeValue* jsListenerObj return false; } +// void JsWindow::ListenerProcess(std::string type, sptr listener, bool isRegister) +// { +// switch (type) +// { +// case WINDOW_SIZE_CHANGE_CB: { +// sptr thisListener(listener); +// if (isRegister) { +// windowToken_->RegisterWindowChangeListener(thisListener); +// } else { +// windowToken_->UnregisterWindowChangeListener(thisListener); +// } +// break; +// } +// case SYSTEM_AVOID_AREA_CHANGE_CB: { +// sptr thisListener(listener); +// if (isRegister) { +// windowToken_->RegisterAvoidAreaChangeListener(thisListener); +// } else { +// windowToken_->UnregisterAvoidAreaChangeListener(thisListener); +// } +// break; +// } +// case LIFECYCLE_EVENT_CB: { +// sptr thisListener(listener); +// if (isRegister) { +// windowToken_->RegisterAvoidAreaChangeListener(thisListener); +// } else { +// windowToken_->RegisterLifeCycleListener(thisListener); +// } +// break; +// } +// default: { +// WLOGFE("JsWindow::RegisterWindowListenerWithType failed method: %{public}s not support!", +// type.c_str()); +// break; +// } +// } +// } + void JsWindow::RegisterWindowListenerWithType(NativeEngine& engine, std::string type, NativeValue* value) { if (IsCallbackRegistered(type, value)) { WLOGFE("JsWindow::RegisterWindowListenerWithType callback already registered!"); return; } - std::unique_ptr callbackRef; + + std::shared_ptr callbackRef; callbackRef.reset(engine.CreateReference(value, 1)); - if (jsListenerMap_.find(type) == jsListenerMap_.end()) { - sptr windowListener = new(std::nothrow) JsWindowListener(&engine); - if (windowListener == nullptr) { - WLOGFE("JsWindow::RegisterWindowListenerWithType windowListener malloc failed"); - return; - } - if (type.compare(WINDOW_SIZE_CHANGE_CB) == 0) { - sptr thisListener(windowListener); - windowToken_->RegisterWindowChangeListener(thisListener); - WLOGFI("JsWindow::RegisterWindowListenerWithType windowSizeChange success"); - } else if (type.compare(SYSTEM_AVOID_AREA_CHANGE_CB) == 0) { - sptr thisListener(windowListener); - windowToken_->RegisterAvoidAreaChangeListener(thisListener); - WLOGFI("JsWindow::RegisterWindowListenerWithType systemAvoidAreaChange success"); - } else { - WLOGFE("JsWindow::RegisterWindowListenerWithType failed method: %{public}s not support!", - type.c_str()); - return; - } - windowListener->AddCallback(value); - jsListenerMap_[type] = windowListener; - } else { - jsListenerMap_[type]->AddCallback(value); + sptr windowListener = new(std::nothrow) JsWindowListener(&engine, callbackRef); + if (windowListener == nullptr) { + WLOGFE("JsWindow::RegisterWindowListenerWithType windowListener malloc failed"); + return; } - jsCallbackMap_[type].push_back(std::move(callbackRef)); - return; + if (type.compare(WINDOW_SIZE_CHANGE_CB) == 0) { + sptr thisListener(windowListener); + windowToken_->RegisterWindowChangeListener(thisListener); + } else if (type.compare(SYSTEM_AVOID_AREA_CHANGE_CB) == 0) { + sptr thisListener(windowListener); + windowToken_->RegisterAvoidAreaChangeListener(thisListener); + } else if (type.compare(LIFECYCLE_EVENT_CB) == 0) { + sptr thisListener(windowListener); + windowToken_->RegisterLifeCycleListener(thisListener); + } else { + WLOGFE("JsWindow::RegisterWindowListenerWithType failed method: %{public}s not support!", + type.c_str()); + return; + } + jsCbMap_[type][callbackRef] = windowListener; + WLOGFI("JsWindow::RegisterWindowListenerWithType %{public}s success! callback map size: %{public}u ", + type.c_str(), jsCbMap_[type].size()); } void JsWindow::UnregisterAllWindowListenerWithType(std::string type) { - if (jsListenerMap_.empty() || jsListenerMap_.find(type) == jsListenerMap_.end()) { + if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { WLOGFI("JsWindow::UnregisterAllWindowListenerWithType methodName %{public}s not registerted!", type.c_str()); return; } - jsListenerMap_[type]->RemoveAllCallback(); - if (type.compare(WINDOW_SIZE_CHANGE_CB) == 0) { - sptr thisListener(jsListenerMap_[type]); - windowToken_->UnregisterWindowChangeListener(thisListener); - WLOGFI("JsWindow::UnregisterAllWindowListenerWithType windowSizeChange success"); + for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) { + if (type.compare(WINDOW_SIZE_CHANGE_CB) == 0) { + sptr thisListener(it->second); + windowToken_->UnregisterWindowChangeListener(thisListener); + } else if (type.compare(SYSTEM_AVOID_AREA_CHANGE_CB) == 0) { + sptr thisListener(it->second); + windowToken_->UnregisterAvoidAreaChangeListener(thisListener); + } else if (type.compare(LIFECYCLE_EVENT_CB) == 0) { + sptr thisListener(it->second); + windowToken_->UnregisterLifeCycleListener(thisListener); + } else { + WLOGFE("JsWindow::UnregisterWindowListenerWithType failed method: %{public}s not support!", + type.c_str()); + return; + } + jsCbMap_[type].erase(it++); } - if (type.compare(SYSTEM_AVOID_AREA_CHANGE_CB) == 0) { - windowToken_->UnregisterAvoidAreaChangeListener(); - WLOGFI("JsWindow::UnregisterAllWindowListenerWithType systemAvoidAreaChange success"); - } - jsListenerMap_.erase(type); - jsCallbackMap_.erase(type); - return; + WLOGFI("JsWindow::UnregisterWindowListenerWithType %{public}s success! callback map size: %{public}u", + type.c_str(), jsCbMap_[type].size()); + + jsCbMap_.erase(type); } void JsWindow::UnregisterWindowListenerWithType(std::string type, NativeValue* value) { - if (jsListenerMap_.empty() || jsListenerMap_.find(type) == jsListenerMap_.end()) { + if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { WLOGFI("JsWindow::UnregisterWindowListenerWithType methodName %{public}s not registerted!", type.c_str()); return; } - for (auto it = jsCallbackMap_[type].begin(); it != jsCallbackMap_[type].end();) { - if (value->StrictEquals((*it)->Get())) { - jsListenerMap_[type]->RemoveCallback(value); - jsCallbackMap_[type].erase(it++); + for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();it++) { + if (value->StrictEquals(it->first->Get())) { + if (type.compare(WINDOW_SIZE_CHANGE_CB) == 0) { + sptr thisListener(it->second); + windowToken_->UnregisterWindowChangeListener (thisListener); + WLOGFI("JsWindow::UnregisterWindowListenerWithType windowSizeChange success"); + } else if (type.compare(SYSTEM_AVOID_AREA_CHANGE_CB) == 0) { + sptr thisListener(it->second); + windowToken_->UnregisterAvoidAreaChangeListener(thisListener); + WLOGFI("JsWindow::UnregisterWindowListenerWithType systemAvoidAreaChange success"); + } else if (type.compare(LIFECYCLE_EVENT_CB) == 0) { + sptr thisListener(it->second); + windowToken_->UnregisterLifeCycleListener(thisListener); + } else { + WLOGFE("JsWindow::UnregisterWindowListenerWithType failed method: %{public}s not support!", + type.c_str()); + return; + } + jsCbMap_[type].erase(it++); break; - } else { - it++; } } // one type with multi jscallback, erase type when there is no callback in one type - if (jsCallbackMap_[type].empty()) { - if (type.compare(WINDOW_SIZE_CHANGE_CB) == 0) { - sptr thisListener(jsListenerMap_[type]); - windowToken_->UnregisterWindowChangeListener (thisListener); - WLOGFI("JsWindow::UnregisterWindowListenerWithType windowSizeChange success"); - } - if (type.compare(SYSTEM_AVOID_AREA_CHANGE_CB) == 0) { - windowToken_->UnregisterAvoidAreaChangeListener(); - WLOGFI("JsWindow::UnregisterWindowListenerWithType systemAvoidAreaChange success"); - } - jsCallbackMap_.erase(type); - jsListenerMap_.erase(type); + WLOGFI("JsWindow::UnregisterWindowListenerWithType callback map size: %{public}u success", jsCbMap_[type].size()); + if (jsCbMap_[type].empty()) { + jsCbMap_.erase(type); } - return; } NativeValue* JsWindow::OnRegisterWindowCallback(NativeEngine& engine, NativeCallbackInfo& info) @@ -649,12 +704,8 @@ NativeValue* JsWindow::OnRegisterWindowCallback(NativeEngine& engine, NativeCall NativeValue* JsWindow::OnUnregisterWindowCallback(NativeEngine& engine, NativeCallbackInfo& info) { WLOGFI("JsWindow::OnUnregisterWindowCallback is called"); - if (windowToken_ == nullptr) { - WLOGFE("JsWindow windowToken_ is nullptr"); - return engine.CreateUndefined(); - } - if (info.argc == 0) { - WLOGFE("Params not match"); + if (windowToken_ == nullptr || info.argc < 1 || info.argc > 2) { + WLOGFE("JsWindow windowToken_ is nullptr or params not match"); return engine.CreateUndefined(); } std::string cbType; @@ -900,9 +951,9 @@ NativeValue* JsWindow::OnSetSystemBarProperties(NativeEngine& engine, NativeCall NativeValue* JsWindow::OnGetAvoidArea(NativeEngine& engine, NativeCallbackInfo& info) { - WLOGFI("JsWindow::OnGetAvoidArea is called"); + WLOGFI("JsWindow::OnGetAvoidArea is called info.argc: %{public}d", info.argc); WMError errCode = WMError::WM_OK; - if (windowToken_ == nullptr || info.argc < ARGC_ONE) { + if (windowToken_ == nullptr || info.argc < 1 || info.argc > 2) { // 2 is max num of argv WLOGFE("JsWindow windowToken_ is nullptr or param is too small!"); errCode = WMError::WM_ERROR_INVALID_PARAM; } @@ -1117,4 +1168,4 @@ NativeValue* CreateJsWindowObject(NativeEngine& engine, sptr& window) return objValue; } } // namespace Rosen -} // namespace OHOS +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window.h b/interfaces/kits/napi/window_runtime/window_napi/js_window.h index c7dcd96a..7568839a 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window.h +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window.h @@ -85,8 +85,7 @@ private: NativeValue* OnGetColorSpace(NativeEngine& engine, NativeCallbackInfo& info); sptr windowToken_ = nullptr; - std::map>> jsCallbackMap_; - std::map> jsListenerMap_; + std::map, sptr>> jsCbMap_; std::mutex mtx_; }; } // namespace Rosen diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.cpp b/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.cpp index 5becc3e2..956bc7fb 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.cpp +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.cpp @@ -25,53 +25,19 @@ namespace { constexpr uint32_t AVOID_AREA_NUM = 4; -void JsWindowListener::AddCallback(NativeValue* jsListenerObject) -{ - WLOGFI("JsWindowListener::AddCallback is called"); - std::lock_guard lock(mtx_); - std::unique_ptr callbackRef; - callbackRef.reset(engine_->CreateReference(jsListenerObject, 1)); - jsCallBack_.push_back(std::move(callbackRef)); - WLOGFI("JsWindowListener::AddCallback success jsCallBack_ size: %{public}d!", - static_cast(jsCallBack_.size())); - return; -} - -void JsWindowListener::RemoveAllCallback() -{ - std::lock_guard lock(mtx_); - jsCallBack_.clear(); -} - -void JsWindowListener::RemoveCallback(NativeValue* jsListenerObject) -{ - std::lock_guard lock(mtx_); - for (auto iter = jsCallBack_.begin(); iter != jsCallBack_.end(); ++iter) { - if (jsListenerObject->StrictEquals((*iter)->Get())) { - iter = jsCallBack_.erase(iter); - break; - } - } - WLOGFI("JsWindowListener::RemoveCallback success jsCallBack_ size: %{public}d!", - static_cast(jsCallBack_.size())); - return; -} - void JsWindowListener::CallJsMethod(const char* methodName, NativeValue* const* argv, size_t argc) { WLOGFI("CallJsMethod methodName = %{public}s", methodName); - if (engine_ == nullptr || jsCallBack_.empty()) { - WLOGFE("engine_ nullptr or jsCallBack_ is empty"); + if (engine_ == nullptr || jsCallBack_ == nullptr) { + WLOGFE("engine_ nullptr or jsCallBack_ is nullptr"); return; } - for (auto &item : jsCallBack_) { - NativeValue* method = item->Get(); - if (method == nullptr) { - WLOGFE("Failed to get method callback from object"); - continue; - } - engine_->CallFunction(engine_->CreateUndefined(), method, argv, argc); + NativeValue* method = jsCallBack_->Get(); + if (method == nullptr) { + WLOGFE("Failed to get method callback from object"); + return; } + engine_->CallFunction(engine_->CreateUndefined(), method, argv, argc); } void JsWindowListener::OnSizeChange(Rect rect, WindowSizeChangeReason reason) @@ -159,5 +125,61 @@ void JsWindowListener::OnAvoidAreaChanged(const std::vector avoidAreas) std::unique_ptr execute = nullptr; AsyncTask::Schedule(*engine_, std::make_unique(callback, std::move(execute), std::move(complete))); } + +void JsWindowListener::AfterForeground() +{ + WLOGFI("JsWindowListener::AfterForeground is called"); + std::unique_ptr complete = std::make_unique( + [=] (NativeEngine &engine, AsyncTask &task, int32_t status) { + NativeValue* argv[] = {CreateJsValue(*engine_, static_cast(LifeCycleEventType::FOREGROUND))}; + CallJsMethod(LIFECYCLE_EVENT_CB.c_str(), argv, ArraySize(argv)); + } + ); + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule(*engine_, std::make_unique(callback, std::move(execute), std::move(complete))); +} + +void JsWindowListener::AfterBackground() +{ + WLOGFI("JsWindowListener::AfterBackground is called"); + std::unique_ptr complete = std::make_unique( + [=] (NativeEngine &engine, AsyncTask &task, int32_t status) { + NativeValue* argv[] = {CreateJsValue(*engine_, static_cast(LifeCycleEventType::BACKGROUND))}; + CallJsMethod(LIFECYCLE_EVENT_CB.c_str(), argv, ArraySize(argv)); + } + ); + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule(*engine_, std::make_unique(callback, std::move(execute), std::move(complete))); +} + +void JsWindowListener::AfterFocused() +{ + WLOGFI("JsWindowListener::AfterFocused is called"); + std::unique_ptr complete = std::make_unique( + [=] (NativeEngine &engine, AsyncTask &task, int32_t status) { + NativeValue* argv[] = {CreateJsValue(*engine_, static_cast(LifeCycleEventType::ACTIVE))}; + CallJsMethod(LIFECYCLE_EVENT_CB.c_str(), argv, ArraySize(argv)); + } + ); + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule(*engine_, std::make_unique(callback, std::move(execute), std::move(complete))); +} + +void JsWindowListener::AfterUnfocused() +{ + WLOGFI("JsWindowListener::AfterUnfocused is called"); + std::unique_ptr complete = std::make_unique( + [=] (NativeEngine &engine, AsyncTask &task, int32_t status) { + NativeValue* argv[] = {CreateJsValue(*engine_, static_cast(LifeCycleEventType::INACTIVE))}; + CallJsMethod(LIFECYCLE_EVENT_CB.c_str(), argv, ArraySize(argv)); + } + ); + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule(*engine_, std::make_unique(callback, std::move(execute), std::move(complete))); +} } // namespace Rosen } // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.h b/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.h index a087a8db..281cca98 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.h +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.h @@ -18,7 +18,6 @@ #include #include -#include #include "native_engine/native_engine.h" #include "native_engine/native_value.h" #include "refbase.h" @@ -31,26 +30,33 @@ namespace Rosen { const std::string WINDOW_SIZE_CHANGE_CB = "windowSizeChange"; const std::string SYSTEM_BAR_TINT_CHANGE_CB = "systemBarTintChange"; const std::string SYSTEM_AVOID_AREA_CHANGE_CB = "systemAvoidAreaChange"; - +const std::string LIFECYCLE_EVENT_CB = "lifeCycleEvent"; class JsWindowListener : public IWindowChangeListener, public ISystemBarChangedListener, - public IAvoidAreaChangedListener { + public IAvoidAreaChangedListener, + public IWindowLifeCycle { public: - explicit JsWindowListener(NativeEngine* engine) : engine_(engine) {} + JsWindowListener(NativeEngine* engine, std::shared_ptr callback) + : engine_(engine), jsCallBack_(callback) {} virtual ~JsWindowListener() = default; - void AddCallback(NativeValue* jsListenerObject); - void RemoveAllCallback(); - void RemoveCallback(NativeValue* jsListenerObject); void OnSystemBarPropertyChange(DisplayId displayId, const SystemBarRegionTints& tints) override; void OnSizeChange(Rect rect, WindowSizeChangeReason reason) override; void OnModeChange(WindowMode mode) override; void OnAvoidAreaChanged(std::vector avoidAreas) override; - + void AfterForeground() override; + void AfterBackground() override; + void AfterFocused() override; + void AfterUnfocused() override; private: + enum class LifeCycleEventType : uint32_t { + FOREGROUND = 1, + ACTIVE, + INACTIVE, + BACKGROUND, + }; void CallJsMethod(const char* methodName, NativeValue* const* argv = nullptr, size_t argc = 0); NativeEngine* engine_ = nullptr; - std::mutex mtx_; - std::vector> jsCallBack_; + std::shared_ptr jsCallBack_ = nullptr; }; } // namespace Rosen } // namespace OHOS diff --git a/interfaces/kits/napi/window_runtime/window_stage_napi/js_window_stage.cpp b/interfaces/kits/napi/window_runtime/window_stage_napi/js_window_stage.cpp index 3e7f2c5d..1592e8e9 100644 --- a/interfaces/kits/napi/window_runtime/window_stage_napi/js_window_stage.cpp +++ b/interfaces/kits/napi/window_runtime/window_stage_napi/js_window_stage.cpp @@ -17,6 +17,7 @@ #include #include "js_runtime_utils.h" #include "js_window.h" +#include "js_window_listener.h" #include "js_window_utils.h" #include "window_manager_hilog.h" namespace OHOS { @@ -27,6 +28,7 @@ const int CONTENT_STORAGE_ARG = 2; constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "JsWindowStage"}; } // namespace +static std::map, sptr> g_jsCbMap; void JsWindowStage::Finalizer(NativeEngine* engine, void* data, void* hint) { WLOGFI("JsWindowStage::Finalizer is called"); @@ -89,47 +91,6 @@ NativeValue* JsWindowStage::GetSubWindow(NativeEngine* engine, NativeCallbackInf return (me != nullptr) ? me->OnGetSubWindow(*engine, *info) : nullptr; } -void JsWindowStage::AfterForeground() -{ - LifeCycleCallBack(WindowStageEventType::FOREGROUND); -} - -void JsWindowStage::AfterBackground() -{ - LifeCycleCallBack(WindowStageEventType::BACKGROUND); -} - -void JsWindowStage::AfterFocused() -{ - LifeCycleCallBack(WindowStageEventType::ACTIVE); -} - -void JsWindowStage::AfterUnfocused() -{ - LifeCycleCallBack(WindowStageEventType::INACTIVE); -} - -void JsWindowStage::LifeCycleCallBack(WindowStageEventType type) -{ - WLOGFI("JsWindowStage::LifeCycleCallBack is called, type: %{public}d", type); - std::unique_ptr complete = std::make_unique( - [=] (NativeEngine &engine, AsyncTask &task, int32_t status) { - NativeValue* argv[] = {CreateJsValue(*engine_, static_cast(type))}; - for (auto &iter : eventCallbackMap_) { - NativeValue* method = (iter.first)->Get(); - if (method == nullptr) { - WLOGFE("callback is null"); - return; - } - engine_->CallFunction(engine_->CreateUndefined(), method, argv, ArraySize(argv)); - } - } - ); - NativeReference* callback = nullptr; - std::unique_ptr execute = nullptr; - AsyncTask::Schedule(*engine_, std::make_unique(callback, std::move(execute), std::move(complete))); -} - NativeValue* JsWindowStage::OnSetUIContent(NativeEngine& engine, NativeCallbackInfo& info) { WLOGFI("JsWindowStage::OnSetUIContent is called"); @@ -194,19 +155,29 @@ NativeValue* JsWindowStage::OnGetMainWindow(NativeEngine& engine, NativeCallback return result; } +bool JsWindowStage::IsCallbackRegistered(std::string type, NativeValue* jsListenerObject) +{ + if (g_jsCbMap.empty()) { + WLOGFI("JsWindowStage::JsWindowStage methodName %{public}s not registerted!", type.c_str()); + return false; + } + + for (auto iter = g_jsCbMap.begin(); iter != g_jsCbMap.end(); iter++) { + if (jsListenerObject->StrictEquals(iter->first->Get())) { + WLOGFE("JsWindowStage::IsCallbackRegistered callback already registered!"); + return true; + } + } + return false; +} + NativeValue* JsWindowStage::OnEvent(NativeEngine& engine, NativeCallbackInfo& info) { WLOGFI("JsWindowStage::OnEvent is called"); - if (windowScene_ == nullptr) { - WLOGFE("JsWindowStage::OnEvent windowScene_ is nullptr"); + if (windowScene_ == nullptr || info.argc < 2) { // 2: minimum param nums + WLOGFE("JsWindowStage::OnEvent windowScene_ is nullptr or params not match"); return engine.CreateUndefined(); } - - if (info.argc < 2) { // 2: minimum param nums - WLOGFE("JsWindowStage::OnEvent wrong input params"); - return engine.CreateUndefined(); - } - // Parse info->argv[0] as string std::string eventString; if (!ConvertFromJsValue(engine, info.argv[0], eventString)) { @@ -218,33 +189,78 @@ NativeValue* JsWindowStage::OnEvent(NativeEngine& engine, NativeCallbackInfo& in eventString.c_str()); return engine.CreateUndefined(); } - NativeValue* value = info.argv[1]; if (!value->IsCallable()) { WLOGFE("JsWindowStage::OnEvent info->argv[1] is not callable"); return engine.CreateUndefined(); } - + std::lock_guard lock(mtx_); + if (IsCallbackRegistered(eventString, value)) { + WLOGFE("JsWindowStage::OnEvent callback already registered!"); + return engine.CreateUndefined(); + } std::shared_ptr reference = nullptr; reference.reset(engine.CreateReference(value, 1)); - eventCallbackMap_[reference] = 1; - engine_ = &engine; - WLOGFI("JsWindowStage::OnEvent eventCallbackMap_ size: %{public}d", - static_cast(eventCallbackMap_.size())); - if (!regLifeCycleListenerFlag_) { - auto window = windowScene_->GetMainWindow(); - if (window != nullptr) { - sptr listener = this; - window->RegisterLifeCycleListener(listener); - regLifeCycleListenerFlag_ = true; - WLOGFI("JsWindowStage::OnEvent regist lifecycle success"); - } - } else { - WLOGFI("JsWindowStage::OnEvent already regist lifecycle"); + sptr windowListener = new(std::nothrow) JsWindowListener(&engine, reference); + if (windowListener == nullptr) { + WLOGFE("JsWindowStage::OnEvent windowListener malloc failed"); + return engine.CreateUndefined(); } + auto window = windowScene_->GetMainWindow(); + if (window != nullptr) { + sptr thisListener(windowListener); + window->RegisterLifeCycleListener(thisListener); + } + g_jsCbMap[reference] = windowListener; + WLOGFI("JsWindowStage::OnEvent callback map size: %{public}u success", g_jsCbMap.size()); return engine.CreateUndefined(); } +void JsWindowStage::UnregisterAllWindowListenerWithType(std::string type) +{ + if (g_jsCbMap.empty()) { + WLOGFE("JsWindowStage::UnregisterAllWindowListenerWithType methodName %{public}s not registerted!", + type.c_str()); + return; + } + auto window = windowScene_->GetMainWindow(); + if (window == nullptr) { + WLOGFE("JsWindowStage::UnregisterAllWindowListenerWithType mainWindow is null!"); + return; + } + for (auto it = g_jsCbMap.begin(); it != g_jsCbMap.end();) { + sptr thisListener(it->second); + window->UnregisterLifeCycleListener(thisListener); + g_jsCbMap.erase(it++); + } + WLOGFI("JsWindowStage::UnregisterWindowListenerWithType callback map size: %{public}u success", + g_jsCbMap.size()); +} + +void JsWindowStage::UnregisterWindowListenerWithType(std::string type, NativeValue* value) +{ + if (g_jsCbMap.empty()) { + WLOGFE("JsWindowStage::UnregisterWindowListenerWithType methodName %{public}s not registerted!", + type.c_str()); + return; + } + + for (auto it = g_jsCbMap.begin(); it != g_jsCbMap.end();it++) { + if (value->StrictEquals(it->first->Get())) { + auto window = windowScene_->GetMainWindow(); + if (window != nullptr) { + sptr thisListener(it->second); + window->UnregisterLifeCycleListener(thisListener); + } + g_jsCbMap.erase(it++); + break; + } + } + // one type with multi jscallback, erase type when there is no callback in one type + WLOGFI("JsWindowStage::UnregisterWindowListenerWithType callback map size: %{public}u success", + g_jsCbMap.size()); +} + NativeValue* JsWindowStage::OffEvent(NativeEngine& engine, NativeCallbackInfo& info) { WLOGFI("JsWindowStage::OffEvent is called"); @@ -269,19 +285,13 @@ NativeValue* JsWindowStage::OffEvent(NativeEngine& engine, NativeCallbackInfo& i } NativeValue* value = info.argv[1]; - if (value->IsCallable()) { + std::lock_guard lock(mtx_); + if (value->TypeOf() == NATIVE_FUNCTION) { WLOGFI("JsWindowStage::OffEvent info->argv[1] is callable type"); - for (auto iter = eventCallbackMap_.begin(); iter != eventCallbackMap_.end(); iter++) { - std::shared_ptr callback = iter->first; - if (value->StrictEquals(callback->Get())) { - eventCallbackMap_.erase(iter); - break; - } - } - return engine.CreateUndefined(); + UnregisterWindowListenerWithType(eventString, value); } else if (value->TypeOf() == NativeValueType::NATIVE_UNDEFINED) { WLOGFI("JsWindowStage::OffEvent info->argv[1] is native undefined type"); - eventCallbackMap_.clear(); + UnregisterAllWindowListenerWithType(eventString); } else { WLOGFE("JsWindowStage::OffEvent info->argv[1] is InValid param"); } diff --git a/interfaces/kits/napi/window_runtime/window_stage_napi/js_window_stage.h b/interfaces/kits/napi/window_runtime/window_stage_napi/js_window_stage.h index 6ba16063..e99df90f 100644 --- a/interfaces/kits/napi/window_runtime/window_stage_napi/js_window_stage.h +++ b/interfaces/kits/napi/window_runtime/window_stage_napi/js_window_stage.h @@ -24,8 +24,7 @@ namespace OHOS { namespace Rosen { NativeValue* CreateJsWindowStage(NativeEngine& engine, std::shared_ptr windowScene); - -class JsWindowStage : Rosen::IWindowLifeCycle { +class JsWindowStage { public: explicit JsWindowStage(const std::shared_ptr& windowScene) : windowScene_(windowScene) {} @@ -39,12 +38,11 @@ public: static NativeValue* GetWindowMode(NativeEngine* engine, NativeCallbackInfo* info); static NativeValue* CreateSubWindow(NativeEngine* engine, NativeCallbackInfo* info); static NativeValue* GetSubWindow(NativeEngine* engine, NativeCallbackInfo* info); - virtual void AfterForeground() override; - virtual void AfterBackground() override; - virtual void AfterFocused() override; - virtual void AfterUnfocused() override; private: + bool IsCallbackRegistered(std::string type, NativeValue* jsListenerObject); + void UnregisterAllWindowListenerWithType(std::string type); + void UnregisterWindowListenerWithType(std::string type, NativeValue* value); NativeValue* CreateJsSubWindowArrayObject(NativeEngine& engine, std::vector> subWinVec); NativeValue* OnSetUIContent(NativeEngine& engine, NativeCallbackInfo& info); NativeValue* OnGetMainWindow(NativeEngine& engine, NativeCallbackInfo& info); @@ -54,19 +52,9 @@ private: NativeValue* OnGetWindowMode(NativeEngine& engine, NativeCallbackInfo& info); NativeValue* OnCreateSubWindow(NativeEngine& engine, NativeCallbackInfo& info); NativeValue* OnGetSubWindow(NativeEngine& engine, NativeCallbackInfo& info); - enum class WindowStageEventType : uint32_t { - FOREGROUND = 1, - ACTIVE, - INACTIVE, - BACKGROUND, - }; - void LifeCycleCallBack(WindowStageEventType type); std::shared_ptr windowScene_; - NativeEngine* engine_ = nullptr; - sptr lifecycleListener_ = nullptr; - std::map, int> eventCallbackMap_; - bool regLifeCycleListenerFlag_ = false; + std::mutex mtx_; }; } // namespace Rosen } // namespace OHOS diff --git a/wm/include/window_impl.h b/wm/include/window_impl.h index 846ae2d5..090214dd 100644 --- a/wm/include/window_impl.h +++ b/wm/include/window_impl.h @@ -105,7 +105,7 @@ public: virtual void UnregisterLifeCycleListener(sptr& listener) override; virtual void UnregisterWindowChangeListener(sptr& listener) override; virtual void RegisterAvoidAreaChangeListener(sptr& listener) override; - virtual void UnregisterAvoidAreaChangeListener() override; + virtual void UnregisterAvoidAreaChangeListener(sptr& listener) override; virtual void RegisterDragListener(sptr& listener) override; virtual void UnregisterDragListener(sptr& listener) override; virtual void RegisterDisplayMoveListener(sptr& listener) override; @@ -197,7 +197,7 @@ private: WindowState state_ { WindowState::STATE_INITIAL }; std::vector> lifecycleListeners_; std::vector> windowChangeListeners_; - sptr avoidAreaChangeListener_; + std::vector> avoidAreaChangeListeners_; std::vector> windowDragListeners_; std::vector> displayMoveListeners_; std::shared_ptr surfaceNode_; diff --git a/wm/src/window_impl.cpp b/wm/src/window_impl.cpp index c1a1c417..546c9054 100644 --- a/wm/src/window_impl.cpp +++ b/wm/src/window_impl.cpp @@ -852,20 +852,21 @@ void WindowImpl::UnregisterWindowChangeListener(sptr& lis void WindowImpl::RegisterAvoidAreaChangeListener(sptr& listener) { - if (avoidAreaChangeListener_ != nullptr) { - WLOGFE("RegisterAvoidAreaChangeListener failed. AvoidAreaChangeListene is not nullptr"); + if (listener == nullptr) { + WLOGFE("RegisterAvoidAreaChangeListener failed. AvoidAreaChangeListener is nullptr"); return; } - avoidAreaChangeListener_ = listener; + std::lock_guard lock(mutex_); + avoidAreaChangeListeners_.emplace_back(listener); } -void WindowImpl::UnregisterAvoidAreaChangeListener() +void WindowImpl::UnregisterAvoidAreaChangeListener(sptr& listener) { - if (avoidAreaChangeListener_ == nullptr) { - WLOGFE("UnregisterAvoidAreaChangeListener failed. AvoidAreaChangeListene is nullptr"); - return; - } - avoidAreaChangeListener_ = nullptr; + std::lock_guard lock(mutex_); + avoidAreaChangeListeners_.erase(std::remove_if(avoidAreaChangeListeners_.begin(), avoidAreaChangeListeners_.end(), + [listener](sptr registeredListener) { + return registeredListener == listener; + }), avoidAreaChangeListeners_.end()); } void WindowImpl::RegisterDragListener(sptr& listener) @@ -920,6 +921,7 @@ void WindowImpl::UpdateRect(const struct Rect& rect, WindowSizeChangeReason reas WLOGFI("winId:%{public}u, rect[%{public}d, %{public}d, %{public}u, %{public}u], vpr:%{public}f, reason:%{public}u", GetWindowId(), rect.posX_, rect.posY_, rect.width_, rect.height_, virtualPixelRatio, reason); property_->SetWindowRect(rect); + WLOGFI("sizeChange callback size: %{public}u", windowChangeListeners_.size()); for (auto& listener : windowChangeListeners_) { if (listener != nullptr) { listener->OnSizeChange(rect, reason); @@ -1065,7 +1067,7 @@ void WindowImpl::ReadyToMoveOrDragWindow(int32_t globalX, int32_t globalY, int32 return; } float virtualPixelRatio = display->GetVirtualPixelRatio(); - + startRectExceptFrame_.posX_ = startPointRect_.posX_ + static_cast(WINDOW_FRAME_WIDTH * virtualPixelRatio); startRectExceptFrame_.posY_ = startPointRect_.posY_ + @@ -1200,8 +1202,10 @@ void WindowImpl::UpdateConfiguration(const std::shared_ptr& avoidArea) { WLOGFI("Window Update AvoidArea, id: %{public}d", property_->GetWindowId()); - if (avoidAreaChangeListener_ != nullptr) { - avoidAreaChangeListener_->OnAvoidAreaChanged(avoidArea); + for (auto& listener : avoidAreaChangeListeners_) { + if (listener != nullptr) { + listener->OnAvoidAreaChanged(avoidArea); + } } }