diff --git a/interfaces/innerkits/wm/window.h b/interfaces/innerkits/wm/window.h index 07df613dc784cd523467e37e9541a648abd319bb..04f67b06150155854fda803b1e9e6b405109585c 100644 --- a/interfaces/innerkits/wm/window.h +++ b/interfaces/innerkits/wm/window.h @@ -541,6 +541,20 @@ public: */ virtual void OnWindowWillClose(sptr window) {} }; +/** + * @class IWindowHighlightChangeListener + * + * @brief IWindowHighlightChangeListener is a listener to observe event when highlight change of window. + */ +class IWindowHighlightChangeListener : virtual public RefBase { +public: + /** + * @brief Notify caller when highlight status changes. + * + * @param isHighlight Whether the window is highlighted. + */ + virtual void OnWindowHighlightChange(bool isHighlight) {} +}; /** * @class ISwitchFreeMultiWindowListener @@ -3046,6 +3060,47 @@ public: { return WMError::WM_OK; } + + /** + * @brief Register window highlight change listener. + * + * @param listener IWindowHighlightChangeListener. + * @return WM_OK means register success, others means register failed. + */ + virtual WMError RegisterWindowHighlightChangeListeners(const sptr& listener) + { + return WMError::WM_ERROR_DEVICE_NOT_SUPPORT; + } + + /** + * @brief Unregister window highlight change listener. + * + * @param listener IWindowHighlightChangeListener. + * @return WM_OK means unregister success, others means unregister failed. + */ + virtual WMError UnregisterWindowHighlightChangeListeners(const sptr& listener) + { + return WMError::WM_ERROR_DEVICE_NOT_SUPPORT; + } + + /** + * @brief Set whether to enable exclusively highlight. + * + * @param isExclusivelyHighlighted the value true means to exclusively highlight, and false means the opposite. + * @return WM_OK means set success, others means set failed. + */ + virtual WMError SetExclusivelyHighlighted(bool isExclusivelyHighlighted) + { + return WMError::WM_ERROR_DEVICE_NOT_SUPPORT; + } + + /** + * @brief Get highlight property of window. + * + * @param highlighted True means the window is highlighted, and false means the opposite. + * @return WM_OK means get success, others means get failed. + */ + virtual WMError IsWindowHighlighted(bool& highlighted) const { return WMError::WM_ERROR_DEVICE_NOT_SUPPORT; } }; } } 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 9eee34c3d55576cc15bf392e2ccfbeeee218aaac..b3e837a0e21d746551c258f2bd23771557a70dc1 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp @@ -1088,6 +1088,20 @@ napi_value JsWindow::IsSystemAvoidAreaEnabled(napi_env env, napi_callback_info i return (me != nullptr) ? me->OnIsSystemAvoidAreaEnabled(env, info) : nullptr; } +napi_value JsWindow::SetExclusivelyHighlighted(napi_env env, napi_callback_info info) +{ + TLOGD(WmsLogTag::WMS_FOCUS, "[NAPI]"); + JsWindow* me = CheckParamsAndGetThis(env, info); + return (me != nullptr) ? me->OnSetExclusivelyHighlighted(env, info) : nullptr; +} + +napi_value JsWindow::IsWindowHighlighted(napi_env env, napi_callback_info info) +{ + TLOGD(WmsLogTag::WMS_FOCUS, "[NAPI]"); + JsWindow* me = CheckParamsAndGetThis(env, info); + return (me != nullptr) ? me->OnIsWindowHighlighted(env, info) : nullptr; +} + static WMError UpdateSystemBarProperties(const std::map& systemBarProperties, const std::map& systemBarPropertyFlags, const sptr& window) { @@ -7719,6 +7733,63 @@ napi_value JsWindow::OnIsSystemAvoidAreaEnabled(napi_env env, napi_callback_info } } +napi_value JsWindow::OnSetExclusivelyHighlighted(napi_env env, napi_callback_info info) +{ + size_t argc = FOUR_PARAMS_SIZE; + napi_value argv[FOUR_PARAMS_SIZE] = { nullptr }; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc != ARG_COUNT_ONE) { + TLOGE(WmsLogTag::WMS_FOCUS, "argc is invalid: %{public}zu", argc); + return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM); + } + bool exclusivelyHighlighted = true; + if (!ConvertFromJsValue(env, argv[INDEX_ZERO], exclusivelyHighlighted)) { + TLOGE(WmsLogTag::WMS_FOCUS, "Failed to convert parameter to exclusivelyHighlighted"); + return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM); + } + napi_value result = nullptr; + std::shared_ptr napiAsyncTask = CreateEmptyAsyncTask(env, nullptr, &result); + auto asyncTask = [weakToken = wptr(windowToken_), exclusivelyHighlighted, env, + task = napiAsyncTask, where = __func__] { + auto window = weakToken.promote(); + if (window == nullptr) { + TLOGNE(WmsLogTag::WMS_FOCUS, "%{public}s: window is nullptr", where); + task->Reject(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY)); + return; + } + WMError ret = window->SetExclusivelyHighlighted(exclusivelyHighlighted); + if (ret == WMError::WM_OK) { + task->Resolve(env, NapiGetUndefined(env)); + } else { + WmErrorCode wmErrorCode = WM_JS_TO_ERROR_CODE_MAP.at(ret); + task->Reject(env, JsErrUtils::CreateJsError(env, wmErrorCode, "Set exclusively highlighted failed")); + } + TLOGNI(WmsLogTag::WMS_FOCUS, "%{public}s: end, window: [%{public}u, %{public}s]", + where, window->GetWindowId(), window->GetWindowName().c_str()); + }; + if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_high)) { + napiAsyncTask->Reject(env, CreateJsError(env, + static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY), "send event failed")); + } + return result; +} + +napi_value JsWindow::OnIsWindowHighlighted(napi_env env, napi_callback_info info) +{ + if (windowToken_ == nullptr) { + TLOGE(WmsLogTag::WMS_FOCUS, "windowToken is nullptr"); + return NapiThrowError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY); + } + bool isHighlighted = false; + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(windowToken_->IsWindowHighlighted(isHighlighted)); + if (ret != WmErrorCode::WM_OK) { + TLOGE(WmsLogTag::WMS_FOCUS, "get window highlight failed, ret: %{public}d", ret); + return NapiThrowError(env, ret); + } + TLOGI(WmsLogTag::WMS_FOCUS, "get window highlight end, isHighlighted: %{public}u", isHighlighted); + return CreateJsValue(env, isHighlighted); +} + void BindFunctions(napi_env env, napi_value object, const char* moduleName) { BindNativeFunction(env, object, "startMoving", moduleName, JsWindow::StartMoving); @@ -7865,6 +7936,8 @@ void BindFunctions(napi_env env, napi_value object, const char* moduleName) BindNativeFunction(env, object, "getWindowDensityInfo", moduleName, JsWindow::GetWindowDensityInfo); BindNativeFunction(env, object, "setSystemAvoidAreaEnabled", moduleName, JsWindow::SetSystemAvoidAreaEnabled); BindNativeFunction(env, object, "isSystemAvoidAreaEnabled", moduleName, JsWindow::IsSystemAvoidAreaEnabled); + BindNativeFunction(env, object, "setExclusivelyHighlighted", moduleName, JsWindow::SetExclusivelyHighlighted); + BindNativeFunction(env, object, "isWindowHighlighted", moduleName, JsWindow::IsWindowHighlighted); } } // namespace Rosen } // namespace OHOS 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 5673d224a0e564bf6c9784e147bf0ca2493584b1..6419ced90f4a23f4fe61cae5c4dbe1bd7889c51d 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window.h +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window.h @@ -118,6 +118,8 @@ public: static napi_value StopMoving(napi_env env, napi_callback_info info); static napi_value GetWindowDensityInfo(napi_env env, napi_callback_info info); static napi_value EnableDrag(napi_env env, napi_callback_info info); + static napi_value SetExclusivelyHighlighted(napi_env env, napi_callback_info info); + static napi_value IsWindowHighlighted(napi_env env, napi_callback_info info); // colorspace, gamut static napi_value IsSupportWideGamut(napi_env env, napi_callback_info info); @@ -268,6 +270,8 @@ private: napi_value OnIsFocused(napi_env env, napi_callback_info info); napi_value OnRequestFocus(napi_env env, napi_callback_info info); napi_value OnGetWindowDensityInfo(napi_env env, napi_callback_info info); + napi_value OnSetExclusivelyHighlighted(napi_env env, napi_callback_info info); + napi_value OnIsWindowHighlighted(napi_env env, napi_callback_info info); // colorspace, gamut napi_value OnIsSupportWideGamut(napi_env env, napi_callback_info info); 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 2b5c6b1479dfd34bae3710657fdfcc804312ca2f..305efa6f0132a6d2992a753103a7485df559dc18 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 @@ -634,6 +634,24 @@ void JsWindowListener::OnMainWindowClose(bool& terminateCloseProcess) AppExecFwk::EventQueue::Priority::IMMEDIATE); } +void JsWindowListener::OnWindowHighlightChange(bool isHighlight) +{ + TLOGD(WmsLogTag::WMS_FOCUS, "isHighlight: %{public}d", isHighlight); + auto jsCallback = [self = weakRef_, isHighlight, env = env_, where = __func__] { + auto thisListener = self.promote(); + if (thisListener == nullptr || env == nullptr) { + TLOGNE(WmsLogTag::WMS_FOCUS, "%{public}s: this listener or env is nullptr", where); + return; + } + HandleScope handleScope(env); + napi_value argv[] = { CreateJsValue(env, isHighlight) }; + thisListener->CallJsMethod(WINDOW_HIGHLIGHT_CHANGE_CB.c_str(), argv, ArraySize(argv)); + }; + if (napi_status::napi_ok != napi_send_event(env_, jsCallback, napi_eprio_immediate)) { + TLOGE(WmsLogTag::WMS_FOCUS, "failed to send event"); + } +} + WmErrorCode JsWindowListener::CanCancelUnregister(const std::string& eventType) { if (eventType == WINDOW_WILL_CLOSE_CB) { 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 5801c0d0426e9e328b5c4fd7e1b65c9e9954adb9..4d6be4f5d93fd3d82a6c82950560c4eb55e979ab 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 @@ -53,6 +53,7 @@ const std::string WINDOW_NO_INTERACTION_DETECT_CB = "noInteractionDetected"; const std::string WINDOW_RECT_CHANGE_CB = "windowRectChange"; const std::string SUB_WINDOW_CLOSE_CB = "subWindowClose"; const std::string WINDOW_STAGE_CLOSE_CB = "windowStageClose"; +const std::string WINDOW_HIGHLIGHT_CHANGE_CB = "windowHighlightChange"; const std::string WINDOW_WILL_CLOSE_CB = "windowWillClose"; class JsWindowListener : public IWindowChangeListener, @@ -75,7 +76,8 @@ class JsWindowListener : public IWindowChangeListener, public IWindowRectChangeListener, public IWindowWillCloseListener, public IMainWindowCloseListener, - public ISubWindowCloseListener { + public ISubWindowCloseListener, + public IWindowHighlightChangeListener { public: JsWindowListener(napi_env env, std::shared_ptr callback, CaseType caseType) : env_(env), jsCallBack_(callback), caseType_(caseType), weakRef_(wptr (this)) {} @@ -112,6 +114,7 @@ public: void SetTimeout(int64_t timeout) override; int64_t GetTimeout() const override; void OnRectChange(Rect rect, WindowSizeChangeReason reason) override; + void OnWindowHighlightChange(bool isHighlight) override; /* * Window Decor listener diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.cpp b/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.cpp index 6b87e37a785790d99de5f8e0b684b572659095a2..588d61a778dd63f06a04582c99b5a7535bbc4656 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.cpp +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.cpp @@ -51,6 +51,7 @@ const std::map WINDOW_LISTENER_MAP { {WINDOW_NO_INTERACTION_DETECT_CB, RegisterListenerType::WINDOW_NO_INTERACTION_DETECT_CB}, {WINDOW_RECT_CHANGE_CB, RegisterListenerType::WINDOW_RECT_CHANGE_CB}, {SUB_WINDOW_CLOSE_CB, RegisterListenerType::SUB_WINDOW_CLOSE_CB}, + {WINDOW_HIGHLIGHT_CHANGE_CB, RegisterListenerType::WINDOW_HIGHLIGHT_CHANGE_CB}, {WINDOW_WILL_CLOSE_CB, RegisterListenerType::WINDOW_WILL_CLOSE_CB}, }; const std::map WINDOW_STAGE_LISTENER_MAP { @@ -482,6 +483,8 @@ WmErrorCode JsWindowRegisterManager::ProcessListener(RegisterListenerType regist return ProcessWindowRectChangeRegister(windowManagerListener, window, isRegister, env, parameter); case static_cast(RegisterListenerType::SUB_WINDOW_CLOSE_CB): return ProcessSubWindowCloseRegister(windowManagerListener, window, isRegister, env, parameter); + case static_cast(RegisterListenerType::WINDOW_HIGHLIGHT_CHANGE_CB): + return ProcessWindowHighlightChangeRegister(windowManagerListener, window, isRegister, env, parameter); case static_cast(RegisterListenerType::WINDOW_WILL_CLOSE_CB): return ProcessWindowWillCloseRegister(windowManagerListener, window, isRegister, env, parameter); default: @@ -643,5 +646,21 @@ WmErrorCode JsWindowRegisterManager::ProcessWindowWillCloseRegister(const sptrUnRegisterWindowWillCloseListeners(listener)); return ret; } + +WmErrorCode JsWindowRegisterManager::ProcessWindowHighlightChangeRegister(const sptr& listener, + const sptr& window, bool isRegister, napi_env env, napi_value parameter) +{ + if (window == nullptr) { + return WmErrorCode::WM_ERROR_STATE_ABNORMALLY; + } + sptr thisListener(listener); + WmErrorCode ret = WmErrorCode::WM_OK; + if (isRegister) { + ret = WM_JS_TO_ERROR_CODE_MAP.at(window->RegisterWindowHighlightChangeListeners(thisListener)); + } else { + ret = WM_JS_TO_ERROR_CODE_MAP.at(window->UnregisterWindowHighlightChangeListeners(thisListener)); + } + return ret; +} } // namespace Rosen } // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.h b/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.h index f7c4720b77e4a12e91f6241c81c0223e20abb5dd..ebb00ef20d92720a25badd2d28cbd7b8f0ea3284 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.h +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.h @@ -50,6 +50,7 @@ enum class RegisterListenerType : uint32_t { WINDOW_WILL_CLOSE_CB, WINDOW_STAGE_EVENT_CB, WINDOW_STAGE_CLOSE_CB, + WINDOW_HIGHLIGHT_CHANGE_CB, }; class JsWindowRegisterManager { @@ -106,6 +107,8 @@ private: bool isRegister, napi_env env, napi_value parameter = nullptr); WmErrorCode ProcessWindowWillCloseRegister(const sptr& listener, const sptr& window, bool isRegister, napi_env env, napi_value parameter = nullptr); + WmErrorCode ProcessWindowHighlightChangeRegister(const sptr& listener, const sptr& window, + bool isRegister, napi_env env, napi_value parameter = nullptr); WmErrorCode ProcessListener(RegisterListenerType registerListenerType, CaseType caseType, const sptr& windowManagerListener, const sptr& window, bool isRegister, napi_env env, napi_value parameter); diff --git a/previewer/include/window.h b/previewer/include/window.h index 0735b0fdbb4dd279ae45208e7daa177b9266cc1b..be5f5fccfdfeea32e2305eb4b6b26c0e7fe252e1 100644 --- a/previewer/include/window.h +++ b/previewer/include/window.h @@ -475,6 +475,25 @@ public: * @return True means window delay raise is enabled */ virtual bool IsWindowDelayRaiseEnabled() const { return false; } + + /** + * @brief Set whether to enable exclusively highlight. + * + * @param isExclusivelyHighlighted the value true means to exclusively highlight, and false means the opposite. + * @return WM_OK means set success, others means set failed. + */ + virtual WMError SetExclusivelyHighlighted(bool isExclusivelyHighlighted) + { + return WMError::WM_ERROR_DEVICE_NOT_SUPPORT; + } + + /** + * @brief Get highlight property of window. + * + * @param highlighted True means the window is highlighted, and false means the opposite. + * @return WM_OK means get success, others means get failed. + */ + virtual WMError IsWindowHighlighted(bool& highlighted) const { return WMError::WM_ERROR_DEVICE_NOT_SUPPORT; } }; } } diff --git a/utils/include/window_helper.h b/utils/include/window_helper.h index 73a5cc87727701ff60b977c07e4ff8f0003d2400..1d3415421b66e628283134f8b1bb2e75d9781c83 100644 --- a/utils/include/window_helper.h +++ b/utils/include/window_helper.h @@ -64,6 +64,11 @@ public: return IsSubWindow(type) && (windowFlags & static_cast(WindowFlag::WINDOW_FLAG_IS_TOAST)); } + static inline bool IsModalWindow(uint32_t windowFlags) + { + return windowFlags & static_cast(WindowFlag::WINDOW_FLAG_IS_APPLICATION_MODAL); + } + static inline bool IsDialogWindow(WindowType type) { return type == WindowType::WINDOW_TYPE_DIALOG; diff --git a/window_scene/common/include/window_session_property.h b/window_scene/common/include/window_session_property.h index e6df9ba49b9579c2afd4ef76850c14b2847f1f93..13b1b394fed6fecb7a258bb108adc509c8e7de44 100755 --- a/window_scene/common/include/window_session_property.h +++ b/window_scene/common/include/window_session_property.h @@ -117,10 +117,8 @@ public: Rect GetRequestRect() const; RectAnimationConfig GetRectAnimationConfig() const; WindowType GetWindowType() const; - bool GetFocusable() const; - bool GetFocusableOnShow() const; - bool GetTouchable() const; bool GetDragEnabled() const; + bool GetTouchable() const; bool GetHideNonSystemFloatingWindows() const; bool GetForceHide() const; bool GetRaiseEnabled() const; @@ -259,6 +257,14 @@ public: void SetKeyboardViewMode(KeyboardViewMode mode); KeyboardViewMode GetKeyboardViewMode() const; + /* + * Window focus + */ + bool GetFocusable() const; + bool GetFocusableOnShow() const; + bool GetExclusivelyHighlighted() const; + void SetExclusivelyHighlighted(bool isExclusivelyHighlighted); + private: void setTouchHotAreasInner(const std::vector& rects, std::vector& touchHotAreas); bool MarshallingTouchHotAreasInner(const std::vector& touchHotAreas, Parcel& parcel) const; @@ -294,6 +300,7 @@ private: bool WriteActionUpdateWindowModeSupportType(Parcel& parcel); bool WriteActionUpdateAvoidAreaOption(Parcel& parcel); bool WriteActionUpdateBackgroundAlpha(Parcel& parcel); + bool WriteActionUpdateExclusivelyHighlighted(Parcel& parcel); void ReadActionUpdateTurnScreenOn(Parcel& parcel); void ReadActionUpdateKeepScreenOn(Parcel& parcel); void ReadActionUpdateFocusable(Parcel& parcel); @@ -321,6 +328,7 @@ private: void ReadActionUpdateWindowModeSupportType(Parcel& parcel); void ReadActionUpdateAvoidAreaOption(Parcel& parcel); void ReadActionUpdateBackgroundAlpha(Parcel& parcel); + void ReadActionUpdateExclusivelyHighlighted(Parcel& parcel); std::string windowName_; SessionInfo sessionInfo_; mutable std::mutex windowRectMutex_; @@ -330,8 +338,6 @@ private: mutable std::mutex rectAnimationConfigMutex_; RectAnimationConfig rectAnimationConfig_ { 0, 0.0f, 0.0f, 0.0f, 0.0f }; WindowType type_ { WindowType::WINDOW_TYPE_APP_MAIN_WINDOW }; // type main window - bool focusable_ { true }; - bool focusableOnShow_ { true }; bool touchable_ { true }; bool dragEnabled_ = { true }; bool raiseEnabled_ = { true }; @@ -444,6 +450,13 @@ private: */ uint32_t avoidAreaOption_ = 0; + /* + * Window Focus + */ + bool focusable_ { true }; + bool focusableOnShow_ { true }; + bool isExclusivelyHighlighted_ { true }; + /* * Window Property */ diff --git a/window_scene/common/src/window_session_property.cpp b/window_scene/common/src/window_session_property.cpp index e9554ace2f80b7333ae6cf8951fcde2e563bfc82..89674e68af6ae7d9b3a21f2203e746a47aeabd47 100755 --- a/window_scene/common/src/window_session_property.cpp +++ b/window_scene/common/src/window_session_property.cpp @@ -89,6 +89,8 @@ const std::map WindowSessionProperty::writeFun &WindowSessionProperty::WriteActionUpdateAvoidAreaOption), std::make_pair(static_cast(WSPropertyChangeAction::ACTION_UPDATE_BACKGROUND_ALPHA), &WindowSessionProperty::WriteActionUpdateBackgroundAlpha), + std::make_pair(static_cast(WSPropertyChangeAction::ACTION_UPDATE_EXCLUSIVE_HIGHLIGHTED), + &WindowSessionProperty::WriteActionUpdateExclusivelyHighlighted), }; const std::map WindowSessionProperty::readFuncMap_ { @@ -154,6 +156,8 @@ const std::map WindowSessionProperty::readFuncM &WindowSessionProperty::ReadActionUpdateAvoidAreaOption), std::make_pair(static_cast(WSPropertyChangeAction::ACTION_UPDATE_BACKGROUND_ALPHA), &WindowSessionProperty::ReadActionUpdateBackgroundAlpha), + std::make_pair(static_cast(WSPropertyChangeAction::ACTION_UPDATE_EXCLUSIVE_HIGHLIGHTED), + &WindowSessionProperty::ReadActionUpdateExclusivelyHighlighted), }; WindowSessionProperty::WindowSessionProperty(const sptr& property) @@ -1186,8 +1190,7 @@ bool WindowSessionProperty::Marshalling(Parcel& parcel) const parcel.WriteUint32(static_cast(uiExtensionUsage_)) && parcel.WriteUint32(static_cast(parentWindowType_)) && MarshallingWindowMask(parcel) && - parcel.WriteParcelable(&keyboardLayoutParams_) && - parcel.WriteBool(compatibleModeInPc_) && + parcel.WriteParcelable(&keyboardLayoutParams_) && parcel.WriteBool(compatibleModeInPc_) && parcel.WriteInt32(compatibleInPcPortraitWidth_) && parcel.WriteInt32(compatibleInPcPortraitHeight_) && parcel.WriteInt32(compatibleInPcLandscapeWidth_) && parcel.WriteInt32(compatibleInPcLandscapeHeight_) && parcel.WriteBool(isAppSupportPhoneInPc_) && parcel.WriteBool(isSupportDragInPcCompatibleMode_) && @@ -1195,7 +1198,7 @@ bool WindowSessionProperty::Marshalling(Parcel& parcel) const parcel.WriteString(appInstanceKey_) && parcel.WriteBool(isSystemKeyboard_) && parcel.WriteUint32(avoidAreaOption_) && parcel.WriteBool(isWindowDelayRaiseEnabled_) && parcel.WriteUint8(backgroundAlpha_) && parcel.WriteUint32(static_cast(KeyboardViewMode_)) && - parcel.WriteFloat(cornerRadius_); + parcel.WriteFloat(cornerRadius_) && parcel.WriteBool(isExclusivelyHighlighted_); } WindowSessionProperty* WindowSessionProperty::Unmarshalling(Parcel& parcel) @@ -1281,6 +1284,7 @@ WindowSessionProperty* WindowSessionProperty::Unmarshalling(Parcel& parcel) property->SetBackgroundAlpha(parcel.ReadUint8()); property->SetKeyboardViewMode(static_cast(parcel.ReadUint32())); property->SetWindowCornerRadius(parcel.ReadFloat()); + property->SetExclusivelyHighlighted(parcel.ReadBool()); return property; } @@ -1367,6 +1371,7 @@ void WindowSessionProperty::CopyFrom(const sptr& property isWindowDelayRaiseEnabled_ = property->isWindowDelayRaiseEnabled_; backgroundAlpha_ = property->backgroundAlpha_; KeyboardViewMode_ = property->KeyboardViewMode_; + isExclusivelyHighlighted_ = property->isExclusivelyHighlighted_; cornerRadius_ = property->cornerRadius_; } @@ -1518,6 +1523,11 @@ bool WindowSessionProperty::WriteActionUpdateBackgroundAlpha(Parcel& parcel) return parcel.WriteUint8(backgroundAlpha_); } +bool WindowSessionProperty::WriteActionUpdateExclusivelyHighlighted(Parcel& parcel) +{ + return parcel.WriteBool(isExclusivelyHighlighted_); +} + void WindowSessionProperty::Read(Parcel& parcel, WSPropertyChangeAction action) { const auto funcIter = readFuncMap_.find(static_cast(action)); @@ -1669,6 +1679,11 @@ void WindowSessionProperty::ReadActionUpdateBackgroundAlpha(Parcel& parcel) SetBackgroundAlpha(parcel.ReadUint8()); } +void WindowSessionProperty::ReadActionUpdateExclusivelyHighlighted(Parcel& parcel) +{ + SetExclusivelyHighlighted(parcel.ReadBool()); +} + void WindowSessionProperty::SetTransform(const Transform& trans) { trans_ = trans; @@ -1883,5 +1898,15 @@ void WindowSessionProperty::SetBackgroundAlpha(uint8_t alpha) { backgroundAlpha_ = alpha; } + +void WindowSessionProperty::SetExclusivelyHighlighted(bool isExclusivelyHighlighted) +{ + isExclusivelyHighlighted_ = isExclusivelyHighlighted; +} + +bool WindowSessionProperty::GetExclusivelyHighlighted() const +{ + return isExclusivelyHighlighted_; +} } // namespace Rosen } // namespace OHOS diff --git a/window_scene/interfaces/include/ws_common_inner.h b/window_scene/interfaces/include/ws_common_inner.h index bdc83ff2853a05aedf909e0145476dd576fc6be9..5c51b74f60fed4a71655173ae0daf09374d3e2a5 100644 --- a/window_scene/interfaces/include/ws_common_inner.h +++ b/window_scene/interfaces/include/ws_common_inner.h @@ -59,7 +59,8 @@ enum class WSPropertyChangeAction : uint64_t { ACTION_UPDATE_AVOID_AREA_OPTION = 1llu << 32, ACTION_UPDATE_KEYBOARD_TOUCH_HOT_AREA = 1llu << 33, ACTION_UPDATE_BACKGROUND_ALPHA = 1llu << 34, - ACTION_UPDATE_END = ACTION_UPDATE_BACKGROUND_ALPHA, + ACTION_UPDATE_EXCLUSIVE_HIGHLIGHTED = 1llu << 35, + ACTION_UPDATE_END = ACTION_UPDATE_EXCLUSIVE_HIGHLIGHTED, }; enum class AreaType : uint32_t { diff --git a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.cpp b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.cpp index 9685875018e4cea0bd0e72222b4cda5b4251cb04..6a89165170235e3efe977bfe9cb53245c49ef2d8 100644 --- a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.cpp +++ b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.cpp @@ -89,7 +89,10 @@ const std::string UPDATE_SESSION_LABEL_AND_ICON_CB = "updateSessionLabelAndIcon" const std::string KEYBOARD_STATE_CHANGE_CB = "keyboardStateChange"; const std::string KEYBOARD_VIEW_MODE_CHANGE_CB = "keyboardViewModeChange"; const std::string SET_WINDOW_CORNER_RADIUS_CB = "setWindowCornerRadius"; +const std::string HIGHLIGHT_CHANGE_CB = "highlightChange"; +constexpr int ARG_COUNT_1 = 1; +constexpr int ARG_COUNT_2 = 2; constexpr int ARG_COUNT_3 = 3; constexpr int ARG_COUNT_4 = 4; constexpr int ARG_INDEX_0 = 0; @@ -163,6 +166,7 @@ const std::map ListenerFuncMap { {KEYBOARD_STATE_CHANGE_CB, ListenerFuncType::KEYBOARD_STATE_CHANGE_CB}, {KEYBOARD_VIEW_MODE_CHANGE_CB, ListenerFuncType::KEYBOARD_VIEW_MODE_CHANGE_CB}, {SET_WINDOW_CORNER_RADIUS_CB, ListenerFuncType::SET_WINDOW_CORNER_RADIUS_CB}, + {HIGHLIGHT_CHANGE_CB, ListenerFuncType::HIGHLIGHT_CHANGE_CB}, }; const std::vector g_syncGlobalPositionPermission { @@ -452,6 +456,8 @@ void JsSceneSession::BindNativeMethodForFocus(napi_env env, napi_value objValue, BindNativeFunction(env, objValue, "setSystemFocusable", moduleName, JsSceneSession::SetSystemFocusable); BindNativeFunction(env, objValue, "setSystemSceneBlockingFocus", moduleName, JsSceneSession::SetSystemSceneBlockingFocus); + BindNativeFunction(env, objValue, "setExclusivelyHighlighted", moduleName, + JsSceneSession::SetExclusivelyHighlighted); } void JsSceneSession::BindNativeMethodForWaterfall(napi_env env, napi_value objValue, const char* moduleName) @@ -1920,6 +1926,13 @@ napi_value JsSceneSession::SetSystemSceneBlockingFocus(napi_env env, napi_callba return (me != nullptr) ? me->OnSetSystemSceneBlockingFocus(env, info) : nullptr; } +napi_value JsSceneSession::SetExclusivelyHighlighted(napi_env env, napi_callback_info info) +{ + TLOGD(WmsLogTag::WMS_FOCUS, "[NAPI]"); + JsSceneSession* me = CheckParamsAndGetThis(env, info); + return (me != nullptr) ? me->OnSetExclusivelyHighlighted(env, info) : nullptr; +} + napi_value JsSceneSession::MaskSupportEnterWaterfallMode(napi_env env, napi_callback_info info) { TLOGD(WmsLogTag::WMS_LAYOUT_PC, "[NAPI]"); @@ -2545,6 +2558,9 @@ void JsSceneSession::ProcessRegisterCallback(ListenerFuncType listenerFuncType) case static_cast(ListenerFuncType::KEYBOARD_VIEW_MODE_CHANGE_CB): ProcessKeyboardViewModeChangeRegister(); break; + case static_cast(ListenerFuncType::HIGHLIGHT_CHANGE_CB): + ProcessSetHighlightChangeRegister(); + break; case static_cast(ListenerFuncType::SET_WINDOW_CORNER_RADIUS_CB): ProcessSetWindowCornerRadiusRegister(); break; @@ -2820,6 +2836,34 @@ napi_value JsSceneSession::OnSetSystemSceneBlockingFocus(napi_env env, napi_call return NapiGetUndefined(env); } +napi_value JsSceneSession::OnSetExclusivelyHighlighted(napi_env env, napi_callback_info info) +{ + size_t argc = ARG_COUNT_4; + napi_value argv[ARG_COUNT_4] = { nullptr }; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc != ARG_COUNT_1) { + TLOGE(WmsLogTag::WMS_FOCUS, "Argc is invalid: %{public}zu", argc); + napi_throw(env, CreateJsError(env, static_cast(WSErrorCode::WS_ERROR_INVALID_PARAM), + "Input parameter is missing or invalid")); + return NapiGetUndefined(env); + } + bool isExclusivelyHighlighted = true; + if (!ConvertFromJsValue(env, argv[ARG_INDEX_0], isExclusivelyHighlighted)) { + TLOGE(WmsLogTag::WMS_FOCUS, "Failed to convert parameter to isExclusivelyHighlighted"); + napi_throw(env, CreateJsError(env, static_cast(WSErrorCode::WS_ERROR_INVALID_PARAM), + "Input parameter is missing or invalid")); + return NapiGetUndefined(env); + } + auto session = weakSession_.promote(); + if (session == nullptr) { + TLOGE(WmsLogTag::WMS_FOCUS, "session is nullptr, id: %{public}d", persistentId_); + return NapiGetUndefined(env); + } + session->SetExclusivelyHighlighted(isExclusivelyHighlighted); + TLOGD(WmsLogTag::WMS_FOCUS, "end"); + return NapiGetUndefined(env); +} + napi_value JsSceneSession::OnMaskSupportEnterWaterfallMode(napi_env env, napi_callback_info info) { auto session = weakSession_.promote(); @@ -6091,6 +6135,46 @@ void JsSceneSession::OnSetWindowCornerRadius(float cornerRadius) }, __func__); } +void JsSceneSession::ProcessSetHighlightChangeRegister() +{ + NotifyHighlightChangeFunc func = [weakThis = wptr(this), where = __func__](bool isHighlight) { + auto jsSceneSession = weakThis.promote(); + if (!jsSceneSession) { + TLOGNE(WmsLogTag::WMS_FOCUS, "%{public}s: jsSceneSession is null", where); + return; + } + jsSceneSession->NotifyHighlightChange(isHighlight); + }; + auto session = weakSession_.promote(); + if (session == nullptr) { + TLOGE(WmsLogTag::WMS_FOCUS, "session is nullptr"); + return; + } + session->SetHighlightChangeNotifyFunc(func); +} + +void JsSceneSession::NotifyHighlightChange(bool isHighlight) +{ + TLOGI(WmsLogTag::WMS_FOCUS, "isHighlight: %{public}d, id: %{public}d", isHighlight, persistentId_); + auto task = [weakThis = wptr(this), isHighlight, env = env_, persistentId = persistentId_, where = __func__] { + auto jsSceneSession = weakThis.promote(); + if (!jsSceneSession || jsSceneSessionMap_.find(persistentId) == jsSceneSessionMap_.end()) { + TLOGNE(WmsLogTag::WMS_FOCUS, "%{public}s: jsSceneSession id: %{public}d has been destroyed", + where, persistentId); + return; + } + auto jsCallBack = jsSceneSession->GetJSCallback(HIGHLIGHT_CHANGE_CB); + if (!jsCallBack) { + TLOGNE(WmsLogTag::WMS_FOCUS, "%{public}s: jsCallBack is nullptr", where); + return; + } + napi_value jsIsHighlight = CreateJsValue(env, isHighlight); + napi_value argv[] = { jsIsHighlight }; + napi_call_function(env, NapiGetUndefined(env), jsCallBack->GetNapiValue(), ArraySize(argv), argv, nullptr); + }; + taskScheduler_->PostMainThreadTask(task, "NotifyHighlightChange"); +} + napi_value JsSceneSession::OnSetColorSpace(napi_env env, napi_callback_info info) { size_t argc = ARGC_FOUR; diff --git a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.h b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.h index 024c0b471625d2764db9d2ee1f41110b3379549b..d40b7619cbc11d0e06f80182f78323d5977b5afb 100644 --- a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.h +++ b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.h @@ -90,6 +90,7 @@ enum class ListenerFuncType : uint32_t { KEYBOARD_STATE_CHANGE_CB, KEYBOARD_VIEW_MODE_CHANGE_CB, SET_WINDOW_CORNER_RADIUS_CB, + HIGHLIGHT_CHANGE_CB, }; class SceneSession; @@ -204,6 +205,7 @@ private: static napi_value SetBehindWindowFilterEnabled(napi_env env, napi_callback_info info); static napi_value SetFreezeImmediately(napi_env env, napi_callback_info info); static napi_value SendContainerModalEvent(napi_env env, napi_callback_info info); + static napi_value SetExclusivelyHighlighted(napi_env env, napi_callback_info info); static napi_value SetColorSpace(napi_env env, napi_callback_info info); napi_value OnActivateDragBySystem(napi_env env, napi_callback_info info); @@ -274,6 +276,7 @@ private: napi_value OnMaskSupportEnterWaterfallMode(napi_env env, napi_callback_info info); napi_value OnUpdateFullScreenWaterfallMode(napi_env env, napi_callback_info info); napi_value OnSendContainerModalEvent(napi_env env, napi_callback_info info); + napi_value OnSetExclusivelyHighlighted(napi_env env, napi_callback_info info); napi_value OnSetColorSpace(napi_env env, napi_callback_info info); bool IsCallbackRegistered(napi_env env, const std::string& type, napi_value jsListenerObject); @@ -327,6 +330,7 @@ private: void ProcessUpdateSessionLabelAndIconRegister(); void ProcessKeyboardStateChangeRegister(); void ProcessKeyboardViewModeChangeRegister(); + void ProcessSetHighlightChangeRegister(); /* * Window Property @@ -392,6 +396,7 @@ private: void UpdateSessionLabelAndIcon(const std::string& label, const std::shared_ptr& icon); void OnKeyboardStateChange(SessionState state, KeyboardViewMode mode); void OnKeyboardViewModeChange(KeyboardViewMode mode); + void NotifyHighlightChange(bool isHighlight); /* * Window Property diff --git a/window_scene/session/container/include/zidl/session_stage_interface.h b/window_scene/session/container/include/zidl/session_stage_interface.h index 2112c4ecfcd767cf52b249188c67e4b68d3eaa2d..8a2b593a1368052f11d95f246df798c78db7c9ec 100644 --- a/window_scene/session/container/include/zidl/session_stage_interface.h +++ b/window_scene/session/container/include/zidl/session_stage_interface.h @@ -86,6 +86,7 @@ public: */ virtual WSError UpdateFocus(bool isFocused) = 0; virtual WSError NotifyDestroy() = 0; + virtual WSError NotifyHighlightChange(bool isHighlight) = 0; /** * @brief Notify client to close the existing pip window. diff --git a/window_scene/session/container/include/zidl/session_stage_ipc_interface_code.h b/window_scene/session/container/include/zidl/session_stage_ipc_interface_code.h index b54deedc66c988a17e2535f6c69da90153aa86c2..a8a055d3ca385561df6bb74458fcf93f954564aa 100644 --- a/window_scene/session/container/include/zidl/session_stage_ipc_interface_code.h +++ b/window_scene/session/container/include/zidl/session_stage_ipc_interface_code.h @@ -72,6 +72,7 @@ enum class SessionStageInterfaceCode { TRANS_ID_SET_SUPPORT_ENTER_WATERFALL_MODE, TRANS_ID_SEND_CONTAINER_MODAL_EVENT, TRANS_ID_SET_DRAG_ACTIVATED, + TRANS_ID_NOTIFY_HIGHLIGHT_CHANGE, }; } // namespace Rosen } // namespace OHOS diff --git a/window_scene/session/container/include/zidl/session_stage_proxy.h b/window_scene/session/container/include/zidl/session_stage_proxy.h index d7d37c40c660b80173bec31c0cedebd81223ead6..997045c04f75a5663ca0ffa497805065bd760a23 100644 --- a/window_scene/session/container/include/zidl/session_stage_proxy.h +++ b/window_scene/session/container/include/zidl/session_stage_proxy.h @@ -85,6 +85,7 @@ public: WSError SetFullScreenWaterfallMode(bool isWaterfallMode) override; WSError SetSupportEnterWaterfallMode(bool isSupportEnter) override; WSError SendContainerModalEvent(const std::string& eventName, const std::string& eventValue) override; + WSError NotifyHighlightChange(bool isHighlight) override; private: static inline BrokerDelegator delegator_; diff --git a/window_scene/session/container/include/zidl/session_stage_stub.h b/window_scene/session/container/include/zidl/session_stage_stub.h index 7aebbc6166591edb823270af6ba772084856f86b..d220c73d10c511bbbffa8abe5db8f2de2a694b8e 100644 --- a/window_scene/session/container/include/zidl/session_stage_stub.h +++ b/window_scene/session/container/include/zidl/session_stage_stub.h @@ -82,6 +82,7 @@ private: int HandleSetFullScreenWaterfallMode(MessageParcel& data, MessageParcel& reply); int HandleSetSupportEnterWaterfallMode(MessageParcel& data, MessageParcel& reply); int HandleSendContainerModalEvent(MessageParcel& data, MessageParcel& reply); + int HandleNotifyHighlightChange(MessageParcel& data, MessageParcel& reply); }; } // namespace OHOS::Rosen #endif // OHOS_WINDOW_SCENE_SESSION_STAGE_STUB_H diff --git a/window_scene/session/container/src/zidl/session_stage_proxy.cpp b/window_scene/session/container/src/zidl/session_stage_proxy.cpp index cd37b985a69d1df55022522b36b5144c11b49f3d..f00ecc1920bc5073558d08f0788823d6ef6f4bf9 100644 --- a/window_scene/session/container/src/zidl/session_stage_proxy.cpp +++ b/window_scene/session/container/src/zidl/session_stage_proxy.cpp @@ -1530,4 +1530,34 @@ WSError SessionStageProxy::SendContainerModalEvent(const std::string& eventName, } return WSError::WS_OK; } + +WSError SessionStageProxy::NotifyHighlightChange(bool isHighlight) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + TLOGE(WmsLogTag::WMS_FOCUS, "Write interfaceToken failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + + if (!data.WriteBool(isHighlight)) { + TLOGE(WmsLogTag::WMS_FOCUS, "Write isHighlight failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + + sptr remote = Remote(); + if (remote == nullptr) { + TLOGE(WmsLogTag::WMS_FOCUS, "remote is null"); + return WSError::WS_ERROR_IPC_FAILED; + } + + if (remote->SendRequest(static_cast(SessionStageInterfaceCode::TRANS_ID_NOTIFY_HIGHLIGHT_CHANGE), + data, reply, option) != ERR_NONE) { + TLOGE(WmsLogTag::WMS_FOCUS, "SendRequest failed"); + return WSError::WS_ERROR_IPC_FAILED; + } + int32_t ret = reply.ReadInt32(); + return static_cast(ret); +} } // namespace OHOS::Rosen diff --git a/window_scene/session/container/src/zidl/session_stage_stub.cpp b/window_scene/session/container/src/zidl/session_stage_stub.cpp index 1931af397b4948a5195f63ef8c8d83a5b57da810..d3c92352e7c28d307d8792f0519000a61684697a 100644 --- a/window_scene/session/container/src/zidl/session_stage_stub.cpp +++ b/window_scene/session/container/src/zidl/session_stage_stub.cpp @@ -192,6 +192,8 @@ int SessionStageStub::OnRemoteRequest(uint32_t code, MessageParcel& data, Messag return HandleSendContainerModalEvent(data, reply); case static_cast(SessionStageInterfaceCode::TRANS_ID_SET_DRAG_ACTIVATED): return HandleSetDragActivated(data, reply); + case static_cast(SessionStageInterfaceCode::TRANS_ID_NOTIFY_HIGHLIGHT_CHANGE): + return HandleNotifyHighlightChange(data, reply); default: WLOGFE("Failed to find function handler!"); return IPCObjectStub::OnRemoteRequest(code, data, reply, option); @@ -756,4 +758,17 @@ int SessionStageStub::HandleSendContainerModalEvent(MessageParcel& data, Message SendContainerModalEvent(eventName, eventValue); return ERR_NONE; } + +int SessionStageStub::HandleNotifyHighlightChange(MessageParcel& data, MessageParcel& reply) +{ + TLOGD(WmsLogTag::WMS_FOCUS, "called!"); + bool isHighlight = false; + if (!data.ReadBool(isHighlight)) { + TLOGE(WmsLogTag::WMS_FOCUS, "Read isHighlight failed."); + return ERR_INVALID_DATA; + } + WSError errCode = NotifyHighlightChange(isHighlight); + reply.WriteUint32(static_cast(errCode)); + return ERR_NONE; +} } // namespace OHOS::Rosen diff --git a/window_scene/session/host/include/scene_session.h b/window_scene/session/host/include/scene_session.h index 36d628a8b13a64166b2bcd76588e4f27a58c6f1a..d76aa1430af909215bd83044d8b26f83c3ff8fce 100644 --- a/window_scene/session/host/include/scene_session.h +++ b/window_scene/session/host/include/scene_session.h @@ -624,6 +624,12 @@ public: bool IsKeyboardAvoidAreaActive() const; virtual void SetKeyboardViewModeChangeListener(const NotifyKeyboarViewModeChangeFunc& func) {}; + /* + * Window Focus + */ + bool IsSameMainSession(const sptr& prevSession); + void SetHighlightChangeNotifyFunc(const NotifyHighlightChangeFunc& func); + /* * Window Property */ @@ -878,6 +884,8 @@ private: WMError HandleActionUpdateAvoidAreaOption(const sptr& property, WSPropertyChangeAction action); WMError HandleBackgroundAlpha(const sptr& property, WSPropertyChangeAction action); + WMError HandleActionUpdateExclusivelyHighlighted(const sptr& property, + WSPropertyChangeAction action); void HandleSpecificSystemBarProperty(WindowType type, const sptr& property); void SetWindowFlags(const sptr& property); void NotifySessionChangeByActionNotifyManager(const sptr& property, diff --git a/window_scene/session/host/include/session.h b/window_scene/session/host/include/session.h index c69213b71e22d5f6549c071dda14f94623b6b62e..39cd053418e257429c9fa8996a1ccd6179247d07 100644 --- a/window_scene/session/host/include/session.h +++ b/window_scene/session/host/include/session.h @@ -95,6 +95,7 @@ using NotifyWindowMovingFunc = std::function& icon)>; using NotifyKeyboardStateChangeFunc = std::function; +using NotifyHighlightChangeFunc = std::function; class ILifecycleListener { public: @@ -398,6 +399,9 @@ public: void NotifyUIRequestFocus(); virtual void NotifyUILostFocus(); WSError NotifyFocusStatus(bool isFocused); + virtual WSError UpdateHighlightStatus(bool isHighlight, bool isNotifyHighlightChange = true); + WSError NotifyHighlightChange(bool isHighlight); + void SetExclusivelyHighlighted(bool isExclusivelyHighlighted); /* * Multi Window @@ -696,6 +700,8 @@ protected: NotifySystemSessionKeyEventFunc systemSessionKeyEventFunc_; NotifyContextTransparentFunc contextTransparentFunc_; NotifyFrameLayoutFinishFunc frameLayoutFinishFunc_; + std::mutex highlightChangeFuncMutex_; + NotifyHighlightChangeFunc highlightChangeFunc_; /* * Window LifeCycle @@ -752,7 +758,8 @@ protected: * Window Focus */ bool isFocused_ = false; - bool blockingFocus_ {false}; + bool blockingFocus_ { false }; + bool isHighlight_ { false }; uint32_t uiNodeId_ = 0; float aspectRatio_ = 0.0f; diff --git a/window_scene/session/host/src/scene_session.cpp b/window_scene/session/host/src/scene_session.cpp index f47bd590c9c214f91a209c6f4140b6847d16ee31..4366913f149ca892a2a91cd591943cdd2b9bb788 100644 --- a/window_scene/session/host/src/scene_session.cpp +++ b/window_scene/session/host/src/scene_session.cpp @@ -3659,6 +3659,14 @@ bool SceneSession::IsSystemSessionAboveApp() const return false; } +/** @note @window.focus */ +bool SceneSession::IsSameMainSession(const sptr& prevSession) +{ + int32_t currSessionId = GetMainSessionId(); + int32_t prevSessionId = prevSession->GetMainSessionId(); + return currSessionId == prevSessionId && prevSessionId != INVALID_SESSION_ID; +} + void SceneSession::NotifyIsCustomAnimationPlaying(bool isPlaying) { WLOGFI("id %{public}d %{public}u", GetPersistentId(), isPlaying); @@ -4463,6 +4471,8 @@ WMError SceneSession::ProcessUpdatePropertyByAction(const sptr(WSPropertyChangeAction::ACTION_UPDATE_BACKGROUND_ALPHA): return HandleBackgroundAlpha(property, action); + case static_cast(WSPropertyChangeAction::ACTION_UPDATE_EXCLUSIVE_HIGHLIGHTED): + return HandleActionUpdateExclusivelyHighlighted(property, action); default: TLOGE(WmsLogTag::DEFAULT, "Failed to find func handler!"); return WMError::WM_DO_NOTHING; @@ -4790,6 +4800,18 @@ WMError SceneSession::HandleBackgroundAlpha(const sptr& p return WMError::WM_OK; } +WMError SceneSession::HandleActionUpdateExclusivelyHighlighted(const sptr& property, + WSPropertyChangeAction action) +{ + auto sessionProperty = GetSessionProperty(); + if (!sessionProperty) { + TLOGE(WmsLogTag::WMS_FOCUS, "property is null"); + return WMError::WM_ERROR_INVALID_PARAM; + } + sessionProperty->SetExclusivelyHighlighted(property->GetExclusivelyHighlighted()); + return WMError::WM_OK; +} + void SceneSession::HandleSpecificSystemBarProperty(WindowType type, const sptr& property) { auto systemBarProperties = property->GetSystemBarProperty(); @@ -5782,6 +5804,12 @@ void SceneSession::SetPrivacyModeChangeNotifyFunc(const NotifyPrivacyModeChangeF privacyModeChangeNotifyFunc_ = func; } +void SceneSession::SetHighlightChangeNotifyFunc(const NotifyHighlightChangeFunc& func) +{ + std::lock_guard lock(highlightChangeFuncMutex_); + highlightChangeFunc_ = func; +} + int32_t SceneSession::GetStatusBarHeight() { int32_t height = 0; diff --git a/window_scene/session/host/src/session.cpp b/window_scene/session/host/src/session.cpp index 943b0d16d983c2b3ac8229671af9d3433b865347..4b453c4d3d771d26f596dfd06d2295be0258ff7e 100644 --- a/window_scene/session/host/src/session.cpp +++ b/window_scene/session/host/src/session.cpp @@ -2660,6 +2660,55 @@ WSError Session::RequestFocus(bool isFocused) return WSError::WS_OK; } +void Session::SetExclusivelyHighlighted(bool isExclusivelyHighlighted) +{ + auto property = GetSessionProperty(); + if (property == nullptr) { + TLOGE(WmsLogTag::WMS_FOCUS, "property is nullptr, windowId: %{public}d", persistentId_); + return; + } + if (isExclusivelyHighlighted == property->GetExclusivelyHighlighted()) { + return; + } + TLOGI(WmsLogTag::WMS_FOCUS, "windowId: %{public}d, isExclusivelyHighlighted: %{public}d", persistentId_, + isExclusivelyHighlighted); + property->SetExclusivelyHighlighted(isExclusivelyHighlighted); +} + +WSError Session::UpdateHighlightStatus(bool isHighlight, bool isNotifyHighlightChange) +{ + TLOGD(WmsLogTag::WMS_FOCUS, + "windowId: %{public}d, currHighlight: %{public}d, nextHighlight: %{public}d, isNotify:%{public}d", + persistentId_, isHighlight_, isHighlight, isNotifyHighlightChange); + if (isHighlight_ == isHighlight) { + return WSError::WS_DO_NOTHING; + } + isHighlight_ = isHighlight; + if (isNotifyHighlightChange) { + NotifyHighlightChange(isHighlight); + std::lock_guard lock(highlightChangeFuncMutex_); + if (highlightChangeFunc_ != nullptr) { + highlightChangeFunc_(isHighlight); + } + } + return WSError::WS_OK; +} + +WSError Session::NotifyHighlightChange(bool isHighlight) +{ + if (IsSystemSession()) { + TLOGW(WmsLogTag::WMS_FOCUS, "Session is invalid, id: %{public}d state: %{public}u", + persistentId_, GetSessionState()); + return WSError::WS_ERROR_INVALID_SESSION; + } + if (!sessionStage_) { + TLOGE(WmsLogTag::WMS_FOCUS, "sessionStage is null"); + return WSError::WS_ERROR_NULLPTR; + } + sessionStage_->NotifyHighlightChange(isHighlight); + return WSError::WS_OK; +} + WSError Session::SetCompatibleModeInPc(bool enable, bool isSupportDragInPcCompatibleMode) { TLOGI(WmsLogTag::WMS_SCB, "SetCompatibleModeInPc enable: %{public}d, isSupportDragInPcCompatibleMode: %{public}d", diff --git a/window_scene/session_manager/include/scene_session_manager.h b/window_scene/session_manager/include/scene_session_manager.h index 5051175b42032e3d4a506cabbfccd20d1fcfcb25..1604388940f943fb8f9e3aaca7d687ecbd9e7033 100644 --- a/window_scene/session_manager/include/scene_session_manager.h +++ b/window_scene/session_manager/include/scene_session_manager.h @@ -689,6 +689,10 @@ private: void ResetWantInfo(const sptr& sceneSession); void ResetSceneSessionInfoWant(const sptr& sceneSessionInfo); + /* + * Window Focus + */ + std::unordered_set highlightIds_; std::vector>> GetSceneSessionVector(CmpFunc cmp); void TraverseSessionTree(TraverseFunc func, bool isFromTopToBottom); void TraverseSessionTreeFromTopToBottom(TraverseFunc func); @@ -718,7 +722,7 @@ private: sptr GetTopNearestBlockingFocusSession(DisplayId displayId, uint32_t zOrder, bool includingAppSession); sptr GetTopFocusableNonAppSession(); - WSError ShiftFocus(DisplayId displayId, const sptr& nextSession, + WSError ShiftFocus(DisplayId displayId, const sptr& nextSession, bool isProactiveUnfocus, FocusChangeReason reason = FocusChangeReason::DEFAULT); void UpdateFocusStatus(DisplayId displayId, const sptr& sceneSession, bool isFocused); void NotifyFocusStatus(const sptr& sceneSession, bool isFocused, @@ -746,6 +750,12 @@ private: std::vector> GetSceneSessionVectorByType(WindowType type); void UpdateOccupiedAreaIfNeed(int32_t persistentId); void NotifyMMIWindowPidChange(int32_t windowId, bool startMoving); + void UpdateHighlightStatus(const sptr& preSceneSession, const sptr& currSceneSession, + bool isProactiveUnfocus); + void SetHighlightSessionIds(const sptr& sceneSession); + void AddHighlightSessionIds(const sptr& sceneSession); + void RemoveHighlightSessionIds(const sptr& sceneSession); + std::string GetHighlightIdsStr(); /* * Window Immersive diff --git a/window_scene/session_manager/src/scene_session_manager.cpp b/window_scene/session_manager/src/scene_session_manager.cpp index c56c98df00d035c73cf1b34f1dad94a2eaa48383..d82de8d16a78aa0b8aace40c73897c8b29c80b47 100644 --- a/window_scene/session_manager/src/scene_session_manager.cpp +++ b/window_scene/session_manager/src/scene_session_manager.cpp @@ -5018,9 +5018,8 @@ void SceneSessionManager::DumpFocusInfo(std::ostringstream& oss) WSError SceneSessionManager::GetAllSessionDumpInfo(std::string& dumpInfo) { - int32_t screenGroupId = 0; std::ostringstream oss; - oss << "-------------------------------------ScreenGroup " << screenGroupId + oss << "-------------------------------------ScreenGroup 0" << "-------------------------------------" << std::endl; oss << "WindowName DisplayId Pid WinId Type Mode Flag ZOrd Orientation [ x y w h ]" << " [ OffsetX OffsetY ] [ ScaleX ScaleY PivotX PivotY ]" << std::endl; @@ -5064,6 +5063,7 @@ WSError SceneSessionManager::GetAllSessionDumpInfo(std::string& dumpInfo) oss << "SingleHand: X[" << singleHandTransform_.posX << "] Y[" << singleHandTransform_.posY << "] scale[" << singleHandTransform_.scaleX << "]" << std::endl; oss << "Total window num: " << sceneSessionMapCopy.size() << std::endl; + oss << "Highlighted windows: " << GetHighlightIdsStr() << std::endl; dumpInfo.append(oss.str()); return WSError::WS_OK; } @@ -5479,7 +5479,7 @@ WSError SceneSessionManager::RequestSessionFocusImmediately(int32_t persistentId if (!sceneSession->GetSessionInfo().isSystem_ && !IsSessionVisibleForeground(sceneSession)) { focusGroup->SetNeedBlockNotifyFocusStatusUntilForeground(true); } - ShiftFocus(displayId, sceneSession, reason); + ShiftFocus(displayId, sceneSession, false, reason); return WSError::WS_OK; } @@ -5532,7 +5532,7 @@ WSError SceneSessionManager::RequestSessionFocus(int32_t persistentId, bool byFo } focusGroup->SetNeedBlockNotifyUnfocusStatus(focusGroup->GetNeedBlockNotifyFocusStatusUntilForeground()); focusGroup->SetNeedBlockNotifyFocusStatusUntilForeground(false); - ShiftFocus(displayId, sceneSession, reason); + ShiftFocus(displayId, sceneSession, false, reason); return WSError::WS_OK; } @@ -5579,7 +5579,7 @@ WSError SceneSessionManager::RequestSessionUnfocus(int32_t persistentId, FocusCh return WSError::WS_OK; } - return ShiftFocus(displayId, nextSession, reason); + return ShiftFocus(displayId, nextSession, true, reason); } WSError SceneSessionManager::RequestAllAppSessionUnfocusInner() @@ -5603,7 +5603,7 @@ WSError SceneSessionManager::RequestAllAppSessionUnfocusInner() focusGroup->SetNeedBlockNotifyUnfocusStatus(focusGroup->GetNeedBlockNotifyFocusStatusUntilForeground()); focusGroup->SetNeedBlockNotifyFocusStatusUntilForeground(false); - return ShiftFocus(DEFAULT_DISPLAY_ID, nextSession, FocusChangeReason::WIND); + return ShiftFocus(DEFAULT_DISPLAY_ID, nextSession, true, FocusChangeReason::WIND); } WSError SceneSessionManager::RequestFocusBasicCheck(int32_t persistentId, const sptr& focusGroup) @@ -5961,7 +5961,7 @@ void SceneSessionManager::SetAbilityManagerCollaboratorRegisteredFunc( } WSError SceneSessionManager::ShiftFocus(DisplayId displayId, const sptr& nextSession, - FocusChangeReason reason) + bool isProactiveUnfocus, FocusChangeReason reason) { // unfocus auto focusedSessionId = windowFocusController_->GetFocusedSessionId(displayId); @@ -5978,6 +5978,7 @@ WSError SceneSessionManager::ShiftFocus(DisplayId displayId, const sptrGetPersistentId(); } UpdateFocusStatus(displayId, nextSession, true); + UpdateHighlightStatus(focusedSession, nextSession, isProactiveUnfocus); if (shiftFocusFunc_ != nullptr) { shiftFocusFunc_(nextId, displayId); } @@ -6033,6 +6034,101 @@ void SceneSessionManager::UpdateFocusStatus(DisplayId displayId, const sptr& preSceneSession, + const sptr& currSceneSession, bool isProactiveUnfocus) +{ + if (preSceneSession == nullptr || currSceneSession == nullptr) { + TLOGE(WmsLogTag::WMS_FOCUS, "sceneSession is nullptr"); + return; + } + if(isProactiveUnfocus){ + TLOGD(WmsLogTag::WMS_FOCUS, "proactiveUnfocus"); + RemoveHighlightSessionIds(preSceneSession); + } + if(currSceneSession->GetSessionProperty()->GetExclusivelyHighlighted()) { + TLOGD(WmsLogTag::WMS_FOCUS, "exclusively highlighted"); + SetHighlightSessionIds(currSceneSession); + return; + } + if(currSceneSession->GetSessionInfo().isSystem_) { + TLOGD(WmsLogTag::WMS_FOCUS, "system highlighted"); + AddHighlightSessionIds(currSceneSession); + return; + } + if(currSceneSession->IsSameMainSession(preSceneSession)) { + TLOGD(WmsLogTag::WMS_FOCUS, "related highlighted"); + AddHighlightSessionIds(currSceneSession); + return; + } + TLOGD(WmsLogTag::WMS_FOCUS, "highlighted"); + SetHighlightSessionIds(currSceneSession); +} + +/** @note @window.focus */ +void SceneSessionManager::SetHighlightSessionIds(const sptr& sceneSession) +{ + if (sceneSession == nullptr) { + TLOGE(WmsLogTag::WMS_FOCUS, "sceneSession is nullptr"); + return; + } + for (auto persistentId : highlightIds_) { + auto session = GetSceneSession(persistentId); + if (session == nullptr) { + TLOGE(WmsLogTag::WMS_FOCUS, "session is nullptr"); + continue; + } + if (sceneSession->GetPersistentId() != persistentId) { + session->UpdateHighlightStatus(false); + } + } + sceneSession->UpdateHighlightStatus(true); + highlightIds_.clear(); + highlightIds_.insert(sceneSession->GetPersistentId()); + TLOGI(WmsLogTag::WMS_FOCUS, "highlightIds: %{public}s", GetHighlightIdsStr().c_str()); +} + +/** @note @window.focus */ +void SceneSessionManager::AddHighlightSessionIds(const sptr& sceneSession) +{ + if (sceneSession == nullptr) { + TLOGE(WmsLogTag::WMS_FOCUS, "sceneSession is nullptr"); + return; + } + sceneSession->UpdateHighlightStatus(true); + highlightIds_.insert(sceneSession->GetPersistentId()); + TLOGI(WmsLogTag::WMS_FOCUS, "highlightIds: %{public}s", GetHighlightIdsStr().c_str()); +} + +/** @note @window.focus */ +void SceneSessionManager::RemoveHighlightSessionIds(const sptr& sceneSession) +{ + if (sceneSession == nullptr) { + TLOGE(WmsLogTag::WMS_FOCUS, "sceneSession is nullptr"); + return; + } + if (highlightIds_.find(sceneSession->GetPersistentId()) != highlightIds_.end()) { + sceneSession->UpdateHighlightStatus(false); + highlightIds_.erase(sceneSession->GetPersistentId()); + } else { + TLOGE(WmsLogTag::WMS_FOCUS, "not found scene session with id: %{public}d", sceneSession->GetPersistentId()); + } + TLOGI(WmsLogTag::WMS_FOCUS, "highlightIds: %{public}s", GetHighlightIdsStr().c_str()); +} + +/** @note @window.focus */ +std::string SceneSessionManager::GetHighlightIdsStr() +{ + std::ostringstream oss; + for (auto it = highlightIds_.begin(); it != highlightIds_.end(); it++) { + oss << *it; + if(std::next(it) != highlightIds_.end()) { + oss << ", "; + } + } + return oss.str(); +} + void SceneSessionManager::NotifyFocusStatus(const sptr& sceneSession, bool isFocused, const sptr& focusGroup) { diff --git a/window_scene/test/mock/mock_session_stage.h b/window_scene/test/mock/mock_session_stage.h index 9e3db174e25ac843569c55397d5adf984906aea4..1a985d728055a3e31cfd1f8a51ed4140eec619fa 100644 --- a/window_scene/test/mock/mock_session_stage.h +++ b/window_scene/test/mock/mock_session_stage.h @@ -74,6 +74,7 @@ public: MOCK_METHOD1(SetSplitButtonVisible, WSError(bool isVisible)); MOCK_METHOD1(SetEnableDragBySystem, WSError(bool enableDrag)); MOCK_METHOD2(SendContainerModalEvent, WSError(const std::string& eventName, const std::string& eventValue)); + MOCK_METHOD1(NotifyHighlightChange, WSError(bool isHighlight)); MOCK_METHOD1(SetDragActivated, WSError(bool dragActivated)); }; } // namespace Rosen diff --git a/window_scene/test/unittest/scene_session_manager_test12.cpp b/window_scene/test/unittest/scene_session_manager_test12.cpp index eb0b5a2f15d7ce74e2552afe1a6f12d29caece29..08445e3429a622d629abe5f5e97566a812d781cf 100644 --- a/window_scene/test/unittest/scene_session_manager_test12.cpp +++ b/window_scene/test/unittest/scene_session_manager_test12.cpp @@ -1303,6 +1303,146 @@ HWTEST_F(SceneSessionManagerTest12, HasFloatingWindowForeground06, Function | Sm EXPECT_EQ(result, WMError::WM_OK); EXPECT_EQ(hasFloatWindowForeground, false); } + +/** + * @tc.name: UpdateHighlightStatus + * @tc.desc: UpdateHighlightStatus + * @tc.type: FUNC + */ +HWTEST_F(SceneSessionManagerTest12, UpdateHighlightStatus, Function | SmallTest | Level3) +{ + ASSERT_NE(ssm_, nullptr); + sptr property1 = sptr::MakeSptr(); + sptr property2 = sptr::MakeSptr(); + + SessionInfo info1; + info1.abilityName_ = "abilityName_test1"; + info1.bundleName_ = "bundleName_test1"; + + SessionInfo info2; + info2.abilityName_ = "abilityName_test2"; + info2.bundleName_ = "bundleName_test2"; + + sptr preSceneSession = sptr::MakeSptr(info1, nullptr); + sptr currSceneSession = sptr::MakeSptr(info2, nullptr); + + preSceneSession->property_ = property1; + currSceneSession->property_ = property2; + preSceneSession->property_->SetPersistentId(1); + currSceneSession->property_->SetPersistentId(2); + + sptr nullSceneSession1; + sptr nullSceneSession2; + + ssm_->UpdateHighlightStatus(nullSceneSession1, nullSceneSession2, false); + ssm_->UpdateHighlightStatus(preSceneSession, nullSceneSession2, false); + ssm_->UpdateHighlightStatus(preSceneSession, currSceneSession, true); + ssm_->UpdateHighlightStatus(preSceneSession, currSceneSession, false); + currSceneSession->property_->isExclusivelyHighlighted_ = false; + info1.isSystem_ = true; + ssm_->UpdateHighlightStatus(preSceneSession, currSceneSession, false); + info1.isSystem_ = false; + ssm_->UpdateHighlightStatus(preSceneSession, currSceneSession, false); + preSceneSession->property_->SetPersistentId(2); + ssm_->UpdateHighlightStatus(preSceneSession, currSceneSession, false); +} + +/** + * @tc.name: SetHighlightSessionIds + * @tc.desc: SetHighlightSessionIds + * @tc.type: FUNC + */ +HWTEST_F(SceneSessionManagerTest12, SetHighlightSessionIds, Function | SmallTest | Level3) +{ + ASSERT_NE(ssm_, nullptr); + sptr property = sptr::MakeSptr(); + SessionInfo info1; + info1.abilityName_ = "abilityName_test1"; + info1.bundleName_ = "bundleName_test1"; + + sptr currSceneSession = sptr::MakeSptr(info1, nullptr); + currSceneSession->property_ = property; + currSceneSession->property_->SetPersistentId(1); + currSceneSession->persistentId_ = 1; + ssm_->highlightIds_.clear(); + ssm_->SetHighlightSessionIds(currSceneSession); + ASSERT_EQ(ssm_->highlightIds_.count(1) == 1, true); +} + +/** + * @tc.name: AddHighlightSessionIds + * @tc.desc: AddHighlightSessionIds + * @tc.type: FUNC + */ +HWTEST_F(SceneSessionManagerTest12, AddHighlightSessionIds, Function | SmallTest | Level3) +{ + ASSERT_NE(ssm_, nullptr); + sptr property1 = sptr::MakeSptr(); + sptr property2 = sptr::MakeSptr(); + + SessionInfo info1; + info1.abilityName_ = "abilityName_test1"; + info1.bundleName_ = "bundleName_test1"; + + SessionInfo info2; + info2.abilityName_ = "abilityName_test2"; + info2.bundleName_ = "bundleName_test2"; + + sptr preSceneSession = sptr::MakeSptr(info1, nullptr); + sptr currSceneSession = sptr::MakeSptr(info2, nullptr); + + preSceneSession->property_->SetPersistentId(1); + currSceneSession->property_->SetPersistentId(2); + preSceneSession->persistentId_ = 1; + currSceneSession->persistentId_ = 2; + preSceneSession->property_ = property1; + currSceneSession->property_ = property2; + ssm_->AddHighlightSessionIds(currSceneSession); + ssm_->AddHighlightSessionIds(preSceneSession); + ASSERT_EQ(ssm_->highlightIds_.count(1) == 1, true); + ASSERT_EQ(ssm_->highlightIds_.count(2) == 1, true); +} + +/** + * @tc.name: RemoveHighlightSessionIds + * @tc.desc: RemoveHighlightSessionIds + * @tc.type: FUNC + */ +HWTEST_F(SceneSessionManagerTest12, RemoveHighlightSessionIds, Function | SmallTest | Level3) +{ + ASSERT_NE(ssm_, nullptr); + sptr property1 = sptr::MakeSptr(); + sptr property2 = sptr::MakeSptr(); + + SessionInfo info1; + info1.abilityName_ = "abilityName_test1"; + info1.bundleName_ = "bundleName_test1"; + + SessionInfo info2; + info2.abilityName_ = "abilityName_test2"; + info2.bundleName_ = "bundleName_test2"; + + sptr preSceneSession = sptr::MakeSptr(info1, nullptr); + sptr currSceneSession = sptr::MakeSptr(info2, nullptr); + + preSceneSession->property_->SetPersistentId(1); + currSceneSession->property_->SetPersistentId(2); + + preSceneSession->persistentId_ = 1; + currSceneSession->persistentId_ = 2; + + preSceneSession->property_ = property1; + currSceneSession->property_ = property2; + ssm_->AddHighlightSessionIds(currSceneSession); + ssm_->AddHighlightSessionIds(preSceneSession); + ASSERT_EQ(ssm_->highlightIds_.count(1) == 1, true); + ASSERT_EQ(ssm_->highlightIds_.count(2) == 1, true); + ssm_->RemoveHighlightSessionIds(currSceneSession); + ASSERT_EQ(ssm_->highlightIds_.count(2) == 0, true); + ssm_->RemoveHighlightSessionIds(preSceneSession); + ASSERT_EQ(ssm_->highlightIds_.count(1) == 0, true); +} + } } // namespace Rosen } // namespace OHOS diff --git a/window_scene/test/unittest/scene_session_manager_test5.cpp b/window_scene/test/unittest/scene_session_manager_test5.cpp index 4707dc5abfdbf02756b96a81c2fe8ea804f2d721..04d602d41e3bd132697fc89835fe3ae83203e98d 100644 --- a/window_scene/test/unittest/scene_session_manager_test5.cpp +++ b/window_scene/test/unittest/scene_session_manager_test5.cpp @@ -708,7 +708,7 @@ HWTEST_F(SceneSessionManagerTest5, SetShiftFocusListener, Function | SmallTest | info.bundleName_ = "test2"; FocusChangeReason reason = FocusChangeReason::SPLIT_SCREEN; sptr sceneSession = nullptr; - ssm_->ShiftFocus(DEFAULT_DISPLAY_ID, sceneSession, reason); + ssm_->ShiftFocus(DEFAULT_DISPLAY_ID, sceneSession, false, reason); info.isSystem_ = true; sptr property = sptr::MakeSptr(); ASSERT_NE(property, nullptr); @@ -723,7 +723,7 @@ HWTEST_F(SceneSessionManagerTest5, SetShiftFocusListener, Function | SmallTest | ssm_->SetCallingSessionIdSessionListenser(func1); ProcessStartUIAbilityErrorFunc func2; ssm_->SetStartUIAbilityErrorListener(func2); - ssm_->ShiftFocus(DEFAULT_DISPLAY_ID, sceneSession1, reason); + ssm_->ShiftFocus(DEFAULT_DISPLAY_ID, sceneSession1, false, reason); } /** diff --git a/window_scene/test/unittest/scene_session_manager_test9.cpp b/window_scene/test/unittest/scene_session_manager_test9.cpp index 4cdf582fd258ac287a8fffef817011fbc7c4c76f..f74d35f1f452ce2d8b3545007e65900241fdfa33 100644 --- a/window_scene/test/unittest/scene_session_manager_test9.cpp +++ b/window_scene/test/unittest/scene_session_manager_test9.cpp @@ -1099,7 +1099,7 @@ HWTEST_F(SceneSessionManagerTest9, ShiftFocus, Function | SmallTest | Level3) ssm_->sceneSessionMap_.insert({4, nextSession}); auto focusGroup = ssm_->windowFocusController_->GetFocusGroup(DEFAULT_DISPLAY_ID); focusGroup->SetFocusedSessionId(1); - WSError ret = ssm_->ShiftFocus(DEFAULT_DISPLAY_ID, nextSession, FocusChangeReason::DEFAULT); + WSError ret = ssm_->ShiftFocus(DEFAULT_DISPLAY_ID, nextSession, false, FocusChangeReason::DEFAULT); ASSERT_EQ(ret, WSError::WS_OK); ASSERT_EQ(focusedSession->isFocused_, false); ASSERT_EQ(nextSession->isFocused_, true); diff --git a/window_scene/test/unittest/scene_session_test5.cpp b/window_scene/test/unittest/scene_session_test5.cpp index ab030a829370d306d1ff018f84e7badd0b0db4b4..ac8403bfb31d6f92495c43f11121c8c169b22bbc 100644 --- a/window_scene/test/unittest/scene_session_test5.cpp +++ b/window_scene/test/unittest/scene_session_test5.cpp @@ -1726,6 +1726,76 @@ HWTEST_F(SceneSessionTest5, ActivateKeyboardAvoidArea01, Function | SmallTest | ASSERT_EQ(true, sceneSession->IsKeyboardAvoidAreaActive()); } +/** + * @tc.name: IsSameMainSession + * @tc.desc: test IsSameMainSession + * @tc.type: FUNC + */ +HWTEST_F(SceneSessionTest5, IsSameMainSession, Function | SmallTest | Level2) +{ + SessionInfo info1; + info1.abilityName_ = "abilityName_test1"; + info1.bundleName_ = "bundleName_test1"; + SessionInfo info2; + info2.abilityName_ = "abilityName_test2"; + info2.bundleName_ = "bundleName_test2"; + sptr preSceneSession = sptr::MakeSptr(info1, nullptr); + sptr currSceneSession = sptr::MakeSptr(info2, nullptr); + preSceneSession->persistentId_ = 1; + currSceneSession->persistentId_ = 1; + ASSERT_EQ(true, currSceneSession->IsSameMainSession(preSceneSession)); + currSceneSession->persistentId_ = 2; + ASSERT_EQ(false, currSceneSession->IsSameMainSession(preSceneSession)); + + sptr subSession1 = sptr::MakeSptr(info1, nullptr); + sptr subSession2 = sptr::MakeSptr(info2, nullptr); + subSession1->SetParentSession(preSceneSession); + subSession2->SetParentSession(currSceneSession); + currSceneSession->persistentId_ = 1; + subSession1->property_->SetWindowType(WindowType::APP_SUB_WINDOW_BASE); + subSession2->property_->SetWindowType(WindowType::APP_SUB_WINDOW_BASE); + ASSERT_EQ(true, subSession1->IsSameMainSession(subSession1)); + currSceneSession->persistentId_ = 2; + ASSERT_EQ(false, subSession1->IsSameMainSession(subSession1)); +} + +/** + * @tc.name: HandleActionUpdateExclusivelyHighlighted + * @tc.desc: test HandleActionUpdateExclusivelyHighlighted + * @tc.type: FUNC + */ +HWTEST_F(SceneSessionTest5, HandleActionUpdateExclusivelyHighlighted, Function | SmallTest | Level2) +{ + SessionInfo info; + info.abilityName_ = "HandleActionUpdateExclusivelyHighlighted"; + info.bundleName_ = "HandleActionUpdateExclusivelyHighlighted"; + info.isSystem_ = true; + sptr session = sptr::MakeSptr(info, nullptr); + ASSERT_NE(nullptr, session); + sptr property = sptr::MakeSptr(); + ASSERT_NE(nullptr, property); + property->SetExclusivelyHighlighted(true); + WSPropertyChangeAction action = WSPropertyChangeAction::ACTION_UPDATE_EXCLUSIVE_HIGHLIGHTED; + auto res = session->HandleActionUpdateExclusivelyHighlighted(property, action); + EXPECT_EQ(WMError::WM_OK, res); +} + +/** + * @tc.name: SetHighlightChangeNotifyFunc + * @tc.desc: SetHighlightChangeNotifyFunc Test + * @tc.type: FUNC + */ +HWTEST_F(SceneSessionTest5, SetHighlightChangeNotifyFunc, Function | SmallTest | Level2) +{ + SessionInfo info; + info.abilityName_ = "test"; + info.bundleName_ = "test"; + sptr session = sptr::MakeSptr(info, nullptr); + EXPECT_NE(session, nullptr); + session->SetHighlightChangeNotifyFunc([](int32_t persistentId) {}); + EXPECT_NE(session->highlightChangeFunc_, nullptr); +} + /** * @tc.name: StartMovingWithCoordinate_01 * @tc.desc: StartMovingWithCoordinate diff --git a/window_scene/test/unittest/session_stage_stub_test.cpp b/window_scene/test/unittest/session_stage_stub_test.cpp index 0ef062f9e2aeb89670c4f486a8f795f48648b374..74141b7a23608111afb373da9ae377fbe811f8d9 100644 --- a/window_scene/test/unittest/session_stage_stub_test.cpp +++ b/window_scene/test/unittest/session_stage_stub_test.cpp @@ -890,6 +890,21 @@ HWTEST_F(SessionStageStubTest, HandleSendContainerModalEvent, Function | SmallTe data.WriteString("value2"); ASSERT_EQ(0, sessionStageStub_->HandleSendContainerModalEvent(data, reply)); } + +/** + * @tc.name: HandleNotifyHighlightChange + * @tc.desc: test function : HandleNotifyHighlightChange + * @tc.type: FUNC + */ +HWTEST_F(SessionStageStubTest, HandleNotifyHighlightChange, Function | SmallTest | Level1) +{ + MessageParcel data; + MessageParcel reply; + + data.WriteBool(false); + ASSERT_TRUE(sessionStageStub_ != nullptr); + ASSERT_EQ(0, sessionStageStub_->HandleNotifyHighlightChange(data, reply)); +} } } } \ No newline at end of file diff --git a/window_scene/test/unittest/session_test.cpp b/window_scene/test/unittest/session_test.cpp index 6959d2ef8b7530dba5bc42d8f8e7af718f65f4a1..6a15b5e247f9d5e4505e3bebe52b30d6813da223 100644 --- a/window_scene/test/unittest/session_test.cpp +++ b/window_scene/test/unittest/session_test.cpp @@ -1624,6 +1624,53 @@ HWTEST_F(WindowSessionTest, UpdateClientRectPosYAndDisplayId03, Function | Small session_->UpdateClientRectPosYAndDisplayId(rect); EXPECT_EQ(rect.posY_, 1000); } + +/** + * @tc.name: SetExclusivelyHighlighted + * @tc.desc: SetExclusivelyHighlighted Test + * @tc.type: FUNC + */ +HWTEST_F(WindowSessionTest, SetExclusivelyHighlighted, Function | SmallTest | Level2) +{ + ASSERT_NE(session_, nullptr); + session_->SetExclusivelyHighlighted(false); + bool isExclusivelyHighlighted = session_->GetSessionProperty()->GetExclusivelyHighlighted(); + ASSERT_EQ(isExclusivelyHighlighted, false); + session_->SetExclusivelyHighlighted(true); + isExclusivelyHighlighted = session_->GetSessionProperty()->GetExclusivelyHighlighted(); + ASSERT_EQ(isExclusivelyHighlighted, true); +} + +/** + * @tc.name: UpdateHighlightStatus + * @tc.desc: UpdateHighlightStatus Test + * @tc.type: FUNC + */ +HWTEST_F(WindowSessionTest, UpdateHighlightStatus, Function | SmallTest | Level2) +{ + ASSERT_NE(session_, nullptr); + EXPECT_EQ(session_->UpdateHighlightStatus(false, false), WSError::WS_DO_NOTHING); + + EXPECT_EQ(session_->UpdateHighlightStatus(true, false), WSError::WS_OK); + session_->isHighlight_ = false; + EXPECT_EQ(session_->UpdateHighlightStatus(true, true), WSError::WS_OK); +} + +/** + * @tc.name: NotifyHighlightChange + * @tc.desc: NotifyHighlightChange Test + * @tc.type: FUNC + */ +HWTEST_F(WindowSessionTest, NotifyHighlightChange, Function | SmallTest | Level2) +{ + ASSERT_NE(session_, nullptr); + EXPECT_EQ(session_->NotifyHighlightChange(true), WSError::WS_ERROR_INVALID_SESSION); + session_->sessionStage_ = mockSessionStage_; + session_->state_ = SessionState::STATE_CONNECT; + EXPECT_EQ(session_->NotifyHighlightChange(true), WSError::WS_OK); + session_->sessionStage_ = nullptr; + EXPECT_EQ(session_->NotifyHighlightChange(true), WSError::WS_ERROR_NULLPTR); +} } } // namespace Rosen } // namespace OHOS diff --git a/wm/include/window_session_impl.h b/wm/include/window_session_impl.h index 880afa0eeb4b7629d2474f058e10268d488041ae..6e17f93ed3188e03f887b8d98dfbb579dfe0b763 100644 --- a/wm/include/window_session_impl.h +++ b/wm/include/window_session_impl.h @@ -354,6 +354,16 @@ public: void RegisterWatchFocusActiveChangeCallback(); void NotifyConsumeResultToFloatWindow(const std::shared_ptr& keyEvent, bool isConsumed); + /* + * HightLight Window + */ + bool GetExclusivelyHighlighted() const; + WMError IsWindowHighlighted(bool& highlighted) const override; + WMError SetExclusivelyHighlighted(bool isExclusivelyHighlighted) override; + WMError RegisterWindowHighlightChangeListeners(const sptr& listener) override; + WMError UnregisterWindowHighlightChangeListeners(const sptr& listener) override; + WSError NotifyHighlightChange(bool isHighlight) override; + protected: WMError Connect(); bool IsWindowSessionInvalid() const; @@ -445,6 +455,7 @@ protected: bool isIgnoreSafeAreaNeedNotify_ = false; bool isIgnoreSafeArea_ = false; std::atomic_bool isFocused_ = false; + std::atomic_bool isHighlighted_ = false; std::shared_ptr handler_ = nullptr; bool shouldReNotifyFocus_ = false; std::shared_ptr vsyncStation_ = nullptr; @@ -558,6 +569,8 @@ private: EnableIfSame>> GetListeners(); template EnableIfSame>> GetListeners(); + template + EnableIfSame>> GetListeners(); void NotifyAfterFocused(); void NotifyUIContentFocusStatus(); void NotifyAfterUnfocused(bool needNotifyUiContent = true); @@ -625,6 +638,7 @@ private: static std::mutex displayMoveListenerMutex_; static std::mutex windowRectChangeListenerMutex_; static std::mutex switchFreeMultiWindowListenerMutex_; + static std::mutex highlightChangeListenerMutex_; static std::map>> lifecycleListeners_; static std::map>> displayMoveListeners_; static std::map>> windowChangeListeners_; @@ -643,6 +657,7 @@ private: static std::map>> windowStatusChangeListeners_; static std::map>> windowRectChangeListeners_; static std::map>> switchFreeMultiWindowListeners_; + static std::map>> highlightChangeListeners_; // FA only sptr aceAbilityHandler_; diff --git a/wm/src/window_session_impl.cpp b/wm/src/window_session_impl.cpp index d0b26a450a429011877dbd6cc2ae7fe560778ec7..49d7431024e851fb794e87750094c8da1fc6bba1 100644 --- a/wm/src/window_session_impl.cpp +++ b/wm/src/window_session_impl.cpp @@ -123,6 +123,7 @@ std::map> WindowSessionImpl::subWindowClo std::map> WindowSessionImpl::mainWindowCloseListeners_; std::unordered_map>> WindowSessionImpl::windowWillCloseListeners_; std::map>> WindowSessionImpl::switchFreeMultiWindowListeners_; +std::map>> WindowSessionImpl::highlightChangeListeners_; std::recursive_mutex WindowSessionImpl::lifeCycleListenerMutex_; std::recursive_mutex WindowSessionImpl::windowChangeListenerMutex_; std::recursive_mutex WindowSessionImpl::avoidAreaChangeListenerMutex_; @@ -141,6 +142,7 @@ std::mutex WindowSessionImpl::subWindowCloseListenersMutex_; std::mutex WindowSessionImpl::mainWindowCloseListenersMutex_; std::mutex WindowSessionImpl::windowWillCloseListenersMutex_; std::mutex WindowSessionImpl::switchFreeMultiWindowListenerMutex_; +std::mutex WindowSessionImpl::highlightChangeListenerMutex_; std::map>> WindowSessionImpl::windowSessionMap_; std::shared_mutex WindowSessionImpl::windowSessionMutex_; std::set> WindowSessionImpl::windowExtensionSessionSet_; @@ -1666,6 +1668,65 @@ WindowState WindowSessionImpl::GetRequestWindowState() const return requestState_; } +/** @note @window.focus */ +WMError WindowSessionImpl::SetExclusivelyHighlighted(bool isExclusivelyHighlighted) +{ + if (IsWindowSessionInvalid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + TLOGI(WmsLogTag::WMS_FOCUS, "windowId: %{public}d, isExclusivelyHighlighted: %{public}d", + property_->GetPersistentId(), isExclusivelyHighlighted); + if (WindowHelper::IsMainWindow(GetType()) || WindowHelper::IsDialogWindow(GetType()) || + WindowHelper::IsModalWindow(property_->GetWindowFlags())) { + TLOGE(WmsLogTag::WMS_FOCUS, "unsupport window, type: %{public}u, windowFlags: %{public}u ", + GetType(), property_->GetWindowFlags()); + return WMError::WM_ERROR_INVALID_CALLING; + } + if (property_->GetExclusivelyHighlighted() == isExclusivelyHighlighted) { + TLOGD(WmsLogTag::WMS_FOCUS, "already exclusivelyHighlighted"); + return WMError::WM_OK; + } + property_->SetExclusivelyHighlighted(isExclusivelyHighlighted); + return UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_EXCLUSIVE_HIGHLIGHTED); +} + +/** @note @window.focus */ +bool WindowSessionImpl::GetExclusivelyHighlighted() const +{ + bool isExclusivelyHighlighted = property_->GetExclusivelyHighlighted(); + TLOGD(WmsLogTag::WMS_FOCUS, "windowId: %{public}d, isExclusivelyHighlighted: %{public}d", + property_->GetPersistentId(), isExclusivelyHighlighted); + return isExclusivelyHighlighted; +} + +/** @note @window.focus */ +WSError WindowSessionImpl::NotifyHighlightChange(bool isHighlight) +{ + TLOGI(WmsLogTag::WMS_FOCUS, "windowId: %{public}d, isHighlight: %{public}u,", GetPersistentId(), isHighlight); + isHighlighted_ = isHighlight; + std::lock_guard lockListener(highlightChangeListenerMutex_); + auto highlightChangeListeners = GetListeners(); + for (const auto& listener : highlightChangeListeners) { + if (listener != nullptr) { + listener->OnWindowHighlightChange(isHighlight); + } + } + return WSError::WS_OK; +} + +/** @note @window.focus */ +WMError WindowSessionImpl::IsWindowHighlighted(bool& highlighted) const +{ + if (IsWindowSessionInvalid()) { + TLOGE(WmsLogTag::WMS_FOCUS, "session is invalid"); + return WMError::WM_ERROR_INVALID_WINDOW; + } + highlighted = isHighlighted_.load(); + TLOGD(WmsLogTag::WMS_FOCUS, "windowId: %{public}d, isWindowHighlighted: %{public}d", + GetPersistentId(), isHighlighted_.load()); + return WMError::WM_OK; +} + WMError WindowSessionImpl::SetFocusable(bool isFocusable) { if (IsWindowSessionInvalid()) { @@ -2550,6 +2611,32 @@ WMError WindowSessionImpl::UnregisterSubWindowCloseListeners(const sptr +EnableIfSame>> + WindowSessionImpl::GetListeners() +{ + std::vector> highlightChangeListeners; + for (auto& listener : highlightChangeListeners_[GetPersistentId()]) { + highlightChangeListeners.push_back(listener); + } + return highlightChangeListeners; +} + +WMError WindowSessionImpl::RegisterWindowHighlightChangeListeners(const sptr& listener) +{ + TLOGD(WmsLogTag::WMS_FOCUS, "name=%{public}s, id=%{public}u", GetWindowName().c_str(), GetPersistentId()); + std::lock_guard lockListener(highlightChangeListenerMutex_); + return RegisterListener(highlightChangeListeners_[GetPersistentId()], listener); +} + +WMError WindowSessionImpl::UnregisterWindowHighlightChangeListeners( + const sptr& listener) +{ + TLOGD(WmsLogTag::WMS_FOCUS, "name=%{public}s, id=%{public}u", GetWindowName().c_str(), GetPersistentId()); + std::lock_guard lockListener(highlightChangeListenerMutex_); + return UnregisterListener(highlightChangeListeners_[GetPersistentId()], listener); +} + template EnableIfSame> WindowSessionImpl::GetListeners() { @@ -2878,6 +2965,10 @@ void WindowSessionImpl::ClearListenersById(int32_t persistentId) std::lock_guard lockListener(occupiedAreaChangeListenerMutex_); ClearUselessListeners(occupiedAreaChangeListeners_, persistentId); } + { + std::lock_guard lockListener(highlightChangeListenerMutex_); + ClearUselessListeners(highlightChangeListeners_, persistentId); + } ClearSwitchFreeMultiWindowListenersById(persistentId); TLOGI(WmsLogTag::WMS_LIFE, "Clear success, id: %{public}d.", GetPersistentId()); } diff --git a/wm/test/unittest/window_session_impl_test4.cpp b/wm/test/unittest/window_session_impl_test4.cpp index 082492a84af26c23befb188a15aa07cbcb561933..0dfdb70700c865dc4bce6ce862fa69be233332cc 100644 --- a/wm/test/unittest/window_session_impl_test4.cpp +++ b/wm/test/unittest/window_session_impl_test4.cpp @@ -2444,6 +2444,100 @@ HWTEST_F(WindowSessionImplTest4, GetLayoutTransform, Function | SmallTest | Leve ASSERT_EQ(transform.scaleY_, layoutTransform.scaleY_); ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->Destroy()); } + +/** + * @tc.name: SetExclusivelyHighlighted + * @tc.desc: SetExclusivelyHighlighted + * @tc.type: FUNC + */ +HWTEST_F(WindowSessionImplTest4, SetExclusivelyHighlighted, Function | SmallTest | Level2) +{ + sptr option = sptr::MakeSptr(); + option->SetWindowName("SetExclusivelyHighlighted"); + sptr window = sptr::MakeSptr(option); + SessionInfo sessionInfo = { "CreateTestBundle", "CreateTestModule", "CreateTestAbility" }; + sptr session = sptr::MakeSptr(sessionInfo); + ASSERT_EQ(WMError::WM_OK, window->Create(nullptr, session)); + window->hostSession_ = session; + window->property_->SetPersistentId(INVALID_SESSION_ID); + ASSERT_EQ(window->SetExclusivelyHighlighted(true), WMError::WM_ERROR_INVALID_WINDOW); + window->property_->SetPersistentId(1); + window->property_->SetWindowType(WindowType::APP_MAIN_WINDOW_BASE); + ASSERT_EQ(window->SetExclusivelyHighlighted(true), WMError::WM_ERROR_INVALID_CALLING); + window->property_->SetWindowType(WindowType::WINDOW_TYPE_DIALOG); + ASSERT_EQ(window->SetExclusivelyHighlighted(true), WMError::WM_ERROR_INVALID_CALLING); + window->property_->SetWindowType(WindowType::APP_SUB_WINDOW_BASE); + window->property_->AddWindowFlag(WindowFlag::WINDOW_FLAG_IS_APPLICATION_MODAL); + ASSERT_EQ(window->SetExclusivelyHighlighted(true), WMError::WM_ERROR_INVALID_CALLING); + window->property_->flags_ = 0; + ASSERT_EQ(window->SetExclusivelyHighlighted(true), WMError::WM_OK); + ASSERT_EQ(window->SetExclusivelyHighlighted(false), WMError::WM_OK); +} + +/** + * @tc.name: GetExclusivelyHighlighted + * @tc.desc: GetExclusivelyHighlighted + * @tc.type: FUNC + */ +HWTEST_F(WindowSessionImplTest4, GetExclusivelyHighlighted, Function | SmallTest | Level2) +{ + sptr option = sptr::MakeSptr(); + option->SetWindowName("GetExclusivelyHighlighted"); + sptr window = sptr::MakeSptr(option); + ASSERT_EQ(window->GetExclusivelyHighlighted(), true); +} + +/** + * @tc.name: NotifyHighlightChange + * @tc.desc: NotifyHighlightChange + * @tc.type: FUNC + */ +HWTEST_F(WindowSessionImplTest4, NotifyHighlightChange, Function | SmallTest | Level2) +{ + sptr option = sptr::MakeSptr(); + option->SetWindowName("NotifyHighlightChange01"); + sptr window = sptr::MakeSptr(option); + SessionInfo sessionInfo = { "CreateTestBundle", "CreateTestModule", "CreateTestAbility" }; + sptr session = sptr::MakeSptr(sessionInfo); + window->hostSession_ = session; + window->property_->SetPersistentId(1); + + bool highlight = false; + WSError res = window->NotifyHighlightChange(highlight); + EXPECT_EQ(highlight, false); + EXPECT_EQ(res, WSError::WS_ERROR_NULLPTR); + sptr listener = sptr::MakeSptr(); + window->RegisterWindowHighlightChangeListeners(listener); + res = window->NotifyHighlightChange(highlight); + EXPECT_EQ(highlight, false); + EXPECT_EQ(res, WSError::WS_OK); + window->UnregisterWindowHighlightChangeListeners(listener); +} + +/** + * @tc.name: IsWindowHighlighted + * @tc.desc: IsWindowHighlighted + * @tc.type: FUNC + */ +HWTEST_F(WindowSessionImplTest4, IsWindowHighlighted, Function | SmallTest | Level2) +{ + sptr option = sptr::MakeSptr(); + option->SetWindowName("IsWindowHighlighted"); + sptr window = sptr::MakeSptr(option); + SessionInfo sessionInfo = { "CreateTestBundle", "CreateTestModule", "CreateTestAbility" }; + sptr session = sptr::MakeSptr(sessionInfo); + ASSERT_EQ(WMError::WM_OK, window->Create(nullptr, session)); + window->hostSession_ = session; + window->property_->SetPersistentId(INVALID_SESSION_ID); + bool isHighlighted = false; + window->IsWindowHighlighted(isHighlighted); + ASSERT_EQ(isHighlighted, false); + window->property_->SetPersistentId(1); + window->isHighlighted_ = true; + window->IsWindowHighlighted(isHighlighted); + ASSERT_EQ(isHighlighted, true); +} + } // namespace } // namespace Rosen } // namespace OHOS