diff --git a/interfaces/innerkits/wm/window.h b/interfaces/innerkits/wm/window.h index 78a2dfaa..68d83d2e 100644 --- a/interfaces/innerkits/wm/window.h +++ b/interfaces/innerkits/wm/window.h @@ -108,6 +108,7 @@ public: virtual WMError Minimize() = 0; virtual WMError Recover() = 0; virtual WMError Close() = 0; + virtual void StartMove() = 0; }; } } diff --git a/interfaces/innerkits/wm/wm_common.h b/interfaces/innerkits/wm/wm_common.h index 95855e1e..125b06a7 100644 --- a/interfaces/innerkits/wm/wm_common.h +++ b/interfaces/innerkits/wm/wm_common.h @@ -112,6 +112,9 @@ namespace { constexpr float DEFAULT_SPLIT_RATIO = 0.5; constexpr uint32_t DIVIDER_WIDTH = 8; constexpr uint32_t INVALID_WINDOW_ID = 0; + constexpr uint32_t HOTZONE = 40; + constexpr uint32_t MIN_VERTICAL_FLOATING_WIDTH = 360; + constexpr uint32_t MIN_VERTICAL_FLOATING_HEIGHT = 480; } struct SystemBarProperty { diff --git a/utils/include/window_helper.h b/utils/include/window_helper.h index bca9272f..37c8bc1f 100644 --- a/utils/include/window_helper.h +++ b/utils/include/window_helper.h @@ -52,6 +52,11 @@ public: return (IsBelowSystemWindow(type) || IsAboveSystemWindow(type)); } + static inline bool IsMainFloatingWindow(WindowType type, WindowMode mode) + { + return ((IsMainWindow(type)) && (mode == WindowMode::WINDOW_MODE_FLOATING)); + } + static inline bool IsSplitWindowMode(WindowMode mode) { return mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || mode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY; @@ -69,6 +74,38 @@ public: return (r.posX_ == 0 && r.posY_ == 0 && r.width_ == 0 && r.height_ == 0); } + static Rect GetFixedWindowRectByMinRect(const Rect& oriDstRect, const Rect& lastRect, bool isVertical) + { + Rect dstRect = oriDstRect; + if (isVertical) { + dstRect.width_ = std::max(MIN_VERTICAL_FLOATING_WIDTH, oriDstRect.width_); + dstRect.height_ = std::max(MIN_VERTICAL_FLOATING_HEIGHT, oriDstRect.height_); + } else { + dstRect.width_ = std::max(MIN_VERTICAL_FLOATING_HEIGHT, oriDstRect.width_); + dstRect.height_ = std::max(MIN_VERTICAL_FLOATING_WIDTH, oriDstRect.height_); + } + + // limit position by fixed width or height + if (oriDstRect.posX_ != lastRect.posX_) { + dstRect.posX_ = oriDstRect.posX_ + oriDstRect.width_ - dstRect.width_; + } + if (oriDstRect.posY_ != lastRect.posY_) { + dstRect.posY_ = oriDstRect.posY_ + oriDstRect.height_ - dstRect.height_; + } + return dstRect; + } + + static bool IsPointInWindow(int32_t pointPosX, int32_t pointPosY, Rect pointRect) + { + if ((pointPosX > pointRect.posX_) && + (pointPosX < static_cast(pointRect.posX_ + pointRect.width_)) && + (pointPosY > pointRect.posY_) && + (pointPosY < static_cast(pointRect.posY_ + pointRect.height_))) { + return true; + } + return false; + } + WindowHelper() = default; ~WindowHelper() = default; }; diff --git a/utils/include/window_property.h b/utils/include/window_property.h index 192c5b88..9533e433 100644 --- a/utils/include/window_property.h +++ b/utils/include/window_property.h @@ -31,6 +31,7 @@ public: void SetWindowName(const std::string& name); void SetWindowRect(const struct Rect& rect); + void SetWindowHotZoneRect(const struct Rect& rect); void SetWindowType(WindowType type); void SetWindowMode(WindowMode mode); void ResumeLastWindowMode(); @@ -49,6 +50,7 @@ public: const std::string& GetWindowName() const; Rect GetWindowRect() const; + Rect GetWindowHotZoneRect() const; WindowType GetWindowType() const; WindowMode GetWindowMode() const; bool GetFullScreen() const; @@ -69,6 +71,7 @@ public: private: std::string windowName_; Rect windowRect_ { 0, 0, 0, 0 }; + Rect hotZoneRect_ { 0, 0, 0, 0 }; WindowType type_ { WindowType::WINDOW_TYPE_APP_MAIN_WINDOW }; WindowMode mode_ { WindowMode::WINDOW_MODE_FULLSCREEN }; WindowMode lastMode_ { WindowMode::WINDOW_MODE_FULLSCREEN }; diff --git a/utils/src/window_property.cpp b/utils/src/window_property.cpp index 233addaf..6aa3a62c 100644 --- a/utils/src/window_property.cpp +++ b/utils/src/window_property.cpp @@ -28,6 +28,14 @@ void WindowProperty::SetWindowRect(const struct Rect& rect) windowRect_ = rect; } +void WindowProperty::SetWindowHotZoneRect(const struct Rect& rect) +{ + hotZoneRect_.posX_ = rect.posX_ - HOTZONE; + hotZoneRect_.posY_ = rect.posY_ - HOTZONE; + hotZoneRect_.width_ = rect.width_ + HOTZONE + HOTZONE; + hotZoneRect_.height_ = rect.height_ + HOTZONE + HOTZONE; +} + void WindowProperty::SetWindowType(WindowType type) { type_ = type; @@ -111,6 +119,11 @@ Rect WindowProperty::GetWindowRect() const return windowRect_; } +Rect WindowProperty::GetWindowHotZoneRect() const +{ + return hotZoneRect_; +} + WindowType WindowProperty::GetWindowType() const { return type_; diff --git a/wm/include/window_adapter.h b/wm/include/window_adapter.h index d7d3db98..379a3301 100644 --- a/wm/include/window_adapter.h +++ b/wm/include/window_adapter.h @@ -43,6 +43,7 @@ public: virtual WMError SaveAbilityToken(const sptr& abilityToken, uint32_t windowId); virtual WMError MoveTo(uint32_t windowId, int32_t x, int32_t y); virtual WMError Resize(uint32_t windowId, uint32_t width, uint32_t height); + virtual WMError Drag(uint32_t windowId, const Rect& rect); virtual WMError RequestFocus(uint32_t windowId); virtual WMError SetWindowFlags(uint32_t windowId, uint32_t flags); virtual WMError SetSystemBarProperty(uint32_t windowId, WindowType type, const SystemBarProperty& property); diff --git a/wm/include/window_impl.h b/wm/include/window_impl.h index 4ed5c504..3515b76b 100644 --- a/wm/include/window_impl.h +++ b/wm/include/window_impl.h @@ -86,6 +86,7 @@ public: virtual WMError Minimize() override; virtual WMError Recover() override; virtual WMError Close() override; + virtual void StartMove() override; virtual WMError RequestFocus() const override; virtual void AddInputEventListener(std::shared_ptr& inputEventListener) override; @@ -99,7 +100,6 @@ public: void UpdateMode(WindowMode mode); virtual void ConsumeKeyEvent(std::shared_ptr& inputEvent) override; virtual void ConsumePointerEvent(std::shared_ptr& inputEvent) override; - void ConsumeDividerPointerEvent(std::shared_ptr& inputEvent); virtual void RequestFrame() override; void UpdateFocusStatus(bool focused); virtual void UpdateConfiguration(const std::shared_ptr& configuration) override; @@ -138,6 +138,11 @@ private: bool IsWindowValid() const; void OnVsync(int64_t timeStamp); static sptr FindTopWindow(uint32_t mainWinId, uint32_t topWinId); + WMError Drag(const Rect& rect); + void ConsumeDividerPointerEvent(std::shared_ptr& inputEvent); + void ConsumeDragOrMoveEvent(std::shared_ptr& pointerEvent); + void HandleDragEvent(const MMI::PointerEvent::PointerItem& pointerItem); + void HandleMoveEvent(const MMI::PointerEvent::PointerItem& pointerItem); std::shared_ptr callback_ = std::make_shared(VsyncStation::VsyncCallback()); @@ -157,6 +162,12 @@ private: const float NAVIGATION_BAR_RATIO = 0.07; const float SYSTEM_ALARM_WINDOW_WIDTH_RATIO = 0.8; const float SYSTEM_ALARM_WINDOW_HEIGHT_RATIO = 0.3; + + int32_t startPointPosX_ = 0; + int32_t startPointPosY_ = 0; + Rect startPointRect_ = {0, 0, 0, 0}; + bool startDragFlag_ = false; + bool startMoveFlag_ = false; }; } } diff --git a/wm/src/window_adapter.cpp b/wm/src/window_adapter.cpp index d14e7180..c29fb6aa 100644 --- a/wm/src/window_adapter.cpp +++ b/wm/src/window_adapter.cpp @@ -97,6 +97,16 @@ WMError WindowAdapter::Resize(uint32_t windowId, uint32_t width, uint32_t height return windowManagerServiceProxy_->Resize(windowId, width, height); } +WMError WindowAdapter::Drag(uint32_t windowId, const Rect& rect) +{ + std::lock_guard lock(mutex_); + + if (!InitWMSProxyLocked()) { + return WMError::WM_ERROR_SAMGR; + } + return windowManagerServiceProxy_->Drag(windowId, rect); +} + WMError WindowAdapter::RequestFocus(uint32_t windowId) { std::lock_guard lock(mutex_); diff --git a/wm/src/window_impl.cpp b/wm/src/window_impl.cpp index dfac5df5..00c3161a 100644 --- a/wm/src/window_impl.cpp +++ b/wm/src/window_impl.cpp @@ -570,6 +570,14 @@ WMError WindowImpl::Resize(uint32_t width, uint32_t height) return SingletonContainer::Get().Resize(property_->GetWindowId(), width, height); } +WMError WindowImpl::Drag(const Rect& rect) +{ + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + return SingletonContainer::Get().Drag(property_->GetWindowId(), rect); +} + bool WindowImpl::IsDecorEnable() const { return property_->GetDecorEnable(); @@ -631,6 +639,12 @@ WMError WindowImpl::Close() return WMError::WM_OK; } +void WindowImpl::StartMove() +{ + startMoveFlag_ = true; + return; +} + WMError WindowImpl::RequestFocus() const { if (!IsWindowValid()) { @@ -733,37 +747,109 @@ void WindowImpl::ConsumeKeyEvent(std::shared_ptr& keyEvent) } } -void WindowImpl::ConsumeDividerPointerEvent(std::shared_ptr& pointerEvent) +void WindowImpl::HandleMoveEvent(const MMI::PointerEvent::PointerItem& pointerItem) +{ + int32_t targetX = startPointRect_.posX_ + (pointerItem.GetGlobalX() - startPointPosX_); + int32_t targetY = startPointRect_.posY_ + (pointerItem.GetGlobalY() - startPointPosY_); + auto res = MoveTo(targetX, targetY); + if (res != WMError::WM_OK) { + WLOGFE("move window: %{public}d failed", GetWindowId()); + } +} + +void WindowImpl::HandleDragEvent(const MMI::PointerEvent::PointerItem& pointerItem) +{ + int32_t diffX = pointerItem.GetGlobalX() - startPointPosX_; + int32_t diffY = pointerItem.GetGlobalY() - startPointPosY_; + Rect newRect = startPointRect_; + if (startPointPosX_ <= startPointRect_.posX_) { + newRect.posX_ += diffX; + newRect.width_ -= diffX; + } else if (startPointPosX_ >= static_cast(startPointRect_.posX_ + startPointRect_.width_)) { + newRect.width_ += diffX; + } + if (startPointPosY_ <= startPointRect_.posY_) { + newRect.posY_ += diffY; + newRect.height_ -= diffY; + } else if (startPointPosY_ >= static_cast(startPointRect_.posY_ + startPointRect_.height_)) { + newRect.height_ += diffY; + } + auto res = Drag(newRect); + if (res != WMError::WM_OK) { + WLOGFE("drag window: %{public}d failed", GetWindowId()); + } +} + +void WindowImpl::ConsumeDragOrMoveEvent(std::shared_ptr& pointerEvent) { - static int32_t diffX = 0; - static int32_t diffY = 0; - static bool beginMove = false; int32_t action = pointerEvent->GetPointerAction(); MMI::PointerEvent::PointerItem pointerItem; switch (action) { case MMI::PointerEvent::POINTER_ACTION_DOWN: { if (pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem)) { - beginMove = true; - diffX = abs(pointerItem.GetGlobalX() - GetRect().posX_); - diffY = abs(pointerItem.GetGlobalY() - GetRect().posY_); - WLOGFI("point down divider, diff: [%{public}d, %{public}d]", diffX, diffY); + startPointRect_ = GetRect(); + startPointPosX_ = pointerItem.GetGlobalX(); + startPointPosY_ = pointerItem.GetGlobalY(); + if (!WindowHelper::IsPointInWindow(startPointPosX_, startPointPosY_, startPointRect_)) { + startDragFlag_ = true; + } + WLOGFI("[PointDown] windowId: %{public}d, pointPos: [%{public}d, %{public}d], winRect: " + "[%{public}d, %{public}d, %{public}d, %{public}d], startDragFlag: %{public}d", + GetWindowId(), startPointPosX_, startPointPosY_, startPointRect_.posX_, startPointRect_.posY_, + startPointRect_.width_, startPointRect_.height_, startDragFlag_); } break; } case MMI::PointerEvent::POINTER_ACTION_MOVE: { - if (beginMove && (pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem))) { - int32_t targetX = pointerItem.GetGlobalX() - diffX; - int32_t targetY = pointerItem.GetGlobalY() - diffY; - auto res = MoveTo(targetX, targetY); - if (res != WMError::WM_OK) { - WLOGFE("move divider failed"); + if (pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem)) { + if (startMoveFlag_) { + HandleMoveEvent(pointerItem); + } + if (startDragFlag_) { + HandleDragEvent(pointerItem); } } break; } case MMI::PointerEvent::POINTER_ACTION_UP: case MMI::PointerEvent::POINTER_ACTION_CANCEL: - beginMove = false; + startDragFlag_ = false; + startMoveFlag_ = false; + WLOGFE("[Point Up/Cancel] windowId: %{public}d", GetWindowId()); + break; + default: + break; + } +} + +void WindowImpl::ConsumeDividerPointerEvent(std::shared_ptr& pointerEvent) +{ + int32_t action = pointerEvent->GetPointerAction(); + MMI::PointerEvent::PointerItem pointerItem; + switch (action) { + case MMI::PointerEvent::POINTER_ACTION_DOWN: { + if (pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem)) { + startMoveFlag_ = true; + startPointRect_ = GetRect(); + startPointPosX_ = pointerItem.GetGlobalX(); + startPointPosY_ = pointerItem.GetGlobalY(); + WLOGFI("[Point divider] point pos: [%{public}d, %{public}d], " + "winRect: [%{public}d, %{public}d, %{public}d, %{public}d]", + startPointPosX_, startPointPosY_, startPointRect_.posX_, startPointRect_.posY_, + startPointRect_.width_, startPointRect_.height_); + } + break; + } + case MMI::PointerEvent::POINTER_ACTION_MOVE: { + if (startMoveFlag_ && (pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem))) { + HandleMoveEvent(pointerItem); + } + break; + } + case MMI::PointerEvent::POINTER_ACTION_UP: + case MMI::PointerEvent::POINTER_ACTION_CANCEL: + startMoveFlag_ = false; + WLOGFE("[Point divider Up/Cancel] windowId: %{public}d", GetWindowId()); break; default: break; @@ -780,8 +866,16 @@ void WindowImpl::ConsumePointerEvent(std::shared_ptr& pointer ConsumeDividerPointerEvent(pointerEvent); return; } + + if (WindowHelper::IsMainFloatingWindow(GetType(), GetMode())) { + ConsumeDragOrMoveEvent(pointerEvent); + if (startDragFlag_ || startMoveFlag_) { + return; + } + } + if (uiContent_ == nullptr) { - WLOGE("ConsumePointerEvent uiContent is nullptr"); + WLOGE("ConsumePointerEvent uiContent is nullptr, windowId: %{public}d", GetWindowId()); return; } uiContent_->ProcessPointerEvent(pointerEvent); diff --git a/wm/src/window_input_channel.cpp b/wm/src/window_input_channel.cpp index 07196476..8ed85480 100644 --- a/wm/src/window_input_channel.cpp +++ b/wm/src/window_input_channel.cpp @@ -69,7 +69,7 @@ void WindowInputChannel::HandlePointerEvent(std::shared_ptr& WLOGI("HandlePointerEvent RequestVsync"); VsyncStation::GetInstance().RequestVsync(VsyncStation::CallbackType::CALLBACK_INPUT, callback_); } else { - WLOGI("HandlePointerEvent cosume non-move"); + WLOGI("HandlePointerEvent cosume non-move, windowId: %{public}d", window_->GetWindowId()); window_->ConsumePointerEvent(pointerEvent); pointerEvent->MarkProcessed(); } diff --git a/wm/test/systemtest/BUILD.gn b/wm/test/systemtest/BUILD.gn index 7f27fb84..cfdf991d 100644 --- a/wm/test/systemtest/BUILD.gn +++ b/wm/test/systemtest/BUILD.gn @@ -23,6 +23,7 @@ group("systemtest") { ":wm_window_immersive_test", ":wm_window_input_method_test", ":wm_window_layout_test", + ":wm_window_move_drag_test", ":wm_window_multi_ability_test", ":wm_window_split_test", ":wm_window_subwindow_test", @@ -95,6 +96,17 @@ ohos_systemtest("wm_window_split_test") { ## SystemTest wm_window_split_test }}} +## SystemTest wm_window_move_drag_test {{{ +ohos_systemtest("wm_window_move_drag_test") { + module_out_path = module_out_path + + sources = [ "window_move_drag_test.cpp" ] + + deps = [ ":wm_systemtest_common" ] +} + +## SystemTest wm_window_move_drag_test }}} + ## SystemTest window_input_method_test {{{ ohos_systemtest("wm_window_input_method_test") { module_out_path = module_out_path diff --git a/wm/test/systemtest/window_move_drag_test.cpp b/wm/test/systemtest/window_move_drag_test.cpp new file mode 100644 index 00000000..2e62e197 --- /dev/null +++ b/wm/test/systemtest/window_move_drag_test.cpp @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// gtest +#include +#include "pointer_event.h" +#include "window_helper.h" +#include "window_test_utils.h" +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "WindowMoveDrag"}; + constexpr float POINT_HOTZONE_RATIO = 0.5; + constexpr float DRAG_HOTZONE_RATIO = 0.6; +} +using utils = WindowTestUtils; +class WindowMoveDragTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + +private: + std::shared_ptr CreatePointerEvent(int32_t posX, + int32_t posY, + uint32_t pointerId, + int32_t pointerAction); + void CalExpectRects(); + void DoMoveOrDrag(); + static inline std::vector> activeWindows_; + static inline utils::TestWindowInfo winInfo_; + static inline uint32_t pointerId_ = 0; + static inline int32_t pointX_ = 0; + static inline int32_t pointY_ = 0; + static inline int32_t startPointX_ = 0; + static inline int32_t startPointY_ = 0; + static inline Rect startPointRect_ = {0, 0, 0, 0}; + static inline Rect expectRect_ = {0, 0, 0, 0}; + static inline sptr window_ = nullptr; +}; + +void WindowMoveDragTest::SetUpTestCase() +{ + startPointX_ = 0; + startPointY_ = 0; + pointX_ = 0; + pointY_ = 0; + startPointRect_ = {0, 0, 0, 0}; + expectRect_ = {0, 0, 0, 0}; + winInfo_.rect = {0, 0, 0, 0}; +} + +void WindowMoveDragTest::TearDownTestCase() +{ +} + +void WindowMoveDragTest::SetUp() +{ + auto display = DisplayManager::GetInstance().GetDisplayById(0); + if (display == nullptr) { + WLOGFE("GetDefaultDisplay: failed!\n"); + } else { + WLOGFI("GetDefaultDisplay: id %{public}llu, w %{public}d, h %{public}d, fps %{public}u\n", + display->GetId(), display->GetWidth(), display->GetHeight(), display->GetFreshRate()); + } + Rect displayRect = {0, 0, display->GetWidth(), display->GetHeight()}; + utils::InitByDisplayRect(displayRect); + + winInfo_ = { + .name = "Floating", + .rect = {0, 0, 0, 0}, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = true, + .parentLimit = false, + .parentName = "", + }; + window_ = utils::CreateTestWindow(winInfo_); + ASSERT_TRUE((window_ != nullptr)); +} + +void WindowMoveDragTest::TearDown() +{ + ASSERT_EQ(WMError::WM_OK, window_->Destroy()); +} + +std::shared_ptr WindowMoveDragTest::CreatePointerEvent(int32_t posX, + int32_t posY, + uint32_t pointerId, + int32_t pointerAction) +{ + MMI::PointerEvent::PointerItem pointerItem; + pointerItem.SetPointerId(pointerId); + pointerItem.SetGlobalX(posX); + pointerItem.SetGlobalY(posY); + + std::shared_ptr pointerEvent = MMI::PointerEvent::Create(); + pointerEvent->AddPointerItem(pointerItem); + pointerEvent->SetPointerId(pointerId); + pointerEvent->SetPointerAction(pointerAction); + pointerEvent->SetSourceType(MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN); + return pointerEvent; +} + +void WindowMoveDragTest::DoMoveOrDrag() +{ + std::shared_ptr pointerEvent = + CreatePointerEvent(startPointX_, startPointY_, pointerId_++, MMI::PointerEvent::POINTER_ACTION_DOWN); + window_->ConsumePointerEvent(pointerEvent); + ASSERT_TRUE(utils::RectEqualToRect(window_->GetRect(), startPointRect_)); + + pointerEvent = CreatePointerEvent(pointX_, pointY_, pointerId_++, MMI::PointerEvent::POINTER_ACTION_MOVE); + window_->ConsumePointerEvent(pointerEvent); + CalExpectRects(); + ASSERT_TRUE(utils::RectEqualToRect(window_->GetRect(), expectRect_)); + + pointerEvent = CreatePointerEvent(pointX_, pointY_, pointerId_++, MMI::PointerEvent::POINTER_ACTION_UP); + window_->ConsumePointerEvent(pointerEvent); + ASSERT_TRUE(utils::RectEqualToRect(window_->GetRect(), expectRect_)); +} + +void WindowMoveDragTest::CalExpectRects() +{ + bool isPointInWindow; + if ((startPointX_ > startPointRect_.posX_) && + (startPointX_ < static_cast(startPointRect_.posX_ + startPointRect_.width_)) && + (startPointY_ > startPointRect_.posY_) && + (startPointY_ < static_cast(startPointRect_.posY_ + startPointRect_.height_))) { + isPointInWindow = true; + } else { + isPointInWindow = false; + } + + int32_t diffX = pointX_ - startPointX_; + int32_t diffY = pointY_ - startPointY_; + Rect oriRect = startPointRect_; + if (!isPointInWindow) { + if (startPointX_ <= startPointRect_.posX_) { + oriRect.posX_ += diffX; + oriRect.width_ -= diffX; + } else if (startPointX_ >= static_cast(startPointRect_.posX_ + startPointRect_.width_)) { + oriRect.width_ += diffX; + } + + if (startPointY_ <= startPointRect_.posY_) { + oriRect.posY_ += diffY; + oriRect.height_ -= diffY; + } else if (startPointY_ >= static_cast(startPointRect_.posY_ + startPointRect_.height_)) { + oriRect.height_ += diffY; + } + } + bool isVertical = (utils::displayRect_.width_ < utils::displayRect_.height_) ? true : false; + expectRect_ = WindowHelper::GetFixedWindowRectByMinRect(oriRect, startPointRect_, isVertical); +} + +namespace { +/** + * @tc.name: DragWindow01 + * @tc.desc: drag left + * @tc.type: FUNC + * @tc.require: AR000GGTV8 + */ +HWTEST_F(WindowMoveDragTest, DragWindow01, Function | MediumTest | Level3) +{ + ASSERT_EQ(WMError::WM_OK, window_->Show()); + startPointRect_ = window_->GetRect(); + startPointX_ = startPointRect_.posX_ - HOTZONE * POINT_HOTZONE_RATIO; + startPointY_ = startPointRect_.posY_ + startPointRect_.height_ * POINT_HOTZONE_RATIO; + pointX_ = startPointRect_.posX_ + HOTZONE * DRAG_HOTZONE_RATIO; + pointY_ = startPointRect_.posY_ + HOTZONE * DRAG_HOTZONE_RATIO; + DoMoveOrDrag(); + ASSERT_EQ(WMError::WM_OK, window_->Hide()); +} + +/** + * @tc.name: DragWindow02 + * @tc.desc: drag left top + * @tc.type: FUNC + * @tc.require: AR000GGTV8 + */ +HWTEST_F(WindowMoveDragTest, DragWindow02, Function | MediumTest | Level3) +{ + ASSERT_EQ(WMError::WM_OK, window_->Show()); + startPointRect_ = window_->GetRect(); + startPointX_ = startPointRect_.posX_ - HOTZONE * POINT_HOTZONE_RATIO; + startPointY_ = startPointRect_.posY_ - HOTZONE * POINT_HOTZONE_RATIO; + + pointX_ = startPointRect_.posX_ + HOTZONE * DRAG_HOTZONE_RATIO; + pointY_ = startPointRect_.posY_ + HOTZONE * DRAG_HOTZONE_RATIO; + DoMoveOrDrag(); + ASSERT_EQ(WMError::WM_OK, window_->Hide()); +} + +/** + * @tc.name: DragWindow03 + * @tc.desc: drag left bottom + * @tc.type: FUNC + * @tc.require: AR000GGTV8 + */ +HWTEST_F(WindowMoveDragTest, DragWindow03, Function | MediumTest | Level3) +{ + ASSERT_EQ(WMError::WM_OK, window_->Show()); + startPointRect_ = window_->GetRect(); + startPointX_ = startPointRect_.posX_ - HOTZONE * POINT_HOTZONE_RATIO; + startPointY_ = startPointRect_.posY_ + startPointRect_.height_ + HOTZONE * POINT_HOTZONE_RATIO; + + pointX_ = startPointRect_.posX_ + HOTZONE * DRAG_HOTZONE_RATIO; + pointY_ = startPointRect_.posY_ + startPointRect_.height_ + HOTZONE * DRAG_HOTZONE_RATIO; + DoMoveOrDrag(); + ASSERT_EQ(WMError::WM_OK, window_->Hide()); +} + +/** + * @tc.name: DragWindow04 + * @tc.desc: drag right + * @tc.type: FUNC + * @tc.require: AR000GGTV8 + */ +HWTEST_F(WindowMoveDragTest, DragWindow04, Function | MediumTest | Level3) +{ + ASSERT_EQ(WMError::WM_OK, window_->Show()); + startPointRect_ = window_->GetRect(); + startPointX_ = startPointRect_.posX_ + startPointRect_.width_ + HOTZONE * POINT_HOTZONE_RATIO; + startPointY_ = startPointRect_.posY_ + startPointRect_.height_ * POINT_HOTZONE_RATIO; + + pointX_ = startPointRect_.posX_ + startPointRect_.width_ + HOTZONE * DRAG_HOTZONE_RATIO; + pointY_ = startPointRect_.posY_ + startPointRect_.height_ * DRAG_HOTZONE_RATIO; + DoMoveOrDrag(); + ASSERT_EQ(WMError::WM_OK, window_->Hide()); +} + +/** + * @tc.name: DragWindow05 + * @tc.desc: drag right top + * @tc.type: FUNC + * @tc.require: AR000GGTV8 + */ +HWTEST_F(WindowMoveDragTest, DragWindow05, Function | MediumTest | Level3) +{ + ASSERT_EQ(WMError::WM_OK, window_->Show()); + startPointRect_ = window_->GetRect(); + startPointX_ = startPointRect_.posX_ + startPointRect_.width_ + HOTZONE * POINT_HOTZONE_RATIO; + startPointY_ = startPointRect_.posY_ - HOTZONE * POINT_HOTZONE_RATIO; + + pointX_ = startPointRect_.posX_ + startPointRect_.width_ + HOTZONE * DRAG_HOTZONE_RATIO; + pointY_ = startPointRect_.posY_ + HOTZONE * DRAG_HOTZONE_RATIO; + DoMoveOrDrag(); + ASSERT_EQ(WMError::WM_OK, window_->Hide()); +} + +/** + * @tc.name: DragWindow06 + * @tc.desc: drag right bottom + * @tc.type: FUNC + * @tc.require: AR000GGTV8 + */ +HWTEST_F(WindowMoveDragTest, DragWindow06, Function | MediumTest | Level3) +{ + ASSERT_EQ(WMError::WM_OK, window_->Show()); + startPointRect_ = window_->GetRect(); + startPointX_ = startPointRect_.posX_ + startPointRect_.width_ + HOTZONE * POINT_HOTZONE_RATIO; + startPointY_ = startPointRect_.posY_ + startPointRect_.height_ + HOTZONE * POINT_HOTZONE_RATIO; + + pointX_ = startPointRect_.posX_ + startPointRect_.width_ + HOTZONE * DRAG_HOTZONE_RATIO; + pointY_ = startPointRect_.posY_ + startPointRect_.height_ + HOTZONE * DRAG_HOTZONE_RATIO; + DoMoveOrDrag(); + ASSERT_EQ(WMError::WM_OK, window_->Hide()); +} + +/** + * @tc.name: DragWindow07 + * @tc.desc: drag top + * @tc.type: FUNC + * @tc.require: AR000GGTV8 + */ +HWTEST_F(WindowMoveDragTest, DragWindow07, Function | MediumTest | Level3) +{ + ASSERT_EQ(WMError::WM_OK, window_->Show()); + startPointRect_ = window_->GetRect(); + startPointX_ = startPointRect_.posX_ + startPointRect_.width_ * POINT_HOTZONE_RATIO; + startPointY_ = startPointRect_.posY_ - HOTZONE * POINT_HOTZONE_RATIO; + + pointX_ = startPointRect_.posX_ + startPointRect_.width_ * DRAG_HOTZONE_RATIO; + pointY_ = startPointRect_.posY_ - HOTZONE * DRAG_HOTZONE_RATIO; + DoMoveOrDrag(); + ASSERT_EQ(WMError::WM_OK, window_->Hide()); +} + +/** + * @tc.name: DragWindow08 + * @tc.desc: drag bottom + * @tc.type: FUNC + * @tc.require: AR000GGTV8 + */ +HWTEST_F(WindowMoveDragTest, DragWindow08, Function | MediumTest | Level3) +{ + ASSERT_EQ(WMError::WM_OK, window_->Show()); + startPointRect_ = window_->GetRect(); + startPointX_ = startPointRect_.posX_ + startPointRect_.width_ * POINT_HOTZONE_RATIO; + startPointY_ = startPointRect_.posY_ + startPointRect_.height_ + HOTZONE * POINT_HOTZONE_RATIO; + + pointX_ = startPointRect_.posX_ + startPointRect_.width_ * DRAG_HOTZONE_RATIO; + pointY_ = startPointRect_.posY_ + startPointRect_.height_ + HOTZONE * DRAG_HOTZONE_RATIO; + DoMoveOrDrag(); + ASSERT_EQ(WMError::WM_OK, window_->Hide()); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/wm/test/systemtest/window_test_utils.cpp b/wm/test/systemtest/window_test_utils.cpp index 8cdef5e5..9f5ba90d 100644 --- a/wm/test/systemtest/window_test_utils.cpp +++ b/wm/test/systemtest/window_test_utils.cpp @@ -19,8 +19,6 @@ namespace OHOS { namespace Rosen { namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "WindowTestUtils"}; - constexpr uint32_t MIN_VERTICAL_FLOATING_WIDTH = 360; - constexpr uint32_t MIN_VERTICAL_FLOATING_HEIGHT = 480; } Rect WindowTestUtils::displayRect_ = {0, 0, 0, 0}; diff --git a/wmserver/include/window_controller.h b/wmserver/include/window_controller.h index a5c21fa1..e4d353f1 100644 --- a/wmserver/include/window_controller.h +++ b/wmserver/include/window_controller.h @@ -37,6 +37,7 @@ public: WMError DestroyWindow(uint32_t windowId); WMError MoveTo(uint32_t windowId, int32_t x, int32_t y); WMError Resize(uint32_t windowId, uint32_t width, uint32_t height); + WMError Drag(uint32_t windowId, const Rect& rect); WMError RequestFocus(uint32_t windowId); WMError SaveAbilityToken(const sptr& abilityToken, uint32_t windowId); WMError SetWindowMode(uint32_t windowId, WindowMode dstMode); diff --git a/wmserver/include/window_manager_interface.h b/wmserver/include/window_manager_interface.h index ad1c225b..b2c99852 100644 --- a/wmserver/include/window_manager_interface.h +++ b/wmserver/include/window_manager_interface.h @@ -35,6 +35,7 @@ public: TRANS_ID_DESTROY_WINDOW, TRANS_ID_MOVE, TRANS_ID_RESIZE, + TRANS_ID_DRAG, TRANS_ID_REQUEST_FOCUS, TRANS_ID_UPDATE_TYPE, TRANS_ID_UPDATE_MODE, @@ -58,6 +59,7 @@ public: virtual WMError DestroyWindow(uint32_t windowId) = 0; virtual WMError MoveTo(uint32_t windowId, int32_t x, int32_t y) = 0; virtual WMError Resize(uint32_t windowId, uint32_t width, uint32_t height) = 0; + virtual WMError Drag(uint32_t windowId, const Rect& rect) = 0; virtual WMError RequestFocus(uint32_t windowId) = 0; virtual WMError SetWindowMode(uint32_t windowId, WindowMode mode) = 0; virtual WMError SetWindowType(uint32_t windowId, WindowType type) = 0; diff --git a/wmserver/include/window_manager_proxy.h b/wmserver/include/window_manager_proxy.h index 249b590c..e7ae0a09 100644 --- a/wmserver/include/window_manager_proxy.h +++ b/wmserver/include/window_manager_proxy.h @@ -34,6 +34,7 @@ public: WMError DestroyWindow(uint32_t windowId) override; WMError MoveTo(uint32_t windowId, int32_t x, int32_t y) override; WMError Resize(uint32_t windowId, uint32_t width, uint32_t height) override; + WMError Drag(uint32_t windowId, const Rect& rect) override; WMError RequestFocus(uint32_t windowId) override; WMError SaveAbilityToken(const sptr& abilityToken, uint32_t windowId) override; WMError SetWindowMode(uint32_t windowId, WindowMode mode) override; diff --git a/wmserver/include/window_manager_service.h b/wmserver/include/window_manager_service.h index b1a8cc26..898e8d6b 100644 --- a/wmserver/include/window_manager_service.h +++ b/wmserver/include/window_manager_service.h @@ -53,6 +53,7 @@ public: WMError DestroyWindow(uint32_t windowId) override; WMError MoveTo(uint32_t windowId, int32_t x, int32_t y) override; WMError Resize(uint32_t windowId, uint32_t width, uint32_t height) override; + WMError Drag(uint32_t windowId, const Rect& rect) override; WMError RequestFocus(uint32_t windowId) override; WMError SaveAbilityToken(const sptr& abilityToken, uint32_t windowId) override; WMError SetWindowMode(uint32_t windowId, WindowMode mode) override; diff --git a/wmserver/include/window_node.h b/wmserver/include/window_node.h index 18b5a7cd..0a36874e 100644 --- a/wmserver/include/window_node.h +++ b/wmserver/include/window_node.h @@ -53,6 +53,7 @@ public: const std::string& GetWindowName() const; DisplayId GetDisplayId() const; const Rect& GetLayoutRect() const; + Rect GetHotZoneRect() const; WindowType GetWindowType() const; WindowMode GetWindowMode() const; uint32_t GetWindowFlags() const; diff --git a/wmserver/src/input_window_monitor.cpp b/wmserver/src/input_window_monitor.cpp index 9fa6c986..d632513a 100644 --- a/wmserver/src/input_window_monitor.cpp +++ b/wmserver/src/input_window_monitor.cpp @@ -136,27 +136,19 @@ void InputWindowMonitor::TraverseWindowNodes(const std::vector> windowNode->GetWindowProperty()->GetWindowType()); continue; } + Rect hotZone = windowNode->GetHotZoneRect(); + MMI::WindowInfo windowInfo = { .id = static_cast(windowNode->GetWindowId()), .pid = windowNode->GetCallingPid(), .uid = windowNode->GetCallingUid(), - .topLeftX = windowNode->GetLayoutRect().posX_, - .topLeftY = windowNode->GetLayoutRect().posY_, - .width = static_cast(windowNode->GetLayoutRect().width_), - .height = static_cast(windowNode->GetLayoutRect().height_), + .topLeftX = hotZone.posX_, + .topLeftY = hotZone.posY_, + .width = static_cast(hotZone.width_), + .height = static_cast(hotZone.height_), .displayId = static_cast(windowNode->GetDisplayId()), .agentWindowId = static_cast(windowNode->GetWindowId()), }; - if (windowNode->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { - const int32_t divTouchRegion = 20; - if (windowInfo.width < windowInfo.height) { - windowInfo.topLeftX -= divTouchRegion; - windowInfo.width += (divTouchRegion + divTouchRegion); - } else { - windowInfo.topLeftY -= divTouchRegion; - windowInfo.height += (divTouchRegion + divTouchRegion); - } - } iter->windowsInfo_.emplace_back(windowInfo); } } diff --git a/wmserver/src/window_controller.cpp b/wmserver/src/window_controller.cpp index 1d76a2c7..52c23c51 100644 --- a/wmserver/src/window_controller.cpp +++ b/wmserver/src/window_controller.cpp @@ -154,6 +154,27 @@ WMError WindowController::Resize(uint32_t windowId, uint32_t width, uint32_t hei return WMError::WM_OK; } +WMError WindowController::Drag(uint32_t windowId, const Rect& rect) +{ + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + auto property = node->GetWindowProperty(); + + // fix rect in case of moving window when dragging + Rect newRect = WindowHelper::GetFixedWindowRectByMinRect(rect, + property->GetWindowRect(), windowRoot_->isVerticalDisplay(node)); + property->SetWindowRect(newRect); + WMError res = windowRoot_->UpdateWindowNode(windowId); + if (res != WMError::WM_OK) { + return res; + } + RSTransaction::FlushImplicitTransaction(); + return WMError::WM_OK; +} + WMError WindowController::RequestFocus(uint32_t windowId) { return windowRoot_->RequestFocus(windowId); diff --git a/wmserver/src/window_layout_policy.cpp b/wmserver/src/window_layout_policy.cpp index a2498a7d..fb3e150e 100644 --- a/wmserver/src/window_layout_policy.cpp +++ b/wmserver/src/window_layout_policy.cpp @@ -24,8 +24,6 @@ namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "WindowLayoutPolicy"}; constexpr uint32_t WINDOW_TITLE_BAR_HEIGHT = 48; constexpr uint32_t WINDOW_FRAME_WIDTH = 4; - constexpr uint32_t MIN_VERTICAL_FLOATING_WIDTH = 360; - constexpr uint32_t MIN_VERTICAL_FLOATING_HEIGHT = 480; } WindowLayoutPolicy::WindowLayoutPolicy(const Rect& displayRect, const uint64_t& screenId, const sptr& belowAppNode, const sptr& appNode, const sptr& aboveAppNode) @@ -220,7 +218,6 @@ void WindowLayoutPolicy::UpdateLayoutRect(sptr& node) void WindowLayoutPolicy::LimitWindowSize(const sptr& node, const Rect& displayRect, Rect& winRect) { bool floatingWindow = (node->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING); - winRect.width_ = std::min(displayRect.width_, winRect.width_); winRect.height_ = std::min(displayRect.height_, winRect.height_); bool isVertical = (displayRect.height_ > displayRect.width_) ? true : false; diff --git a/wmserver/src/window_manager_proxy.cpp b/wmserver/src/window_manager_proxy.cpp index e9a4fd46..3f71e691 100644 --- a/wmserver/src/window_manager_proxy.cpp +++ b/wmserver/src/window_manager_proxy.cpp @@ -193,6 +193,35 @@ WMError WindowManagerProxy::Resize(uint32_t windowId, uint32_t width, uint32_t h return static_cast(ret); } +WMError WindowManagerProxy::Drag(uint32_t windowId, const Rect& rect) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (!data.WriteUint32(windowId)) { + WLOGFE("Write windowId failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (!(data.WriteInt32(rect.posX_) && data.WriteInt32(rect.posY_) && + data.WriteUint32(rect.width_) && data.WriteUint32(rect.height_))) { + WLOGFE("Write rect failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (Remote()->SendRequest(TRANS_ID_DRAG, data, reply, option) != ERR_NONE) { + return WMError::WM_ERROR_IPC_FAILED; + } + + int32_t ret = reply.ReadInt32(); + return static_cast(ret); +} + WMError WindowManagerProxy::RequestFocus(uint32_t windowId) { MessageParcel data; diff --git a/wmserver/src/window_manager_service.cpp b/wmserver/src/window_manager_service.cpp index 930ae9e4..95cfa623 100644 --- a/wmserver/src/window_manager_service.cpp +++ b/wmserver/src/window_manager_service.cpp @@ -172,6 +172,19 @@ WMError WindowManagerService::Resize(uint32_t windowId, uint32_t width, uint32_t return windowController_->Resize(windowId, width, height); } +WMError WindowManagerService::Drag(uint32_t windowId, const Rect& rect) +{ + WLOGFI("[WMS] Drag: %{public}d [%{public}d, %{public}d, %{public}d, %{public}d]", + windowId, rect.posX_, rect.posY_, rect.width_, rect.height_); + WM_SCOPED_TRACE("wms:Drag"); + std::lock_guard lock(mutex_); + WMError res = windowController_->Drag(windowId, rect); + if (res == WMError::WM_OK) { + inputWindowMonitor_->UpdateInputWindow(windowId); + } + return res; +} + WMError WindowManagerService::RequestFocus(uint32_t windowId) { WLOGFI("[WMS] RequestFocus: %{public}d", windowId); diff --git a/wmserver/src/window_manager_stub.cpp b/wmserver/src/window_manager_stub.cpp index f76f2f15..3cb208ec 100644 --- a/wmserver/src/window_manager_stub.cpp +++ b/wmserver/src/window_manager_stub.cpp @@ -76,6 +76,13 @@ int32_t WindowManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, M reply.WriteInt32(static_cast(errCode)); break; } + case TRANS_ID_DRAG: { + uint32_t windowId = data.ReadUint32(); + Rect rect = { data.ReadInt32(), data.ReadInt32(), data.ReadUint32(), data.ReadUint32() }; + WMError errCode = Drag(windowId, rect); + reply.WriteInt32(static_cast(errCode)); + break; + } case TRANS_ID_REQUEST_FOCUS: { uint32_t windowId = data.ReadUint32(); WMError errCode = RequestFocus(windowId); diff --git a/wmserver/src/window_node.cpp b/wmserver/src/window_node.cpp index 9b811d0b..3caaa8cc 100644 --- a/wmserver/src/window_node.cpp +++ b/wmserver/src/window_node.cpp @@ -14,6 +14,7 @@ */ #include "window_node.h" +#include "window_helper.h" #include "window_manager_hilog.h" namespace OHOS { @@ -78,6 +79,25 @@ const Rect& WindowNode::GetLayoutRect() const return layoutRect_; } +Rect WindowNode::GetHotZoneRect() const +{ + Rect rect = layoutRect_; + if (GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + const int32_t divTouchRegion = 20; + if (rect.width_ < rect.height_) { + rect.posX_ -= divTouchRegion; + rect.width_ += (divTouchRegion + divTouchRegion); + } else { + rect.posY_ -= divTouchRegion; + rect.height_ += (divTouchRegion + divTouchRegion); + } + } else if (WindowHelper::IsMainFloatingWindow(GetWindowType(), GetWindowMode())) { + property_->SetWindowHotZoneRect(rect); + rect = property_->GetWindowHotZoneRect(); + } + return rect; +} + WindowType WindowNode::GetWindowType() const { return property_->GetWindowType();