1e0dac50fSopenharmony_ci/*
2e0dac50fSopenharmony_ci * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3e0dac50fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e0dac50fSopenharmony_ci * you may not use this file except in compliance with the License.
5e0dac50fSopenharmony_ci * You may obtain a copy of the License at
6e0dac50fSopenharmony_ci *
7e0dac50fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e0dac50fSopenharmony_ci *
9e0dac50fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e0dac50fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e0dac50fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e0dac50fSopenharmony_ci * See the License for the specific language governing permissions and
13e0dac50fSopenharmony_ci * limitations under the License.
14e0dac50fSopenharmony_ci */
15e0dac50fSopenharmony_ci#include "drag_controller.h"
16e0dac50fSopenharmony_ci
17e0dac50fSopenharmony_ci#include <vector>
18e0dac50fSopenharmony_ci
19e0dac50fSopenharmony_ci#include "display.h"
20e0dac50fSopenharmony_ci#include "window_helper.h"
21e0dac50fSopenharmony_ci#include "window_inner_manager.h"
22e0dac50fSopenharmony_ci#include "window_manager_hilog.h"
23e0dac50fSopenharmony_ci#include "window_manager_service.h"
24e0dac50fSopenharmony_ci#include "window_node.h"
25e0dac50fSopenharmony_ci#include "window_node_container.h"
26e0dac50fSopenharmony_ci#include "window_property.h"
27e0dac50fSopenharmony_ci#include "wm_common.h"
28e0dac50fSopenharmony_ci#include "wm_math.h"
29e0dac50fSopenharmony_ci#include "xcollie/watchdog.h"
30e0dac50fSopenharmony_ci
31e0dac50fSopenharmony_cinamespace OHOS {
32e0dac50fSopenharmony_cinamespace Rosen {
33e0dac50fSopenharmony_cinamespace {
34e0dac50fSopenharmony_ciconstexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "DragController"};
35e0dac50fSopenharmony_ci}
36e0dac50fSopenharmony_ci
37e0dac50fSopenharmony_civoid DragController::UpdateDragInfo(uint32_t windowId)
38e0dac50fSopenharmony_ci{
39e0dac50fSopenharmony_ci    PointInfo point;
40e0dac50fSopenharmony_ci    if (!GetHitPoint(windowId, point)) {
41e0dac50fSopenharmony_ci        return;
42e0dac50fSopenharmony_ci    }
43e0dac50fSopenharmony_ci    sptr<WindowNode> dragNode = windowRoot_->GetWindowNode(windowId);
44e0dac50fSopenharmony_ci    if (dragNode == nullptr) {
45e0dac50fSopenharmony_ci        return;
46e0dac50fSopenharmony_ci    }
47e0dac50fSopenharmony_ci    sptr<WindowNode> hitWindowNode = GetHitWindow(dragNode->GetDisplayId(), point);
48e0dac50fSopenharmony_ci    if (hitWindowNode == nullptr) {
49e0dac50fSopenharmony_ci        WLOGFE("Get point failed %{public}d %{public}d", point.x, point.y);
50e0dac50fSopenharmony_ci        return;
51e0dac50fSopenharmony_ci    }
52e0dac50fSopenharmony_ci    auto token = hitWindowNode->GetWindowToken();
53e0dac50fSopenharmony_ci    if (token) {
54e0dac50fSopenharmony_ci        if (hitWindowNode->GetWindowId() == hitWindowId_) {
55e0dac50fSopenharmony_ci            token->UpdateWindowDragInfo(point, DragEvent::DRAG_EVENT_MOVE);
56e0dac50fSopenharmony_ci            return;
57e0dac50fSopenharmony_ci        }
58e0dac50fSopenharmony_ci        token->UpdateWindowDragInfo(point, DragEvent::DRAG_EVENT_IN);
59e0dac50fSopenharmony_ci    }
60e0dac50fSopenharmony_ci    sptr<WindowNode> oldHitWindow = windowRoot_->GetWindowNode(hitWindowId_);
61e0dac50fSopenharmony_ci    if (oldHitWindow != nullptr && oldHitWindow->GetWindowToken()) {
62e0dac50fSopenharmony_ci        oldHitWindow->GetWindowToken()->UpdateWindowDragInfo(point, DragEvent::DRAG_EVENT_OUT);
63e0dac50fSopenharmony_ci    }
64e0dac50fSopenharmony_ci    hitWindowId_ = hitWindowNode->GetWindowId();
65e0dac50fSopenharmony_ci}
66e0dac50fSopenharmony_ci
67e0dac50fSopenharmony_civoid DragController::StartDrag(uint32_t windowId)
68e0dac50fSopenharmony_ci{
69e0dac50fSopenharmony_ci    PointInfo point;
70e0dac50fSopenharmony_ci    if (!GetHitPoint(windowId, point)) {
71e0dac50fSopenharmony_ci        WLOGFE("Get hit point failed");
72e0dac50fSopenharmony_ci        return;
73e0dac50fSopenharmony_ci    }
74e0dac50fSopenharmony_ci    sptr<WindowNode> dragNode = windowRoot_->GetWindowNode(windowId);
75e0dac50fSopenharmony_ci    if (dragNode == nullptr) {
76e0dac50fSopenharmony_ci        return;
77e0dac50fSopenharmony_ci    }
78e0dac50fSopenharmony_ci    sptr<WindowNode> hitWindow = GetHitWindow(dragNode->GetDisplayId(), point);
79e0dac50fSopenharmony_ci    if (hitWindow == nullptr) {
80e0dac50fSopenharmony_ci        WLOGFE("Get point failed %{public}d %{public}d", point.x, point.y);
81e0dac50fSopenharmony_ci        return;
82e0dac50fSopenharmony_ci    }
83e0dac50fSopenharmony_ci    if (hitWindow->GetWindowToken()) {
84e0dac50fSopenharmony_ci        hitWindow->GetWindowToken()->UpdateWindowDragInfo(point, DragEvent::DRAG_EVENT_IN);
85e0dac50fSopenharmony_ci    }
86e0dac50fSopenharmony_ci    hitWindowId_ = windowId;
87e0dac50fSopenharmony_ci    WLOGI("start Drag");
88e0dac50fSopenharmony_ci}
89e0dac50fSopenharmony_ci
90e0dac50fSopenharmony_civoid DragController::FinishDrag(uint32_t windowId)
91e0dac50fSopenharmony_ci{
92e0dac50fSopenharmony_ci    sptr<WindowNode> node = windowRoot_->GetWindowNode(windowId);
93e0dac50fSopenharmony_ci    if (node == nullptr) {
94e0dac50fSopenharmony_ci        WLOGFE("get node failed");
95e0dac50fSopenharmony_ci        return;
96e0dac50fSopenharmony_ci    }
97e0dac50fSopenharmony_ci    if (node->GetWindowType() != WindowType::WINDOW_TYPE_DRAGGING_EFFECT) {
98e0dac50fSopenharmony_ci        return;
99e0dac50fSopenharmony_ci    }
100e0dac50fSopenharmony_ci
101e0dac50fSopenharmony_ci    sptr<WindowNode> hitWindow = windowRoot_->GetWindowNode(hitWindowId_);
102e0dac50fSopenharmony_ci    if (hitWindow != nullptr) {
103e0dac50fSopenharmony_ci        auto property = node->GetWindowProperty();
104e0dac50fSopenharmony_ci        PointInfo point = {property->GetWindowRect().posX_ + property->GetHitOffset().x,
105e0dac50fSopenharmony_ci            property->GetWindowRect().posY_ + property->GetHitOffset().y};
106e0dac50fSopenharmony_ci        if (hitWindow->GetWindowToken()) {
107e0dac50fSopenharmony_ci            hitWindow->GetWindowToken()->UpdateWindowDragInfo(point, DragEvent::DRAG_EVENT_END);
108e0dac50fSopenharmony_ci        }
109e0dac50fSopenharmony_ci    }
110e0dac50fSopenharmony_ci    WLOGI("end drag");
111e0dac50fSopenharmony_ci}
112e0dac50fSopenharmony_ci
113e0dac50fSopenharmony_cisptr<WindowNode> DragController::GetHitWindow(DisplayId id, PointInfo point)
114e0dac50fSopenharmony_ci{
115e0dac50fSopenharmony_ci    // Need get display by point
116e0dac50fSopenharmony_ci    if (id == DISPLAY_ID_INVALID) {
117e0dac50fSopenharmony_ci        WLOGFE("Get invalid display");
118e0dac50fSopenharmony_ci        return nullptr;
119e0dac50fSopenharmony_ci    }
120e0dac50fSopenharmony_ci    sptr<WindowNodeContainer> container = windowRoot_->GetOrCreateWindowNodeContainer(id);
121e0dac50fSopenharmony_ci    if (container == nullptr) {
122e0dac50fSopenharmony_ci        WLOGFE("get container failed %{public}" PRIu64"", id);
123e0dac50fSopenharmony_ci        return nullptr;
124e0dac50fSopenharmony_ci    }
125e0dac50fSopenharmony_ci
126e0dac50fSopenharmony_ci    std::vector<sptr<WindowNode>> windowNodes;
127e0dac50fSopenharmony_ci    container->TraverseContainer(windowNodes);
128e0dac50fSopenharmony_ci    for (auto windowNode : windowNodes) {
129e0dac50fSopenharmony_ci        if (windowNode->GetWindowType() >= WindowType::WINDOW_TYPE_PANEL) {
130e0dac50fSopenharmony_ci            continue;
131e0dac50fSopenharmony_ci        }
132e0dac50fSopenharmony_ci        if (WindowHelper::IsPointInTargetRect(point.x, point.y, windowNode->GetWindowRect())) {
133e0dac50fSopenharmony_ci            return windowNode;
134e0dac50fSopenharmony_ci        }
135e0dac50fSopenharmony_ci    }
136e0dac50fSopenharmony_ci    return nullptr;
137e0dac50fSopenharmony_ci}
138e0dac50fSopenharmony_ci
139e0dac50fSopenharmony_cibool DragController::GetHitPoint(uint32_t windowId, PointInfo& point)
140e0dac50fSopenharmony_ci{
141e0dac50fSopenharmony_ci    sptr<WindowNode> windowNode = windowRoot_->GetWindowNode(windowId);
142e0dac50fSopenharmony_ci    if (windowNode == nullptr || windowNode->GetWindowType() != WindowType::WINDOW_TYPE_DRAGGING_EFFECT) {
143e0dac50fSopenharmony_ci        WLOGFE("Get hit point failed");
144e0dac50fSopenharmony_ci        return false;
145e0dac50fSopenharmony_ci    }
146e0dac50fSopenharmony_ci    sptr<WindowProperty> property = windowNode->GetWindowProperty();
147e0dac50fSopenharmony_ci    point.x = property->GetWindowRect().posX_ + property->GetHitOffset().x;
148e0dac50fSopenharmony_ci    point.y = property->GetWindowRect().posY_ + property->GetHitOffset().y;
149e0dac50fSopenharmony_ci    return true;
150e0dac50fSopenharmony_ci}
151e0dac50fSopenharmony_ci
152e0dac50fSopenharmony_civoid DragInputEventListener::OnInputEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) const
153e0dac50fSopenharmony_ci{
154e0dac50fSopenharmony_ci    if (keyEvent == nullptr) {
155e0dac50fSopenharmony_ci        WLOGFE("KeyEvent is nullptr");
156e0dac50fSopenharmony_ci        return;
157e0dac50fSopenharmony_ci    }
158e0dac50fSopenharmony_ci    uint32_t windowId = static_cast<uint32_t>(keyEvent->GetAgentWindowId());
159e0dac50fSopenharmony_ci    WLOGFD("[WMS] Receive keyEvent, windowId: %{public}u", windowId);
160e0dac50fSopenharmony_ci    keyEvent->MarkProcessed();
161e0dac50fSopenharmony_ci}
162e0dac50fSopenharmony_ci
163e0dac50fSopenharmony_civoid DragInputEventListener::OnInputEvent(std::shared_ptr<MMI::AxisEvent> axisEvent) const
164e0dac50fSopenharmony_ci{
165e0dac50fSopenharmony_ci    if (axisEvent == nullptr) {
166e0dac50fSopenharmony_ci        WLOGFE("AxisEvent is nullptr");
167e0dac50fSopenharmony_ci        return;
168e0dac50fSopenharmony_ci    };
169e0dac50fSopenharmony_ci    WLOGFD("[WMS] Receive axisEvent, windowId: %{public}u", axisEvent->GetAgentWindowId());
170e0dac50fSopenharmony_ci    axisEvent->MarkProcessed();
171e0dac50fSopenharmony_ci}
172e0dac50fSopenharmony_ci
173e0dac50fSopenharmony_civoid DragInputEventListener::OnInputEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const
174e0dac50fSopenharmony_ci{
175e0dac50fSopenharmony_ci    if (pointerEvent == nullptr) {
176e0dac50fSopenharmony_ci        WLOGFE("PointerEvent is nullptr");
177e0dac50fSopenharmony_ci        return;
178e0dac50fSopenharmony_ci    }
179e0dac50fSopenharmony_ci    uint32_t windowId = static_cast<uint32_t>(pointerEvent->GetAgentWindowId());
180e0dac50fSopenharmony_ci    WLOGFD("[WMS] Receive pointerEvent, windowId: %{public}u", windowId);
181e0dac50fSopenharmony_ci
182e0dac50fSopenharmony_ci    WindowInnerManager::GetInstance().ConsumePointerEvent(pointerEvent);
183e0dac50fSopenharmony_ci}
184e0dac50fSopenharmony_ci
185e0dac50fSopenharmony_civoid MoveDragController::SetInputEventConsumer()
186e0dac50fSopenharmony_ci{
187e0dac50fSopenharmony_ci    if (!inputListener_ || !inputEventHandler_) {
188e0dac50fSopenharmony_ci        WLOGFE("InputListener or inputEventHandler is nullptr");
189e0dac50fSopenharmony_ci        return;
190e0dac50fSopenharmony_ci    }
191e0dac50fSopenharmony_ci    MMI::InputManager::GetInstance()->SetWindowInputEventConsumer(inputListener_, inputEventHandler_);
192e0dac50fSopenharmony_ci}
193e0dac50fSopenharmony_ci
194e0dac50fSopenharmony_civoid MoveDragController::SetWindowRoot(const sptr<WindowRoot>& windowRoot)
195e0dac50fSopenharmony_ci{
196e0dac50fSopenharmony_ci    windowRoot_ = windowRoot;
197e0dac50fSopenharmony_ci}
198e0dac50fSopenharmony_ci
199e0dac50fSopenharmony_cibool MoveDragController::Init()
200e0dac50fSopenharmony_ci{
201e0dac50fSopenharmony_ci    // create handler for input event
202e0dac50fSopenharmony_ci    inputEventHandler_ = std::make_shared<AppExecFwk::EventHandler>(
203e0dac50fSopenharmony_ci        AppExecFwk::EventRunner::Create(INNER_WM_INPUT_THREAD_NAME));
204e0dac50fSopenharmony_ci    if (inputEventHandler_ == nullptr) {
205e0dac50fSopenharmony_ci        return false;
206e0dac50fSopenharmony_ci    }
207e0dac50fSopenharmony_ci    int ret = HiviewDFX::Watchdog::GetInstance().AddThread(INNER_WM_INPUT_THREAD_NAME, inputEventHandler_);
208e0dac50fSopenharmony_ci    if (ret != 0) {
209e0dac50fSopenharmony_ci        WLOGFE("Add watchdog thread failed");
210e0dac50fSopenharmony_ci    }
211e0dac50fSopenharmony_ci    inputListener_ = std::make_shared<DragInputEventListener>(DragInputEventListener());
212e0dac50fSopenharmony_ci    SetInputEventConsumer();
213e0dac50fSopenharmony_ci    return true;
214e0dac50fSopenharmony_ci}
215e0dac50fSopenharmony_ci
216e0dac50fSopenharmony_civoid MoveDragController::Stop()
217e0dac50fSopenharmony_ci{
218e0dac50fSopenharmony_ci    if (inputEventHandler_ != nullptr) {
219e0dac50fSopenharmony_ci        inputEventHandler_.reset();
220e0dac50fSopenharmony_ci    }
221e0dac50fSopenharmony_ci}
222e0dac50fSopenharmony_ci
223e0dac50fSopenharmony_civoid MoveDragController::HandleReadyToMoveOrDrag(uint32_t windowId, sptr<WindowProperty>& windowProperty,
224e0dac50fSopenharmony_ci    sptr<MoveDragProperty>& moveDragProperty)
225e0dac50fSopenharmony_ci{
226e0dac50fSopenharmony_ci    SetActiveWindowId(windowId);
227e0dac50fSopenharmony_ci    SetWindowProperty(windowProperty);
228e0dac50fSopenharmony_ci    SetDragProperty(moveDragProperty);
229e0dac50fSopenharmony_ci}
230e0dac50fSopenharmony_ci
231e0dac50fSopenharmony_civoid MoveDragController::HandleEndUpMovingOrDragging(uint32_t windowId)
232e0dac50fSopenharmony_ci{
233e0dac50fSopenharmony_ci    if (activeWindowId_ != windowId) {
234e0dac50fSopenharmony_ci        WLOGFE("end up moving or dragging failed, windowId: %{public}u", windowId);
235e0dac50fSopenharmony_ci        return;
236e0dac50fSopenharmony_ci    }
237e0dac50fSopenharmony_ci    ResetMoveOrDragState();
238e0dac50fSopenharmony_ci}
239e0dac50fSopenharmony_ci
240e0dac50fSopenharmony_civoid MoveDragController::HandleWindowRemovedOrDestroyed(uint32_t windowId)
241e0dac50fSopenharmony_ci{
242e0dac50fSopenharmony_ci    if (GetMoveDragProperty() == nullptr) {
243e0dac50fSopenharmony_ci        return;
244e0dac50fSopenharmony_ci    }
245e0dac50fSopenharmony_ci    if (!(GetMoveDragProperty()->startMoveFlag_ || GetMoveDragProperty()->startDragFlag_)) {
246e0dac50fSopenharmony_ci        return;
247e0dac50fSopenharmony_ci    }
248e0dac50fSopenharmony_ci
249e0dac50fSopenharmony_ci    {
250e0dac50fSopenharmony_ci        std::lock_guard<std::mutex> lock(mtx_);
251e0dac50fSopenharmony_ci        auto iter = vsyncStationMap_.find(windowId);
252e0dac50fSopenharmony_ci        if (iter != vsyncStationMap_.end()) {
253e0dac50fSopenharmony_ci            auto vsyncStation = iter->second;
254e0dac50fSopenharmony_ci            vsyncStation->RemoveCallback();
255e0dac50fSopenharmony_ci            vsyncStationMap_.erase(windowId);
256e0dac50fSopenharmony_ci        }
257e0dac50fSopenharmony_ci    }
258e0dac50fSopenharmony_ci
259e0dac50fSopenharmony_ci    ResetMoveOrDragState();
260e0dac50fSopenharmony_ci}
261e0dac50fSopenharmony_ci
262e0dac50fSopenharmony_civoid MoveDragController::ConvertPointerPosToDisplayGroupPos(DisplayId displayId, int32_t& posX, int32_t& posY)
263e0dac50fSopenharmony_ci{
264e0dac50fSopenharmony_ci    auto displayRect = DisplayGroupInfo::GetInstance().GetDisplayRect(displayId);
265e0dac50fSopenharmony_ci    posX += displayRect.posX_;
266e0dac50fSopenharmony_ci    posY += displayRect.posY_;
267e0dac50fSopenharmony_ci}
268e0dac50fSopenharmony_ci
269e0dac50fSopenharmony_civoid MoveDragController::HandleDisplayLimitRectChange(const std::map<DisplayId, Rect>& limitRectMap)
270e0dac50fSopenharmony_ci{
271e0dac50fSopenharmony_ci    limitRectMap_.clear();
272e0dac50fSopenharmony_ci    for (auto& elem : limitRectMap) {
273e0dac50fSopenharmony_ci        limitRectMap_.insert(elem);
274e0dac50fSopenharmony_ci    }
275e0dac50fSopenharmony_ci}
276e0dac50fSopenharmony_ci
277e0dac50fSopenharmony_civoid MoveDragController::ConsumePointerEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
278e0dac50fSopenharmony_ci{
279e0dac50fSopenharmony_ci    if (pointerEvent == nullptr) {
280e0dac50fSopenharmony_ci        WLOGFE("pointerEvent is nullptr or is handling pointer event");
281e0dac50fSopenharmony_ci        return;
282e0dac50fSopenharmony_ci    }
283e0dac50fSopenharmony_ci    if (pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_MOVE) {
284e0dac50fSopenharmony_ci        moveEvent_ = pointerEvent;
285e0dac50fSopenharmony_ci        uint32_t windowId = static_cast<uint32_t>(pointerEvent->GetAgentWindowId());
286e0dac50fSopenharmony_ci        auto vsyncStation = GetVsyncStationByWindowId(windowId);
287e0dac50fSopenharmony_ci        if (vsyncStation != nullptr) {
288e0dac50fSopenharmony_ci            vsyncStation->RequestVsync(vsyncCallback_);
289e0dac50fSopenharmony_ci        }
290e0dac50fSopenharmony_ci    } else {
291e0dac50fSopenharmony_ci        WLOGFD("[WMS] Dispatch non-move event, action: %{public}d", pointerEvent->GetPointerAction());
292e0dac50fSopenharmony_ci        HandlePointerEvent(pointerEvent);
293e0dac50fSopenharmony_ci        pointerEvent->MarkProcessed();
294e0dac50fSopenharmony_ci    }
295e0dac50fSopenharmony_ci}
296e0dac50fSopenharmony_ci
297e0dac50fSopenharmony_civoid MoveDragController::OnReceiveVsync(int64_t timeStamp)
298e0dac50fSopenharmony_ci{
299e0dac50fSopenharmony_ci    if (moveEvent_ == nullptr) {
300e0dac50fSopenharmony_ci        WLOGFE("moveEvent is nullptr");
301e0dac50fSopenharmony_ci        return;
302e0dac50fSopenharmony_ci    }
303e0dac50fSopenharmony_ci    WLOGFD("[OnReceiveVsync] receive move event, action: %{public}d", moveEvent_->GetPointerAction());
304e0dac50fSopenharmony_ci    HandlePointerEvent(moveEvent_);
305e0dac50fSopenharmony_ci    moveEvent_->MarkProcessed();
306e0dac50fSopenharmony_ci}
307e0dac50fSopenharmony_ci
308e0dac50fSopenharmony_ciRect MoveDragController::GetHotZoneRect()
309e0dac50fSopenharmony_ci{
310e0dac50fSopenharmony_ci    auto startPointPosX = moveDragProperty_->startPointPosX_;
311e0dac50fSopenharmony_ci    auto startPointPosY = moveDragProperty_->startPointPosY_;
312e0dac50fSopenharmony_ci    ConvertPointerPosToDisplayGroupPos(moveDragProperty_->targetDisplayId_, startPointPosX, startPointPosY);
313e0dac50fSopenharmony_ci
314e0dac50fSopenharmony_ci    Rect hotZoneRect;
315e0dac50fSopenharmony_ci    const auto& startRectExceptCorner =  moveDragProperty_->startRectExceptCorner_;
316e0dac50fSopenharmony_ci    const auto& startRectExceptFrame =  moveDragProperty_->startRectExceptFrame_;
317e0dac50fSopenharmony_ci    if ((startPointPosX > startRectExceptCorner.posX_ &&
318e0dac50fSopenharmony_ci        (startPointPosX < startRectExceptCorner.posX_ +
319e0dac50fSopenharmony_ci         static_cast<int32_t>(startRectExceptCorner.width_))) &&
320e0dac50fSopenharmony_ci        (startPointPosY > startRectExceptCorner.posY_ &&
321e0dac50fSopenharmony_ci        (startPointPosY < startRectExceptCorner.posY_ +
322e0dac50fSopenharmony_ci        static_cast<int32_t>(startRectExceptCorner.height_)))) {
323e0dac50fSopenharmony_ci        hotZoneRect = startRectExceptFrame; // drag type: left/right/top/bottom
324e0dac50fSopenharmony_ci    } else {
325e0dac50fSopenharmony_ci        hotZoneRect = startRectExceptCorner; // drag type: left_top/right_top/left_bottom/right_bottom
326e0dac50fSopenharmony_ci    }
327e0dac50fSopenharmony_ci    return hotZoneRect;
328e0dac50fSopenharmony_ci}
329e0dac50fSopenharmony_ci
330e0dac50fSopenharmony_cibool MoveDragController::CheckWindowRect(DisplayId displayId, float vpr, const Rect& rect)
331e0dac50fSopenharmony_ci{
332e0dac50fSopenharmony_ci    uint32_t titleBarHeight = static_cast<uint32_t>(WINDOW_TITLE_BAR_HEIGHT * vpr);
333e0dac50fSopenharmony_ci    auto iter = limitRectMap_.find(displayId);
334e0dac50fSopenharmony_ci    Rect limitRect;
335e0dac50fSopenharmony_ci    if (iter != limitRectMap_.end()) {
336e0dac50fSopenharmony_ci        limitRect = iter->second;
337e0dac50fSopenharmony_ci    }
338e0dac50fSopenharmony_ci    if (WindowHelper::IsEmptyRect(limitRect) || MathHelper::NearZero(vpr)) {
339e0dac50fSopenharmony_ci        return true; // If limitRect is empty, we can't use limitRect to check window rect
340e0dac50fSopenharmony_ci    }
341e0dac50fSopenharmony_ci
342e0dac50fSopenharmony_ci    if ((rect.posX_ > static_cast<int32_t>(limitRect.posX_ + limitRect.width_ - titleBarHeight)) ||
343e0dac50fSopenharmony_ci        (rect.posX_ + static_cast<int32_t>(rect.width_) <
344e0dac50fSopenharmony_ci         static_cast<int32_t>(limitRect.posX_ + titleBarHeight)) ||
345e0dac50fSopenharmony_ci        (rect.posY_ < limitRect.posY_) ||
346e0dac50fSopenharmony_ci        (rect.posY_ > static_cast<int32_t>(limitRect.posY_ + limitRect.height_ - titleBarHeight))) {
347e0dac50fSopenharmony_ci        WLOGFD("[WMS] Invalid window rect, id: %{public}u, rect: [%{public}d, %{public}d, %{public}d, %{public}d]",
348e0dac50fSopenharmony_ci            windowProperty_->GetWindowId(), rect.posX_, rect.posY_, rect.width_, rect.height_);
349e0dac50fSopenharmony_ci        return false;
350e0dac50fSopenharmony_ci    }
351e0dac50fSopenharmony_ci    return true;
352e0dac50fSopenharmony_ci}
353e0dac50fSopenharmony_ci
354e0dac50fSopenharmony_civoid MoveDragController::CalculateNewWindowRect(Rect& newRect, DisplayId displayId, int32_t posX, int32_t posY)
355e0dac50fSopenharmony_ci{
356e0dac50fSopenharmony_ci    auto startPointPosX = moveDragProperty_->startPointPosX_;
357e0dac50fSopenharmony_ci    auto startPointPosY = moveDragProperty_->startPointPosY_;
358e0dac50fSopenharmony_ci    ConvertPointerPosToDisplayGroupPos(moveDragProperty_->targetDisplayId_, startPointPosX, startPointPosY);
359e0dac50fSopenharmony_ci    const auto& startPointRect = moveDragProperty_->startPointRect_;
360e0dac50fSopenharmony_ci    Rect hotZoneRect = GetHotZoneRect();
361e0dac50fSopenharmony_ci    int32_t diffX = posX - startPointPosX;
362e0dac50fSopenharmony_ci    int32_t diffY = posY - startPointPosY;
363e0dac50fSopenharmony_ci
364e0dac50fSopenharmony_ci    float vpr = DisplayGroupInfo::GetInstance().GetDisplayVirtualPixelRatio(displayId);
365e0dac50fSopenharmony_ci    if (MathHelper::NearZero(vpr)) {
366e0dac50fSopenharmony_ci        return;
367e0dac50fSopenharmony_ci    }
368e0dac50fSopenharmony_ci    uint32_t minWidth = static_cast<uint32_t>(MIN_FLOATING_WIDTH * vpr);
369e0dac50fSopenharmony_ci    uint32_t minHeight = static_cast<uint32_t>(MIN_FLOATING_HEIGHT * vpr);
370e0dac50fSopenharmony_ci    if (startPointPosX <= hotZoneRect.posX_) {
371e0dac50fSopenharmony_ci        if (diffX > static_cast<int32_t>(startPointRect.width_ - minWidth)) {
372e0dac50fSopenharmony_ci            diffX = static_cast<int32_t>(startPointRect.width_ - minWidth);
373e0dac50fSopenharmony_ci        }
374e0dac50fSopenharmony_ci        newRect.posX_ += diffX;
375e0dac50fSopenharmony_ci        newRect.width_ = static_cast<uint32_t>(static_cast<int32_t>(newRect.width_) - diffX);
376e0dac50fSopenharmony_ci    } else if (startPointPosX >= hotZoneRect.posX_ + static_cast<int32_t>(hotZoneRect.width_)) {
377e0dac50fSopenharmony_ci        if (diffX < 0 && (-diffX > static_cast<int32_t>(startPointRect.width_ - minWidth))) {
378e0dac50fSopenharmony_ci            diffX = -(static_cast<int32_t>(startPointRect.width_ - minWidth));
379e0dac50fSopenharmony_ci        }
380e0dac50fSopenharmony_ci        newRect.width_ = static_cast<uint32_t>(static_cast<int32_t>(newRect.width_) + diffX);
381e0dac50fSopenharmony_ci    }
382e0dac50fSopenharmony_ci    if (startPointPosY <= hotZoneRect.posY_) {
383e0dac50fSopenharmony_ci        if (diffY > static_cast<int32_t>(startPointRect.height_ - minHeight)) {
384e0dac50fSopenharmony_ci            diffY = static_cast<int32_t>(startPointRect.height_ - minHeight);
385e0dac50fSopenharmony_ci        }
386e0dac50fSopenharmony_ci        newRect.posY_ += diffY;
387e0dac50fSopenharmony_ci        newRect.height_ = static_cast<uint32_t>(static_cast<int32_t>(newRect.height_) - diffY);
388e0dac50fSopenharmony_ci    } else if (startPointPosY >= hotZoneRect.posY_ + static_cast<int32_t>(hotZoneRect.height_)) {
389e0dac50fSopenharmony_ci        if (diffY < 0 && (-diffY > static_cast<int32_t>(startPointRect.height_ - minHeight))) {
390e0dac50fSopenharmony_ci            diffY = -(static_cast<int32_t>(startPointRect.height_ - minHeight));
391e0dac50fSopenharmony_ci        }
392e0dac50fSopenharmony_ci        newRect.height_ = static_cast<uint32_t>(static_cast<int32_t>(newRect.height_) + diffY);
393e0dac50fSopenharmony_ci    }
394e0dac50fSopenharmony_ci}
395e0dac50fSopenharmony_ci
396e0dac50fSopenharmony_civoid MoveDragController::HandleDragEvent(DisplayId displayId, int32_t posX, int32_t posY,
397e0dac50fSopenharmony_ci                                         int32_t pointId, int32_t sourceType)
398e0dac50fSopenharmony_ci{
399e0dac50fSopenharmony_ci    if (moveDragProperty_ == nullptr || !moveDragProperty_->startDragFlag_ ||
400e0dac50fSopenharmony_ci        (pointId != moveDragProperty_->startPointerId_) || (sourceType != moveDragProperty_->sourceType_)) {
401e0dac50fSopenharmony_ci        return;
402e0dac50fSopenharmony_ci    }
403e0dac50fSopenharmony_ci
404e0dac50fSopenharmony_ci    Rect newRect = moveDragProperty_->startPointRect_;
405e0dac50fSopenharmony_ci    CalculateNewWindowRect(newRect, displayId, posX, posY);
406e0dac50fSopenharmony_ci
407e0dac50fSopenharmony_ci    if (!CheckWindowRect(displayId, DisplayGroupInfo::GetInstance().GetDisplayVirtualPixelRatio(displayId), newRect)) {
408e0dac50fSopenharmony_ci        return;
409e0dac50fSopenharmony_ci    }
410e0dac50fSopenharmony_ci
411e0dac50fSopenharmony_ci    WLOGFD("[WMS] HandleDragEvent, id: %{public}u, newRect: [%{public}d, %{public}d, %{public}d, %{public}d]",
412e0dac50fSopenharmony_ci        windowProperty_->GetWindowId(), newRect.posX_, newRect.posY_, newRect.width_, newRect.height_);
413e0dac50fSopenharmony_ci    windowProperty_->SetRequestRect(newRect);
414e0dac50fSopenharmony_ci    windowProperty_->SetWindowSizeChangeReason(WindowSizeChangeReason::DRAG);
415e0dac50fSopenharmony_ci    windowProperty_->SetDragType(moveDragProperty_->dragType_);
416e0dac50fSopenharmony_ci    WindowManagerService::GetInstance().UpdateProperty(windowProperty_, PropertyChangeAction::ACTION_UPDATE_RECT, true);
417e0dac50fSopenharmony_ci}
418e0dac50fSopenharmony_ci
419e0dac50fSopenharmony_civoid MoveDragController::HandleMoveEvent(DisplayId displayId, int32_t posX, int32_t posY,
420e0dac50fSopenharmony_ci                                         int32_t pointId, int32_t sourceType)
421e0dac50fSopenharmony_ci{
422e0dac50fSopenharmony_ci    if (moveDragProperty_ == nullptr) {
423e0dac50fSopenharmony_ci        return;
424e0dac50fSopenharmony_ci    }
425e0dac50fSopenharmony_ci    if (!moveDragProperty_->startMoveFlag_ ||
426e0dac50fSopenharmony_ci        (pointId != moveDragProperty_->startPointerId_) ||
427e0dac50fSopenharmony_ci        (sourceType != moveDragProperty_->sourceType_)) {
428e0dac50fSopenharmony_ci        return;
429e0dac50fSopenharmony_ci    }
430e0dac50fSopenharmony_ci    auto startPointPosX = moveDragProperty_->startPointPosX_;
431e0dac50fSopenharmony_ci    auto startPointPosY = moveDragProperty_->startPointPosY_;
432e0dac50fSopenharmony_ci    ConvertPointerPosToDisplayGroupPos(moveDragProperty_->targetDisplayId_, startPointPosX, startPointPosY);
433e0dac50fSopenharmony_ci    int32_t targetX = moveDragProperty_->startPointRect_.posX_ + (posX - startPointPosX);
434e0dac50fSopenharmony_ci    int32_t targetY = moveDragProperty_->startPointRect_.posY_ + (posY - startPointPosY);
435e0dac50fSopenharmony_ci
436e0dac50fSopenharmony_ci    const Rect& oriRect = moveDragProperty_->startPointRect_;
437e0dac50fSopenharmony_ci    Rect newRect = { targetX, targetY, oriRect.width_, oriRect.height_ };
438e0dac50fSopenharmony_ci    if (limitRectMap_.find(displayId) != limitRectMap_.end()) {
439e0dac50fSopenharmony_ci        newRect.posY_ = std::max(newRect.posY_, limitRectMap_[displayId].posY_);
440e0dac50fSopenharmony_ci    }
441e0dac50fSopenharmony_ci    WLOGFD("[WMS] HandleMoveEvent, id: %{public}u, newRect: [%{public}d, %{public}d, %{public}d, %{public}d]",
442e0dac50fSopenharmony_ci        windowProperty_->GetWindowId(), newRect.posX_, newRect.posY_, newRect.width_, newRect.height_);
443e0dac50fSopenharmony_ci    windowProperty_->SetRequestRect(newRect);
444e0dac50fSopenharmony_ci    windowProperty_->SetWindowSizeChangeReason(WindowSizeChangeReason::MOVE);
445e0dac50fSopenharmony_ci    WindowManagerService::GetInstance().UpdateProperty(windowProperty_, PropertyChangeAction::ACTION_UPDATE_RECT, true);
446e0dac50fSopenharmony_ci}
447e0dac50fSopenharmony_ci
448e0dac50fSopenharmony_civoid MoveDragController::HandlePointerEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
449e0dac50fSopenharmony_ci{
450e0dac50fSopenharmony_ci    if (windowProperty_) {
451e0dac50fSopenharmony_ci        windowProperty_->UpdatePointerEvent(pointerEvent);
452e0dac50fSopenharmony_ci    }
453e0dac50fSopenharmony_ci    MMI::PointerEvent::PointerItem pointerItem;
454e0dac50fSopenharmony_ci    int32_t pointId = pointerEvent->GetPointerId();
455e0dac50fSopenharmony_ci    int32_t sourceType = pointerEvent->GetSourceType();
456e0dac50fSopenharmony_ci    if (!pointerEvent->GetPointerItem(pointId, pointerItem) ||
457e0dac50fSopenharmony_ci        (sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE &&
458e0dac50fSopenharmony_ci        pointerEvent->GetButtonId() != MMI::PointerEvent::MOUSE_BUTTON_LEFT)) {
459e0dac50fSopenharmony_ci        WLOGFW("invalid pointerEvent");
460e0dac50fSopenharmony_ci        return;
461e0dac50fSopenharmony_ci    }
462e0dac50fSopenharmony_ci
463e0dac50fSopenharmony_ci    int32_t pointPosX = pointerItem.GetDisplayX();
464e0dac50fSopenharmony_ci    int32_t pointPosY = pointerItem.GetDisplayY();
465e0dac50fSopenharmony_ci    int32_t action = pointerEvent->GetPointerAction();
466e0dac50fSopenharmony_ci    int32_t targetDisplayId = pointerEvent->GetTargetDisplayId();
467e0dac50fSopenharmony_ci    ConvertPointerPosToDisplayGroupPos(targetDisplayId, pointPosX, pointPosY);
468e0dac50fSopenharmony_ci    switch (action) {
469e0dac50fSopenharmony_ci        case MMI::PointerEvent::POINTER_ACTION_DOWN:
470e0dac50fSopenharmony_ci        case MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN: {
471e0dac50fSopenharmony_ci            if (pointId == moveDragProperty_->startPointerId_ && sourceType == moveDragProperty_->sourceType_) {
472e0dac50fSopenharmony_ci                moveDragProperty_->startMoveFlag_ = false;
473e0dac50fSopenharmony_ci                moveDragProperty_->startDragFlag_ = false;
474e0dac50fSopenharmony_ci            }
475e0dac50fSopenharmony_ci            TLOGD(WmsLogTag::WMS_EVENT, "windowId:%{public}u, pointId:%{public}d, sourceType:%{public}d, "
476e0dac50fSopenharmony_ci                "hasPointStarted:%{public}d, startMove:%{public}d, startDrag:%{public}d, targetDisplayId:"
477e0dac50fSopenharmony_ci                "%{public}d, pointPos:[%{private}d, %{private}d]", activeWindowId_, pointId, sourceType,
478e0dac50fSopenharmony_ci                moveDragProperty_->pointEventStarted_, moveDragProperty_->startMoveFlag_,
479e0dac50fSopenharmony_ci                moveDragProperty_->startDragFlag_, targetDisplayId, pointPosX, pointPosY);
480e0dac50fSopenharmony_ci            break;
481e0dac50fSopenharmony_ci        }
482e0dac50fSopenharmony_ci        // ready to move or drag
483e0dac50fSopenharmony_ci        case MMI::PointerEvent::POINTER_ACTION_MOVE: {
484e0dac50fSopenharmony_ci            HandleMoveEvent(targetDisplayId, pointPosX, pointPosY, pointId, sourceType);
485e0dac50fSopenharmony_ci            HandleDragEvent(targetDisplayId, pointPosX, pointPosY, pointId, sourceType);
486e0dac50fSopenharmony_ci            break;
487e0dac50fSopenharmony_ci        }
488e0dac50fSopenharmony_ci        // End move or drag
489e0dac50fSopenharmony_ci        case MMI::PointerEvent::POINTER_ACTION_UP:
490e0dac50fSopenharmony_ci        case MMI::PointerEvent::POINTER_ACTION_BUTTON_UP:
491e0dac50fSopenharmony_ci        case MMI::PointerEvent::POINTER_ACTION_CANCEL: {
492e0dac50fSopenharmony_ci            WindowManagerService::GetInstance().NotifyWindowClientPointUp(activeWindowId_, pointerEvent);
493e0dac50fSopenharmony_ci            WLOGFD("[Server Point Up/Cancel]: windowId: %{public}u, action: %{public}d, sourceType: %{public}d",
494e0dac50fSopenharmony_ci                activeWindowId_, action, sourceType);
495e0dac50fSopenharmony_ci            break;
496e0dac50fSopenharmony_ci        }
497e0dac50fSopenharmony_ci        default:
498e0dac50fSopenharmony_ci            break;
499e0dac50fSopenharmony_ci    }
500e0dac50fSopenharmony_ci}
501e0dac50fSopenharmony_ci
502e0dac50fSopenharmony_civoid MoveDragController::SetDragProperty(const sptr<MoveDragProperty>& moveDragProperty)
503e0dac50fSopenharmony_ci{
504e0dac50fSopenharmony_ci    moveDragProperty_->CopyFrom(moveDragProperty);
505e0dac50fSopenharmony_ci}
506e0dac50fSopenharmony_ci
507e0dac50fSopenharmony_civoid MoveDragController::SetWindowProperty(const sptr<WindowProperty>& windowProperty)
508e0dac50fSopenharmony_ci{
509e0dac50fSopenharmony_ci    windowProperty_->CopyFrom(windowProperty);
510e0dac50fSopenharmony_ci}
511e0dac50fSopenharmony_ci
512e0dac50fSopenharmony_ciconst sptr<MoveDragProperty>& MoveDragController::GetMoveDragProperty() const
513e0dac50fSopenharmony_ci{
514e0dac50fSopenharmony_ci    return moveDragProperty_;
515e0dac50fSopenharmony_ci}
516e0dac50fSopenharmony_ci
517e0dac50fSopenharmony_ciconst sptr<WindowProperty>& MoveDragController::GetWindowProperty() const
518e0dac50fSopenharmony_ci{
519e0dac50fSopenharmony_ci    return windowProperty_;
520e0dac50fSopenharmony_ci}
521e0dac50fSopenharmony_ci
522e0dac50fSopenharmony_civoid MoveDragController::ResetMoveOrDragState()
523e0dac50fSopenharmony_ci{
524e0dac50fSopenharmony_ci    activeWindowId_ = INVALID_WINDOW_ID;
525e0dac50fSopenharmony_ci    auto moveDragProperty = new MoveDragProperty();
526e0dac50fSopenharmony_ci    SetDragProperty(moveDragProperty);
527e0dac50fSopenharmony_ci}
528e0dac50fSopenharmony_ci
529e0dac50fSopenharmony_civoid MoveDragController::SetActiveWindowId(uint32_t activeWindowId)
530e0dac50fSopenharmony_ci{
531e0dac50fSopenharmony_ci    activeWindowId_ = activeWindowId;
532e0dac50fSopenharmony_ci}
533e0dac50fSopenharmony_ci
534e0dac50fSopenharmony_ciuint32_t MoveDragController::GetActiveWindowId() const
535e0dac50fSopenharmony_ci{
536e0dac50fSopenharmony_ci    return activeWindowId_;
537e0dac50fSopenharmony_ci}
538e0dac50fSopenharmony_ci
539e0dac50fSopenharmony_cistd::shared_ptr<VsyncStation> MoveDragController::GetVsyncStationByWindowId(uint32_t windowId)
540e0dac50fSopenharmony_ci{
541e0dac50fSopenharmony_ci    {
542e0dac50fSopenharmony_ci        std::lock_guard<std::mutex> lock(mtx_);
543e0dac50fSopenharmony_ci        auto iter = vsyncStationMap_.find(windowId);
544e0dac50fSopenharmony_ci        if (iter != vsyncStationMap_.end()) {
545e0dac50fSopenharmony_ci            return iter->second;
546e0dac50fSopenharmony_ci        }
547e0dac50fSopenharmony_ci    }
548e0dac50fSopenharmony_ci
549e0dac50fSopenharmony_ci    if (windowRoot_ == nullptr) {
550e0dac50fSopenharmony_ci        TLOGE(WmsLogTag::WMS_MAIN, "Get vsync station failed, windowRoot is nullptr");
551e0dac50fSopenharmony_ci        return nullptr;
552e0dac50fSopenharmony_ci    }
553e0dac50fSopenharmony_ci
554e0dac50fSopenharmony_ci    sptr<WindowNode> node = windowRoot_->GetWindowNode(windowId);
555e0dac50fSopenharmony_ci    if (node == nullptr || node->surfaceNode_ == nullptr) {
556e0dac50fSopenharmony_ci        TLOGE(WmsLogTag::WMS_MAIN, "Get vsync station failed, surfaceNode is nullptr");
557e0dac50fSopenharmony_ci        return nullptr;
558e0dac50fSopenharmony_ci    }
559e0dac50fSopenharmony_ci
560e0dac50fSopenharmony_ci    auto vsyncStation = std::make_shared<VsyncStation>(node->surfaceNode_->GetId(), inputEventHandler_);
561e0dac50fSopenharmony_ci    if (vsyncStation == nullptr) {
562e0dac50fSopenharmony_ci        TLOGE(WmsLogTag::WMS_MAIN, "Get vsync station failed, create vsyncStation is nullptr");
563e0dac50fSopenharmony_ci        return nullptr;
564e0dac50fSopenharmony_ci    }
565e0dac50fSopenharmony_ci
566e0dac50fSopenharmony_ci    {
567e0dac50fSopenharmony_ci        std::lock_guard<std::mutex> lock(mtx_);
568e0dac50fSopenharmony_ci        vsyncStationMap_.emplace(windowId, vsyncStation);
569e0dac50fSopenharmony_ci    }
570e0dac50fSopenharmony_ci
571e0dac50fSopenharmony_ci    return vsyncStation;
572e0dac50fSopenharmony_ci}
573e0dac50fSopenharmony_ci}
574e0dac50fSopenharmony_ci}
575