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 <hitrace_meter.h>
19 #include <pointer_event.h>
20 #include "input_manager.h"
21 #include <transaction/rs_transaction.h>
22 #include <ui/rs_surface_node.h>
23 
24 #include "display_manager.h"
25 #include "session/host/include/scene_persistent_storage.h"
26 #include "session/host/include/scene_session.h"
27 #include "session/host/include/session_utils.h"
28 #include "window_helper.h"
29 #include "session_helper.h"
30 #include "window_manager_hilog.h"
31 #include "wm_common_inner.h"
32 
33 #ifdef RES_SCHED_ENABLE
34 #include "res_type.h"
35 #include "res_sched_client.h"
36 #endif
37 
38 namespace OHOS::Rosen {
39 namespace {
40 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "MoveDragController" };
41 }
42 
MoveDragController(int32_t persistentId)43 MoveDragController::MoveDragController(int32_t persistentId)
44 {
45     persistentId_ = persistentId;
46 }
47 
RegisterMoveDragCallback(const MoveDragCallback & callBack)48 void MoveDragController::RegisterMoveDragCallback(const MoveDragCallback& callBack)
49 {
50     moveDragCallback_ = callBack;
51 }
52 
NotifyWindowInputPidChange(bool isServerPid)53 void MoveDragController::NotifyWindowInputPidChange(bool isServerPid)
54 {
55     if (pidChangeCallback_) {
56         pidChangeCallback_(persistentId_, isServerPid);
57         WLOGFI("id: %{public}d, isServerPid:%{public}d", persistentId_, isServerPid);
58     }
59 }
60 
HasPointDown()61 bool MoveDragController::HasPointDown()
62 {
63     return hasPointDown_;
64 }
65 
SetStartMoveFlag(bool flag)66 void MoveDragController::SetStartMoveFlag(bool flag)
67 {
68     if (flag && (!hasPointDown_ || isStartDrag_)) {
69         WLOGFD("StartMove, but has not pointed down or is dragging, hasPointDown_: %{public}d, isStartFlag: %{public}d",
70             hasPointDown_, isStartDrag_);
71         return;
72     }
73     NotifyWindowInputPidChange(flag);
74     isStartMove_ = flag;
75     ResSchedReportData(OHOS::ResourceSchedule::ResType::RES_TYPE_MOVE_WINDOW, flag);
76     WLOGFI("SetStartMoveFlag, isStartMove_: %{public}d id:%{public}d", isStartMove_, persistentId_);
77 }
78 
SetNotifyWindowPidChangeCallback(const NotifyWindowPidChangeCallback & callback)79 void MoveDragController::SetNotifyWindowPidChangeCallback(const NotifyWindowPidChangeCallback& callback)
80 {
81     pidChangeCallback_ = callback;
82 }
83 
GetStartMoveFlag() const84 bool MoveDragController::GetStartMoveFlag() const
85 {
86     WLOGFD("GetStartMoveFlag, isStartMove_: %{public}d id:%{public}d", isStartMove_, persistentId_);
87     return isStartMove_;
88 }
89 
GetStartDragFlag() const90 bool MoveDragController::GetStartDragFlag() const
91 {
92     return isStartDrag_;
93 }
94 
GetTargetRect() const95 WSRect MoveDragController::GetTargetRect() const
96 {
97     return moveDragProperty_.targetRect_;
98 }
99 
InitMoveDragProperty()100 void MoveDragController::InitMoveDragProperty()
101 {
102     moveDragProperty_ = { -1, -1, -1, -1, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } };
103 }
104 
SetOriginalValue(int32_t pointerId,int32_t pointerType,int32_t pointerPosX,int32_t pointerPosY,const WSRect & winRect)105 void MoveDragController::SetOriginalValue(int32_t pointerId, int32_t pointerType,
106     int32_t pointerPosX, int32_t pointerPosY, const WSRect& winRect)
107 {
108     moveDragProperty_.pointerId_ = pointerId;
109     moveDragProperty_.pointerType_ = pointerType;
110     moveDragProperty_.originalPointerPosX_ = pointerPosX;
111     moveDragProperty_.originalPointerPosY_ = pointerPosY;
112     moveDragProperty_.originalRect_ = winRect;
113 }
114 
GetFullScreenToFloatingRect(const WSRect & originalRect,const WSRect & windowRect)115 WSRect MoveDragController::GetFullScreenToFloatingRect(const WSRect& originalRect, const WSRect& windowRect)
116 {
117     if (moveTempProperty_.isEmpty()) {
118         TLOGI(WmsLogTag::WMS_LAYOUT, "move temporary property is empty");
119         return originalRect;
120     }
121     if (originalRect.width_ == 0) {
122         TLOGI(WmsLogTag::WMS_LAYOUT, "original rect witch is zero");
123         return windowRect;
124     }
125     // Drag and drop to full screen in proportion
126     float newPosX = static_cast<float>(windowRect.width_) / static_cast<float>(originalRect.width_) *
127         static_cast<float>(moveTempProperty_.lastDownPointerPosX_ - originalRect.posX_);
128     WSRect targetRect = {
129         moveTempProperty_.lastDownPointerPosX_ - static_cast<int32_t>(newPosX),
130         originalRect.posY_,
131         windowRect.width_,
132         windowRect.height_,
133     };
134     TLOGI(WmsLogTag::WMS_LAYOUT, "target rect [%{public}d,%{public}d,%{public}u,%{public}u]", targetRect.posX_,
135         targetRect.posY_, targetRect.width_, targetRect.height_);
136     return targetRect;
137 }
138 
SetAspectRatio(float ratio)139 void MoveDragController::SetAspectRatio(float ratio)
140 {
141     aspectRatio_ = ratio;
142 }
143 
ConsumeMoveEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent,const WSRect & originalRect)144 bool MoveDragController::ConsumeMoveEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
145     const WSRect& originalRect)
146 {
147     if (pointerEvent == nullptr) {
148         WLOGE("ConsumeMoveEvent stop because of nullptr");
149         return false;
150     }
151     if (GetStartDragFlag()) {
152         WLOGFI("the window is being resized");
153         return false;
154     }
155     int32_t pointerId = pointerEvent->GetPointerId();
156     int32_t startPointerId = moveDragProperty_.pointerId_;
157     int32_t startPointerType = moveDragProperty_.pointerType_;
158     if ((startPointerId != -1 && startPointerId != pointerId) ||
159         (startPointerType != -1 && pointerEvent->GetSourceType() != startPointerType)) {
160         WLOGFI("block unnecessary pointer event inside the window");
161         return false;
162     }
163     MMI::PointerEvent::PointerItem pointerItem;
164     int32_t sourceType = pointerEvent->GetSourceType();
165     if (!pointerEvent->GetPointerItem(pointerId, pointerItem) ||
166         (sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE &&
167         (pointerEvent->GetButtonId() != MMI::PointerEvent::MOUSE_BUTTON_LEFT &&
168         !GetStartMoveFlag()))) {
169         WLOGFD("invalid pointerEvent id: %{public}d", persistentId_);
170         return false;
171     }
172 
173     UpdateMoveTempProperty(pointerEvent);
174 
175     int32_t action = pointerEvent->GetPointerAction();
176     if (!GetStartMoveFlag()) {
177         if (action == MMI::PointerEvent::POINTER_ACTION_DOWN ||
178             action == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN) {
179             WLOGFD("Move event hasPointDown");
180             hasPointDown_ = true;
181         } else if (action == MMI::PointerEvent::POINTER_ACTION_UP ||
182             action == MMI::PointerEvent::POINTER_ACTION_BUTTON_UP ||
183             action == MMI::PointerEvent::POINTER_ACTION_CANCEL) {
184             WLOGFD("Reset hasPointDown_ when point up or cancel");
185             hasPointDown_ = false;
186         }
187         WLOGFD("No need to move action id: %{public}d", action);
188         return false;
189     }
190 
191     SizeChangeReason reason = SizeChangeReason::DRAG_MOVE;
192     bool ret = true;
193     switch (action) {
194         case MMI::PointerEvent::POINTER_ACTION_MOVE: {
195             reason = SizeChangeReason::DRAG_MOVE;
196             uint32_t oldWindowDragHotAreaType = windowDragHotAreaType_;
197             UpdateHotAreaType(pointerEvent);
198             ProcessWindowDragHotAreaFunc(oldWindowDragHotAreaType != windowDragHotAreaType_, reason);
199             break;
200         }
201         case MMI::PointerEvent::POINTER_ACTION_UP:
202         case MMI::PointerEvent::POINTER_ACTION_BUTTON_UP:
203         case MMI::PointerEvent::POINTER_ACTION_CANCEL:
204         case MMI::PointerEvent::POINTER_ACTION_DOWN:
205         case MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN: {
206             reason = SizeChangeReason::DRAG_END;
207             SetStartMoveFlag(false);
208             hasPointDown_ = false;
209             ProcessWindowDragHotAreaFunc(windowDragHotAreaType_ != WINDOW_HOT_AREA_TYPE_UNDEFINED, reason);
210             // The Pointer up event sent to the ArkUI.
211             ret = false;
212             break;
213         }
214         default:
215             break;
216     }
217     if (CalcMoveTargetRect(pointerEvent, originalRect)) {
218         ProcessSessionRectChange(reason);
219     }
220     return ret;
221 }
222 
ProcessWindowDragHotAreaFunc(bool isSendHotAreaMessage,const SizeChangeReason & reason)223 void MoveDragController::ProcessWindowDragHotAreaFunc(bool isSendHotAreaMessage, const SizeChangeReason& reason)
224 {
225     if (isSendHotAreaMessage) {
226         WLOGFI("ProcessWindowDragHotAreaFunc start, isSendHotAreaMessage: %{public}u, reason: %{public}d",
227             isSendHotAreaMessage, reason);
228     }
229     if (windowDragHotAreaFunc_ && isSendHotAreaMessage) {
230         windowDragHotAreaFunc_(windowDragHotAreaType_, reason);
231     }
232 }
233 
UpdateGravityWhenDrag(const std::shared_ptr<MMI::PointerEvent> & pointerEvent,const std::shared_ptr<RSSurfaceNode> & surfaceNode)234 void MoveDragController::UpdateGravityWhenDrag(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
235     const std::shared_ptr<RSSurfaceNode>& surfaceNode)
236 {
237     if (surfaceNode == nullptr || pointerEvent == nullptr || type_ == AreaType::UNDEFINED) {
238         return;
239     }
240     if (pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_DOWN ||
241         pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN) {
242         Gravity dragGravity = GRAVITY_MAP.at(type_);
243         if (dragGravity >= Gravity::TOP && dragGravity <= Gravity::BOTTOM_RIGHT) {
244             WLOGFI("begin SetFrameGravity:%{public}d, type:%{public}d", dragGravity, type_);
245             surfaceNode->SetFrameGravity(dragGravity);
246             RSTransaction::FlushImplicitTransaction();
247         }
248         return;
249     }
250     if (pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_BUTTON_UP ||
251         pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_UP ||
252         pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_CANCEL) {
253         surfaceNode->SetFrameGravity(Gravity::TOP_LEFT);
254         RSTransaction::FlushImplicitTransaction();
255         WLOGFI("recover gravity to TOP_LEFT");
256     }
257 }
258 
ConsumeDragEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent,const WSRect & originalRect,const sptr<WindowSessionProperty> property,const SystemSessionConfig & sysConfig)259 bool MoveDragController::ConsumeDragEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
260     const WSRect& originalRect, const sptr<WindowSessionProperty> property, const SystemSessionConfig& sysConfig)
261 {
262     if (!CheckDragEventLegal(pointerEvent, property)) {
263         return false;
264     }
265 
266     int32_t pointerId = pointerEvent->GetPointerId();
267     MMI::PointerEvent::PointerItem pointerItem;
268     if (!pointerEvent->GetPointerItem(pointerId, pointerItem)) {
269         WLOGE("Get PointerItem failed");
270         return false;
271     }
272 
273     SizeChangeReason reason = SizeChangeReason::UNDEFINED;
274     switch (pointerEvent->GetPointerAction()) {
275         case MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN:
276         case MMI::PointerEvent::POINTER_ACTION_DOWN: {
277             if (!EventDownInit(pointerEvent, originalRect, property, sysConfig)) {
278                 return false;
279             }
280             reason = SizeChangeReason::DRAG_START;
281             ResSchedReportData(OHOS::ResourceSchedule::ResType::RES_TYPE_RESIZE_WINDOW, true);
282             break;
283         }
284         case MMI::PointerEvent::POINTER_ACTION_MOVE: {
285             reason = SizeChangeReason::DRAG;
286             break;
287         }
288         case MMI::PointerEvent::POINTER_ACTION_UP:
289         case MMI::PointerEvent::POINTER_ACTION_BUTTON_UP:
290         case MMI::PointerEvent::POINTER_ACTION_CANCEL: {
291             reason = SizeChangeReason::DRAG_END;
292             isStartDrag_ = false;
293             hasPointDown_ = false;
294             ResSchedReportData(OHOS::ResourceSchedule::ResType::RES_TYPE_RESIZE_WINDOW, false);
295             NotifyWindowInputPidChange(isStartDrag_);
296             break;
297         }
298         default:
299             return false;
300     }
301     int32_t tranX = pointerItem.GetDisplayX() - moveDragProperty_.originalPointerPosX_;
302     int32_t tranY = pointerItem.GetDisplayY() - moveDragProperty_.originalPointerPosY_;
303 
304     if (aspectRatio_ > NEAR_ZERO) {
305         moveDragProperty_.targetRect_ = CalcFixedAspectRatioTargetRect(type_, tranX, tranY, aspectRatio_,
306             moveDragProperty_.originalRect_);
307     } else {
308         moveDragProperty_.targetRect_ = CalcFreeformTargetRect(type_, tranX, tranY, moveDragProperty_.originalRect_);
309     }
310     TLOGD(WmsLogTag::WMS_LAYOUT, "targetRect:%{public}s, originalRect:%{public}s, tranX:%{public}d, tranY:%{public}d",
311         moveDragProperty_.targetRect_.ToString().c_str(), moveDragProperty_.originalRect_.ToString().c_str(),
312         tranX, tranY);
313     ProcessSessionRectChange(reason);
314     return true;
315 }
316 
CalcMoveTargetRect(const std::shared_ptr<MMI::PointerEvent> & pointerEvent,const WSRect & originalRect)317 bool MoveDragController::CalcMoveTargetRect(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
318     const WSRect& originalRect)
319 {
320     MMI::PointerEvent::PointerItem pointerItem;
321     int32_t pointerId = pointerEvent->GetPointerId();
322     pointerEvent->GetPointerItem(pointerId, pointerItem);
323     int32_t pointerDisplayX = pointerItem.GetDisplayX();
324     int32_t pointerDisplayY = pointerItem.GetDisplayY();
325     if (moveDragProperty_.isEmpty()) {
326         moveDragProperty_.pointerId_ = pointerId;
327         moveDragProperty_.pointerType_ = pointerEvent->GetSourceType();
328         moveDragProperty_.originalPointerPosX_ = pointerDisplayX;
329         moveDragProperty_.originalPointerPosY_ = pointerDisplayY;
330         int32_t pointerWindowX = pointerItem.GetWindowX();
331         int32_t pointerWindowY = pointerItem.GetWindowY();
332         moveDragProperty_.originalRect_ = originalRect;
333         moveDragProperty_.originalRect_.posX_ = pointerDisplayX - pointerWindowX;
334         moveDragProperty_.originalRect_.posY_ = pointerDisplayY - pointerWindowY;
335         return false;
336     } else {
337         int32_t offsetX = pointerDisplayX - moveDragProperty_.originalPointerPosX_;
338         int32_t offsetY = pointerDisplayY - moveDragProperty_.originalPointerPosY_;
339         moveDragProperty_.targetRect_ = {
340             moveDragProperty_.originalRect_.posX_ + offsetX,
341             moveDragProperty_.originalRect_.posY_ + offsetY,
342             originalRect.width_,
343             originalRect.height_};
344         WLOGFD("move rect: [%{public}d, %{public}d, %{public}u, %{public}u]",
345             moveDragProperty_.targetRect_.posX_, moveDragProperty_.targetRect_.posY_,
346             moveDragProperty_.targetRect_.width_, moveDragProperty_.targetRect_.height_);
347         return true;
348     }
349 }
350 
EventDownInit(const std::shared_ptr<MMI::PointerEvent> & pointerEvent,const WSRect & originalRect,const sptr<WindowSessionProperty> property,const SystemSessionConfig & sysConfig)351 bool MoveDragController::EventDownInit(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
352     const WSRect& originalRect, const sptr<WindowSessionProperty> property, const SystemSessionConfig& sysConfig)
353 {
354     const auto& sourceType = pointerEvent->GetSourceType();
355     if (sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE &&
356         pointerEvent->GetButtonId() != MMI::PointerEvent::MOUSE_BUTTON_LEFT) {
357         TLOGD(WmsLogTag::WMS_LAYOUT, "Mouse click event but not left click");
358         return false;
359     }
360     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "MoveDragController::EventDownInit");
361     int32_t pointerId = pointerEvent->GetPointerId();
362     MMI::PointerEvent::PointerItem pointerItem;
363     pointerEvent->GetPointerItem(pointerId, pointerItem);
364     InitMoveDragProperty();
365     hasPointDown_ = true;
366     moveDragProperty_.originalRect_ = originalRect;
367     auto display = DisplayManager::GetInstance().GetDisplayById(pointerEvent->GetTargetDisplayId());
368     if (display) {
369         vpr_ = display->GetVirtualPixelRatio();
370     } else {
371         vpr_ = 1.5f; // 1.5f: default virtual pixel ratio
372     }
373     int outside = (sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE) ? HOTZONE_POINTER * vpr_ :
374         HOTZONE_TOUCH * vpr_;
375     type_ = SessionHelper::GetAreaType(pointerItem.GetWindowX(), pointerItem.GetWindowY(), sourceType, outside, vpr_,
376         moveDragProperty_.originalRect_);
377     if (type_ == AreaType::UNDEFINED) {
378         return false;
379     }
380     InitDecorValue(property, sysConfig);
381     limits_ = property->GetWindowLimits();
382     moveDragProperty_.pointerId_ = pointerEvent->GetPointerId();
383     moveDragProperty_.pointerType_ = sourceType;
384     moveDragProperty_.originalPointerPosX_ = pointerItem.GetDisplayX();
385     moveDragProperty_.originalPointerPosY_ = pointerItem.GetDisplayY();
386     if (aspectRatio_ <= NEAR_ZERO) {
387         CalcFreeformTranslateLimits(type_);
388     }
389     moveDragProperty_.originalRect_.posX_ = pointerItem.GetDisplayX() - pointerItem.GetWindowX();
390     moveDragProperty_.originalRect_.posY_ = pointerItem.GetDisplayY() - pointerItem.GetWindowY();
391     mainMoveAxis_ = AxisType::UNDEFINED;
392     isStartDrag_ = true;
393     NotifyWindowInputPidChange(isStartDrag_);
394     return true;
395 }
396 
CalcFreeformTargetRect(AreaType type,int32_t tranX,int32_t tranY,WSRect originalRect)397 WSRect MoveDragController::CalcFreeformTargetRect(AreaType type, int32_t tranX, int32_t tranY, WSRect originalRect)
398 {
399     WSRect targetRect = originalRect;
400     FixTranslateByLimits(tranX, tranY);
401     TLOGD(WmsLogTag::WMS_LAYOUT, "areaType:%{public}u", type);
402     if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::LEFT)) {
403         targetRect.posX_ += tranX;
404         targetRect.width_ -= tranX;
405     } else if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::RIGHT)) {
406         targetRect.width_ += tranX;
407     }
408     if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::TOP)) {
409         targetRect.posY_ += tranY;
410         targetRect.height_ -= tranY;
411     } else if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::BOTTOM)) {
412         targetRect.height_ += tranY;
413     }
414     // check current ratio limits
415     if (targetRect.height_ == 0) {
416         return targetRect;
417     }
418     float curRatio = static_cast<float>(targetRect.width_) / static_cast<float>(targetRect.height_);
419     if (!MathHelper::GreatNotEqual(limits_.minRatio_, curRatio) &&
420         !MathHelper::GreatNotEqual(curRatio, limits_.maxRatio_)) {
421         return targetRect;
422     }
423     float newRatio = MathHelper::LessNotEqual(curRatio, limits_.minRatio_) ? limits_.minRatio_ : limits_.maxRatio_;
424     if (MathHelper::NearZero(newRatio)) {
425         return targetRect;
426     }
427     if ((static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::LEFT)) ||
428         (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::RIGHT))) {
429         targetRect.height_ = static_cast<int32_t>(static_cast<float>(targetRect.width_) / newRatio);
430     } else {
431         targetRect.width_ = static_cast<int32_t>(static_cast<float>(targetRect.height_) * newRatio);
432     }
433     TLOGD(WmsLogTag::WMS_LAYOUT, "curRatio:%{public}f, newRatio:%{public}f", curRatio, newRatio);
434     return targetRect;
435 }
436 
CalcFixedAspectRatioTargetRect(AreaType type,int32_t tranX,int32_t tranY,float aspectRatio,WSRect originalRect)437 WSRect MoveDragController::CalcFixedAspectRatioTargetRect(AreaType type, int32_t tranX, int32_t tranY,
438     float aspectRatio, WSRect originalRect)
439 {
440     TLOGD(WmsLogTag::WMS_LAYOUT, "in");
441     int32_t posX = originalRect.posX_;
442     int32_t posY = originalRect.posY_;
443     int32_t width = static_cast<int32_t>(originalRect.width_);
444     int32_t height = static_cast<int32_t>(originalRect.height_);
445     FixTranslateByLimits(tranX, tranY);
446     if (mainMoveAxis_ == AxisType::UNDEFINED) {
447         if (!InitMainAxis(type, tranX, tranY)) {
448             return originalRect;
449         }
450     }
451 
452     TLOGD(WmsLogTag::WMS_LAYOUT, "ratio:%{public}f, areaType:%{public}u", aspectRatio, type);
453     ConvertXYByAspectRatio(tranX, tranY, aspectRatio);
454     switch (type) {
455         case AreaType::LEFT_TOP: {
456             return { posX + tranX, posY + tranY, width - tranX, height - tranY };
457         }
458         case AreaType::RIGHT_TOP: {
459             return { posX, posY + (mainMoveAxis_ == AxisType::X_AXIS ? (-tranY) : (tranY)),
460                      width + (mainMoveAxis_ == AxisType::X_AXIS ? (tranX) : (-tranX)),
461                      height + (mainMoveAxis_ == AxisType::X_AXIS ? (tranY) : (-tranY)) };
462         }
463         case AreaType::RIGHT_BOTTOM: {
464             return { posX, posY, width + tranX, height + tranY };
465         }
466         case AreaType::LEFT_BOTTOM: {
467             return { posX + (mainMoveAxis_ == AxisType::X_AXIS ? (tranX) : (-tranX)), posY,
468                      width - (mainMoveAxis_ == AxisType::X_AXIS ? (tranX) : (-tranX)),
469                      height - (mainMoveAxis_ == AxisType::X_AXIS ? (tranY) : (-tranY)) };
470         }
471         case AreaType::LEFT: {
472             return { posX + tranX, posY, width - tranX, height - tranY };
473         }
474         case AreaType::TOP: {
475             return { posX, posY + tranY, width - tranX, height - tranY };
476         }
477         case AreaType::RIGHT: {
478             return { posX, posY, width + tranX, height + tranY };
479         }
480         case AreaType::BOTTOM: {
481             return { posX, posY, width + tranX, height + tranY };
482         }
483         default:
484             break;
485     }
486     return originalRect;
487 }
488 
CalcFreeformTranslateLimits(AreaType type)489 void MoveDragController::CalcFreeformTranslateLimits(AreaType type)
490 {
491     TLOGD(WmsLogTag::WMS_LAYOUT, "areaType:%{public}u, minWidth:%{public}u, maxWidth:%{public}u, "
492         "minHeight:%{public}u, maxHeight:%{public}u", type,
493         limits_.minWidth_, limits_.maxWidth_, limits_.minHeight_, limits_.maxHeight_);
494     if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::LEFT)) {
495         minTranX_ = moveDragProperty_.originalRect_.width_ - static_cast<int32_t>(limits_.maxWidth_);
496         maxTranX_ = moveDragProperty_.originalRect_.width_ - static_cast<int32_t>(limits_.minWidth_);
497     } else if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::RIGHT)) {
498         minTranX_ = static_cast<int32_t>(limits_.minWidth_) - moveDragProperty_.originalRect_.width_;
499         maxTranX_ = static_cast<int32_t>(limits_.maxWidth_) - moveDragProperty_.originalRect_.width_;
500     }
501     if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::TOP)) {
502         minTranY_ = moveDragProperty_.originalRect_.height_ - static_cast<int32_t>(limits_.maxHeight_);
503         maxTranY_ = moveDragProperty_.originalRect_.height_ - static_cast<int32_t>(limits_.minHeight_);
504     } else if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::BOTTOM)) {
505         minTranY_ = static_cast<int32_t>(limits_.minHeight_) - moveDragProperty_.originalRect_.height_;
506         maxTranY_ = static_cast<int32_t>(limits_.maxHeight_) - moveDragProperty_.originalRect_.height_;
507     }
508 }
509 
CalcFixedAspectRatioTranslateLimits(AreaType type,AxisType axis)510 void MoveDragController::CalcFixedAspectRatioTranslateLimits(AreaType type, AxisType axis)
511 {
512     int32_t minW = static_cast<int32_t>(limits_.minWidth_);
513     int32_t maxW = static_cast<int32_t>(limits_.maxWidth_);
514     int32_t minH = static_cast<int32_t>(limits_.minHeight_);
515     int32_t maxH = static_cast<int32_t>(limits_.maxHeight_);
516     if (isDecorEnable_) {
517         if (SessionUtils::ToLayoutWidth(minW, vpr_) < SessionUtils::ToLayoutHeight(minH, vpr_) * aspectRatio_) {
518             minW = SessionUtils::ToWinWidth(SessionUtils::ToLayoutHeight(minH, vpr_) * aspectRatio_, vpr_);
519         } else {
520             minH = SessionUtils::ToWinHeight(SessionUtils::ToLayoutWidth(minW, vpr_) / aspectRatio_, vpr_);
521         }
522         if (SessionUtils::ToLayoutWidth(maxW, vpr_) < SessionUtils::ToLayoutHeight(maxH, vpr_) * aspectRatio_) {
523             maxH = SessionUtils::ToWinHeight(SessionUtils::ToLayoutWidth(maxW, vpr_) * aspectRatio_, vpr_);
524         } else {
525             maxW = SessionUtils::ToWinWidth(SessionUtils::ToLayoutHeight(maxH, vpr_) / aspectRatio_, vpr_);
526         }
527     } else {
528         if (minW < minH * aspectRatio_) {
529             minW = minH * aspectRatio_;
530         } else {
531             minH = minW / aspectRatio_;
532         }
533         if (maxW < maxH * aspectRatio_) {
534             maxH = maxW * aspectRatio_;
535         } else {
536             maxW = maxH / aspectRatio_;
537         }
538     }
539 
540     TLOGD(WmsLogTag::WMS_LAYOUT, "areaType:%{public}u, axisType:%{public}d", type, axis);
541     if (axis == AxisType::X_AXIS) {
542         if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::LEFT)) {
543             minTranX_ = static_cast<int32_t>(moveDragProperty_.originalRect_.width_) - maxW;
544             maxTranX_ = static_cast<int32_t>(moveDragProperty_.originalRect_.width_) - minW;
545         } else if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::RIGHT)) {
546             minTranX_ = minW - static_cast<int32_t>(moveDragProperty_.originalRect_.width_);
547             maxTranX_ = maxW - static_cast<int32_t>(moveDragProperty_.originalRect_.width_);
548         }
549     } else if (axis == AxisType::Y_AXIS) {
550         if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::TOP)) {
551             minTranY_ = static_cast<int32_t>(moveDragProperty_.originalRect_.height_) - maxH;
552             maxTranY_ = static_cast<int32_t>(moveDragProperty_.originalRect_.height_) - minH;
553         } else if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::BOTTOM)) {
554             minTranY_ = minH - static_cast<int32_t>(moveDragProperty_.originalRect_.height_);
555             maxTranY_ = maxH - static_cast<int32_t>(moveDragProperty_.originalRect_.height_);
556         }
557     }
558 }
559 
FixTranslateByLimits(int32_t & tranX,int32_t & tranY)560 void MoveDragController::FixTranslateByLimits(int32_t& tranX, int32_t& tranY)
561 {
562     if (tranX < minTranX_) {
563         tranX = minTranX_;
564     } else if (tranX > maxTranX_) {
565         tranX = maxTranX_;
566     }
567     if (tranY < minTranY_) {
568         tranY = minTranY_;
569     } else if (tranY > maxTranY_) {
570         tranY = maxTranY_;
571     }
572     TLOGD(WmsLogTag::WMS_LAYOUT, "tranX:%{public}d, tranY:%{public}d, minTranX:%{public}d, maxTranX:%{public}d, "
573         "minTranY:%{public}d, maxTranY:%{public}d", tranX, tranY, minTranX_, maxTranX_, minTranY_, maxTranY_);
574 }
575 
InitMainAxis(AreaType type,int32_t tranX,int32_t tranY)576 bool MoveDragController::InitMainAxis(AreaType type, int32_t tranX, int32_t tranY)
577 {
578     if (type == AreaType::LEFT || type == AreaType::RIGHT) {
579         mainMoveAxis_ = AxisType::X_AXIS;
580     } else if (type == AreaType::TOP || type == AreaType::BOTTOM) {
581         mainMoveAxis_ = AxisType::Y_AXIS;
582     } else if (tranX == 0 && tranY == 0) {
583         return false;
584     } else {
585         mainMoveAxis_ = (std::abs(tranX) > std::abs(tranY)) ? AxisType::X_AXIS : AxisType::Y_AXIS;
586     }
587     CalcFixedAspectRatioTranslateLimits(type, mainMoveAxis_);
588     return true;
589 }
590 
ConvertXYByAspectRatio(int32_t & tx,int32_t & ty,float aspectRatio)591 void MoveDragController::ConvertXYByAspectRatio(int32_t& tx, int32_t& ty, float aspectRatio)
592 {
593     if (mainMoveAxis_ == AxisType::X_AXIS) {
594         ty = tx / aspectRatio;
595     } else if (mainMoveAxis_ == AxisType::Y_AXIS) {
596         tx = ty * aspectRatio;
597     }
598     return;
599 }
600 
InitDecorValue(const sptr<WindowSessionProperty> property,const SystemSessionConfig & sysConfig)601 void MoveDragController::InitDecorValue(const sptr<WindowSessionProperty> property,
602     const SystemSessionConfig& sysConfig)
603 {
604     auto windowType = property->GetWindowType();
605     bool isMainWindow = WindowHelper::IsMainWindow(windowType);
606     bool isSubWindow = WindowHelper::IsSubWindow(windowType);
607     bool isDialogWindow = WindowHelper::IsDialogWindow(windowType);
608     isDecorEnable_ = (isMainWindow ||
609             ((isSubWindow || isDialogWindow) && property->IsDecorEnable())) &&
610         sysConfig.isSystemDecorEnable_ &&
611         WindowHelper::IsWindowModeSupported(sysConfig.decorWindowModeSupportType_, property->GetWindowMode());
612 }
613 
ProcessSessionRectChange(const SizeChangeReason & reason)614 void MoveDragController::ProcessSessionRectChange(const SizeChangeReason& reason)
615 {
616     if (moveDragCallback_) {
617         moveDragCallback_(reason);
618     }
619 }
620 
GetVirtualPixelRatio() const621 float MoveDragController::GetVirtualPixelRatio() const
622 {
623     float vpr = 1.5;
624     auto displayInfo = DisplayManager::GetInstance().GetDefaultDisplay();
625     if (displayInfo != nullptr) {
626         vpr = displayInfo->GetVirtualPixelRatio();
627     }
628     WLOGFD("vpr: %{public}f", vpr);
629     return vpr;
630 }
631 
UpdateDragType(int32_t startPointPosX,int32_t startPointPosY)632 void MoveDragController::UpdateDragType(int32_t startPointPosX, int32_t startPointPosY)
633 {
634     if (startPointPosX > rectExceptCorner_.posX_ &&
635         (startPointPosX < rectExceptCorner_.posX_ +
636         static_cast<int32_t>(rectExceptCorner_.width_))) {
637         dragType_ = DragType::DRAG_BOTTOM_OR_TOP;
638     } else if (startPointPosY > rectExceptCorner_.posY_ &&
639         (startPointPosY < rectExceptCorner_.posY_ +
640         static_cast<int32_t>(rectExceptCorner_.height_))) {
641         dragType_ = DragType::DRAG_LEFT_OR_RIGHT;
642     } else if ((startPointPosX <= rectExceptCorner_.posX_ && startPointPosY <= rectExceptCorner_.posY_) ||
643         (startPointPosX >= rectExceptCorner_.posX_ + static_cast<int32_t>(rectExceptCorner_.width_) &&
644          startPointPosY >= rectExceptCorner_.posY_ + static_cast<int32_t>(rectExceptCorner_.height_))) {
645         dragType_ = DragType::DRAG_LEFT_TOP_CORNER;
646     } else {
647         dragType_ = DragType::DRAG_RIGHT_TOP_CORNER;
648     }
649 }
650 
IsPointInDragHotZone(int32_t startPointPosX,int32_t startPointPosY,int32_t sourceType,const WSRect & winRect)651 bool MoveDragController::IsPointInDragHotZone(int32_t startPointPosX, int32_t startPointPosY,
652     int32_t sourceType, const WSRect& winRect)
653 {
654     // calculate rect with hotzone
655     Rect rectWithHotzone;
656     rectWithHotzone.posX_ = winRect.posX_ - static_cast<int32_t>(HOTZONE_POINTER);
657     rectWithHotzone.posY_ = winRect.posY_ - static_cast<int32_t>(HOTZONE_POINTER);
658     rectWithHotzone.width_ = winRect.width_ + HOTZONE_POINTER * 2u; // double hotZone
659     rectWithHotzone.height_ = winRect.height_ + HOTZONE_POINTER * 2u; // double hotZone
660 
661     if (sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE &&
662         !WindowHelper::IsPointInTargetRectWithBound(startPointPosX, startPointPosY, rectWithHotzone)) {
663         return false;
664     } else if ((!WindowHelper::IsPointInTargetRect(startPointPosX,
665         startPointPosY, rectExceptFrame_)) ||
666         (!WindowHelper::IsPointInWindowExceptCorner(startPointPosX,
667         startPointPosY, rectExceptCorner_))) {
668         return true;
669     }
670     return false;
671 }
672 
CalculateStartRectExceptHotZone(float vpr,const WSRect & winRect)673 void MoveDragController::CalculateStartRectExceptHotZone(float vpr, const WSRect& winRect)
674 {
675     rectExceptFrame_.posX_ = winRect.posX_ +
676         static_cast<int32_t>(WINDOW_FRAME_WIDTH * vpr);
677     rectExceptFrame_.posY_ = winRect.posY_ +
678         static_cast<int32_t>(WINDOW_FRAME_WIDTH * vpr);
679     rectExceptFrame_.width_ = winRect.width_ -
680         static_cast<uint32_t>((WINDOW_FRAME_WIDTH + WINDOW_FRAME_WIDTH) * vpr);
681     rectExceptFrame_.height_ = winRect.height_ -
682         static_cast<uint32_t>((WINDOW_FRAME_WIDTH + WINDOW_FRAME_WIDTH) * vpr);
683 
684     rectExceptCorner_.posX_ = winRect.posX_ +
685         static_cast<int32_t>(WINDOW_FRAME_CORNER_WIDTH * vpr);
686     rectExceptCorner_.posY_ = winRect.posY_ +
687         static_cast<int32_t>(WINDOW_FRAME_CORNER_WIDTH * vpr);
688     rectExceptCorner_.width_ = winRect.width_ -
689         static_cast<uint32_t>((WINDOW_FRAME_CORNER_WIDTH + WINDOW_FRAME_CORNER_WIDTH) * vpr);
690     rectExceptCorner_.height_ = winRect.height_ -
691         static_cast<uint32_t>((WINDOW_FRAME_CORNER_WIDTH + WINDOW_FRAME_CORNER_WIDTH) * vpr);
692 }
693 
UpdateMoveTempProperty(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)694 WSError MoveDragController::UpdateMoveTempProperty(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
695 {
696     int32_t pointerId = pointerEvent->GetPointerId();
697     int32_t startPointerId = moveTempProperty_.pointerId_;
698     int32_t pointerType = pointerEvent->GetSourceType();
699     int32_t startPointerType = moveDragProperty_.pointerType_;
700     MMI::PointerEvent::PointerItem pointerItem;
701     int32_t sourceType = pointerEvent->GetSourceType();
702     if (!pointerEvent->GetPointerItem(pointerId, pointerItem) ||
703         (sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE &&
704         pointerEvent->GetButtonId() != MMI::PointerEvent::MOUSE_BUTTON_LEFT)) {
705         WLOGFW("invalid pointerEvent");
706         return WSError::WS_ERROR_NULLPTR;
707     }
708 
709     int32_t pointerDisplayX = pointerItem.GetDisplayX();
710     int32_t pointerDisplayY = pointerItem.GetDisplayY();
711     switch (pointerEvent->GetPointerAction()) {
712         case MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN:
713         case MMI::PointerEvent::POINTER_ACTION_DOWN:
714             moveTempProperty_.pointerId_ = pointerId;
715             moveTempProperty_.pointerType_ = pointerType;
716             moveTempProperty_.lastDownPointerPosX_ = pointerDisplayX;
717             moveTempProperty_.lastDownPointerPosY_ = pointerDisplayY;
718             moveTempProperty_.lastMovePointerPosX_ = pointerDisplayX;
719             moveTempProperty_.lastMovePointerPosY_ = pointerDisplayY;
720             moveTempProperty_.lastDownPointerWindowX_ = pointerItem.GetWindowX();
721             moveTempProperty_.lastDownPointerWindowY_ = pointerItem.GetWindowY();
722             break;
723         case MMI::PointerEvent::POINTER_ACTION_MOVE:
724             if ((startPointerId != -1 && startPointerId != pointerId) ||
725                 (startPointerType != -1 && pointerType != startPointerType)) {
726                 WLOGFI("block unnecessary pointer event inside the window");
727                 return WSError::WS_DO_NOTHING;
728             }
729             moveTempProperty_.lastMovePointerPosX_ = pointerDisplayX;
730             moveTempProperty_.lastMovePointerPosY_ = pointerDisplayY;
731             break;
732         case MMI::PointerEvent::POINTER_ACTION_UP:
733         case MMI::PointerEvent::POINTER_ACTION_BUTTON_UP:
734         case MMI::PointerEvent::POINTER_ACTION_CANCEL: {
735             moveTempProperty_ = { -1, -1, -1, -1, -1, -1, -1, -1 };
736             break;
737         }
738         default:
739             break;
740     }
741     return WSError::WS_OK;
742 }
743 
CalcFirstMoveTargetRect(const WSRect & windowRect,bool isFullToFloating)744 void MoveDragController::CalcFirstMoveTargetRect(const WSRect& windowRect, bool isFullToFloating)
745 {
746     if (!GetStartMoveFlag() || moveTempProperty_.isEmpty()) {
747         return;
748     }
749 
750     WSRect originalRect = {
751         moveTempProperty_.lastDownPointerPosX_ - moveTempProperty_.lastDownPointerWindowX_,
752         moveTempProperty_.lastDownPointerPosY_ - moveTempProperty_.lastDownPointerWindowY_,
753         windowRect.width_,
754         windowRect.height_
755     };
756     if (isFullToFloating) {
757         originalRect.posX_ = windowRect.posX_;
758         originalRect.posY_ = windowRect.posY_;
759     }
760     SetOriginalValue(moveTempProperty_.pointerId_, moveTempProperty_.pointerType_,
761         moveTempProperty_.lastDownPointerPosX_, moveTempProperty_.lastDownPointerPosY_, originalRect);
762 
763     int32_t offsetX = moveTempProperty_.lastMovePointerPosX_ - moveTempProperty_.lastDownPointerPosX_;
764     int32_t offsetY = moveTempProperty_.lastMovePointerPosY_ - moveTempProperty_.lastDownPointerPosY_;
765     WSRect targetRect = {
766         originalRect.posX_ + offsetX,
767         originalRect.posY_ + offsetY,
768         originalRect.width_,
769         originalRect.height_
770     };
771     WLOGFD("first move rect: [%{public}d, %{public}d, %{public}u, %{public}u]", targetRect.posX_, targetRect.posY_,
772         targetRect.width_, targetRect.height_);
773     moveDragProperty_.targetRect_ = targetRect;
774     ProcessSessionRectChange(SizeChangeReason::DRAG_MOVE);
775 }
776 
CheckDragEventLegal(const std::shared_ptr<MMI::PointerEvent> & pointerEvent,const sptr<WindowSessionProperty> property)777 bool MoveDragController::CheckDragEventLegal(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
778     const sptr<WindowSessionProperty> property)
779 {
780     if (pointerEvent == nullptr || property == nullptr) {
781         WLOGE("ConsumeDragEvent stop because of nullptr");
782         return false;
783     }
784     if (GetStartMoveFlag()) {
785         WLOGFD("the window is being moved");
786         return false;
787     }
788     if (!GetStartDragFlag() && pointerEvent->GetPointerAction() != MMI::PointerEvent::POINTER_ACTION_DOWN &&
789         pointerEvent->GetPointerAction() != MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN) {
790         return false;
791     }
792     int32_t pointerId = pointerEvent->GetPointerId();
793     int32_t startPointerId = moveDragProperty_.pointerId_;
794     if (GetStartDragFlag() && startPointerId != -1 && startPointerId != pointerId) {
795         WLOGFI("block unnecessary pointer event inside the window");
796         return false;
797     }
798     return true;
799 }
800 
UpdateHotAreaType(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)801 void MoveDragController::UpdateHotAreaType(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
802 {
803     int32_t pointerId = pointerEvent->GetPointerId();
804     MMI::PointerEvent::PointerItem pointerItem;
805     if (!pointerEvent->GetPointerItem(pointerId, pointerItem)) {
806         WLOGFW("invalid pointerEvent");
807         return;
808     }
809     int32_t pointerDisplayX = pointerItem.GetDisplayX();
810     int32_t pointerDisplayY = pointerItem.GetDisplayY();
811     uint32_t windowDragHotAreaType = SceneSession::GetWindowDragHotAreaType(WINDOW_HOT_AREA_TYPE_UNDEFINED,
812         pointerDisplayX, pointerDisplayY);
813     if (windowDragHotAreaType_ != windowDragHotAreaType) {
814         WLOGFI("the pointerEvent is window drag hot area, old type is: %{public}d, new type is: %{public}d",
815             windowDragHotAreaType_, windowDragHotAreaType);
816     }
817     windowDragHotAreaType_ = windowDragHotAreaType;
818 }
819 
GetOriginalPointerPosX()820 int32_t MoveDragController::GetOriginalPointerPosX()
821 {
822     return moveDragProperty_.originalPointerPosX_;
823 }
824 
GetOriginalPointerPosY()825 int32_t MoveDragController::GetOriginalPointerPosY()
826 {
827     return moveDragProperty_.originalPointerPosY_;
828 }
829 
SetWindowDragHotAreaFunc(const NotifyWindowDragHotAreaFunc & func)830 void MoveDragController::SetWindowDragHotAreaFunc(const NotifyWindowDragHotAreaFunc& func)
831 {
832     windowDragHotAreaFunc_ = func;
833 }
834 
OnLostFocus()835 void MoveDragController::OnLostFocus()
836 {
837     if (isStartMove_ || isStartDrag_) {
838         WLOGFI("window id %{public}d lost focus, should stop MoveDrag isMove: %{public}d, isDrag: %{public}d",
839             persistentId_, isStartMove_, isStartDrag_);
840         isStartMove_ = false;
841         isStartDrag_ = false;
842         NotifyWindowInputPidChange(isStartDrag_);
843         if (windowDragHotAreaType_ != WINDOW_HOT_AREA_TYPE_UNDEFINED) {
844             ProcessWindowDragHotAreaFunc(true, SizeChangeReason::DRAG_END);
845         }
846         ProcessSessionRectChange(SizeChangeReason::DRAG_END);
847     }
848 }
849 
ResSchedReportData(int32_t type,bool onOffTag)850 void MoveDragController::ResSchedReportData(int32_t type, bool onOffTag)
851 {
852 #ifdef RES_SCHED_ENABLE
853     std::unordered_map<std::string, std::string> payload;
854     // 0 is start, 1 is end
855     if (onOffTag) {
856         OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(type, 0, payload);
857     } else {
858         OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(type, 1, payload);
859     }
860     WLOGFD("ResSchedReportData success type: %{public}d onOffTag: %{public}d", type, onOffTag);
861 #endif
862 }
863 } // namespace OHOS::Rosen
864