diff --git a/adapter/ohos/entrance/ace_ability.cpp b/adapter/ohos/entrance/ace_ability.cpp index 617dea11..83cb0baa 100644 --- a/adapter/ohos/entrance/ace_ability.cpp +++ b/adapter/ohos/entrance/ace_ability.cpp @@ -36,6 +36,7 @@ #include "adapter/ohos/entrance/flutter_ace_view.h" #include "adapter/ohos/entrance/plugin_utils_impl.h" #include "adapter/ohos/entrance/utils.h" +#include "base/geometry/rect.h" #include "base/log/log.h" #include "base/subwindow/subwindow_manager.h" #include "base/utils/system_properties.h" @@ -191,6 +192,10 @@ void AceAbility::OnStart(const Want& want) OHOS::sptr dragWindowListener(this); window->RegisterDragListener(dragWindowListener); + // register drag event callback + OHOS::sptr occupiedAreaChangeListener(this); + window->RegisterOccupiedAreaChangeListener(occupiedAreaChangeListener); + int32_t width = window->GetRect().width_; int32_t height = window->GetRect().height_; LOGI("AceAbility: windowConfig: width: %{public}d, height: %{public}d, left: %{public}d, top: %{public}d", width, @@ -667,6 +672,34 @@ void AceAbility::OnModeChange(OHOS::Rosen::WindowMode mode) LOGI("AceAbility::OnModeChange"); } +void AceAbility::OnSizeChange(const sptr& info) +{ + auto rect = info->rect_; + auto type = info->type_; + Rect keyboardRect = Rect(rect.posX_, rect.posY_, rect.width_, rect.height_); + LOGI("AceAbility::OccupiedAreaChange rect:%{public}s type: %{public}d", keyboardRect.ToString().c_str(), type); + if (type == OHOS::Rosen::OccupiedAreaType::TYPE_INPUT) { + auto container = Platform::AceContainer::GetContainer(abilityId_); + if (!container) { + LOGE("container may be destroyed."); + return; + } + auto taskExecutor = container->GetTaskExecutor(); + if (!taskExecutor) { + LOGE("OnSizeChange: taskExecutor is null."); + return; + } + + ContainerScope scope(abilityId_); + taskExecutor->PostTask([container, keyboardRect] { + auto context = container->GetPipelineContext(); + if (context != nullptr) { + context->OnVirtualKeyboardAreaChange(keyboardRect); + } + }, TaskExecutor::TaskType::UI); + } +} + void AceAbility::Dump(const std::vector& params, std::vector& info) { auto container = Platform::AceContainer::GetContainer(abilityId_); @@ -674,10 +707,18 @@ void AceAbility::Dump(const std::vector& params, std::vectorGetPipelineContext(); - if (context != nullptr) { - context->DumpInfo(params, info); + auto taskExecutor = container->GetTaskExecutor(); + if (!taskExecutor) { + LOGE("OnSizeChange: taskExecutor is null."); + return; } + ContainerScope scope(abilityId_); + taskExecutor->PostSyncTask([container, params, &info] { + auto context = container->GetPipelineContext(); + if (context != nullptr) { + context->DumpInfo(params, info); + } + }, TaskExecutor::TaskType::UI); } void AceAbility::OnDrag(int32_t x, int32_t y, OHOS::Rosen::DragEvent event) diff --git a/adapter/ohos/entrance/ace_ability.h b/adapter/ohos/entrance/ace_ability.h index 6e1a8f60..65a2dcf0 100644 --- a/adapter/ohos/entrance/ace_ability.h +++ b/adapter/ohos/entrance/ace_ability.h @@ -30,7 +30,8 @@ namespace OHOS::Ace { class AceAbility final : public OHOS::AppExecFwk::Ability, public OHOS::Rosen::IWindowChangeListener, - public OHOS::Rosen::IWindowDragListener { + public OHOS::Rosen::IWindowDragListener, + public OHOS::Rosen::IOccupiedAreaChangeListener { public: AceAbility() { @@ -68,6 +69,8 @@ public: // override Rosen::IWindowChangeListener virtual callback function void OnSizeChange(OHOS::Rosen::Rect rect, OHOS::Rosen::WindowSizeChangeReason reason) override; void OnModeChange(OHOS::Rosen::WindowMode mode) override; + // override Rosen::IOccupiedAreaChangeListener virtual callback function + void OnSizeChange(const sptr& info) override; void Dump(const std::vector& params, std::vector& info) override; diff --git a/adapter/ohos/entrance/ui_content_impl.cpp b/adapter/ohos/entrance/ui_content_impl.cpp index 612b5d3a..f5d70367 100644 --- a/adapter/ohos/entrance/ui_content_impl.cpp +++ b/adapter/ohos/entrance/ui_content_impl.cpp @@ -125,6 +125,43 @@ extern "C" ACE_EXPORT void* OHOS_ACE_CreateUIContent(void* context, void* runtim return new UIContentImpl(reinterpret_cast(context), runtime); } +class OccupiedAreaChangeListener : public OHOS::Rosen::IOccupiedAreaChangeListener { +public: + explicit OccupiedAreaChangeListener(int32_t instanceId) : instanceId_(instanceId) {} + ~OccupiedAreaChangeListener() = default; + + void OnSizeChange(const sptr& info) + { + auto rect = info->rect_; + auto type = info->type_; + Rect keyboardRect = Rect(rect.posX_, rect.posY_, rect.width_, rect.height_); + LOGI("UIContent::OccupiedAreaChange rect:%{public}s type: %{public}d", keyboardRect.ToString().c_str(), type); + if (type == OHOS::Rosen::OccupiedAreaType::TYPE_INPUT) { + auto container = Platform::AceContainer::GetContainer(instanceId_); + if (!container) { + LOGE("container may be destroyed."); + return; + } + auto taskExecutor = container->GetTaskExecutor(); + if (!taskExecutor) { + LOGE("OnSizeChange: taskExecutor is null."); + return; + } + + ContainerScope scope(instanceId_); + taskExecutor->PostTask([container, keyboardRect] { + auto context = container->GetPipelineContext(); + if (context != nullptr) { + context->OnVirtualKeyboardAreaChange(keyboardRect); + } + }, TaskExecutor::TaskType::UI); + } + } + +private: + int32_t instanceId_ = -1; +}; + class DragWindowListener : public OHOS::Rosen::IWindowDragListener { public: explicit DragWindowListener(int32_t instanceId) : instanceId_(instanceId) {} @@ -705,6 +742,8 @@ void UIContentImpl::InitWindowCallback(const std::shared_ptrRegisterDragListener(dragWindowListener_); + occupiedAreaChangeListener_ = new OccupiedAreaChangeListener(instanceId_); + window->RegisterOccupiedAreaChangeListener(occupiedAreaChangeListener_); } void UIContentImpl::InitializeSubWindow(OHOS::Rosen::Window* window) diff --git a/adapter/ohos/entrance/ui_content_impl.h b/adapter/ohos/entrance/ui_content_impl.h index f13b68c9..a060ae18 100644 --- a/adapter/ohos/entrance/ui_content_impl.h +++ b/adapter/ohos/entrance/ui_content_impl.h @@ -75,6 +75,7 @@ private: int32_t instanceId_ = -1; bool updateConfig_ = false; OHOS::sptr dragWindowListener_ = nullptr; + OHOS::sptr occupiedAreaChangeListener_ = nullptr; }; } // namespace OHOS::Ace diff --git a/frameworks/core/common/manager_interface.h b/frameworks/core/common/manager_interface.h index e269f87a..d6905af7 100644 --- a/frameworks/core/common/manager_interface.h +++ b/frameworks/core/common/manager_interface.h @@ -28,6 +28,11 @@ class ManagerInterface : public AceType { public: virtual void SetClickPosition(const Offset& position) {} + virtual const Offset& GetClickPosition() + { + static Offset empty; + return empty; + } virtual void MovePage(int32_t pageId, const Offset& rootRect, double offsetHeight) {} virtual void SetScrollElement(int32_t pageId, const WeakPtr& scrollElement) {} virtual void RemovePageId(int32_t pageId) {} diff --git a/frameworks/core/common/text_field_manager.h b/frameworks/core/common/text_field_manager.h index 906bfb7e..e57bd1e3 100644 --- a/frameworks/core/common/text_field_manager.h +++ b/frameworks/core/common/text_field_manager.h @@ -32,7 +32,7 @@ public: ~TextFieldManager() override = default; void SetClickPosition(const Offset& position) override; - const Offset& GetClickPosition(); + const Offset& GetClickPosition() override; void MovePage(int32_t pageId, const Offset& rootRect, double offsetHeight) override; void SetScrollElement(int32_t pageId, const WeakPtr& scrollElement) override; void RemovePageId(int32_t pageId) override; diff --git a/frameworks/core/pipeline/pipeline_context.cpp b/frameworks/core/pipeline/pipeline_context.cpp index 52c5b5a1..c20bb691 100644 --- a/frameworks/core/pipeline/pipeline_context.cpp +++ b/frameworks/core/pipeline/pipeline_context.cpp @@ -1785,6 +1785,24 @@ void PipelineContext::OnActionEvent(const std::string& action) } } +void PipelineContext::OnVirtualKeyboardAreaChange(Rect keyboardArea) +{ + CHECK_RUN_ON(UI); + double keyboardHeight = keyboardArea.Height(); + double positionY = 0; + if (textFieldManager_) { + positionY = textFieldManager_->GetClickPosition().GetY(); + } + double offsetFix = (height_ - positionY) > 100.0 ? keyboardHeight - (height_ - positionY) / 2.0 : keyboardHeight; + LOGI("OnVirtualKeyboardAreaChange positionY:%{public}f safeArea:%{public}f offsetFix:%{public}f", positionY, + (height_ - keyboardHeight), offsetFix); + if (NearZero(keyboardHeight)) { + SetRootSizeWithWidthHeight(width_, height_, 0); + } else if (positionY > (height_ - keyboardHeight) && offsetFix > 0.0) { + SetRootSizeWithWidthHeight(width_, height_, -offsetFix); + } +} + void PipelineContext::FlushPipelineImmediately() { CHECK_RUN_ON(UI); @@ -1980,7 +1998,7 @@ double PipelineContext::ConvertPxToVp(const Dimension& dimension) const return dimension.Value(); } -void PipelineContext::SetRootSizeWithWidthHeight(int32_t width, int32_t height) +void PipelineContext::SetRootSizeWithWidthHeight(int32_t width, int32_t height, int32_t offset) { CHECK_RUN_ON(UI); auto frontend = weakFrontend_.Upgrade(); @@ -2008,7 +2026,7 @@ void PipelineContext::SetRootSizeWithWidthHeight(int32_t width, int32_t height) dipScale_ = density_ / viewScale_; rootHeight_ = height / viewScale_; rootWidth_ = width / viewScale_; - SetRootRect(rootWidth_, rootHeight_); + SetRootRect(rootWidth_, rootHeight_, offset); GridSystemManager::GetInstance().SetWindowInfo(rootWidth_, density_, dipScale_); } @@ -2028,14 +2046,14 @@ void PipelineContext::SetRootSize(double density, int32_t width, int32_t height) TaskExecutor::TaskType::UI); } -void PipelineContext::SetRootRect(double width, double height) const +void PipelineContext::SetRootRect(double width, double height, double offset) const { CHECK_RUN_ON(UI); if (NearZero(viewScale_) || !rootElement_) { LOGW("the view scale is zero or root element is nullptr"); return; } - const Rect paintRect(0.0, 0.0, width, height); + const Rect paintRect(0.0, offset, width, height); auto rootNode = AceType::DynamicCast(rootElement_->GetRenderNode()); if (!rootNode) { return; @@ -2561,6 +2579,7 @@ void PipelineContext::OnHide() } #endif context->NotifyPopupDismiss(); + context->OnVirtualKeyboardAreaChange(Rect()); const auto& rootElement = context->rootElement_; if (!rootElement) { LOGE("render element is null!"); diff --git a/frameworks/core/pipeline/pipeline_context.h b/frameworks/core/pipeline/pipeline_context.h index 0c6b1bd8..97622063 100644 --- a/frameworks/core/pipeline/pipeline_context.h +++ b/frameworks/core/pipeline/pipeline_context.h @@ -239,6 +239,8 @@ public: void OnActionEvent(const std::string& action); + void OnVirtualKeyboardAreaChange(Rect keyboardArea); + // Set card position for barrierfree void SetCardViewPosition(int id, float offsetX, float offsetY); @@ -1237,8 +1239,8 @@ private: void FlushPageUpdateTasks(); void ProcessPreFlush(); void ProcessPostFlush(); - void SetRootSizeWithWidthHeight(int32_t width, int32_t height); - void SetRootRect(double width, double height) const; + void SetRootSizeWithWidthHeight(int32_t width, int32_t height, int32_t offset = 0); + void SetRootRect(double width, double height, double offset = 0.0) const; void FlushBuildAndLayoutBeforeSurfaceReady(); void FlushAnimationTasks(); void DumpAccessibility(const std::vector& params) const;