1 /*
2  * Copyright (C) 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 
16 #include "accessibility_mouse_autoclick.h"
17 #include "accessible_ability_manager_service.h"
18 #include "hilog_wrapper.h"
19 #include "utils.h"
20 
21 namespace OHOS {
22 namespace Accessibility {
23 namespace {
24     constexpr size_t POINTER_COUNT_1 = 1;
25     constexpr uint32_t AUTOCLICK_TIMEOUT_MSG = 1;
26 } // namespace
27 
AccessibilityMouseAutoclick()28 AccessibilityMouseAutoclick::AccessibilityMouseAutoclick()
29 {
30     HILOG_DEBUG();
31 
32     std::shared_ptr<AppExecFwk::EventRunner> runner =
33         Singleton<AccessibleAbilityManagerService>::GetInstance().GetMainRunner();
34     if (!runner) {
35         HILOG_ERROR("get runner failed");
36         return;
37     }
38 
39     timeoutHandler_ = std::make_shared<MouseAutoclickEventHandler>(runner, *this);
40     if (!timeoutHandler_) {
41         HILOG_ERROR("create event handler failed");
42     }
43 }
44 
~AccessibilityMouseAutoclick()45 AccessibilityMouseAutoclick::~AccessibilityMouseAutoclick()
46 {
47     HILOG_DEBUG();
48 
49     timeoutHandler_ = nullptr;
50     lastMouseEvent_ = nullptr;
51 }
52 
OnPointerEvent(MMI::PointerEvent & event)53 bool AccessibilityMouseAutoclick::OnPointerEvent(MMI::PointerEvent &event)
54 {
55     HILOG_DEBUG();
56 
57     int32_t source = event.GetSourceType();
58     int32_t action = event.GetPointerAction();
59     std::vector<int32_t> pointers = event.GetPointerIds();
60     size_t pointerCount = pointers.size();
61     if ((source != MMI::PointerEvent::SOURCE_TYPE_MOUSE) ||
62         (action != MMI::PointerEvent::POINTER_ACTION_MOVE) ||
63         (pointerCount != POINTER_COUNT_1)) {
64         CancelAutoclick();
65     } else {
66         RecognizeAutoclick(event);
67     }
68 
69     EventTransmission::OnPointerEvent(event);
70     return false;
71 }
72 
SendMouseClickEvent()73 void AccessibilityMouseAutoclick::SendMouseClickEvent()
74 {
75     HILOG_DEBUG();
76 
77     if (!lastMouseEvent_) {
78         HILOG_DEBUG("No mouse event to be sent.");
79         return;
80     }
81 
82     int64_t nowTime = GetSystemTime();
83     // Update event information.
84     lastMouseEvent_->SetActionTime(nowTime);
85     lastMouseEvent_->SetActionStartTime(nowTime);
86     lastMouseEvent_->SetButtonId(MMI::PointerEvent::MOUSE_BUTTON_LEFT);
87     lastMouseEvent_->SetButtonPressed(MMI::PointerEvent::MOUSE_BUTTON_LEFT);
88 
89     // Update pointer item information.
90     int32_t pointerId = lastMouseEvent_->GetPointerId();
91     MMI::PointerEvent::PointerItem item;
92     lastMouseEvent_->GetPointerItem(pointerId, item);
93     item.SetDownTime(nowTime);
94     item.SetPressed(true);
95     lastMouseEvent_->UpdatePointerItem(pointerId, item);
96 
97     // Send mouse left button down event.
98     lastMouseEvent_->SetPointerAction(MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN);
99     EventTransmission::OnPointerEvent(*lastMouseEvent_);
100 
101     // Send mouse left button up event.
102     lastMouseEvent_->SetPointerAction(MMI::PointerEvent::POINTER_ACTION_BUTTON_UP);
103     EventTransmission::OnPointerEvent(*lastMouseEvent_);
104 }
105 
ResetAutoclickInfo()106 void AccessibilityMouseAutoclick::ResetAutoclickInfo()
107 {
108     HILOG_DEBUG();
109 
110     lastMouseEvent_ = nullptr;
111 }
112 
DestroyEvents()113 void AccessibilityMouseAutoclick::DestroyEvents()
114 {
115     HILOG_DEBUG();
116 
117     CancelAutoclick();
118     EventTransmission::DestroyEvents();
119 }
120 
RecognizeAutoclick(MMI::PointerEvent & event)121 void AccessibilityMouseAutoclick::RecognizeAutoclick(MMI::PointerEvent &event)
122 {
123     HILOG_DEBUG();
124 
125     bool isMove = IsMouseMovement(event);
126     if (!isMove) {
127         HILOG_DEBUG("Mouse is not moving.");
128         return;
129     }
130 
131     lastMouseEvent_ = std::make_shared<MMI::PointerEvent>(event);
132     if (!timeoutHandler_) {
133         HILOG_ERROR("handler is null.");
134         return;
135     }
136     int64_t delayTime = GetDelayTime();
137     timeoutHandler_->RemoveEvent(AUTOCLICK_TIMEOUT_MSG);
138     timeoutHandler_->SendEvent(AUTOCLICK_TIMEOUT_MSG, 0, delayTime);
139 }
140 
IsMouseMovement(MMI::PointerEvent & event)141 bool AccessibilityMouseAutoclick::IsMouseMovement(MMI::PointerEvent &event)
142 {
143     HILOG_DEBUG();
144 
145     if (!lastMouseEvent_) {
146         return true;
147     }
148 
149     int32_t pointerId = event.GetPointerId();
150     MMI::PointerEvent::PointerItem item;
151     event.GetPointerItem(pointerId, item);
152     int32_t newX = item.GetDisplayX();
153     int32_t newY = item.GetDisplayY();
154 
155     pointerId = lastMouseEvent_->GetPointerId();
156     lastMouseEvent_->GetPointerItem(pointerId, item);
157     int32_t oldX = item.GetDisplayX();
158     int32_t oldY = item.GetDisplayY();
159     if ((newX != oldX) || (newY != oldY)) {
160         HILOG_DEBUG("Mouse is moving.");
161         return true;
162     }
163     return false;
164 }
165 
CancelAutoclick()166 void AccessibilityMouseAutoclick::CancelAutoclick()
167 {
168     HILOG_DEBUG();
169 
170     ResetAutoclickInfo();
171     timeoutHandler_->RemoveEvent(AUTOCLICK_TIMEOUT_MSG);
172 }
173 
GetSystemTime()174 int64_t AccessibilityMouseAutoclick::GetSystemTime()
175 {
176     HILOG_DEBUG();
177 
178     int64_t microsecond = Utils::GetSystemTime() * 1000;
179     return microsecond;
180 }
181 
GetDelayTime()182 int64_t AccessibilityMouseAutoclick::GetDelayTime()
183 {
184     HILOG_DEBUG();
185 
186     sptr<AccessibilityAccountData> accountData =
187         Singleton<AccessibleAbilityManagerService>::GetInstance().GetCurrentAccountData();
188     if (!accountData) {
189         HILOG_ERROR("GetCurrentAccountData failed");
190         return 0;
191     }
192 
193     int32_t delayTime = accountData->GetConfig()->GetMouseAutoClick();
194     return delayTime;
195 }
196 
MouseAutoclickEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> & runner,AccessibilityMouseAutoclick & mouseAutoclick)197 AccessibilityMouseAutoclick::MouseAutoclickEventHandler::MouseAutoclickEventHandler(
198     const std::shared_ptr<AppExecFwk::EventRunner> &runner,
199     AccessibilityMouseAutoclick &mouseAutoclick)
200     : AppExecFwk::EventHandler(runner), mouseAutoclick_(mouseAutoclick)
201 {
202     HILOG_DEBUG();
203 }
204 
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)205 void AccessibilityMouseAutoclick::MouseAutoclickEventHandler::ProcessEvent(
206     const AppExecFwk::InnerEvent::Pointer &event)
207 {
208     HILOG_DEBUG();
209 
210     switch (event->GetInnerEventId()) {
211         case AUTOCLICK_TIMEOUT_MSG:
212             mouseAutoclick_.SendMouseClickEvent();
213             mouseAutoclick_.ResetAutoclickInfo();
214             break;
215         default:
216             break;
217     }
218 }
219 } // namespace Accessibility
220 } // namespace OHOS