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