1 /*
2  * Copyright (c) 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 
16 #include "session/host/include/move_drag_controller.h"
17 
18 #include <cinttypes>
19 
20 #include <hitrace_meter.h>
21 #include <pointer_event.h>
22 #include "input_manager.h"
23 #include <transaction/rs_transaction.h>
24 #include <ui/rs_surface_node.h>
25 
26 #include "display_manager.h"
27 #include "session/host/include/scene_persistent_storage.h"
28 #include "session/host/include/scene_session.h"
29 #include "session/host/include/session_utils.h"
30 #include "window_helper.h"
31 #include "session_helper.h"
32 #include "window_manager_hilog.h"
33 #include "wm_common_inner.h"
34 #include "ws_common.h"
35 #include "screen_session_manager_client/include/screen_session_manager_client.h"
36 
37 #ifdef RES_SCHED_ENABLE
38 #include "res_type.h"
39 #include "res_sched_client.h"
40 #endif
41 
42 namespace OHOS::Rosen {
43 namespace {
44 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "MoveDragController" };
45 }
46 
MoveDragController(int32_t persistentId, bool isSystemWindow)47 MoveDragController::MoveDragController(int32_t persistentId, bool isSystemWindow)
48 {
49     persistentId_ = persistentId;
50     isSystemWindow_ = isSystemWindow;
51 }
52 
OnConnect(ScreenId id)53 void MoveDragController::OnConnect(ScreenId id)
54 {
55     TLOGW(WmsLogTag::WMS_LAYOUT, "Moving or dragging is interrupt due to new screen %{public}" PRIu64
56         " connection.", id);
57     moveDragIsInterrupted_ = true;
58 }
59 
OnDisconnect(ScreenId id)60 void MoveDragController::OnDisconnect(ScreenId id)
61 {
62     TLOGW(WmsLogTag::WMS_LAYOUT, "Moving or dragging is interrupt due to screen %{public}" PRIu64
63         " disconnection.", id);
64     moveDragIsInterrupted_ = true;
65 }
66 
OnChange(ScreenId id)67 void MoveDragController::OnChange(ScreenId id)
68 {
69     TLOGW(WmsLogTag::WMS_LAYOUT, "Moving or dragging is interrupt due to screen %{public}" PRIu64
70         " change.", id);
71     moveDragIsInterrupted_ = true;
72 }
73 
RegisterMoveDragCallback(const MoveDragCallback& callBack)74 void MoveDragController::RegisterMoveDragCallback(const MoveDragCallback& callBack)
75 {
76     moveDragCallback_ = callBack;
77 }
78 
SetAsSystemWindow(bool isSystemWindow)79 void MoveDragController::SetAsSystemWindow(bool isSystemWindow)
80 {
81     isSystemWindow_ = isSystemWindow;
82 }
83 
IsSystemWindow() const84 bool MoveDragController::IsSystemWindow() const
85 {
86     return isSystemWindow_;
87 }
88 
NotifyWindowInputPidChange(bool isServerPid)89 void MoveDragController::NotifyWindowInputPidChange(bool isServerPid)
90 {
91     if (pidChangeCallback_) {
92         pidChangeCallback_(persistentId_, isServerPid);
93         WLOGFI("id: %{public}d, isServerPid:%{public}d", persistentId_, isServerPid);
94     }
95 }
96 
HasPointDown()97 bool MoveDragController::HasPointDown()
98 {
99     return hasPointDown_;
100 }
101 
SetStartMoveFlag(bool flag)102 void MoveDragController::SetStartMoveFlag(bool flag)
103 {
104     if (flag && (!hasPointDown_ || isStartDrag_)) {
105         WLOGFD("StartMove, but has not pointed down or is dragging, hasPointDown_: %{public}d, isStartFlag: %{public}d",
106             hasPointDown_, isStartDrag_);
107         return;
108     }
109     NotifyWindowInputPidChange(flag);
110     isStartMove_ = flag;
111     ResSchedReportData(OHOS::ResourceSchedule::ResType::RES_TYPE_MOVE_WINDOW, flag);
112     WLOGFI("SetStartMoveFlag, isStartMove_: %{public}d id:%{public}d", isStartMove_, persistentId_);
113 }
114 
SetMovable(bool isMovable)115 void MoveDragController::SetMovable(bool isMovable)
116 {
117     isMovable_ = isMovable;
118 }
119 
SetNotifyWindowPidChangeCallback(const NotifyWindowPidChangeCallback& callback)120 void MoveDragController::SetNotifyWindowPidChangeCallback(const NotifyWindowPidChangeCallback& callback)
121 {
122     pidChangeCallback_ = callback;
123 }
124 
GetStartMoveFlag() const125 bool MoveDragController::GetStartMoveFlag() const
126 {
127     WLOGFD("GetStartMoveFlag, isStartMove_: %{public}d id:%{public}d", isStartMove_, persistentId_);
128     return isStartMove_;
129 }
130 
GetStartDragFlag() const131 bool MoveDragController::GetStartDragFlag() const
132 {
133     return isStartDrag_;
134 }
135 
GetMoveDragStartDisplayId() const136 uint64_t MoveDragController::GetMoveDragStartDisplayId() const
137 {
138     return moveDragStartDisplayId_;
139 }
140 
GetMoveDragEndDisplayId() const141 uint64_t MoveDragController::GetMoveDragEndDisplayId() const
142 {
143     return moveDragEndDisplayId_;
144 }
145 
GetInitParentNodeId() const146 uint64_t MoveDragController::GetInitParentNodeId() const
147 {
148     return initParentNodeId_;
149 }
150 
GetDisplayIdsDuringMoveDrag()151 std::set<uint64_t> MoveDragController::GetDisplayIdsDuringMoveDrag()
152 {
153     std::lock_guard<std::mutex> lock(displayIdSetDuringMoveDragMutex_);
154     return displayIdSetDuringMoveDrag_;
155 }
156 
GetMovable() const157 bool MoveDragController::GetMovable() const
158 {
159     return isMovable_;
160 }
161 
GetTargetRect(TargetRectCoordinate coordinate) const162 WSRect MoveDragController::GetTargetRect(TargetRectCoordinate coordinate) const
163 {
164     DisplayId relatedDisplayId = DISPLAY_ID_INVALID;
165     switch (coordinate) {
166         case TargetRectCoordinate::GLOBAL:
167             return {
168                 moveDragProperty_.targetRect_.posX_ + originalDisplayOffsetX_,
169                 moveDragProperty_.targetRect_.posY_ + originalDisplayOffsetY_,
170                 moveDragProperty_.targetRect_.width_,
171                 moveDragProperty_.targetRect_.height_ };
172         case TargetRectCoordinate::RELATED_TO_START_DISPLAY:
173             return moveDragProperty_.targetRect_;
174         case TargetRectCoordinate::RELATED_TO_END_DISPLAY:
175             relatedDisplayId = moveDragEndDisplayId_;
176             break;
177         default:
178             return moveDragProperty_.targetRect_;
179     }
180     sptr<ScreenSession> screenSession =
181         ScreenSessionManagerClient::GetInstance().GetScreenSessionById(relatedDisplayId);
182     if (!screenSession) {
183         TLOGW(WmsLogTag::WMS_LAYOUT, "Screen session is null, return relative coordinates.");
184         return moveDragProperty_.targetRect_;
185     }
186     ScreenProperty screenProperty = screenSession->GetScreenProperty();
187     int32_t currentDisplayOffsetX = screenProperty.GetStartX();
188     int32_t currentDisplayOffsetY = screenProperty.GetStartY();
189     return {
190             moveDragProperty_.targetRect_.posX_ + originalDisplayOffsetX_ - currentDisplayOffsetX,
191             moveDragProperty_.targetRect_.posY_ + originalDisplayOffsetY_ - currentDisplayOffsetY,
192             moveDragProperty_.targetRect_.width_,
193             moveDragProperty_.targetRect_.height_ };
194 }
195 
InitMoveDragProperty()196 void MoveDragController::InitMoveDragProperty()
197 {
198     moveDragProperty_ = { -1, -1, -1, -1, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } };
199 }
200 
InitCrossDisplayProperty(DisplayId displayId, uint64_t initParentNodeId)201 void MoveDragController::InitCrossDisplayProperty(DisplayId displayId, uint64_t initParentNodeId)
202 {
203     DMError error = ScreenManager::GetInstance().RegisterScreenListener(this);
204     if (error != DMError::DM_OK) {
205         TLOGW(WmsLogTag::WMS_LAYOUT, "Register ScreenListener false.");
206     }
207     {
208         std::lock_guard<std::mutex> lock(displayIdSetDuringMoveDragMutex_);
209         displayIdSetDuringMoveDrag_.insert(displayId);
210     }
211     moveDragStartDisplayId_ = displayId;
212     initParentNodeId_ = initParentNodeId;
213     sptr<ScreenSession> screenSession = ScreenSessionManagerClient::GetInstance().
214         GetScreenSessionById(moveDragStartDisplayId_);
215     if (!screenSession) {
216         return;
217     }
218     ScreenProperty screenProperty = screenSession->GetScreenProperty();
219     originalDisplayOffsetX_ = screenProperty.GetStartX();
220     originalDisplayOffsetY_ = screenProperty.GetStartY();
221     TLOGI(WmsLogTag::WMS_LAYOUT, "moveDragStartDisplayId: %{public}" PRIu64 ", "
222         "originalDisplayOffsetX: %{public}d, originalDisplayOffsetY: %{public}d",
223         moveDragStartDisplayId_, originalDisplayOffsetX_, originalDisplayOffsetY_);
224 }
225 
ResetCrossMoveDragProperty()226 void MoveDragController::ResetCrossMoveDragProperty()
227 {
228     moveDragProperty_ = { -1, -1, -1, -1, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } };
229     DMError error = ScreenManager::GetInstance().UnregisterScreenListener(this);
230     if (error != DMError::DM_OK) {
231         TLOGW(WmsLogTag::WMS_LAYOUT, "Register ScreenListener false.");
232     }
233     {
234         std::lock_guard<std::mutex> lock(displayIdSetDuringMoveDragMutex_);
235         displayIdSetDuringMoveDrag_.clear();
236     }
237     moveDragStartDisplayId_ = DISPLAY_ID_INVALID;
238     moveDragEndDisplayId_ = DISPLAY_ID_INVALID;
239     initParentNodeId_ = -1;
240     originalDisplayOffsetX_ = 0;
241     originalDisplayOffsetY_ = 0;
242     isSystemWindow_ = false;
243     moveDragIsInterrupted_ = false;
244 }
245 
SetOriginalValue(int32_t pointerId, int32_t pointerType, int32_t pointerPosX, int32_t pointerPosY, const WSRect& winRect)246 void MoveDragController::SetOriginalValue(int32_t pointerId, int32_t pointerType,
247     int32_t pointerPosX, int32_t pointerPosY, const WSRect& winRect)
248 {
249     moveDragProperty_.pointerId_ = pointerId;
250     moveDragProperty_.pointerType_ = pointerType;
251     moveDragProperty_.originalPointerPosX_ = pointerPosX;
252     moveDragProperty_.originalPointerPosY_ = pointerPosY;
253     moveDragProperty_.originalRect_ = winRect;
254 }
255 
GetFullScreenToFloatingRect(const WSRect& originalRect, const WSRect& windowRect)256 WSRect MoveDragController::GetFullScreenToFloatingRect(const WSRect& originalRect, const WSRect& windowRect)
257 {
258     if (moveTempProperty_.isEmpty()) {
259         TLOGI(WmsLogTag::WMS_LAYOUT, "move temporary property is empty");
260         return originalRect;
261     }
262     if (originalRect.width_ == 0) {
263         WLOGE("original rect witch is zero");
264         return windowRect;
265     }
266     float newPosX = static_cast<float>(windowRect.width_) / static_cast<float>(originalRect.width_) *
267         static_cast<float>(moveTempProperty_.lastDownPointerPosX_);
268     WSRect targetRect = {
269         moveTempProperty_.lastDownPointerPosX_ - static_cast<int32_t>(newPosX),
270         originalRect.posY_,
271         windowRect.width_,
272         windowRect.height_,
273     };
274     TLOGI(WmsLogTag::WMS_LAYOUT, "original rect [%{public}d,%{public}d,%{public}u,%{public}u]", targetRect.posX_,
275         targetRect.posY_, targetRect.width_, targetRect.height_);
276     return targetRect;
277 }
278 
SetAspectRatio(float ratio)279 void MoveDragController::SetAspectRatio(float ratio)
280 {
281     aspectRatio_ = ratio;
282 }
283 
ConsumeMoveEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent, const WSRect& originalRect)284 bool MoveDragController::ConsumeMoveEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
285     const WSRect& originalRect)
286 {
287     if (pointerEvent == nullptr) {
288         WLOGE("ConsumeMoveEvent stop because of nullptr");
289         return false;
290     }
291     if (GetStartDragFlag()) {
292         WLOGFI("the window is being resized");
293         return false;
294     }
295     int32_t pointerId = pointerEvent->GetPointerId();
296     int32_t startPointerId = moveDragProperty_.pointerId_;
297     int32_t startPointerType = moveDragProperty_.pointerType_;
298     if ((startPointerId != -1 && startPointerId != pointerId) ||
299         (startPointerType != -1 && pointerEvent->GetSourceType() != startPointerType)) {
300         WLOGFI("block unnecessary pointer event inside the window");
301         return false;
302     }
303     MMI::PointerEvent::PointerItem pointerItem;
304     int32_t sourceType = pointerEvent->GetSourceType();
305     if (!pointerEvent->GetPointerItem(pointerId, pointerItem) ||
306         (sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE &&
307         (pointerEvent->GetButtonId() != MMI::PointerEvent::MOUSE_BUTTON_LEFT &&
308         !GetStartMoveFlag()))) {
309         WLOGFD("invalid pointerEvent id: %{public}d", persistentId_);
310         return false;
311     }
312 
313     UpdateMoveTempProperty(pointerEvent);
314 
315     int32_t action = pointerEvent->GetPointerAction();
316     if (!GetStartMoveFlag()) {
317         if (action == MMI::PointerEvent::POINTER_ACTION_DOWN ||
318             action == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN) {
319             WLOGFD("Move event hasPointDown");
320             hasPointDown_ = true;
321         } else if (action == MMI::PointerEvent::POINTER_ACTION_UP ||
322             action == MMI::PointerEvent::POINTER_ACTION_BUTTON_UP ||
323             action == MMI::PointerEvent::POINTER_ACTION_CANCEL) {
324             WLOGFD("Reset hasPointDown_ when point up or cancel");
325             hasPointDown_ = false;
326         }
327         WLOGFD("No need to move action id: %{public}d", action);
328         return false;
329     }
330 
331     SizeChangeReason reason = SizeChangeReason::MOVE;
332     bool ret = true;
333     switch (action) {
334         case MMI::PointerEvent::POINTER_ACTION_MOVE: {
335             if (moveDragIsInterrupted_) {
336                 MoveDragInterrupt();
337                 return true;
338             }
339             reason = SizeChangeReason::MOVE;
340             uint32_t oldWindowDragHotAreaType = windowDragHotAreaType_;
341             UpdateHotAreaType(pointerEvent);
342             ProcessWindowDragHotAreaFunc(oldWindowDragHotAreaType != windowDragHotAreaType_, reason);
343             break;
344         }
345         case MMI::PointerEvent::POINTER_ACTION_UP:
346         case MMI::PointerEvent::POINTER_ACTION_BUTTON_UP:
347         case MMI::PointerEvent::POINTER_ACTION_CANCEL:
348         case MMI::PointerEvent::POINTER_ACTION_DOWN:
349         case MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN: {
350             if (!hasPointDown_) {
351                 return true;
352             }
353             if (moveDragIsInterrupted_) {
354                 MoveDragInterrupt();
355                 return true;
356             }
357             reason = SizeChangeReason::DRAG_END;
358             SetStartMoveFlag(false);
359             hasPointDown_ = false;
360             moveDragEndDisplayId_ = pointerEvent->GetTargetDisplayId();
361             ProcessWindowDragHotAreaFunc(windowDragHotAreaType_ != WINDOW_HOT_AREA_TYPE_UNDEFINED, reason);
362             // The Pointer up event sent to the ArkUI.
363             ret = false;
364             break;
365         }
366         default:
367             break;
368     }
369     if (CalcMoveTargetRect(pointerEvent, originalRect)) {
370         ProcessSessionRectChange(reason);
371     }
372     return ret;
373 }
374 
ProcessWindowDragHotAreaFunc(bool isSendHotAreaMessage, const SizeChangeReason reason)375 void MoveDragController::ProcessWindowDragHotAreaFunc(bool isSendHotAreaMessage, const SizeChangeReason reason)
376 {
377     if (isSendHotAreaMessage) {
378         WLOGFI("ProcessWindowDragHotAreaFunc start, isSendHotAreaMessage: %{public}u, reason: %{public}d",
379             isSendHotAreaMessage, reason);
380     }
381     if (windowDragHotAreaFunc_ && isSendHotAreaMessage) {
382         windowDragHotAreaFunc_(hotAreaDisplayId_, windowDragHotAreaType_, reason);
383     }
384 }
385 
UpdateGravityWhenDrag(const std::shared_ptr<MMI::PointerEvent>& pointerEvent, const std::shared_ptr<RSSurfaceNode>& surfaceNode)386 void MoveDragController::UpdateGravityWhenDrag(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
387     const std::shared_ptr<RSSurfaceNode>& surfaceNode)
388 {
389     if (surfaceNode == nullptr || pointerEvent == nullptr || type_ == AreaType::UNDEFINED) {
390         return;
391     }
392     if (pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_DOWN ||
393         pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN) {
394         bool isNeedFlush = false;
395         if (isStartDrag_ && isPcWindow_) {
396             surfaceNode->MarkUifirstNode(false);
397             isNeedFlush = true;
398         }
399         Gravity dragGravity = GRAVITY_MAP.at(type_);
400         if (dragGravity >= Gravity::TOP && dragGravity <= Gravity::BOTTOM_RIGHT) {
401             WLOGFI("begin SetFrameGravity:%{public}d, type:%{public}d", dragGravity, type_);
402             surfaceNode->SetFrameGravity(dragGravity);
403             RSTransaction::FlushImplicitTransaction();
404         } else if (isNeedFlush) {
405             RSTransaction::FlushImplicitTransaction();
406         }
407         return;
408     }
409     if (pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_BUTTON_UP ||
410         pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_UP ||
411         pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_CANCEL) {
412         if (!isStartDrag_ && isPcWindow_) {
413             surfaceNode->MarkUifirstNode(true);
414         }
415         surfaceNode->SetFrameGravity(Gravity::TOP_LEFT);
416         RSTransaction::FlushImplicitTransaction();
417         WLOGFI("recover gravity to TOP_LEFT");
418     }
419 }
420 
CalcDragTargetRect(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)421 void MoveDragController::CalcDragTargetRect(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
422 {
423     if (!IsSystemWindow() || static_cast<uint64_t>(pointerEvent->GetTargetDisplayId()) == moveDragStartDisplayId_) {
424         std::pair<int32_t, int32_t> trans = CalcUnifiedTranslate(pointerEvent);
425         moveDragProperty_.targetRect_ = MathHelper::GreatNotEqual(aspectRatio_, NEAR_ZERO) ?
426             CalcFixedAspectRatioTargetRect(
427                 type_, trans.first, trans.second, aspectRatio_, moveDragProperty_.originalRect_) :
428             CalcFreeformTargetRect(type_, trans.first, trans.second, moveDragProperty_.originalRect_);
429     }
430     TLOGD(WmsLogTag::WMS_LAYOUT, "drag rect: %{public}s", moveDragProperty_.targetRect_.ToString().c_str());
431 }
432 
ConsumeDragEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent, const WSRect& originalRect, const sptr<WindowSessionProperty> property, const SystemSessionConfig& sysConfig)433 bool MoveDragController::ConsumeDragEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
434     const WSRect& originalRect, const sptr<WindowSessionProperty> property, const SystemSessionConfig& sysConfig)
435 {
436     if (!CheckDragEventLegal(pointerEvent, property)) {
437         return false;
438     }
439     int32_t pointerId = pointerEvent->GetPointerId();
440     MMI::PointerEvent::PointerItem pointerItem;
441     if (!pointerEvent->GetPointerItem(pointerId, pointerItem)) {
442         WLOGE("Get PointerItem failed");
443         return false;
444     }
445     SizeChangeReason reason = SizeChangeReason::UNDEFINED;
446     switch (pointerEvent->GetPointerAction()) {
447         case MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN:
448         case MMI::PointerEvent::POINTER_ACTION_DOWN: {
449             if (!EventDownInit(pointerEvent, originalRect, property, sysConfig)) {
450                 return false;
451             }
452             reason = SizeChangeReason::DRAG_START;
453             ResSchedReportData(OHOS::ResourceSchedule::ResType::RES_TYPE_RESIZE_WINDOW, true);
454             break;
455         }
456         case MMI::PointerEvent::POINTER_ACTION_MOVE: {
457             if (moveDragIsInterrupted_) {
458                 MoveDragInterrupt();
459                 return true;
460             }
461             reason = SizeChangeReason::DRAG;
462             break;
463         }
464         case MMI::PointerEvent::POINTER_ACTION_UP:
465         case MMI::PointerEvent::POINTER_ACTION_BUTTON_UP:
466         case MMI::PointerEvent::POINTER_ACTION_CANCEL: {
467             if (!hasPointDown_) {
468                 return true;
469             }
470             auto screenRect = GetScreenRectById(moveDragStartDisplayId_);
471             if (moveDragIsInterrupted_ || screenRect == WSRect {-1, -1, -1, -1}) {
472                 MoveDragInterrupt();
473                 return true;
474             }
475             reason = SizeChangeReason::DRAG_END;
476             isStartDrag_ = false;
477             hasPointDown_ = false;
478             moveDragEndDisplayId_ = GetTargetRect(TargetRectCoordinate::GLOBAL).IsOverlap(screenRect) ?
479                 moveDragStartDisplayId_ : pointerEvent->GetTargetDisplayId();
480             ResSchedReportData(OHOS::ResourceSchedule::ResType::RES_TYPE_RESIZE_WINDOW, false);
481             NotifyWindowInputPidChange(isStartDrag_);
482             break;
483         }
484         default:
485             return false;
486     }
487     CalcDragTargetRect(pointerEvent);
488     ProcessSessionRectChange(reason);
489     return true;
490 }
491 
MoveDragInterrupt()492 void MoveDragController::MoveDragInterrupt()
493 {
494     TLOGI(WmsLogTag::WMS_LAYOUT, "Screen anomaly, MoveDrag has been interrupted.");
495     SizeChangeReason reason = SizeChangeReason::DRAG_END;
496     hasPointDown_ = false;
497     if (isStartDrag_) {
498         isStartDrag_ = false;
499         ResSchedReportData(OHOS::ResourceSchedule::ResType::RES_TYPE_RESIZE_WINDOW, false);
500         NotifyWindowInputPidChange(isStartDrag_);
501     };
502     if (GetStartMoveFlag()) {
503         SetStartMoveFlag(false);
504         ProcessWindowDragHotAreaFunc(windowDragHotAreaType_ != WINDOW_HOT_AREA_TYPE_UNDEFINED, reason);
505     };
506     moveDragEndDisplayId_ = moveDragStartDisplayId_;
507     moveDragProperty_.targetRect_ = moveDragProperty_.originalRect_;
508     ProcessSessionRectChange(reason);
509 }
510 
GetScreenRectById(DisplayId displayId)511 WSRect MoveDragController::GetScreenRectById(DisplayId displayId)
512 {
513     sptr<ScreenSession> screenSession =
514         ScreenSessionManagerClient::GetInstance().GetScreenSessionById(displayId);
515     if (!screenSession) {
516         TLOGI(WmsLogTag::WMS_LAYOUT, "ScreenSession id null.");
517         return WSRect {-1, -1, -1, -1};
518     }
519     ScreenProperty screenProperty = screenSession->GetScreenProperty();
520     WSRect screenRect = {
521         screenProperty.GetStartX(),
522         screenProperty.GetStartY(),
523         screenProperty.GetBounds().rect_.GetWidth(),
524         screenProperty.GetBounds().rect_.GetHeight(),
525     };
526     return screenRect;
527 }
528 
CalcUnifiedTranslate( const std::shared_ptr<MMI::PointerEvent>& pointerEvent)529 std::pair<int32_t, int32_t> MoveDragController::CalcUnifiedTranslate(
530     const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
531 {
532     int32_t pointerId = pointerEvent->GetPointerId();
533     MMI::PointerEvent::PointerItem pointerItem;
534     pointerEvent->GetPointerItem(pointerId, pointerItem);
535     sptr<ScreenSession> screenSession = ScreenSessionManagerClient::GetInstance().
536         GetScreenSessionById(static_cast<uint64_t>(pointerEvent->GetTargetDisplayId()));
537     if (!screenSession) {
538         return std::make_pair(0, 0);
539     }
540     ScreenProperty screenProperty = screenSession->GetScreenProperty();
541     // calculate trans in unified coordinates
542     int32_t currentDisplayTranX = screenProperty.GetStartX();
543     int32_t currentDisplayTranY = screenProperty.GetStartY();
544     int32_t tranX = (pointerItem.GetDisplayX() + currentDisplayTranX) -
545         (moveDragProperty_.originalPointerPosX_ + originalDisplayOffsetX_);
546     int32_t tranY = (pointerItem.GetDisplayY() + currentDisplayTranY) -
547         (moveDragProperty_.originalPointerPosY_ + originalDisplayOffsetY_);
548     return std::make_pair(tranX, tranY);
549 }
550 
CalcMoveTargetRect(const std::shared_ptr<MMI::PointerEvent>& pointerEvent, const WSRect& originalRect)551 bool MoveDragController::CalcMoveTargetRect(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
552     const WSRect& originalRect)
553 {
554     MMI::PointerEvent::PointerItem pointerItem;
555     int32_t pointerId = pointerEvent->GetPointerId();
556     pointerEvent->GetPointerItem(pointerId, pointerItem);
557     if (moveDragProperty_.isEmpty()) {
558         int32_t pointerDisplayX = pointerItem.GetDisplayX();
559         int32_t pointerDisplayY = pointerItem.GetDisplayY();
560         moveDragProperty_.pointerId_ = pointerId;
561         moveDragProperty_.pointerType_ = pointerEvent->GetSourceType();
562         moveDragProperty_.originalPointerPosX_ = pointerDisplayX;
563         moveDragProperty_.originalPointerPosY_ = pointerDisplayY;
564         int32_t pointerWindowX = pointerItem.GetWindowX();
565         int32_t pointerWindowY = pointerItem.GetWindowY();
566         moveDragProperty_.originalRect_ = originalRect;
567         moveDragProperty_.originalRect_.posX_ = pointerDisplayX - pointerWindowX;
568         moveDragProperty_.originalRect_.posY_ = pointerDisplayY - pointerWindowY;
569         return false;
570     };
571     if (!IsSystemWindow() || static_cast<uint64_t>(pointerEvent->GetTargetDisplayId()) == moveDragStartDisplayId_) {
572         std::pair<int32_t, int32_t> trans = CalcUnifiedTranslate(pointerEvent);
573         moveDragProperty_.targetRect_ = {
574             moveDragProperty_.originalRect_.posX_ + trans.first,
575             moveDragProperty_.originalRect_.posY_ + trans.second,
576             originalRect.width_,
577             originalRect.height_};
578     }
579     WLOGFD("move rect: %{public}s", moveDragProperty_.targetRect_.ToString().c_str());
580     return true;
581 }
582 
EventDownInit(const std::shared_ptr<MMI::PointerEvent>& pointerEvent, const WSRect& originalRect, const sptr<WindowSessionProperty> property, const SystemSessionConfig& sysConfig)583 bool MoveDragController::EventDownInit(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
584     const WSRect& originalRect, const sptr<WindowSessionProperty> property, const SystemSessionConfig& sysConfig)
585 {
586     const auto& sourceType = pointerEvent->GetSourceType();
587     if (sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE &&
588         pointerEvent->GetButtonId() != MMI::PointerEvent::MOUSE_BUTTON_LEFT) {
589         return false;
590     }
591     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "MoveDragController::EventDownInit");
592     int32_t pointerId = pointerEvent->GetPointerId();
593     MMI::PointerEvent::PointerItem pointerItem;
594     pointerEvent->GetPointerItem(pointerId, pointerItem);
595     InitMoveDragProperty();
596     hasPointDown_ = true;
597     moveDragProperty_.originalRect_ = originalRect;
598     auto display = DisplayManager::GetInstance().GetDisplayById(pointerEvent->GetTargetDisplayId());
599     if (display) {
600         vpr_ = display->GetVirtualPixelRatio();
601     } else {
602         vpr_ = 1.5f; // 1.5f: default virtual pixel ratio
603     }
604     int outside = (sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE) ? HOTZONE_POINTER * vpr_ :
605         HOTZONE_TOUCH * vpr_;
606     type_ = SessionHelper::GetAreaType(pointerItem.GetWindowX(), pointerItem.GetWindowY(), sourceType, outside, vpr_,
607         moveDragProperty_.originalRect_);
608     if (type_ == AreaType::UNDEFINED) {
609         return false;
610     }
611     InitDecorValue(property, sysConfig);
612     limits_ = property->GetWindowLimits();
613     moveDragProperty_.pointerId_ = pointerEvent->GetPointerId();
614     moveDragProperty_.pointerType_ = sourceType;
615     moveDragProperty_.originalPointerPosX_ = pointerItem.GetDisplayX();
616     moveDragProperty_.originalPointerPosY_ = pointerItem.GetDisplayY();
617     if (aspectRatio_ <= NEAR_ZERO) {
618         CalcFreeformTranslateLimits(type_);
619     }
620     moveDragProperty_.originalRect_.posX_ = pointerItem.GetDisplayX() - pointerItem.GetWindowX();
621     moveDragProperty_.originalRect_.posY_ = pointerItem.GetDisplayY() - pointerItem.GetWindowY();
622     mainMoveAxis_ = AxisType::UNDEFINED;
623     isStartDrag_ = true;
624     NotifyWindowInputPidChange(isStartDrag_);
625     return true;
626 }
627 
CalcFreeformTargetRect(AreaType type, int32_t tranX, int32_t tranY, WSRect originalRect)628 WSRect MoveDragController::CalcFreeformTargetRect(AreaType type, int32_t tranX, int32_t tranY, WSRect originalRect)
629 {
630     WSRect targetRect = originalRect;
631     FixTranslateByLimits(tranX, tranY);
632     if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::LEFT)) {
633         targetRect.posX_ += tranX;
634         targetRect.width_ -= tranX;
635     } else if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::RIGHT)) {
636         targetRect.width_ += tranX;
637     }
638     if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::TOP)) {
639         targetRect.posY_ += tranY;
640         targetRect.height_ -= tranY;
641     } else if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::BOTTOM)) {
642         targetRect.height_ += tranY;
643     }
644     // check current ratio limits
645     if (targetRect.height_ == 0) {
646         return targetRect;
647     }
648     float curRatio = static_cast<float>(targetRect.width_) / static_cast<float>(targetRect.height_);
649     if (!MathHelper::GreatNotEqual(limits_.minRatio_, curRatio) &&
650         !MathHelper::GreatNotEqual(curRatio, limits_.maxRatio_)) {
651         return targetRect;
652     }
653     float newRatio = MathHelper::LessNotEqual(curRatio, limits_.minRatio_) ? limits_.minRatio_ : limits_.maxRatio_;
654     if (MathHelper::NearZero(newRatio)) {
655         return targetRect;
656     }
657     if ((static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::LEFT)) ||
658         (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::RIGHT))) {
659         targetRect.height_ = static_cast<int32_t>(static_cast<float>(targetRect.width_) / newRatio);
660     } else {
661         targetRect.width_ = static_cast<int32_t>(static_cast<float>(targetRect.height_) * newRatio);
662     }
663     return targetRect;
664 }
665 
CalcFixedAspectRatioTargetRect(AreaType type, int32_t tranX, int32_t tranY, float aspectRatio, WSRect originalRect)666 WSRect MoveDragController::CalcFixedAspectRatioTargetRect(AreaType type, int32_t tranX, int32_t tranY,
667     float aspectRatio, WSRect originalRect)
668 {
669     int32_t posX = originalRect.posX_;
670     int32_t posY = originalRect.posY_;
671     int32_t width = static_cast<int32_t>(originalRect.width_);
672     int32_t height = static_cast<int32_t>(originalRect.height_);
673     FixTranslateByLimits(tranX, tranY);
674     if (mainMoveAxis_ == AxisType::UNDEFINED) {
675         if (!InitMainAxis(type, tranX, tranY)) {
676             return originalRect;
677         }
678     }
679 
680     ConvertXYByAspectRatio(tranX, tranY, aspectRatio);
681     switch (type) {
682         case AreaType::LEFT_TOP: {
683             return { posX + tranX, posY + tranY, width - tranX, height - tranY };
684         }
685         case AreaType::RIGHT_TOP: {
686             return { posX, posY + (mainMoveAxis_ == AxisType::X_AXIS ? (-tranY) : (tranY)),
687                      width + (mainMoveAxis_ == AxisType::X_AXIS ? (tranX) : (-tranX)),
688                      height + (mainMoveAxis_ == AxisType::X_AXIS ? (tranY) : (-tranY)) };
689         }
690         case AreaType::RIGHT_BOTTOM: {
691             return { posX, posY, width + tranX, height + tranY };
692         }
693         case AreaType::LEFT_BOTTOM: {
694             return { posX + (mainMoveAxis_ == AxisType::X_AXIS ? (tranX) : (-tranX)), posY,
695                      width - (mainMoveAxis_ == AxisType::X_AXIS ? (tranX) : (-tranX)),
696                      height - (mainMoveAxis_ == AxisType::X_AXIS ? (tranY) : (-tranY)) };
697         }
698         case AreaType::LEFT: {
699             return { posX + tranX, posY, width - tranX, height - tranY };
700         }
701         case AreaType::TOP: {
702             return { posX, posY + tranY, width - tranX, height - tranY };
703         }
704         case AreaType::RIGHT: {
705             return { posX, posY, width + tranX, height + tranY };
706         }
707         case AreaType::BOTTOM: {
708             return { posX, posY, width + tranX, height + tranY };
709         }
710         default:
711             break;
712     }
713     return originalRect;
714 }
715 
CalcFreeformTranslateLimits(AreaType type)716 void MoveDragController::CalcFreeformTranslateLimits(AreaType type)
717 {
718     if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::LEFT)) {
719         minTranX_ = moveDragProperty_.originalRect_.width_ - static_cast<int32_t>(limits_.maxWidth_);
720         maxTranX_ = moveDragProperty_.originalRect_.width_ - static_cast<int32_t>(limits_.minWidth_);
721     } else if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::RIGHT)) {
722         minTranX_ = static_cast<int32_t>(limits_.minWidth_) - moveDragProperty_.originalRect_.width_;
723         maxTranX_ = static_cast<int32_t>(limits_.maxWidth_) - moveDragProperty_.originalRect_.width_;
724     }
725     if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::TOP)) {
726         minTranY_ = moveDragProperty_.originalRect_.height_ - static_cast<int32_t>(limits_.maxHeight_);
727         maxTranY_ = moveDragProperty_.originalRect_.height_ - static_cast<int32_t>(limits_.minHeight_);
728     } else if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::BOTTOM)) {
729         minTranY_ = static_cast<int32_t>(limits_.minHeight_) - moveDragProperty_.originalRect_.height_;
730         maxTranY_ = static_cast<int32_t>(limits_.maxHeight_) - moveDragProperty_.originalRect_.height_;
731     }
732 }
733 
CalcFixedAspectRatioTranslateLimits(AreaType type, AxisType axis)734 void MoveDragController::CalcFixedAspectRatioTranslateLimits(AreaType type, AxisType axis)
735 {
736     int32_t minW = static_cast<int32_t>(limits_.minWidth_);
737     int32_t maxW = static_cast<int32_t>(limits_.maxWidth_);
738     int32_t minH = static_cast<int32_t>(limits_.minHeight_);
739     int32_t maxH = static_cast<int32_t>(limits_.maxHeight_);
740     if (isDecorEnable_) {
741         if (SessionUtils::ToLayoutWidth(minW, vpr_) < SessionUtils::ToLayoutHeight(minH, vpr_) * aspectRatio_) {
742             minW = SessionUtils::ToWinWidth(SessionUtils::ToLayoutHeight(minH, vpr_) * aspectRatio_, vpr_);
743         } else {
744             minH = SessionUtils::ToWinHeight(SessionUtils::ToLayoutWidth(minW, vpr_) / aspectRatio_, vpr_);
745         }
746         if (SessionUtils::ToLayoutWidth(maxW, vpr_) < SessionUtils::ToLayoutHeight(maxH, vpr_) * aspectRatio_) {
747             maxH = SessionUtils::ToWinHeight(SessionUtils::ToLayoutWidth(maxW, vpr_) * aspectRatio_, vpr_);
748         } else {
749             maxW = SessionUtils::ToWinWidth(SessionUtils::ToLayoutHeight(maxH, vpr_) / aspectRatio_, vpr_);
750         }
751     } else {
752         if (minW < minH * aspectRatio_) {
753             minW = minH * aspectRatio_;
754         } else {
755             minH = minW / aspectRatio_;
756         }
757         if (maxW < maxH * aspectRatio_) {
758             maxH = maxW * aspectRatio_;
759         } else {
760             maxW = maxH / aspectRatio_;
761         }
762     }
763 
764     if (axis == AxisType::X_AXIS) {
765         if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::LEFT)) {
766             minTranX_ = static_cast<int32_t>(moveDragProperty_.originalRect_.width_) - maxW;
767             maxTranX_ = static_cast<int32_t>(moveDragProperty_.originalRect_.width_) - minW;
768         } else if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::RIGHT)) {
769             minTranX_ = minW - static_cast<int32_t>(moveDragProperty_.originalRect_.width_);
770             maxTranX_ = maxW - static_cast<int32_t>(moveDragProperty_.originalRect_.width_);
771         }
772     } else if (axis == AxisType::Y_AXIS) {
773         if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::TOP)) {
774             minTranY_ = static_cast<int32_t>(moveDragProperty_.originalRect_.height_) - maxH;
775             maxTranY_ = static_cast<int32_t>(moveDragProperty_.originalRect_.height_) - minH;
776         } else if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::BOTTOM)) {
777             minTranY_ = minH - static_cast<int32_t>(moveDragProperty_.originalRect_.height_);
778             maxTranY_ = maxH - static_cast<int32_t>(moveDragProperty_.originalRect_.height_);
779         }
780     }
781 }
782 
FixTranslateByLimits(int32_t& tranX, int32_t& tranY)783 void MoveDragController::FixTranslateByLimits(int32_t& tranX, int32_t& tranY)
784 {
785     if (tranX < minTranX_) {
786         tranX = minTranX_;
787     } else if (tranX > maxTranX_) {
788         tranX = maxTranX_;
789     }
790     if (tranY < minTranY_) {
791         tranY = minTranY_;
792     } else if (tranY > maxTranY_) {
793         tranY = maxTranY_;
794     }
795 }
796 
InitMainAxis(AreaType type, int32_t tranX, int32_t tranY)797 bool MoveDragController::InitMainAxis(AreaType type, int32_t tranX, int32_t tranY)
798 {
799     if (type == AreaType::LEFT || type == AreaType::RIGHT) {
800         mainMoveAxis_ = AxisType::X_AXIS;
801     } else if (type == AreaType::TOP || type == AreaType::BOTTOM) {
802         mainMoveAxis_ = AxisType::Y_AXIS;
803     } else if (tranX == 0 && tranY == 0) {
804         return false;
805     } else {
806         mainMoveAxis_ = (std::abs(tranX) > std::abs(tranY)) ? AxisType::X_AXIS : AxisType::Y_AXIS;
807     }
808     CalcFixedAspectRatioTranslateLimits(type, mainMoveAxis_);
809     return true;
810 }
811 
ConvertXYByAspectRatio(int32_t& tx, int32_t& ty, float aspectRatio)812 void MoveDragController::ConvertXYByAspectRatio(int32_t& tx, int32_t& ty, float aspectRatio)
813 {
814     if (mainMoveAxis_ == AxisType::X_AXIS) {
815         ty = tx / aspectRatio;
816     } else if (mainMoveAxis_ == AxisType::Y_AXIS) {
817         tx = ty * aspectRatio;
818     }
819     return;
820 }
821 
InitDecorValue(const sptr<WindowSessionProperty> property, const SystemSessionConfig& sysConfig)822 void MoveDragController::InitDecorValue(const sptr<WindowSessionProperty> property,
823     const SystemSessionConfig& sysConfig)
824 {
825     auto windowType = property->GetWindowType();
826     bool isMainWindow = WindowHelper::IsMainWindow(windowType);
827     bool isSubWindow = WindowHelper::IsSubWindow(windowType);
828     bool isDialogWindow = WindowHelper::IsDialogWindow(windowType);
829     isDecorEnable_ = (isMainWindow ||
830             ((isSubWindow || isDialogWindow) && property->IsDecorEnable())) &&
831         sysConfig.isSystemDecorEnable_ &&
832         WindowHelper::IsWindowModeSupported(sysConfig.decorModeSupportInfo_, property->GetWindowMode());
833 }
834 
ProcessSessionRectChange(const SizeChangeReason reason)835 void MoveDragController::ProcessSessionRectChange(const SizeChangeReason reason)
836 {
837     if (moveDragCallback_) {
838         moveDragCallback_(reason);
839     }
840 }
841 
GetVirtualPixelRatio() const842 float MoveDragController::GetVirtualPixelRatio() const
843 {
844     float vpr = 1.5;
845     auto displayInfo = DisplayManager::GetInstance().GetDefaultDisplay();
846     if (displayInfo != nullptr) {
847         vpr = displayInfo->GetVirtualPixelRatio();
848     }
849     WLOGFD("vpr: %{public}f", vpr);
850     return vpr;
851 }
852 
UpdateDragType(int32_t startPointPosX, int32_t startPointPosY)853 void MoveDragController::UpdateDragType(int32_t startPointPosX, int32_t startPointPosY)
854 {
855     if (startPointPosX > rectExceptCorner_.posX_ &&
856         (startPointPosX < rectExceptCorner_.posX_ +
857         static_cast<int32_t>(rectExceptCorner_.width_))) {
858         dragType_ = DragType::DRAG_BOTTOM_OR_TOP;
859     } else if (startPointPosY > rectExceptCorner_.posY_ &&
860         (startPointPosY < rectExceptCorner_.posY_ +
861         static_cast<int32_t>(rectExceptCorner_.height_))) {
862         dragType_ = DragType::DRAG_LEFT_OR_RIGHT;
863     } else if ((startPointPosX <= rectExceptCorner_.posX_ && startPointPosY <= rectExceptCorner_.posY_) ||
864         (startPointPosX >= rectExceptCorner_.posX_ + static_cast<int32_t>(rectExceptCorner_.width_) &&
865          startPointPosY >= rectExceptCorner_.posY_ + static_cast<int32_t>(rectExceptCorner_.height_))) {
866         dragType_ = DragType::DRAG_LEFT_TOP_CORNER;
867     } else {
868         dragType_ = DragType::DRAG_RIGHT_TOP_CORNER;
869     }
870 }
871 
IsPointInDragHotZone(int32_t startPointPosX, int32_t startPointPosY, int32_t sourceType, const WSRect& winRect)872 bool MoveDragController::IsPointInDragHotZone(int32_t startPointPosX, int32_t startPointPosY,
873     int32_t sourceType, const WSRect& winRect)
874 {
875     // calculate rect with hotzone
876     Rect rectWithHotzone;
877     rectWithHotzone.posX_ = winRect.posX_ - static_cast<int32_t>(HOTZONE_POINTER);
878     rectWithHotzone.posY_ = winRect.posY_ - static_cast<int32_t>(HOTZONE_POINTER);
879     rectWithHotzone.width_ = winRect.width_ + HOTZONE_POINTER * 2u; // double hotZone
880     rectWithHotzone.height_ = winRect.height_ + HOTZONE_POINTER * 2u; // double hotZone
881 
882     if (sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE &&
883         !WindowHelper::IsPointInTargetRectWithBound(startPointPosX, startPointPosY, rectWithHotzone)) {
884         return false;
885     } else if ((!WindowHelper::IsPointInTargetRect(startPointPosX,
886         startPointPosY, rectExceptFrame_)) ||
887         (!WindowHelper::IsPointInWindowExceptCorner(startPointPosX,
888         startPointPosY, rectExceptCorner_))) {
889         return true;
890     }
891     return false;
892 }
893 
CalculateStartRectExceptHotZone(float vpr, const WSRect& winRect)894 void MoveDragController::CalculateStartRectExceptHotZone(float vpr, const WSRect& winRect)
895 {
896     rectExceptFrame_.posX_ = winRect.posX_ +
897         static_cast<int32_t>(WINDOW_FRAME_WIDTH * vpr);
898     rectExceptFrame_.posY_ = winRect.posY_ +
899         static_cast<int32_t>(WINDOW_FRAME_WIDTH * vpr);
900     rectExceptFrame_.width_ = winRect.width_ -
901         static_cast<uint32_t>((WINDOW_FRAME_WIDTH + WINDOW_FRAME_WIDTH) * vpr);
902     rectExceptFrame_.height_ = winRect.height_ -
903         static_cast<uint32_t>((WINDOW_FRAME_WIDTH + WINDOW_FRAME_WIDTH) * vpr);
904 
905     rectExceptCorner_.posX_ = winRect.posX_ +
906         static_cast<int32_t>(WINDOW_FRAME_CORNER_WIDTH * vpr);
907     rectExceptCorner_.posY_ = winRect.posY_ +
908         static_cast<int32_t>(WINDOW_FRAME_CORNER_WIDTH * vpr);
909     rectExceptCorner_.width_ = winRect.width_ -
910         static_cast<uint32_t>((WINDOW_FRAME_CORNER_WIDTH + WINDOW_FRAME_CORNER_WIDTH) * vpr);
911     rectExceptCorner_.height_ = winRect.height_ -
912         static_cast<uint32_t>((WINDOW_FRAME_CORNER_WIDTH + WINDOW_FRAME_CORNER_WIDTH) * vpr);
913 }
914 
UpdateMoveTempProperty(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)915 WSError MoveDragController::UpdateMoveTempProperty(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
916 {
917     int32_t pointerId = pointerEvent->GetPointerId();
918     int32_t startPointerId = moveTempProperty_.pointerId_;
919     int32_t pointerType = pointerEvent->GetSourceType();
920     int32_t startPointerType = moveDragProperty_.pointerType_;
921     MMI::PointerEvent::PointerItem pointerItem;
922     int32_t sourceType = pointerEvent->GetSourceType();
923     if (!pointerEvent->GetPointerItem(pointerId, pointerItem) ||
924         (sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE &&
925         pointerEvent->GetButtonId() != MMI::PointerEvent::MOUSE_BUTTON_LEFT)) {
926         WLOGFW("invalid pointerEvent");
927         return WSError::WS_ERROR_NULLPTR;
928     }
929 
930     int32_t pointerDisplayX = pointerItem.GetDisplayX();
931     int32_t pointerDisplayY = pointerItem.GetDisplayY();
932     switch (pointerEvent->GetPointerAction()) {
933         case MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN:
934         case MMI::PointerEvent::POINTER_ACTION_DOWN:
935             moveTempProperty_.pointerId_ = pointerId;
936             moveTempProperty_.pointerType_ = pointerType;
937             moveTempProperty_.lastDownPointerPosX_ = pointerDisplayX;
938             moveTempProperty_.lastDownPointerPosY_ = pointerDisplayY;
939             moveTempProperty_.lastMovePointerPosX_ = pointerDisplayX;
940             moveTempProperty_.lastMovePointerPosY_ = pointerDisplayY;
941             moveTempProperty_.lastDownPointerWindowX_ = pointerItem.GetWindowX();
942             moveTempProperty_.lastDownPointerWindowY_ = pointerItem.GetWindowY();
943             break;
944         case MMI::PointerEvent::POINTER_ACTION_MOVE:
945             if ((startPointerId != -1 && startPointerId != pointerId) ||
946                 (startPointerType != -1 && pointerType != startPointerType)) {
947                 WLOGFI("block unnecessary pointer event inside the window");
948                 return WSError::WS_DO_NOTHING;
949             }
950             moveTempProperty_.lastMovePointerPosX_ = pointerDisplayX;
951             moveTempProperty_.lastMovePointerPosY_ = pointerDisplayY;
952             break;
953         case MMI::PointerEvent::POINTER_ACTION_UP:
954         case MMI::PointerEvent::POINTER_ACTION_BUTTON_UP:
955         case MMI::PointerEvent::POINTER_ACTION_CANCEL: {
956             moveTempProperty_ = { -1, -1, -1, -1, -1, -1, -1, -1 };
957             break;
958         }
959         default:
960             break;
961     }
962     return WSError::WS_OK;
963 }
964 
CalcFirstMoveTargetRect(const WSRect& windowRect, bool isFullToFloating)965 void MoveDragController::CalcFirstMoveTargetRect(const WSRect& windowRect, bool isFullToFloating)
966 {
967     if (!GetStartMoveFlag() || moveTempProperty_.isEmpty()) {
968         return;
969     }
970 
971     WSRect originalRect = {
972         moveTempProperty_.lastDownPointerPosX_ - moveTempProperty_.lastDownPointerWindowX_,
973         moveTempProperty_.lastDownPointerPosY_ - moveTempProperty_.lastDownPointerWindowY_,
974         windowRect.width_,
975         windowRect.height_
976     };
977     if (isFullToFloating) {
978         originalRect.posX_ = windowRect.posX_;
979         originalRect.posY_ = windowRect.posY_;
980     }
981     SetOriginalValue(moveTempProperty_.pointerId_, moveTempProperty_.pointerType_,
982         moveTempProperty_.lastDownPointerPosX_, moveTempProperty_.lastDownPointerPosY_, originalRect);
983 
984     int32_t offsetX = moveTempProperty_.lastMovePointerPosX_ - moveTempProperty_.lastDownPointerPosX_;
985     int32_t offsetY = moveTempProperty_.lastMovePointerPosY_ - moveTempProperty_.lastDownPointerPosY_;
986     WSRect targetRect = {
987         originalRect.posX_ + offsetX,
988         originalRect.posY_ + offsetY,
989         originalRect.width_,
990         originalRect.height_
991     };
992     WLOGFD("first move rect: [%{public}d, %{public}d, %{public}u, %{public}u]", targetRect.posX_, targetRect.posY_,
993         targetRect.width_, targetRect.height_);
994     moveDragProperty_.targetRect_ = targetRect;
995     ProcessSessionRectChange(SizeChangeReason::MOVE);
996 }
997 
CheckDragEventLegal(const std::shared_ptr<MMI::PointerEvent>& pointerEvent, const sptr<WindowSessionProperty> property)998 bool MoveDragController::CheckDragEventLegal(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
999     const sptr<WindowSessionProperty> property)
1000 {
1001     if (pointerEvent == nullptr || property == nullptr) {
1002         WLOGE("ConsumeDragEvent stop because of nullptr");
1003         return false;
1004     }
1005     if (GetStartMoveFlag()) {
1006         WLOGFD("the window is being moved");
1007         return false;
1008     }
1009     if (!GetStartDragFlag() && pointerEvent->GetPointerAction() != MMI::PointerEvent::POINTER_ACTION_DOWN &&
1010         pointerEvent->GetPointerAction() != MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN) {
1011         return false;
1012     }
1013     int32_t pointerId = pointerEvent->GetPointerId();
1014     int32_t startPointerId = moveDragProperty_.pointerId_;
1015     if (GetStartDragFlag() && startPointerId != -1 && startPointerId != pointerId) {
1016         WLOGFI("block unnecessary pointer event inside the window");
1017         return false;
1018     }
1019     return true;
1020 }
1021 
UpdateHotAreaType(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)1022 void MoveDragController::UpdateHotAreaType(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
1023 {
1024     int32_t pointerId = pointerEvent->GetPointerId();
1025     MMI::PointerEvent::PointerItem pointerItem;
1026     if (!pointerEvent->GetPointerItem(pointerId, pointerItem)) {
1027         WLOGFW("invalid pointerEvent");
1028         return;
1029     }
1030     int32_t pointerDisplayX = pointerItem.GetDisplayX();
1031     int32_t pointerDisplayY = pointerItem.GetDisplayY();
1032     DisplayId displayId = pointerEvent->GetTargetDisplayId();
1033     uint32_t windowDragHotAreaType = SceneSession::GetWindowDragHotAreaType(displayId,
1034         WINDOW_HOT_AREA_TYPE_UNDEFINED, pointerDisplayX, pointerDisplayY);
1035     if (windowDragHotAreaType_ != windowDragHotAreaType) {
1036         WLOGFI("the pointerEvent is window drag hot area, old type is: %{public}d, new type is: %{public}d",
1037             windowDragHotAreaType_, windowDragHotAreaType);
1038     }
1039     if (hotAreaDisplayId_ != displayId) {
1040         TLOGI(WmsLogTag::WMS_LAYOUT, "displayId is changed, old: %{public}" PRIu64 ", new: %{public}" PRIu64,
1041             moveDragStartDisplayId_, displayId);
1042         hotAreaDisplayId_ = displayId;
1043     }
1044     windowDragHotAreaType_ = windowDragHotAreaType;
1045 }
1046 
GetOriginalPointerPosX()1047 int32_t MoveDragController::GetOriginalPointerPosX()
1048 {
1049     return moveDragProperty_.originalPointerPosX_;
1050 }
1051 
GetOriginalPointerPosY()1052 int32_t MoveDragController::GetOriginalPointerPosY()
1053 {
1054     return moveDragProperty_.originalPointerPosY_;
1055 }
1056 
SetWindowDragHotAreaFunc(const NotifyWindowDragHotAreaFunc& func)1057 void MoveDragController::SetWindowDragHotAreaFunc(const NotifyWindowDragHotAreaFunc& func)
1058 {
1059     windowDragHotAreaFunc_ = func;
1060 }
1061 
OnLostFocus()1062 void MoveDragController::OnLostFocus()
1063 {
1064     if (isStartMove_ || isStartDrag_) {
1065         WLOGFI("window id %{public}d lost focus, should stop MoveDrag isMove: %{public}d, isDrag: %{public}d",
1066             persistentId_, isStartMove_, isStartDrag_);
1067         isStartMove_ = false;
1068         isStartDrag_ = false;
1069         NotifyWindowInputPidChange(isStartDrag_);
1070         if (windowDragHotAreaType_ != WINDOW_HOT_AREA_TYPE_UNDEFINED) {
1071             ProcessWindowDragHotAreaFunc(true, SizeChangeReason::DRAG_END);
1072         }
1073         ProcessSessionRectChange(SizeChangeReason::DRAG_END);
1074     }
1075 }
1076 
SetIsPcWindow(bool isPcWindow)1077 void MoveDragController::SetIsPcWindow(bool isPcWindow)
1078 {
1079     isPcWindow_ = isPcWindow;
1080 }
1081 
GetNewAddedDisplayIdsDuringMoveDrag()1082 std::set<uint64_t> MoveDragController::GetNewAddedDisplayIdsDuringMoveDrag()
1083 {
1084     std::set<uint64_t> newAddedDisplayIdSet;
1085     WSRect windowRect = GetTargetRect(TargetRectCoordinate::GLOBAL);
1086     std::map<ScreenId, ScreenProperty> screenProperties = ScreenSessionManagerClient::GetInstance().
1087         GetAllScreensProperties();
1088     std::lock_guard<std::mutex> lock(displayIdSetDuringMoveDragMutex_);
1089     for (const auto& [screenId, screenProperty] : screenProperties) {
1090         if (displayIdSetDuringMoveDrag_.find(screenId) != displayIdSetDuringMoveDrag_.end()) {
1091             continue;
1092         }
1093         WSRect screenRect = {
1094             screenProperty.GetStartX(),
1095             screenProperty.GetStartY(),
1096             screenProperty.GetBounds().rect_.GetWidth(),
1097             screenProperty.GetBounds().rect_.GetHeight(),
1098         };
1099         if (windowRect.IsOverlap(screenRect)) {
1100             displayIdSetDuringMoveDrag_.insert(screenId);
1101             newAddedDisplayIdSet.insert(screenId);
1102         }
1103     }
1104     return newAddedDisplayIdSet;
1105 }
1106 
ResSchedReportData(int32_t type, bool onOffTag)1107 void MoveDragController::ResSchedReportData(int32_t type, bool onOffTag)
1108 {
1109 #ifdef RES_SCHED_ENABLE
1110     std::unordered_map<std::string, std::string> payload;
1111     // 0 is start, 1 is end
1112     if (onOffTag) {
1113         OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(type, 0, payload);
1114     } else {
1115         OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(type, 1, payload);
1116     }
1117     WLOGFD("ResSchedReportData success type: %{public}d onOffTag: %{public}d", type, onOffTag);
1118 #endif
1119 }
1120 } // namespace OHOS::Rosen
1121