diff --git a/utils/include/window_helper.h b/utils/include/window_helper.h index 21515367..6c0601bd 100644 --- a/utils/include/window_helper.h +++ b/utils/include/window_helper.h @@ -101,6 +101,28 @@ public: return (r.posX_ == 0 && r.posY_ == 0 && r.width_ == 0 && r.height_ == 0); } + static inline bool HasOverlap(const Rect& r1, const Rect& r2) + { + int32_t r1XEnd = r1.posX_ + r1.width_; + int32_t r1YEnd = r1.posY_ + r1.height_; + int32_t r2XEnd = r2.posX_ + r2.width_; + int32_t r2YEnd = r2.posY_ + r2.height_; + return !(r1XEnd < r2.posX_ || r1.posX_ > r2XEnd || r1YEnd < r2.posY_ || r1.posY_ > r2YEnd); + } + + static inline Rect GetOverlap(const Rect& rect1, const Rect& rect2, const int offsetX, const int offsetY) + { + const static Rect noOverlapRect = { 0, 0, 0, 0}; + int32_t x_begin = std::max(rect1.posX_, rect2.posX_); + int32_t x_end = std::min(rect1.posX_ + rect1.width_, rect2.posX_ + rect2.width_); + int32_t y_begin = std::max(rect1.posY_, rect2.posY_); + int32_t y_end = std::min(rect1.posY_ + rect1.height_, rect2.posY_ + rect2.height_); + if (y_begin > y_end || x_begin > x_end) { + return noOverlapRect; + } + return { x_begin - offsetX, y_begin - offsetY, x_end - x_begin + 1, y_end - y_begin + 1 }; + } + static bool IsWindowModeSupported(uint32_t modeSupportInfo, WindowMode mode) { switch (mode) { diff --git a/wm/test/systemtest/window_occupied_area_change_test.cpp b/wm/test/systemtest/window_occupied_area_change_test.cpp index eba7b5c4..34b4a305 100644 --- a/wm/test/systemtest/window_occupied_area_change_test.cpp +++ b/wm/test/systemtest/window_occupied_area_change_test.cpp @@ -118,10 +118,11 @@ HWTEST_F(WindowOccupiedAreaChangeTest, KeyboardHeightChangeTest01, Function | Me ASSERT_EQ(WMError::WM_OK, window2->Show()); // Await 100ms and get callback result in listener. usleep(WAIT_ASYNC_US); + ASSERT_EQ(testOccupiedAreaChangeListener_->rect_.posX_, window2->GetRect().posX_); ASSERT_EQ(testOccupiedAreaChangeListener_->rect_.posY_, window2->GetRect().posY_); - ASSERT_EQ(testOccupiedAreaChangeListener_->rect_.width_, window2->GetRect().width_); - ASSERT_EQ(testOccupiedAreaChangeListener_->rect_.height_, window2->GetRect().height_); + ASSERT_EQ(testOccupiedAreaChangeListener_->rect_.width_, window2->GetRect().width_ + 1); + ASSERT_EQ(testOccupiedAreaChangeListener_->rect_.height_, window2->GetRect().height_ + 1); } /** diff --git a/wmserver/include/window_node_container.h b/wmserver/include/window_node_container.h index 54417e7b..69a67d46 100644 --- a/wmserver/include/window_node_container.h +++ b/wmserver/include/window_node_container.h @@ -113,8 +113,10 @@ private: void UpdateFocusStatus(uint32_t id, bool focused) const; void UpdateActiveStatus(uint32_t id, bool isActive) const; - void NotifyIfSystemBarTintChanged(DisplayId displayId); - void NotifyIfSystemBarRegionChanged(DisplayId displayId); + void NotifyIfAvoidAreaChanged(const sptr& node, const AvoidControlType avoidType) const; + void NotifyIfSystemBarTintChanged(DisplayId displayId) const; + void NotifyIfSystemBarRegionChanged(DisplayId displayId) const; + void NotifyIfKeyboardRegionChanged(const sptr& node, const AvoidControlType avoidType) const; void TraverseAndUpdateWindowState(WindowState state, int32_t topPriority); void UpdateWindowTree(sptr& node); void UpdateWindowState(sptr node, int32_t topPriority, WindowState state); diff --git a/wmserver/include/window_root.h b/wmserver/include/window_root.h index cea1d329..b109e63a 100644 --- a/wmserver/include/window_root.h +++ b/wmserver/include/window_root.h @@ -100,8 +100,6 @@ private: void UpdateBrightnessWithWindowRemoved(uint32_t windowId, const sptr& container) const; std::string GenAllWindowsLogInfo() const; bool CheckDisplayInfo(const sptr& display); - void NotifyKeyboardSizeChangeInfo(const sptr& node, - const sptr& container, Rect rect); ScreenId GetScreenGroupId(DisplayId displayId, bool& isRecordedDisplay); void ProcessExpandDisplayCreate(DisplayId displayId, ScreenId displayGroupId); std::map> GetAllDisplayInfos(const std::vector& displayIdVec); diff --git a/wmserver/src/window_node_container.cpp b/wmserver/src/window_node_container.cpp index 9acee352..5d329c2f 100644 --- a/wmserver/src/window_node_container.cpp +++ b/wmserver/src/window_node_container.cpp @@ -178,12 +178,7 @@ WMError WindowNodeContainer::AddWindowNode(sptr& node, sptrAddWindowNode(node); - if (WindowHelper::IsAvoidAreaWindow(node->GetWindowType())) { - avoidController_->AvoidControl(node, AvoidControlType::AVOID_NODE_ADD); - NotifyIfSystemBarRegionChanged(node->GetDisplayId()); - } else { - NotifyIfSystemBarTintChanged(node->GetDisplayId()); - } + NotifyIfAvoidAreaChanged(node, AvoidControlType::AVOID_NODE_ADD); std::vector> infos; UpdateWindowVisibilityInfos(infos); DumpScreenWindowTree(); @@ -299,12 +294,7 @@ WMError WindowNodeContainer::RemoveWindowNode(sptr& node) if (HandleRemoveWindow(node) != WMError::WM_OK) { return WMError::WM_ERROR_NULLPTR; } - if (WindowHelper::IsAvoidAreaWindow(node->GetWindowType())) { - avoidController_->AvoidControl(node, AvoidControlType::AVOID_NODE_REMOVE); - NotifyIfSystemBarRegionChanged(node->GetDisplayId()); - } else { - NotifyIfSystemBarTintChanged(node->GetDisplayId()); - } + NotifyIfAvoidAreaChanged(node, AvoidControlType::AVOID_NODE_REMOVE); if (WindowHelper::IsMainFullScreenWindow(node->GetWindowType(), node->GetWindowMode())) { NotifyDockWindowStateChanged(node, true); } @@ -773,7 +763,20 @@ std::unordered_map WindowNodeContainer::GetExpect return sysBarPropMap; } -void WindowNodeContainer::NotifyIfSystemBarTintChanged(DisplayId displayId) +void WindowNodeContainer::NotifyIfAvoidAreaChanged(const sptr& node, + const AvoidControlType avoidType) const +{ + if (WindowHelper::IsAvoidAreaWindow(node->GetWindowType())) { + avoidController_->AvoidControl(node, avoidType); + NotifyIfSystemBarRegionChanged(node->GetDisplayId()); + } else { + NotifyIfSystemBarTintChanged(node->GetDisplayId()); + } + + NotifyIfKeyboardRegionChanged(node, avoidType); +} + +void WindowNodeContainer::NotifyIfSystemBarTintChanged(DisplayId displayId) const { WM_FUNCTION_TRACE(); auto expectSystemBarProp = GetExpectImmersiveProperty(); @@ -793,7 +796,7 @@ void WindowNodeContainer::NotifyIfSystemBarTintChanged(DisplayId displayId) WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(displayId, tints); } -void WindowNodeContainer::NotifyIfSystemBarRegionChanged(DisplayId displayId) +void WindowNodeContainer::NotifyIfSystemBarRegionChanged(DisplayId displayId) const { WM_FUNCTION_TRACE(); SystemBarRegionTints tints; @@ -815,6 +818,50 @@ void WindowNodeContainer::NotifyIfSystemBarRegionChanged(DisplayId displayId) WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(displayId, tints); } +void WindowNodeContainer::NotifyIfKeyboardRegionChanged(const sptr& node, + const AvoidControlType avoidType) const +{ + if (node->GetWindowType() != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) { + WLOGFD("windowType: %{public}u", node->GetWindowType()); + return; + } + + auto callingWindow = FindWindowNodeById(node->GetCallingWindow()); + if (callingWindow == nullptr) { + WLOGFI("callingWindow: %{public}u does not be set", node->GetCallingWindow()); + callingWindow = FindWindowNodeById(GetFocusWindow()); + } + if (callingWindow == nullptr || callingWindow->GetWindowToken() == nullptr) { + WLOGFE("does not have correct callingWindow for input method window"); + return; + } + const WindowMode callingWindowMode = callingWindow->GetWindowMode(); + if (callingWindowMode == WindowMode::WINDOW_MODE_FULLSCREEN || + callingWindowMode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || + callingWindowMode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY || + callingWindowMode == WindowMode::WINDOW_MODE_FLOATING) { + const Rect keyRect = node->GetWindowRect(); + const Rect callingRect = callingWindow->GetWindowRect(); + if (!WindowHelper::HasOverlap(callingRect, keyRect)) { + WLOGFD("no overlap between two windows"); + return; + } + Rect overlapRect = { 0, 0, 0, 0 }; + if (avoidType == AvoidControlType::AVOID_NODE_ADD || avoidType == AvoidControlType::AVOID_NODE_UPDATE) { + overlapRect = WindowHelper::GetOverlap(keyRect, callingRect, callingRect.posX_, callingRect.posY_); + } + + WLOGFI("keyboard size change callingWindow: [%{public}s, %{public}u], " \ + "overlap rect: [%{public}d, %{public}d, %{public}u, %{public}u]", + callingWindow->GetWindowName().c_str(), callingWindow->GetWindowId(), + overlapRect.posX_, overlapRect.posY_, overlapRect.width_, overlapRect.height_); + sptr info = new OccupiedAreaChangeInfo(OccupiedAreaType::TYPE_INPUT, overlapRect); + callingWindow->GetWindowToken()->UpdateOccupiedAreaChangeInfo(info); + return; + } + WLOGFE("does not have correct callingWindowMode for input method window"); +} + void WindowNodeContainer::NotifySystemBarDismiss(sptr& node) { WM_FUNCTION_TRACE(); diff --git a/wmserver/src/window_root.cpp b/wmserver/src/window_root.cpp index ba2d9ced..35c34a81 100644 --- a/wmserver/src/window_root.cpp +++ b/wmserver/src/window_root.cpp @@ -119,38 +119,6 @@ bool WindowRoot::CheckDisplayInfo(const sptr& display) return true; } -void WindowRoot::NotifyKeyboardSizeChangeInfo(const sptr& node, - const sptr& container, Rect rect) -{ - if (node == nullptr || container == nullptr) { - WLOGFE("invalid parameter"); - return; - } - - if (node->GetWindowType() != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) { - return; - } - - auto callingWindow = GetWindowNode(node->GetCallingWindow()); - if (callingWindow == nullptr) { - WLOGFI("callingWindow: %{public}u does not be set", node->GetCallingWindow()); - callingWindow = GetWindowNode(container->GetFocusWindow()); - } - if (callingWindow != nullptr && callingWindow->GetWindowToken() != nullptr && - (callingWindow->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN || - callingWindow->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || - callingWindow->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY)) { - WLOGFI("keyboard size change callingWindow: [%{public}s, %{public}u], " \ - "input rect: [%{public}d, %{public}d, %{public}u, %{public}u]", - callingWindow->GetWindowName().c_str(), callingWindow->GetWindowId(), - rect.posX_, rect.posY_, rect.width_, rect.height_); - sptr info = new OccupiedAreaChangeInfo(OccupiedAreaType::TYPE_INPUT, rect); - callingWindow->GetWindowToken()->UpdateOccupiedAreaChangeInfo(info); - return; - } - WLOGFE("does not have correct callingWindow for input method window"); -} - sptr WindowRoot::GetWindowNode(uint32_t windowId) const { auto iter = windowNodeMap_.find(windowId); @@ -393,7 +361,7 @@ WMError WindowRoot::PostProcessAddWindowNode(sptr& node, sptrSetActiveWindow(node->GetWindowId(), false); - NotifyKeyboardSizeChangeInfo(node, container, node->GetWindowRect()); + for (auto& child : node->children_) { if (child == nullptr || !child->currentVisibility_) { break; @@ -474,8 +442,6 @@ WMError WindowRoot::RemoveWindowNode(uint32_t windowId) UpdateBrightnessWithWindowRemoved(windowId, container); WMError res = container->RemoveWindowNode(node); if (res == WMError::WM_OK) { - Rect rect = { 0, 0, 0, 0 }; - NotifyKeyboardSizeChangeInfo(node, container, rect); for (auto& child : node->children_) { if (child == nullptr) { break; @@ -625,10 +591,6 @@ WMError WindowRoot::DestroyWindow(uint32_t windowId, bool onlySelf) DestroyWindowInner(node); } } - if (res == WMError::WM_OK) { - Rect rect = { 0, 0, 0, 0 }; - NotifyKeyboardSizeChangeInfo(node, container, rect); - } return res; } }