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 #ifndef OHOS_ROSEN_WINDOW_SCENE_MOVE_DRAG_CONTROLLER_H
17 #define OHOS_ROSEN_WINDOW_SCENE_MOVE_DRAG_CONTROLLER_H
18 
19 #include <mutex>
20 
21 #include <refbase.h>
22 #include <struct_multimodal.h>
23 
24 #include "common/include/window_session_property.h"
25 #include "property/rs_properties_def.h"
26 #include "window.h"
27 #include "screen_manager.h"
28 #include "ws_common_inner.h"
29 
30 namespace OHOS::MMI {
31 class PointerEvent;
32 } // namespace MMI
33 
34 namespace OHOS::Rosen {
35 
36 using MoveDragCallback = std::function<void(const SizeChangeReason)>;
37 
38 using NotifyWindowDragHotAreaFunc = std::function<void(DisplayId displayId, uint32_t type,
39     const SizeChangeReason reason)>;
40 
41 using NotifyWindowPidChangeCallback = std::function<void(int32_t windowId, bool startMoving)>;
42 
43 const uint32_t WINDOW_HOT_AREA_TYPE_UNDEFINED = 0;
44 
45 class MoveDragController : public ScreenManager::IScreenListener {
46 public:
47     MoveDragController(int32_t persistentId, bool isSystemWindow = false);
48     ~MoveDragController() = default;
49 
50     /*
51      * Cross Display Move Drag
52      */
53     enum class TargetRectCoordinate {
54         RELATED_TO_START_DISPLAY,
55         RELATED_TO_END_DISPLAY,
56         GLOBAL
57     };
58 
59     void RegisterMoveDragCallback(const MoveDragCallback& callBack);
60     void SetStartMoveFlag(bool flag);
61     bool GetStartMoveFlag() const;
62     bool GetStartDragFlag() const;
63     void SetAsSystemWindow(bool isSystemWindow);
64     bool IsSystemWindow() const;
65     bool HasPointDown();
66     void SetMovable(bool movable);
67     bool GetMovable() const;
68     void SetNotifyWindowPidChangeCallback(const NotifyWindowPidChangeCallback& callback);
69     WSRect GetTargetRect(TargetRectCoordinate coordinate = TargetRectCoordinate::RELATED_TO_START_DISPLAY) const;
70     void InitMoveDragProperty();
71     void SetOriginalValue(int32_t pointerId, int32_t pointerType,
72         int32_t pointerPosX, int32_t pointerPosY, const WSRect& winRect);
73     void SetAspectRatio(float ratio);
74     bool ConsumeMoveEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent, const WSRect& originalRect);
75     bool ConsumeDragEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent, const WSRect& originalRect,
76         const sptr<WindowSessionProperty> property, const SystemSessionConfig& sysConfig);
77     void CalcFirstMoveTargetRect(const WSRect& windowRect, bool isFullToFloating);
78     WSRect GetFullScreenToFloatingRect(const WSRect& originalRect, const WSRect& windowRect);
79     int32_t GetOriginalPointerPosX();
80     int32_t GetOriginalPointerPosY();
81     void SetWindowDragHotAreaFunc(const NotifyWindowDragHotAreaFunc& func);
82     void UpdateGravityWhenDrag(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
83         const std::shared_ptr<RSSurfaceNode>& surfaceNode);
84     void OnLostFocus();
85     void SetIsPcWindow(bool isPcWindow);
86 
87     /*
88      * Cross Display Move Drag
89      */
90     uint64_t GetMoveDragStartDisplayId() const;
91     uint64_t GetMoveDragEndDisplayId() const;
92     uint64_t GetInitParentNodeId() const;
93     std::set<uint64_t> GetDisplayIdsDuringMoveDrag();
94     std::set<uint64_t> GetNewAddedDisplayIdsDuringMoveDrag();
95     void InitCrossDisplayProperty(DisplayId displayId, uint64_t parentNodeId);
96     WSRect GetScreenRectById(DisplayId displayId);
97     void MoveDragInterrupt();
98     void ResetCrossMoveDragProperty();
99 
100     /*
101      * Monitor screen connection status
102      */
103     void OnConnect(ScreenId screenId) override;
104     void OnDisconnect(ScreenId screenId) override;
105     void OnChange(ScreenId screenId) override;
106 
107 private:
108     struct MoveDragProperty {
109         int32_t pointerId_ = -1;
110         int32_t pointerType_ = -1;
111         int32_t originalPointerPosX_ = -1;
112         int32_t originalPointerPosY_ = -1;
113         WSRect originalRect_ = { 0, 0, 0, 0 };
114         WSRect targetRect_ = { 0, 0, 0, 0 };
115 
isEmptyOHOS::OHOS::Rosen::MoveDragController::MoveDragProperty116         bool isEmpty() const
117         {
118             return (pointerId_ == -1 && originalPointerPosX_ == -1 && originalPointerPosY_ == -1);
119         }
120     };
121 
122     struct MoveTempProperty {
123         int32_t pointerId_ = -1;
124         int32_t pointerType_ = -1;
125         int32_t lastDownPointerPosX_ = -1;
126         int32_t lastDownPointerPosY_ = -1;
127         int32_t lastDownPointerWindowX_ = -1;
128         int32_t lastDownPointerWindowY_ = -1;
129         int32_t lastMovePointerPosX_ = -1;
130         int32_t lastMovePointerPosY_ = -1;
131 
isEmptyOHOS::OHOS::Rosen::MoveDragController::MoveTempProperty132         bool isEmpty() const
133         {
134             return (pointerId_ == -1 && lastDownPointerPosX_ == -1 && lastDownPointerPosY_ == -1);
135         }
136     };
137 
138     enum AxisType { UNDEFINED, X_AXIS, Y_AXIS };
139     constexpr static float NEAR_ZERO = 0.001f;
140 
141     bool CalcMoveTargetRect(const std::shared_ptr<MMI::PointerEvent>& pointerEvent, const WSRect& originalRect);
142     void CalcDragTargetRect(const std::shared_ptr<MMI::PointerEvent>& pointerEvent);
143     bool EventDownInit(const std::shared_ptr<MMI::PointerEvent>& pointerEvent, const WSRect& originalRect,
144         const sptr<WindowSessionProperty> property, const SystemSessionConfig& sysConfig);
145     AreaType GetAreaType(int32_t pointWinX, int32_t pointWinY, int32_t sourceType, const WSRect& rect);
146     WSRect CalcFreeformTargetRect(AreaType type, int32_t tranX, int32_t tranY, WSRect originalRect);
147     WSRect CalcFixedAspectRatioTargetRect(AreaType type, int32_t tranX, int32_t tranY, float aspectRatio,
148         WSRect originalRect);
149     void CalcFreeformTranslateLimits(AreaType type);
150     void CalcFixedAspectRatioTranslateLimits(AreaType type, AxisType axis);
151     void FixTranslateByLimits(int32_t& tranX, int32_t& tranY);
152     bool InitMainAxis(AreaType type, int32_t tranX, int32_t tranY);
153     void ConvertXYByAspectRatio(int32_t& tx, int32_t& ty, float aspectRatio);
154     void ProcessSessionRectChange(const SizeChangeReason reason);
155     void InitDecorValue(const sptr<WindowSessionProperty> property, const SystemSessionConfig& sysConfig);
156 
157     float GetVirtualPixelRatio() const;
158     void UpdateDragType(int32_t startPointPosX, int32_t startPointPosY);
159     bool IsPointInDragHotZone(int32_t startPointPosX, int32_t startPointPosY,
160         int32_t sourceType, const WSRect& winRect);
161     void CalculateStartRectExceptHotZone(float vpr, const WSRect& winRect);
162     WSError UpdateMoveTempProperty(const std::shared_ptr<MMI::PointerEvent>& pointerEvent);
163     bool CheckDragEventLegal(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
164         const sptr<WindowSessionProperty> property);
165     void ResSchedReportData(int32_t type, bool onOffTag);
166     void NotifyWindowInputPidChange(bool isServerPid);
167 
168     /*
169      * Cross Display Move Drag
170      */
171     std::pair<int32_t, int32_t> CalcUnifiedTranslate(const std::shared_ptr<MMI::PointerEvent>& pointerEvent);
172 
173     bool isStartMove_ = false;
174     bool isStartDrag_ = false;
175     bool isMovable_ = true;
176     bool isDecorEnable_ = true;
177     bool hasPointDown_ = false;
178     float aspectRatio_ = 0.0f;
179     float vpr_ = 1.0f;
180     int32_t minTranX_ = INT32_MIN;
181     int32_t minTranY_ = INT32_MIN;
182     int32_t maxTranX_ = INT32_MAX;
183     int32_t maxTranY_ = INT32_MAX;
184     AreaType type_ = AreaType::UNDEFINED;
185     AxisType mainMoveAxis_ = AxisType::UNDEFINED;
186     WindowLimits limits_;
187     MoveDragProperty moveDragProperty_;
188     MoveDragCallback moveDragCallback_;
189     int32_t persistentId_;
190     bool isPcWindow_ = false;
191 
192     enum class DragType : uint32_t {
193         DRAG_UNDEFINED,
194         DRAG_LEFT_OR_RIGHT,
195         DRAG_BOTTOM_OR_TOP,
196         DRAG_LEFT_TOP_CORNER,
197         DRAG_RIGHT_TOP_CORNER,
198     };
199     const std::map<DragType, uint32_t> STYLEID_MAP = {
200         {DragType::DRAG_UNDEFINED,        MMI::MOUSE_ICON::DEFAULT},
201         {DragType::DRAG_BOTTOM_OR_TOP,    MMI::MOUSE_ICON::NORTH_SOUTH},
202         {DragType::DRAG_LEFT_OR_RIGHT,    MMI::MOUSE_ICON::WEST_EAST},
203         {DragType::DRAG_LEFT_TOP_CORNER,  MMI::MOUSE_ICON::NORTH_WEST_SOUTH_EAST},
204         {DragType::DRAG_RIGHT_TOP_CORNER, MMI::MOUSE_ICON::NORTH_EAST_SOUTH_WEST}
205     };
206     Rect rectExceptFrame_ { 0, 0, 0, 0 };
207     Rect rectExceptCorner_ { 0, 0, 0, 0 };
208     uint32_t mouseStyleID_ = 0;
209     DragType dragType_ = DragType::DRAG_UNDEFINED;
210     MoveTempProperty moveTempProperty_;
211 
212     void UpdateHotAreaType(const std::shared_ptr<MMI::PointerEvent>& pointerEvent);
213     void ProcessWindowDragHotAreaFunc(bool flag, const SizeChangeReason reason);
214     uint32_t windowDragHotAreaType_ = WINDOW_HOT_AREA_TYPE_UNDEFINED;
215     NotifyWindowDragHotAreaFunc windowDragHotAreaFunc_;
216     NotifyWindowPidChangeCallback pidChangeCallback_;
217 
218     const std::map<AreaType, Gravity> GRAVITY_MAP = {
219         {AreaType::LEFT,          Gravity::RIGHT},
220         {AreaType::TOP,           Gravity::BOTTOM},
221         {AreaType::RIGHT,         Gravity::LEFT},
222         {AreaType::BOTTOM,        Gravity::TOP},
223         {AreaType::LEFT_TOP,      Gravity::BOTTOM_RIGHT},
224         {AreaType::RIGHT_TOP,     Gravity::BOTTOM_LEFT},
225         {AreaType::RIGHT_BOTTOM,  Gravity::TOP_LEFT},
226         {AreaType::LEFT_BOTTOM,   Gravity::TOP_RIGHT}
227     };
228 
229     /*
230      * Cross Display Move Drag
231      */
232     bool isSystemWindow_ = false;
233     bool moveDragIsInterrupted_ = false;
234     DisplayId moveDragStartDisplayId_ = DISPLAY_ID_INVALID;
235     DisplayId moveDragEndDisplayId_ = DISPLAY_ID_INVALID;
236     uint64_t initParentNodeId_ = -1ULL;
237     DisplayId hotAreaDisplayId_ = 0;
238     int32_t originalDisplayOffsetX_ = 0;
239     int32_t originalDisplayOffsetY_ = 0;
240     std::mutex displayIdSetDuringMoveDragMutex_;
241     std::set<uint64_t> displayIdSetDuringMoveDrag_;
242     // Above guarded by displayIdSetDuringMoveDragMutex_
243 };
244 } // namespace OHOS::Rosen
245 #endif // OHOS_ROSEN_WINDOW_SCENE_MOVE_DRAG_CONTROLLER_H
246