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 "coordination_hotarea.h"
17
18 #include "coordination_sm.h"
19 #include "fi_log.h"
20
21 namespace OHOS {
22 namespace Msdp {
23 namespace DeviceStatus {
24 namespace {
25 constexpr OHOS::HiviewDFX::HiLogLabel LABEL { LOG_CORE, MSDP_DOMAIN_ID, "CoordinationHotArea" };
26 std::shared_ptr<CoordinationHotArea> g_instance = nullptr;
27 constexpr int32_t HOT_AREA_WIDTH { 100 };
28 constexpr int32_t HOT_AREA_MARGIN { 200 };
29 }; // namespace
30
GetInstance()31 std::shared_ptr<CoordinationHotArea> CoordinationHotArea::GetInstance()
32 {
33 static std::once_flag flag;
34 std::call_once(flag, [&]() {
35 g_instance.reset(new (std::nothrow) CoordinationHotArea());
36 });
37 return g_instance;
38 }
39
AddHotAreaListener(sptr<HotAreaInfo> event)40 void CoordinationHotArea::AddHotAreaListener(sptr<HotAreaInfo> event)
41 {
42 CALL_DEBUG_ENTER;
43 CHKPV(event);
44 auto it = std::find_if(hotAreaCallbacks_.begin(), hotAreaCallbacks_.end(),
45 [event](auto info) {
46 return (*info).sess == event->sess;
47 });
48 if (it != hotAreaCallbacks_.end()) {
49 *it = event;
50 return;
51 }
52 hotAreaCallbacks_.emplace_back(event);
53 }
54
RemoveHotAreaListener(sptr<HotAreaInfo> event)55 void CoordinationHotArea::RemoveHotAreaListener(sptr<HotAreaInfo> event)
56 {
57 CALL_DEBUG_ENTER;
58 if (hotAreaCallbacks_.empty() || event == nullptr) {
59 FI_HILOGE("Failed to remove hot area listener");
60 return;
61 }
62 for (auto it = hotAreaCallbacks_.begin(); it != hotAreaCallbacks_.end(); ++it) {
63 if ((*it)->sess == event->sess) {
64 hotAreaCallbacks_.erase(it);
65 return;
66 }
67 }
68 }
69
OnHotAreaMessage(HotAreaType msg,bool isEdge)70 int32_t CoordinationHotArea::OnHotAreaMessage(HotAreaType msg, bool isEdge)
71 {
72 CALL_DEBUG_ENTER;
73 if (hotAreaCallbacks_.empty()) {
74 FI_HILOGW("Failed to invoke the listening interface, hotAreaCallbacks_ is empty");
75 return RET_ERR;
76 }
77 for (auto it = hotAreaCallbacks_.begin(); it != hotAreaCallbacks_.end(); ++it) {
78 sptr<HotAreaInfo> info = *it;
79 CHKPC(info);
80 NotifyHotAreaMessage(info->sess, info->msgId, msg, isEdge);
81 }
82 return RET_OK;
83 }
84
ProcessData(std::shared_ptr<MMI::PointerEvent> pointerEvent)85 int32_t CoordinationHotArea::ProcessData(std::shared_ptr<MMI::PointerEvent> pointerEvent)
86 {
87 CALL_DEBUG_ENTER;
88 if (hotAreaCallbacks_.empty()) {
89 return RET_ERR;
90 }
91 CHKPR(pointerEvent, RET_ERR);
92 MMI::PointerEvent::PointerItem pointerItem;
93 pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem);
94 displayX_ = pointerItem.GetDisplayX();
95 displayY_ = pointerItem.GetDisplayY();
96 deltaX_ = pointerItem.GetRawDx();
97 deltaY_ = pointerItem.GetRawDy();
98 CheckInHotArea();
99 CheckPointerToEdge(type_);
100 NotifyMessage();
101 return RET_OK;
102 }
103
CheckInHotArea()104 void CoordinationHotArea::CheckInHotArea()
105 {
106 CALL_DEBUG_ENTER;
107 if (displayX_ <= HOT_AREA_WIDTH && displayY_ >= HOT_AREA_MARGIN &&
108 displayY_ <= (height_ - HOT_AREA_MARGIN)) {
109 type_ = HotAreaType::AREA_LEFT;
110 } else if (displayX_ >= (width_ - HOT_AREA_WIDTH) && displayY_ >= HOT_AREA_MARGIN &&
111 displayY_ <= (height_ - HOT_AREA_MARGIN)) {
112 type_ = HotAreaType::AREA_RIGHT;
113 } else if (displayY_ <= HOT_AREA_WIDTH && displayX_ >= HOT_AREA_MARGIN &&
114 displayX_ <= (width_ - HOT_AREA_MARGIN)) {
115 type_ = HotAreaType::AREA_TOP;
116 } else if (displayY_ >= (height_ - HOT_AREA_WIDTH) && displayX_ >= HOT_AREA_MARGIN &&
117 displayX_ <= (width_ - HOT_AREA_MARGIN)) {
118 type_ = HotAreaType::AREA_BOTTOM;
119 } else {
120 type_ = HotAreaType::AREA_NONE;
121 }
122 }
123
CheckPointerToEdge(HotAreaType type)124 void CoordinationHotArea::CheckPointerToEdge(HotAreaType type)
125 {
126 CALL_DEBUG_ENTER;
127 if (type == HotAreaType::AREA_LEFT) {
128 isEdge_ = displayX_ <= 0 && deltaX_ < 0;
129 } else if (type == HotAreaType::AREA_RIGHT) {
130 isEdge_ = displayX_ >= (width_ - 1) && deltaX_ > 0;
131 } else if (type == HotAreaType::AREA_TOP) {
132 isEdge_ = displayY_ <= 0 && deltaY_ < 0;
133 } else if (type == HotAreaType::AREA_BOTTOM) {
134 isEdge_ = displayY_ >= (height_ - 1) && deltaY_ > 0;
135 } else {
136 isEdge_ = false;
137 }
138 }
139
NotifyHotAreaMessage(SessionPtr sess,MessageId msgId,HotAreaType msg,bool isEdge)140 void CoordinationHotArea::NotifyHotAreaMessage(SessionPtr sess, MessageId msgId, HotAreaType msg, bool isEdge)
141 {
142 CALL_DEBUG_ENTER;
143 CHKPV(sess);
144 NetPacket pkt(msgId);
145 pkt << displayX_ << displayY_ << static_cast<int32_t>(msg) << isEdge;
146 if (pkt.ChkRWError()) {
147 FI_HILOGE("Packet write data failed");
148 return;
149 }
150 if (!sess->SendMsg(pkt)) {
151 FI_HILOGE("Sending failed");
152 return;
153 }
154 }
155
SetWidth(int32_t screenWidth)156 void CoordinationHotArea::SetWidth(int32_t screenWidth)
157 {
158 width_ = screenWidth;
159 }
160
SetHeight(int32_t screenHight)161 void CoordinationHotArea::SetHeight(int32_t screenHight)
162 {
163 height_ = screenHight;
164 }
165
NotifyMessage()166 void CoordinationHotArea::NotifyMessage()
167 {
168 CALL_DEBUG_ENTER;
169 OnHotAreaMessage(type_, isEdge_);
170 }
171 } // DeviceStatus
172 } // Msdp
173 } // OHOS