1885b47fbSopenharmony_ci/*
2885b47fbSopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd.
3885b47fbSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4885b47fbSopenharmony_ci * you may not use this file except in compliance with the License.
5885b47fbSopenharmony_ci * You may obtain a copy of the License at
6885b47fbSopenharmony_ci *
7885b47fbSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8885b47fbSopenharmony_ci *
9885b47fbSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10885b47fbSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11885b47fbSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12885b47fbSopenharmony_ci * See the License for the specific language governing permissions and
13885b47fbSopenharmony_ci * limitations under the License.
14885b47fbSopenharmony_ci */
15885b47fbSopenharmony_ci
16885b47fbSopenharmony_ci#include "accessibility_mouse_autoclick.h"
17885b47fbSopenharmony_ci#include "accessible_ability_manager_service.h"
18885b47fbSopenharmony_ci#include "hilog_wrapper.h"
19885b47fbSopenharmony_ci#include "utils.h"
20885b47fbSopenharmony_ci
21885b47fbSopenharmony_cinamespace OHOS {
22885b47fbSopenharmony_cinamespace Accessibility {
23885b47fbSopenharmony_cinamespace {
24885b47fbSopenharmony_ci    constexpr size_t POINTER_COUNT_1 = 1;
25885b47fbSopenharmony_ci    constexpr uint32_t AUTOCLICK_TIMEOUT_MSG = 1;
26885b47fbSopenharmony_ci} // namespace
27885b47fbSopenharmony_ci
28885b47fbSopenharmony_ciAccessibilityMouseAutoclick::AccessibilityMouseAutoclick()
29885b47fbSopenharmony_ci{
30885b47fbSopenharmony_ci    HILOG_DEBUG();
31885b47fbSopenharmony_ci
32885b47fbSopenharmony_ci    std::shared_ptr<AppExecFwk::EventRunner> runner =
33885b47fbSopenharmony_ci        Singleton<AccessibleAbilityManagerService>::GetInstance().GetMainRunner();
34885b47fbSopenharmony_ci    if (!runner) {
35885b47fbSopenharmony_ci        HILOG_ERROR("get runner failed");
36885b47fbSopenharmony_ci        return;
37885b47fbSopenharmony_ci    }
38885b47fbSopenharmony_ci
39885b47fbSopenharmony_ci    timeoutHandler_ = std::make_shared<MouseAutoclickEventHandler>(runner, *this);
40885b47fbSopenharmony_ci    if (!timeoutHandler_) {
41885b47fbSopenharmony_ci        HILOG_ERROR("create event handler failed");
42885b47fbSopenharmony_ci    }
43885b47fbSopenharmony_ci}
44885b47fbSopenharmony_ci
45885b47fbSopenharmony_ciAccessibilityMouseAutoclick::~AccessibilityMouseAutoclick()
46885b47fbSopenharmony_ci{
47885b47fbSopenharmony_ci    HILOG_DEBUG();
48885b47fbSopenharmony_ci
49885b47fbSopenharmony_ci    timeoutHandler_ = nullptr;
50885b47fbSopenharmony_ci    lastMouseEvent_ = nullptr;
51885b47fbSopenharmony_ci}
52885b47fbSopenharmony_ci
53885b47fbSopenharmony_cibool AccessibilityMouseAutoclick::OnPointerEvent(MMI::PointerEvent &event)
54885b47fbSopenharmony_ci{
55885b47fbSopenharmony_ci    HILOG_DEBUG();
56885b47fbSopenharmony_ci
57885b47fbSopenharmony_ci    int32_t source = event.GetSourceType();
58885b47fbSopenharmony_ci    int32_t action = event.GetPointerAction();
59885b47fbSopenharmony_ci    std::vector<int32_t> pointers = event.GetPointerIds();
60885b47fbSopenharmony_ci    size_t pointerCount = pointers.size();
61885b47fbSopenharmony_ci    if ((source != MMI::PointerEvent::SOURCE_TYPE_MOUSE) ||
62885b47fbSopenharmony_ci        (action != MMI::PointerEvent::POINTER_ACTION_MOVE) ||
63885b47fbSopenharmony_ci        (pointerCount != POINTER_COUNT_1)) {
64885b47fbSopenharmony_ci        CancelAutoclick();
65885b47fbSopenharmony_ci    } else {
66885b47fbSopenharmony_ci        RecognizeAutoclick(event);
67885b47fbSopenharmony_ci    }
68885b47fbSopenharmony_ci
69885b47fbSopenharmony_ci    EventTransmission::OnPointerEvent(event);
70885b47fbSopenharmony_ci    return false;
71885b47fbSopenharmony_ci}
72885b47fbSopenharmony_ci
73885b47fbSopenharmony_civoid AccessibilityMouseAutoclick::SendMouseClickEvent()
74885b47fbSopenharmony_ci{
75885b47fbSopenharmony_ci    HILOG_DEBUG();
76885b47fbSopenharmony_ci
77885b47fbSopenharmony_ci    if (!lastMouseEvent_) {
78885b47fbSopenharmony_ci        HILOG_DEBUG("No mouse event to be sent.");
79885b47fbSopenharmony_ci        return;
80885b47fbSopenharmony_ci    }
81885b47fbSopenharmony_ci
82885b47fbSopenharmony_ci    int64_t nowTime = GetSystemTime();
83885b47fbSopenharmony_ci    // Update event information.
84885b47fbSopenharmony_ci    lastMouseEvent_->SetActionTime(nowTime);
85885b47fbSopenharmony_ci    lastMouseEvent_->SetActionStartTime(nowTime);
86885b47fbSopenharmony_ci    lastMouseEvent_->SetButtonId(MMI::PointerEvent::MOUSE_BUTTON_LEFT);
87885b47fbSopenharmony_ci    lastMouseEvent_->SetButtonPressed(MMI::PointerEvent::MOUSE_BUTTON_LEFT);
88885b47fbSopenharmony_ci
89885b47fbSopenharmony_ci    // Update pointer item information.
90885b47fbSopenharmony_ci    int32_t pointerId = lastMouseEvent_->GetPointerId();
91885b47fbSopenharmony_ci    MMI::PointerEvent::PointerItem item;
92885b47fbSopenharmony_ci    lastMouseEvent_->GetPointerItem(pointerId, item);
93885b47fbSopenharmony_ci    item.SetDownTime(nowTime);
94885b47fbSopenharmony_ci    item.SetPressed(true);
95885b47fbSopenharmony_ci    lastMouseEvent_->UpdatePointerItem(pointerId, item);
96885b47fbSopenharmony_ci
97885b47fbSopenharmony_ci    // Send mouse left button down event.
98885b47fbSopenharmony_ci    lastMouseEvent_->SetPointerAction(MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN);
99885b47fbSopenharmony_ci    EventTransmission::OnPointerEvent(*lastMouseEvent_);
100885b47fbSopenharmony_ci
101885b47fbSopenharmony_ci    // Send mouse left button up event.
102885b47fbSopenharmony_ci    lastMouseEvent_->SetPointerAction(MMI::PointerEvent::POINTER_ACTION_BUTTON_UP);
103885b47fbSopenharmony_ci    EventTransmission::OnPointerEvent(*lastMouseEvent_);
104885b47fbSopenharmony_ci}
105885b47fbSopenharmony_ci
106885b47fbSopenharmony_civoid AccessibilityMouseAutoclick::ResetAutoclickInfo()
107885b47fbSopenharmony_ci{
108885b47fbSopenharmony_ci    HILOG_DEBUG();
109885b47fbSopenharmony_ci
110885b47fbSopenharmony_ci    lastMouseEvent_ = nullptr;
111885b47fbSopenharmony_ci}
112885b47fbSopenharmony_ci
113885b47fbSopenharmony_civoid AccessibilityMouseAutoclick::DestroyEvents()
114885b47fbSopenharmony_ci{
115885b47fbSopenharmony_ci    HILOG_DEBUG();
116885b47fbSopenharmony_ci
117885b47fbSopenharmony_ci    CancelAutoclick();
118885b47fbSopenharmony_ci    EventTransmission::DestroyEvents();
119885b47fbSopenharmony_ci}
120885b47fbSopenharmony_ci
121885b47fbSopenharmony_civoid AccessibilityMouseAutoclick::RecognizeAutoclick(MMI::PointerEvent &event)
122885b47fbSopenharmony_ci{
123885b47fbSopenharmony_ci    HILOG_DEBUG();
124885b47fbSopenharmony_ci
125885b47fbSopenharmony_ci    bool isMove = IsMouseMovement(event);
126885b47fbSopenharmony_ci    if (!isMove) {
127885b47fbSopenharmony_ci        HILOG_DEBUG("Mouse is not moving.");
128885b47fbSopenharmony_ci        return;
129885b47fbSopenharmony_ci    }
130885b47fbSopenharmony_ci
131885b47fbSopenharmony_ci    lastMouseEvent_ = std::make_shared<MMI::PointerEvent>(event);
132885b47fbSopenharmony_ci    if (!timeoutHandler_) {
133885b47fbSopenharmony_ci        HILOG_ERROR("handler is null.");
134885b47fbSopenharmony_ci        return;
135885b47fbSopenharmony_ci    }
136885b47fbSopenharmony_ci    int64_t delayTime = GetDelayTime();
137885b47fbSopenharmony_ci    timeoutHandler_->RemoveEvent(AUTOCLICK_TIMEOUT_MSG);
138885b47fbSopenharmony_ci    timeoutHandler_->SendEvent(AUTOCLICK_TIMEOUT_MSG, 0, delayTime);
139885b47fbSopenharmony_ci}
140885b47fbSopenharmony_ci
141885b47fbSopenharmony_cibool AccessibilityMouseAutoclick::IsMouseMovement(MMI::PointerEvent &event)
142885b47fbSopenharmony_ci{
143885b47fbSopenharmony_ci    HILOG_DEBUG();
144885b47fbSopenharmony_ci
145885b47fbSopenharmony_ci    if (!lastMouseEvent_) {
146885b47fbSopenharmony_ci        return true;
147885b47fbSopenharmony_ci    }
148885b47fbSopenharmony_ci
149885b47fbSopenharmony_ci    int32_t pointerId = event.GetPointerId();
150885b47fbSopenharmony_ci    MMI::PointerEvent::PointerItem item;
151885b47fbSopenharmony_ci    event.GetPointerItem(pointerId, item);
152885b47fbSopenharmony_ci    int32_t newX = item.GetDisplayX();
153885b47fbSopenharmony_ci    int32_t newY = item.GetDisplayY();
154885b47fbSopenharmony_ci
155885b47fbSopenharmony_ci    pointerId = lastMouseEvent_->GetPointerId();
156885b47fbSopenharmony_ci    lastMouseEvent_->GetPointerItem(pointerId, item);
157885b47fbSopenharmony_ci    int32_t oldX = item.GetDisplayX();
158885b47fbSopenharmony_ci    int32_t oldY = item.GetDisplayY();
159885b47fbSopenharmony_ci    if ((newX != oldX) || (newY != oldY)) {
160885b47fbSopenharmony_ci        HILOG_DEBUG("Mouse is moving.");
161885b47fbSopenharmony_ci        return true;
162885b47fbSopenharmony_ci    }
163885b47fbSopenharmony_ci    return false;
164885b47fbSopenharmony_ci}
165885b47fbSopenharmony_ci
166885b47fbSopenharmony_civoid AccessibilityMouseAutoclick::CancelAutoclick()
167885b47fbSopenharmony_ci{
168885b47fbSopenharmony_ci    HILOG_DEBUG();
169885b47fbSopenharmony_ci
170885b47fbSopenharmony_ci    ResetAutoclickInfo();
171885b47fbSopenharmony_ci    timeoutHandler_->RemoveEvent(AUTOCLICK_TIMEOUT_MSG);
172885b47fbSopenharmony_ci}
173885b47fbSopenharmony_ci
174885b47fbSopenharmony_ciint64_t AccessibilityMouseAutoclick::GetSystemTime()
175885b47fbSopenharmony_ci{
176885b47fbSopenharmony_ci    HILOG_DEBUG();
177885b47fbSopenharmony_ci
178885b47fbSopenharmony_ci    int64_t microsecond = Utils::GetSystemTime() * 1000;
179885b47fbSopenharmony_ci    return microsecond;
180885b47fbSopenharmony_ci}
181885b47fbSopenharmony_ci
182885b47fbSopenharmony_ciint64_t AccessibilityMouseAutoclick::GetDelayTime()
183885b47fbSopenharmony_ci{
184885b47fbSopenharmony_ci    HILOG_DEBUG();
185885b47fbSopenharmony_ci
186885b47fbSopenharmony_ci    sptr<AccessibilityAccountData> accountData =
187885b47fbSopenharmony_ci        Singleton<AccessibleAbilityManagerService>::GetInstance().GetCurrentAccountData();
188885b47fbSopenharmony_ci    if (!accountData) {
189885b47fbSopenharmony_ci        HILOG_ERROR("GetCurrentAccountData failed");
190885b47fbSopenharmony_ci        return 0;
191885b47fbSopenharmony_ci    }
192885b47fbSopenharmony_ci
193885b47fbSopenharmony_ci    int32_t delayTime = accountData->GetConfig()->GetMouseAutoClick();
194885b47fbSopenharmony_ci    return delayTime;
195885b47fbSopenharmony_ci}
196885b47fbSopenharmony_ci
197885b47fbSopenharmony_ciAccessibilityMouseAutoclick::MouseAutoclickEventHandler::MouseAutoclickEventHandler(
198885b47fbSopenharmony_ci    const std::shared_ptr<AppExecFwk::EventRunner> &runner,
199885b47fbSopenharmony_ci    AccessibilityMouseAutoclick &mouseAutoclick)
200885b47fbSopenharmony_ci    : AppExecFwk::EventHandler(runner), mouseAutoclick_(mouseAutoclick)
201885b47fbSopenharmony_ci{
202885b47fbSopenharmony_ci    HILOG_DEBUG();
203885b47fbSopenharmony_ci}
204885b47fbSopenharmony_ci
205885b47fbSopenharmony_civoid AccessibilityMouseAutoclick::MouseAutoclickEventHandler::ProcessEvent(
206885b47fbSopenharmony_ci    const AppExecFwk::InnerEvent::Pointer &event)
207885b47fbSopenharmony_ci{
208885b47fbSopenharmony_ci    HILOG_DEBUG();
209885b47fbSopenharmony_ci
210885b47fbSopenharmony_ci    switch (event->GetInnerEventId()) {
211885b47fbSopenharmony_ci        case AUTOCLICK_TIMEOUT_MSG:
212885b47fbSopenharmony_ci            mouseAutoclick_.SendMouseClickEvent();
213885b47fbSopenharmony_ci            mouseAutoclick_.ResetAutoclickInfo();
214885b47fbSopenharmony_ci            break;
215885b47fbSopenharmony_ci        default:
216885b47fbSopenharmony_ci            break;
217885b47fbSopenharmony_ci    }
218885b47fbSopenharmony_ci}
219885b47fbSopenharmony_ci} // namespace Accessibility
220885b47fbSopenharmony_ci} // namespace OHOS