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::MOVE;
192 bool ret = true;
193 switch (action) {
194 case MMI::PointerEvent::POINTER_ACTION_MOVE: {
195 reason = SizeChangeReason::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 ProcessSessionRectChange(reason);
311 return true;
312 }
313
CalcMoveTargetRect(const std::shared_ptr<MMI::PointerEvent> & pointerEvent,const WSRect & originalRect)314 bool MoveDragController::CalcMoveTargetRect(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
315 const WSRect& originalRect)
316 {
317 MMI::PointerEvent::PointerItem pointerItem;
318 int32_t pointerId = pointerEvent->GetPointerId();
319 pointerEvent->GetPointerItem(pointerId, pointerItem);
320 int32_t pointerDisplayX = pointerItem.GetDisplayX();
321 int32_t pointerDisplayY = pointerItem.GetDisplayY();
322 if (moveDragProperty_.isEmpty()) {
323 moveDragProperty_.pointerId_ = pointerId;
324 moveDragProperty_.pointerType_ = pointerEvent->GetSourceType();
325 moveDragProperty_.originalPointerPosX_ = pointerDisplayX;
326 moveDragProperty_.originalPointerPosY_ = pointerDisplayY;
327 int32_t pointerWindowX = pointerItem.GetWindowX();
328 int32_t pointerWindowY = pointerItem.GetWindowY();
329 moveDragProperty_.originalRect_ = originalRect;
330 moveDragProperty_.originalRect_.posX_ = pointerDisplayX - pointerWindowX;
331 moveDragProperty_.originalRect_.posY_ = pointerDisplayY - pointerWindowY;
332 return false;
333 } else {
334 int32_t offsetX = pointerDisplayX - moveDragProperty_.originalPointerPosX_;
335 int32_t offsetY = pointerDisplayY - moveDragProperty_.originalPointerPosY_;
336 moveDragProperty_.targetRect_ = {
337 moveDragProperty_.originalRect_.posX_ + offsetX,
338 moveDragProperty_.originalRect_.posY_ + offsetY,
339 originalRect.width_,
340 originalRect.height_};
341 WLOGFD("move rect: [%{public}d, %{public}d, %{public}u, %{public}u]",
342 moveDragProperty_.targetRect_.posX_, moveDragProperty_.targetRect_.posY_,
343 moveDragProperty_.targetRect_.width_, moveDragProperty_.targetRect_.height_);
344 return true;
345 }
346 }
347
EventDownInit(const std::shared_ptr<MMI::PointerEvent> & pointerEvent,const WSRect & originalRect,const sptr<WindowSessionProperty> property,const SystemSessionConfig & sysConfig)348 bool MoveDragController::EventDownInit(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
349 const WSRect& originalRect, const sptr<WindowSessionProperty> property, const SystemSessionConfig& sysConfig)
350 {
351 const auto& sourceType = pointerEvent->GetSourceType();
352 if (sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE &&
353 pointerEvent->GetButtonId() != MMI::PointerEvent::MOUSE_BUTTON_LEFT) {
354 return false;
355 }
356 HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "MoveDragController::EventDownInit");
357 int32_t pointerId = pointerEvent->GetPointerId();
358 MMI::PointerEvent::PointerItem pointerItem;
359 pointerEvent->GetPointerItem(pointerId, pointerItem);
360 InitMoveDragProperty();
361 hasPointDown_ = true;
362 moveDragProperty_.originalRect_ = originalRect;
363 auto display = DisplayManager::GetInstance().GetDisplayById(pointerEvent->GetTargetDisplayId());
364 if (display) {
365 vpr_ = display->GetVirtualPixelRatio();
366 } else {
367 vpr_ = 1.5f; // 1.5f: default virtual pixel ratio
368 }
369 int outside = (sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE) ? HOTZONE_POINTER * vpr_ :
370 HOTZONE_TOUCH * vpr_;
371 type_ = SessionHelper::GetAreaType(pointerItem.GetWindowX(), pointerItem.GetWindowY(), sourceType, outside, vpr_,
372 moveDragProperty_.originalRect_);
373 if (type_ == AreaType::UNDEFINED) {
374 return false;
375 }
376 InitDecorValue(property, sysConfig);
377 limits_ = property->GetWindowLimits();
378 moveDragProperty_.pointerId_ = pointerEvent->GetPointerId();
379 moveDragProperty_.pointerType_ = sourceType;
380 moveDragProperty_.originalPointerPosX_ = pointerItem.GetDisplayX();
381 moveDragProperty_.originalPointerPosY_ = pointerItem.GetDisplayY();
382 if (aspectRatio_ <= NEAR_ZERO) {
383 CalcFreeformTranslateLimits(type_);
384 }
385 moveDragProperty_.originalRect_.posX_ = pointerItem.GetDisplayX() - pointerItem.GetWindowX();
386 moveDragProperty_.originalRect_.posY_ = pointerItem.GetDisplayY() - pointerItem.GetWindowY();
387 mainMoveAxis_ = AxisType::UNDEFINED;
388 isStartDrag_ = true;
389 NotifyWindowInputPidChange(isStartDrag_);
390 return true;
391 }
392
CalcFreeformTargetRect(AreaType type,int32_t tranX,int32_t tranY,WSRect originalRect)393 WSRect MoveDragController::CalcFreeformTargetRect(AreaType type, int32_t tranX, int32_t tranY, WSRect originalRect)
394 {
395 WSRect targetRect = originalRect;
396 FixTranslateByLimits(tranX, tranY);
397 if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::LEFT)) {
398 targetRect.posX_ += tranX;
399 targetRect.width_ -= tranX;
400 } else if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::RIGHT)) {
401 targetRect.width_ += tranX;
402 }
403 if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::TOP)) {
404 targetRect.posY_ += tranY;
405 targetRect.height_ -= tranY;
406 } else if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::BOTTOM)) {
407 targetRect.height_ += tranY;
408 }
409 // check current ratio limits
410 if (targetRect.height_ == 0) {
411 return targetRect;
412 }
413 float curRatio = static_cast<float>(targetRect.width_) / static_cast<float>(targetRect.height_);
414 if (!MathHelper::GreatNotEqual(limits_.minRatio_, curRatio) &&
415 !MathHelper::GreatNotEqual(curRatio, limits_.maxRatio_)) {
416 return targetRect;
417 }
418 float newRatio = MathHelper::LessNotEqual(curRatio, limits_.minRatio_) ? limits_.minRatio_ : limits_.maxRatio_;
419 if (MathHelper::NearZero(newRatio)) {
420 return targetRect;
421 }
422 if ((static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::LEFT)) ||
423 (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::RIGHT))) {
424 targetRect.height_ = static_cast<int32_t>(static_cast<float>(targetRect.width_) / newRatio);
425 } else {
426 targetRect.width_ = static_cast<int32_t>(static_cast<float>(targetRect.height_) * newRatio);
427 }
428 return targetRect;
429 }
430
CalcFixedAspectRatioTargetRect(AreaType type,int32_t tranX,int32_t tranY,float aspectRatio,WSRect originalRect)431 WSRect MoveDragController::CalcFixedAspectRatioTargetRect(AreaType type, int32_t tranX, int32_t tranY,
432 float aspectRatio, WSRect originalRect)
433 {
434 int32_t posX = originalRect.posX_;
435 int32_t posY = originalRect.posY_;
436 int32_t width = static_cast<int32_t>(originalRect.width_);
437 int32_t height = static_cast<int32_t>(originalRect.height_);
438 FixTranslateByLimits(tranX, tranY);
439 if (mainMoveAxis_ == AxisType::UNDEFINED) {
440 if (!InitMainAxis(type, tranX, tranY)) {
441 return originalRect;
442 }
443 }
444
445 ConvertXYByAspectRatio(tranX, tranY, aspectRatio);
446 switch (type) {
447 case AreaType::LEFT_TOP: {
448 return { posX + tranX, posY + tranY, width - tranX, height - tranY };
449 }
450 case AreaType::RIGHT_TOP: {
451 return { posX, posY + (mainMoveAxis_ == AxisType::X_AXIS ? (-tranY) : (tranY)),
452 width + (mainMoveAxis_ == AxisType::X_AXIS ? (tranX) : (-tranX)),
453 height + (mainMoveAxis_ == AxisType::X_AXIS ? (tranY) : (-tranY)) };
454 }
455 case AreaType::RIGHT_BOTTOM: {
456 return { posX, posY, width + tranX, height + tranY };
457 }
458 case AreaType::LEFT_BOTTOM: {
459 return { posX + (mainMoveAxis_ == AxisType::X_AXIS ? (tranX) : (-tranX)), posY,
460 width - (mainMoveAxis_ == AxisType::X_AXIS ? (tranX) : (-tranX)),
461 height - (mainMoveAxis_ == AxisType::X_AXIS ? (tranY) : (-tranY)) };
462 }
463 case AreaType::LEFT: {
464 return { posX + tranX, posY, width - tranX, height - tranY };
465 }
466 case AreaType::TOP: {
467 return { posX, posY + tranY, width - tranX, height - tranY };
468 }
469 case AreaType::RIGHT: {
470 return { posX, posY, width + tranX, height + tranY };
471 }
472 case AreaType::BOTTOM: {
473 return { posX, posY, width + tranX, height + tranY };
474 }
475 default:
476 break;
477 }
478 return originalRect;
479 }
480
CalcFreeformTranslateLimits(AreaType type)481 void MoveDragController::CalcFreeformTranslateLimits(AreaType type)
482 {
483 if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::LEFT)) {
484 minTranX_ = moveDragProperty_.originalRect_.width_ - static_cast<int32_t>(limits_.maxWidth_);
485 maxTranX_ = moveDragProperty_.originalRect_.width_ - static_cast<int32_t>(limits_.minWidth_);
486 } else if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::RIGHT)) {
487 minTranX_ = static_cast<int32_t>(limits_.minWidth_) - moveDragProperty_.originalRect_.width_;
488 maxTranX_ = static_cast<int32_t>(limits_.maxWidth_) - moveDragProperty_.originalRect_.width_;
489 }
490 if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::TOP)) {
491 minTranY_ = moveDragProperty_.originalRect_.height_ - static_cast<int32_t>(limits_.maxHeight_);
492 maxTranY_ = moveDragProperty_.originalRect_.height_ - static_cast<int32_t>(limits_.minHeight_);
493 } else if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::BOTTOM)) {
494 minTranY_ = static_cast<int32_t>(limits_.minHeight_) - moveDragProperty_.originalRect_.height_;
495 maxTranY_ = static_cast<int32_t>(limits_.maxHeight_) - moveDragProperty_.originalRect_.height_;
496 }
497 }
498
CalcFixedAspectRatioTranslateLimits(AreaType type,AxisType axis)499 void MoveDragController::CalcFixedAspectRatioTranslateLimits(AreaType type, AxisType axis)
500 {
501 int32_t minW = static_cast<int32_t>(limits_.minWidth_);
502 int32_t maxW = static_cast<int32_t>(limits_.maxWidth_);
503 int32_t minH = static_cast<int32_t>(limits_.minHeight_);
504 int32_t maxH = static_cast<int32_t>(limits_.maxHeight_);
505 if (isDecorEnable_) {
506 if (SessionUtils::ToLayoutWidth(minW, vpr_) < SessionUtils::ToLayoutHeight(minH, vpr_) * aspectRatio_) {
507 minW = SessionUtils::ToWinWidth(SessionUtils::ToLayoutHeight(minH, vpr_) * aspectRatio_, vpr_);
508 } else {
509 minH = SessionUtils::ToWinHeight(SessionUtils::ToLayoutWidth(minW, vpr_) / aspectRatio_, vpr_);
510 }
511 if (SessionUtils::ToLayoutWidth(maxW, vpr_) < SessionUtils::ToLayoutHeight(maxH, vpr_) * aspectRatio_) {
512 maxH = SessionUtils::ToWinHeight(SessionUtils::ToLayoutWidth(maxW, vpr_) * aspectRatio_, vpr_);
513 } else {
514 maxW = SessionUtils::ToWinWidth(SessionUtils::ToLayoutHeight(maxH, vpr_) / aspectRatio_, vpr_);
515 }
516 } else {
517 if (minW < minH * aspectRatio_) {
518 minW = minH * aspectRatio_;
519 } else {
520 minH = minW / aspectRatio_;
521 }
522 if (maxW < maxH * aspectRatio_) {
523 maxH = maxW * aspectRatio_;
524 } else {
525 maxW = maxH / aspectRatio_;
526 }
527 }
528
529 if (axis == AxisType::X_AXIS) {
530 if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::LEFT)) {
531 minTranX_ = static_cast<int32_t>(moveDragProperty_.originalRect_.width_) - maxW;
532 maxTranX_ = static_cast<int32_t>(moveDragProperty_.originalRect_.width_) - minW;
533 } else if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::RIGHT)) {
534 minTranX_ = minW - static_cast<int32_t>(moveDragProperty_.originalRect_.width_);
535 maxTranX_ = maxW - static_cast<int32_t>(moveDragProperty_.originalRect_.width_);
536 }
537 } else if (axis == AxisType::Y_AXIS) {
538 if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::TOP)) {
539 minTranY_ = static_cast<int32_t>(moveDragProperty_.originalRect_.height_) - maxH;
540 maxTranY_ = static_cast<int32_t>(moveDragProperty_.originalRect_.height_) - minH;
541 } else if (static_cast<uint32_t>(type) & static_cast<uint32_t>(AreaType::BOTTOM)) {
542 minTranY_ = minH - static_cast<int32_t>(moveDragProperty_.originalRect_.height_);
543 maxTranY_ = maxH - static_cast<int32_t>(moveDragProperty_.originalRect_.height_);
544 }
545 }
546 }
547
FixTranslateByLimits(int32_t & tranX,int32_t & tranY)548 void MoveDragController::FixTranslateByLimits(int32_t& tranX, int32_t& tranY)
549 {
550 if (tranX < minTranX_) {
551 tranX = minTranX_;
552 } else if (tranX > maxTranX_) {
553 tranX = maxTranX_;
554 }
555 if (tranY < minTranY_) {
556 tranY = minTranY_;
557 } else if (tranY > maxTranY_) {
558 tranY = maxTranY_;
559 }
560 }
561
InitMainAxis(AreaType type,int32_t tranX,int32_t tranY)562 bool MoveDragController::InitMainAxis(AreaType type, int32_t tranX, int32_t tranY)
563 {
564 if (type == AreaType::LEFT || type == AreaType::RIGHT) {
565 mainMoveAxis_ = AxisType::X_AXIS;
566 } else if (type == AreaType::TOP || type == AreaType::BOTTOM) {
567 mainMoveAxis_ = AxisType::Y_AXIS;
568 } else if (tranX == 0 && tranY == 0) {
569 return false;
570 } else {
571 mainMoveAxis_ = (std::abs(tranX) > std::abs(tranY)) ? AxisType::X_AXIS : AxisType::Y_AXIS;
572 }
573 CalcFixedAspectRatioTranslateLimits(type, mainMoveAxis_);
574 return true;
575 }
576
ConvertXYByAspectRatio(int32_t & tx,int32_t & ty,float aspectRatio)577 void MoveDragController::ConvertXYByAspectRatio(int32_t& tx, int32_t& ty, float aspectRatio)
578 {
579 if (mainMoveAxis_ == AxisType::X_AXIS) {
580 ty = tx / aspectRatio;
581 } else if (mainMoveAxis_ == AxisType::Y_AXIS) {
582 tx = ty * aspectRatio;
583 }
584 return;
585 }
586
InitDecorValue(const sptr<WindowSessionProperty> property,const SystemSessionConfig & sysConfig)587 void MoveDragController::InitDecorValue(const sptr<WindowSessionProperty> property,
588 const SystemSessionConfig& sysConfig)
589 {
590 auto windowType = property->GetWindowType();
591 bool isMainWindow = WindowHelper::IsMainWindow(windowType);
592 bool isSubWindow = WindowHelper::IsSubWindow(windowType);
593 bool isDialogWindow = WindowHelper::IsDialogWindow(windowType);
594 isDecorEnable_ = (isMainWindow ||
595 ((isSubWindow || isDialogWindow) && property->IsDecorEnable())) &&
596 sysConfig.isSystemDecorEnable_ &&
597 WindowHelper::IsWindowModeSupported(sysConfig.decorModeSupportInfo_, property->GetWindowMode());
598 }
599
ProcessSessionRectChange(const SizeChangeReason & reason)600 void MoveDragController::ProcessSessionRectChange(const SizeChangeReason& reason)
601 {
602 if (moveDragCallback_) {
603 moveDragCallback_(reason);
604 }
605 }
606
GetVirtualPixelRatio() const607 float MoveDragController::GetVirtualPixelRatio() const
608 {
609 float vpr = 1.5;
610 auto displayInfo = DisplayManager::GetInstance().GetDefaultDisplay();
611 if (displayInfo != nullptr) {
612 vpr = displayInfo->GetVirtualPixelRatio();
613 }
614 WLOGFD("vpr: %{public}f", vpr);
615 return vpr;
616 }
617
UpdateDragType(int32_t startPointPosX,int32_t startPointPosY)618 void MoveDragController::UpdateDragType(int32_t startPointPosX, int32_t startPointPosY)
619 {
620 if (startPointPosX > rectExceptCorner_.posX_ &&
621 (startPointPosX < rectExceptCorner_.posX_ +
622 static_cast<int32_t>(rectExceptCorner_.width_))) {
623 dragType_ = DragType::DRAG_BOTTOM_OR_TOP;
624 } else if (startPointPosY > rectExceptCorner_.posY_ &&
625 (startPointPosY < rectExceptCorner_.posY_ +
626 static_cast<int32_t>(rectExceptCorner_.height_))) {
627 dragType_ = DragType::DRAG_LEFT_OR_RIGHT;
628 } else if ((startPointPosX <= rectExceptCorner_.posX_ && startPointPosY <= rectExceptCorner_.posY_) ||
629 (startPointPosX >= rectExceptCorner_.posX_ + static_cast<int32_t>(rectExceptCorner_.width_) &&
630 startPointPosY >= rectExceptCorner_.posY_ + static_cast<int32_t>(rectExceptCorner_.height_))) {
631 dragType_ = DragType::DRAG_LEFT_TOP_CORNER;
632 } else {
633 dragType_ = DragType::DRAG_RIGHT_TOP_CORNER;
634 }
635 }
636
IsPointInDragHotZone(int32_t startPointPosX,int32_t startPointPosY,int32_t sourceType,const WSRect & winRect)637 bool MoveDragController::IsPointInDragHotZone(int32_t startPointPosX, int32_t startPointPosY,
638 int32_t sourceType, const WSRect& winRect)
639 {
640 // calculate rect with hotzone
641 Rect rectWithHotzone;
642 rectWithHotzone.posX_ = winRect.posX_ - static_cast<int32_t>(HOTZONE_POINTER);
643 rectWithHotzone.posY_ = winRect.posY_ - static_cast<int32_t>(HOTZONE_POINTER);
644 rectWithHotzone.width_ = winRect.width_ + HOTZONE_POINTER * 2u; // double hotZone
645 rectWithHotzone.height_ = winRect.height_ + HOTZONE_POINTER * 2u; // double hotZone
646
647 if (sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE &&
648 !WindowHelper::IsPointInTargetRectWithBound(startPointPosX, startPointPosY, rectWithHotzone)) {
649 return false;
650 } else if ((!WindowHelper::IsPointInTargetRect(startPointPosX,
651 startPointPosY, rectExceptFrame_)) ||
652 (!WindowHelper::IsPointInWindowExceptCorner(startPointPosX,
653 startPointPosY, rectExceptCorner_))) {
654 return true;
655 }
656 return false;
657 }
658
CalculateStartRectExceptHotZone(float vpr,const WSRect & winRect)659 void MoveDragController::CalculateStartRectExceptHotZone(float vpr, const WSRect& winRect)
660 {
661 rectExceptFrame_.posX_ = winRect.posX_ +
662 static_cast<int32_t>(WINDOW_FRAME_WIDTH * vpr);
663 rectExceptFrame_.posY_ = winRect.posY_ +
664 static_cast<int32_t>(WINDOW_FRAME_WIDTH * vpr);
665 rectExceptFrame_.width_ = winRect.width_ -
666 static_cast<uint32_t>((WINDOW_FRAME_WIDTH + WINDOW_FRAME_WIDTH) * vpr);
667 rectExceptFrame_.height_ = winRect.height_ -
668 static_cast<uint32_t>((WINDOW_FRAME_WIDTH + WINDOW_FRAME_WIDTH) * vpr);
669
670 rectExceptCorner_.posX_ = winRect.posX_ +
671 static_cast<int32_t>(WINDOW_FRAME_CORNER_WIDTH * vpr);
672 rectExceptCorner_.posY_ = winRect.posY_ +
673 static_cast<int32_t>(WINDOW_FRAME_CORNER_WIDTH * vpr);
674 rectExceptCorner_.width_ = winRect.width_ -
675 static_cast<uint32_t>((WINDOW_FRAME_CORNER_WIDTH + WINDOW_FRAME_CORNER_WIDTH) * vpr);
676 rectExceptCorner_.height_ = winRect.height_ -
677 static_cast<uint32_t>((WINDOW_FRAME_CORNER_WIDTH + WINDOW_FRAME_CORNER_WIDTH) * vpr);
678 }
679
UpdateMoveTempProperty(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)680 WSError MoveDragController::UpdateMoveTempProperty(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
681 {
682 int32_t pointerId = pointerEvent->GetPointerId();
683 int32_t startPointerId = moveTempProperty_.pointerId_;
684 int32_t pointerType = pointerEvent->GetSourceType();
685 int32_t startPointerType = moveDragProperty_.pointerType_;
686 MMI::PointerEvent::PointerItem pointerItem;
687 int32_t sourceType = pointerEvent->GetSourceType();
688 if (!pointerEvent->GetPointerItem(pointerId, pointerItem) ||
689 (sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE &&
690 pointerEvent->GetButtonId() != MMI::PointerEvent::MOUSE_BUTTON_LEFT)) {
691 WLOGFW("invalid pointerEvent");
692 return WSError::WS_ERROR_NULLPTR;
693 }
694
695 int32_t pointerDisplayX = pointerItem.GetDisplayX();
696 int32_t pointerDisplayY = pointerItem.GetDisplayY();
697 switch (pointerEvent->GetPointerAction()) {
698 case MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN:
699 case MMI::PointerEvent::POINTER_ACTION_DOWN:
700 moveTempProperty_.pointerId_ = pointerId;
701 moveTempProperty_.pointerType_ = pointerType;
702 moveTempProperty_.lastDownPointerPosX_ = pointerDisplayX;
703 moveTempProperty_.lastDownPointerPosY_ = pointerDisplayY;
704 moveTempProperty_.lastMovePointerPosX_ = pointerDisplayX;
705 moveTempProperty_.lastMovePointerPosY_ = pointerDisplayY;
706 moveTempProperty_.lastDownPointerWindowX_ = pointerItem.GetWindowX();
707 moveTempProperty_.lastDownPointerWindowY_ = pointerItem.GetWindowY();
708 break;
709 case MMI::PointerEvent::POINTER_ACTION_MOVE:
710 if ((startPointerId != -1 && startPointerId != pointerId) ||
711 (startPointerType != -1 && pointerType != startPointerType)) {
712 WLOGFI("block unnecessary pointer event inside the window");
713 return WSError::WS_DO_NOTHING;
714 }
715 moveTempProperty_.lastMovePointerPosX_ = pointerDisplayX;
716 moveTempProperty_.lastMovePointerPosY_ = pointerDisplayY;
717 break;
718 case MMI::PointerEvent::POINTER_ACTION_UP:
719 case MMI::PointerEvent::POINTER_ACTION_BUTTON_UP:
720 case MMI::PointerEvent::POINTER_ACTION_CANCEL: {
721 moveTempProperty_ = { -1, -1, -1, -1, -1, -1, -1, -1 };
722 break;
723 }
724 default:
725 break;
726 }
727 return WSError::WS_OK;
728 }
729
CalcFirstMoveTargetRect(const WSRect & windowRect,bool isFullToFloating)730 void MoveDragController::CalcFirstMoveTargetRect(const WSRect& windowRect, bool isFullToFloating)
731 {
732 if (!GetStartMoveFlag() || moveTempProperty_.isEmpty()) {
733 return;
734 }
735
736 WSRect originalRect = {
737 moveTempProperty_.lastDownPointerPosX_ - moveTempProperty_.lastDownPointerWindowX_,
738 moveTempProperty_.lastDownPointerPosY_ - moveTempProperty_.lastDownPointerWindowY_,
739 windowRect.width_,
740 windowRect.height_
741 };
742 if (isFullToFloating) {
743 originalRect.posX_ = windowRect.posX_;
744 originalRect.posY_ = windowRect.posY_;
745 }
746 SetOriginalValue(moveTempProperty_.pointerId_, moveTempProperty_.pointerType_,
747 moveTempProperty_.lastDownPointerPosX_, moveTempProperty_.lastDownPointerPosY_, originalRect);
748
749 int32_t offsetX = moveTempProperty_.lastMovePointerPosX_ - moveTempProperty_.lastDownPointerPosX_;
750 int32_t offsetY = moveTempProperty_.lastMovePointerPosY_ - moveTempProperty_.lastDownPointerPosY_;
751 WSRect targetRect = {
752 originalRect.posX_ + offsetX,
753 originalRect.posY_ + offsetY,
754 originalRect.width_,
755 originalRect.height_
756 };
757 WLOGFD("first move rect: [%{public}d, %{public}d, %{public}u, %{public}u]", targetRect.posX_, targetRect.posY_,
758 targetRect.width_, targetRect.height_);
759 moveDragProperty_.targetRect_ = targetRect;
760 ProcessSessionRectChange(SizeChangeReason::MOVE);
761 }
762
CheckDragEventLegal(const std::shared_ptr<MMI::PointerEvent> & pointerEvent,const sptr<WindowSessionProperty> property)763 bool MoveDragController::CheckDragEventLegal(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
764 const sptr<WindowSessionProperty> property)
765 {
766 if (pointerEvent == nullptr || property == nullptr) {
767 WLOGE("ConsumeDragEvent stop because of nullptr");
768 return false;
769 }
770 if (GetStartMoveFlag()) {
771 WLOGFD("the window is being moved");
772 return false;
773 }
774 if (!GetStartDragFlag() && pointerEvent->GetPointerAction() != MMI::PointerEvent::POINTER_ACTION_DOWN &&
775 pointerEvent->GetPointerAction() != MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN) {
776 return false;
777 }
778 int32_t pointerId = pointerEvent->GetPointerId();
779 int32_t startPointerId = moveDragProperty_.pointerId_;
780 if (GetStartDragFlag() && startPointerId != -1 && startPointerId != pointerId) {
781 WLOGFI("block unnecessary pointer event inside the window");
782 return false;
783 }
784 return true;
785 }
786
UpdateHotAreaType(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)787 void MoveDragController::UpdateHotAreaType(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
788 {
789 int32_t pointerId = pointerEvent->GetPointerId();
790 MMI::PointerEvent::PointerItem pointerItem;
791 if (!pointerEvent->GetPointerItem(pointerId, pointerItem)) {
792 WLOGFW("invalid pointerEvent");
793 return;
794 }
795 int32_t pointerDisplayX = pointerItem.GetDisplayX();
796 int32_t pointerDisplayY = pointerItem.GetDisplayY();
797 uint32_t windowDragHotAreaType = SceneSession::GetWindowDragHotAreaType(WINDOW_HOT_AREA_TYPE_UNDEFINED,
798 pointerDisplayX, pointerDisplayY);
799 if (windowDragHotAreaType_ != windowDragHotAreaType) {
800 WLOGFI("the pointerEvent is window drag hot area, old type is: %{public}d, new type is: %{public}d",
801 windowDragHotAreaType_, windowDragHotAreaType);
802 }
803 windowDragHotAreaType_ = windowDragHotAreaType;
804 }
805
GetOriginalPointerPosX()806 int32_t MoveDragController::GetOriginalPointerPosX()
807 {
808 return moveDragProperty_.originalPointerPosX_;
809 }
810
GetOriginalPointerPosY()811 int32_t MoveDragController::GetOriginalPointerPosY()
812 {
813 return moveDragProperty_.originalPointerPosY_;
814 }
815
SetWindowDragHotAreaFunc(const NotifyWindowDragHotAreaFunc & func)816 void MoveDragController::SetWindowDragHotAreaFunc(const NotifyWindowDragHotAreaFunc& func)
817 {
818 windowDragHotAreaFunc_ = func;
819 }
820
OnLostFocus()821 void MoveDragController::OnLostFocus()
822 {
823 if (isStartMove_ || isStartDrag_) {
824 WLOGFI("window id %{public}d lost focus, should stop MoveDrag isMove: %{public}d, isDrag: %{public}d",
825 persistentId_, isStartMove_, isStartDrag_);
826 isStartMove_ = false;
827 isStartDrag_ = false;
828 NotifyWindowInputPidChange(isStartDrag_);
829 if (windowDragHotAreaType_ != WINDOW_HOT_AREA_TYPE_UNDEFINED) {
830 ProcessWindowDragHotAreaFunc(true, SizeChangeReason::DRAG_END);
831 }
832 ProcessSessionRectChange(SizeChangeReason::DRAG_END);
833 }
834 }
835
ResSchedReportData(int32_t type,bool onOffTag)836 void MoveDragController::ResSchedReportData(int32_t type, bool onOffTag)
837 {
838 #ifdef RES_SCHED_ENABLE
839 std::unordered_map<std::string, std::string> payload;
840 // 0 is start, 1 is end
841 if (onOffTag) {
842 OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(type, 0, payload);
843 } else {
844 OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(type, 1, payload);
845 }
846 WLOGFD("ResSchedReportData success type: %{public}d onOffTag: %{public}d", type, onOffTag);
847 #endif
848 }
849 } // namespace OHOS::Rosen
850