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