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