1886da342Sopenharmony_ci/*
2886da342Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3886da342Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4886da342Sopenharmony_ci * you may not use this file except in compliance with the License.
5886da342Sopenharmony_ci * You may obtain a copy of the License at
6886da342Sopenharmony_ci *
7886da342Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8886da342Sopenharmony_ci *
9886da342Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10886da342Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11886da342Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12886da342Sopenharmony_ci * See the License for the specific language governing permissions and
13886da342Sopenharmony_ci * limitations under the License.
14886da342Sopenharmony_ci */
15886da342Sopenharmony_ci
16886da342Sopenharmony_ci#include <cmath>
17886da342Sopenharmony_ci#include "ui_action.h"
18886da342Sopenharmony_ci
19886da342Sopenharmony_cinamespace OHOS::uitest {
20886da342Sopenharmony_ci    using namespace std;
21886da342Sopenharmony_ci    using namespace nlohmann;
22886da342Sopenharmony_ci
23886da342Sopenharmony_ci    static void DecomposeClick(PointerMatrix &recv, const Point &point, const UiOpArgs &options)
24886da342Sopenharmony_ci    {
25886da342Sopenharmony_ci        constexpr uint32_t fingers = 1;
26886da342Sopenharmony_ci        constexpr uint32_t steps = 2;
27886da342Sopenharmony_ci        PointerMatrix pointer(fingers, steps);
28886da342Sopenharmony_ci        pointer.PushAction(TouchEvent {ActionStage::DOWN, point, 0, options.clickHoldMs_});
29886da342Sopenharmony_ci        pointer.PushAction(TouchEvent {ActionStage::UP, point, options.clickHoldMs_, 0});
30886da342Sopenharmony_ci        recv = move(pointer);
31886da342Sopenharmony_ci    }
32886da342Sopenharmony_ci
33886da342Sopenharmony_ci    static void DecomposeLongClick(PointerMatrix &recv, const Point &point, const UiOpArgs &options)
34886da342Sopenharmony_ci    {
35886da342Sopenharmony_ci        // should sleep after touch-down to make long-click duration
36886da342Sopenharmony_ci        constexpr uint32_t fingers = 1;
37886da342Sopenharmony_ci        constexpr uint32_t steps = 2;
38886da342Sopenharmony_ci        PointerMatrix pointer(fingers, steps);
39886da342Sopenharmony_ci        pointer.PushAction(TouchEvent {ActionStage::DOWN, point, 0, options.longClickHoldMs_});
40886da342Sopenharmony_ci        pointer.PushAction(TouchEvent {ActionStage::UP, point, options.longClickHoldMs_, 0});
41886da342Sopenharmony_ci        recv = move(pointer);
42886da342Sopenharmony_ci    }
43886da342Sopenharmony_ci
44886da342Sopenharmony_ci    static void DecomposeDoubleClick(PointerMatrix &recv, const Point &point, const UiOpArgs &options)
45886da342Sopenharmony_ci    {
46886da342Sopenharmony_ci        const auto msInterval = options.doubleClickIntervalMs_;
47886da342Sopenharmony_ci        constexpr uint32_t fingers = 1;
48886da342Sopenharmony_ci        constexpr uint32_t steps = 4;
49886da342Sopenharmony_ci        PointerMatrix pointer(fingers, steps);
50886da342Sopenharmony_ci        pointer.PushAction(TouchEvent {ActionStage::DOWN, point, 0, options.clickHoldMs_});
51886da342Sopenharmony_ci        pointer.PushAction(TouchEvent {ActionStage::UP, point, options.clickHoldMs_, msInterval});
52886da342Sopenharmony_ci
53886da342Sopenharmony_ci        pointer.PushAction(TouchEvent {ActionStage::DOWN, point, 0, options.clickHoldMs_});
54886da342Sopenharmony_ci        pointer.PushAction(TouchEvent {ActionStage::UP, point, options.clickHoldMs_, 0});
55886da342Sopenharmony_ci        recv = move(pointer);
56886da342Sopenharmony_ci    }
57886da342Sopenharmony_ci
58886da342Sopenharmony_ci    static void DecomposeComputeSwipe(PointerMatrix &recv, const Point &from, const Point &to, TouchOp type,
59886da342Sopenharmony_ci                                      const UiOpArgs &options)
60886da342Sopenharmony_ci    {
61886da342Sopenharmony_ci        const int32_t distanceX = to.px_ - from.px_;
62886da342Sopenharmony_ci        const int32_t distanceY = to.py_ - from.py_;
63886da342Sopenharmony_ci        const uint32_t distance = sqrt(distanceX * distanceX + distanceY * distanceY);
64886da342Sopenharmony_ci        const uint32_t timeCostMs = (distance * 1000) / options.swipeVelocityPps_;
65886da342Sopenharmony_ci        if (distance < 1) {
66886da342Sopenharmony_ci            // do not need to execute swipe
67886da342Sopenharmony_ci            return;
68886da342Sopenharmony_ci        }
69886da342Sopenharmony_ci        uint32_t steps = options.swipeStepsCounts_;
70886da342Sopenharmony_ci        uint32_t intervalMs = timeCostMs / steps + 1;
71886da342Sopenharmony_ci        constexpr uint32_t fingers = 1;
72886da342Sopenharmony_ci        constexpr uint32_t intervalMsInSwipe = 5;
73886da342Sopenharmony_ci        if (type != TouchOp::FLING) {
74886da342Sopenharmony_ci            steps = timeCostMs / intervalMsInSwipe;
75886da342Sopenharmony_ci            intervalMs = intervalMsInSwipe;
76886da342Sopenharmony_ci        }
77886da342Sopenharmony_ci        PointerMatrix pointer(fingers, steps + 1);
78886da342Sopenharmony_ci
79886da342Sopenharmony_ci        pointer.PushAction(TouchEvent {ActionStage::DOWN, {from.px_, from.py_}, 0, intervalMs});
80886da342Sopenharmony_ci        float stepLengthX = static_cast<double>(distanceX) / static_cast<double>(steps);
81886da342Sopenharmony_ci        float stepLengthY = static_cast<double>(distanceY) / static_cast<double>(steps);
82886da342Sopenharmony_ci
83886da342Sopenharmony_ci        for (uint32_t step = 1; step < steps; step++) {
84886da342Sopenharmony_ci            const int32_t pointX = from.px_ + stepLengthX * step;
85886da342Sopenharmony_ci            const int32_t pointY = from.py_ + stepLengthY * step;
86886da342Sopenharmony_ci            const uint32_t timeOffsetMs = (timeCostMs * step) / steps;
87886da342Sopenharmony_ci            pointer.PushAction(TouchEvent {ActionStage::MOVE, {pointX, pointY}, timeOffsetMs, intervalMs});
88886da342Sopenharmony_ci        }
89886da342Sopenharmony_ci
90886da342Sopenharmony_ci        pointer.PushAction(TouchEvent {ActionStage::UP, {to.px_, to.py_}, timeCostMs, intervalMs});
91886da342Sopenharmony_ci        if (type == TouchOp::DRAG) {
92886da342Sopenharmony_ci            // drag needs longPressDown firstly
93886da342Sopenharmony_ci            pointer.At(fingers - 1, 0).holdMs_ += options.longClickHoldMs_;
94886da342Sopenharmony_ci            for (uint32_t idx = 1; idx < pointer.GetSize(); idx++) {
95886da342Sopenharmony_ci                pointer.At(fingers - 1, idx).downTimeOffsetMs_ += options.longClickHoldMs_;
96886da342Sopenharmony_ci            }
97886da342Sopenharmony_ci        }
98886da342Sopenharmony_ci        recv = move(pointer);
99886da342Sopenharmony_ci    }
100886da342Sopenharmony_ci
101886da342Sopenharmony_ci    void GenericClick::Decompose(PointerMatrix &recv, const UiOpArgs &options) const
102886da342Sopenharmony_ci    {
103886da342Sopenharmony_ci        DCHECK(type_ >= TouchOp::CLICK && type_ <= TouchOp::DOUBLE_CLICK_P);
104886da342Sopenharmony_ci        switch (type_) {
105886da342Sopenharmony_ci            case CLICK:
106886da342Sopenharmony_ci                DecomposeClick(recv, point_, options);
107886da342Sopenharmony_ci                break;
108886da342Sopenharmony_ci            case LONG_CLICK:
109886da342Sopenharmony_ci                DecomposeLongClick(recv, point_, options);
110886da342Sopenharmony_ci                break;
111886da342Sopenharmony_ci            case DOUBLE_CLICK_P:
112886da342Sopenharmony_ci                DecomposeDoubleClick(recv, point_, options);
113886da342Sopenharmony_ci                break;
114886da342Sopenharmony_ci            default:
115886da342Sopenharmony_ci                break;
116886da342Sopenharmony_ci        }
117886da342Sopenharmony_ci        for (uint32_t index = 0; index < recv.GetSize(); index++) {
118886da342Sopenharmony_ci            recv.At(recv.GetFingers() - 1, index).flags_ = type_;
119886da342Sopenharmony_ci        }
120886da342Sopenharmony_ci    }
121886da342Sopenharmony_ci
122886da342Sopenharmony_ci    void GenericSwipe::Decompose(PointerMatrix &recv, const UiOpArgs &options) const
123886da342Sopenharmony_ci    {
124886da342Sopenharmony_ci        DCHECK(type_ >= TouchOp::SWIPE && type_ <= TouchOp::FLING);
125886da342Sopenharmony_ci        DecomposeComputeSwipe(recv, from_, to_, type_, options);
126886da342Sopenharmony_ci        for (uint32_t index = 0; index < recv.GetSize(); index++) {
127886da342Sopenharmony_ci            recv.At(recv.GetFingers() - 1, index).flags_ = type_;
128886da342Sopenharmony_ci        }
129886da342Sopenharmony_ci    }
130886da342Sopenharmony_ci
131886da342Sopenharmony_ci    void GenericPinch::Decompose(PointerMatrix &recv, const UiOpArgs &options) const
132886da342Sopenharmony_ci    {
133886da342Sopenharmony_ci        const int32_t distanceX0 = abs(rect_.GetCenterX() - rect_.left_) * abs(scale_ - 1);
134886da342Sopenharmony_ci        PointerMatrix pointer1;
135886da342Sopenharmony_ci        PointerMatrix pointer2;
136886da342Sopenharmony_ci        if (scale_ > 1) {
137886da342Sopenharmony_ci            auto fromPoint0 = Point(rect_.GetCenterX() - options.pinchWidgetDeadZone_, rect_.GetCenterY());
138886da342Sopenharmony_ci            auto toPoint0 = Point((fromPoint0.px_ - distanceX0), rect_.GetCenterY());
139886da342Sopenharmony_ci            auto fromPoint1 = Point(rect_.GetCenterX() + options.pinchWidgetDeadZone_, rect_.GetCenterY());
140886da342Sopenharmony_ci            auto toPoint1 = Point((fromPoint1.px_ + distanceX0), rect_.GetCenterY());
141886da342Sopenharmony_ci            DecomposeComputeSwipe(pointer1, fromPoint0, toPoint0, TouchOp::SWIPE, options);
142886da342Sopenharmony_ci            DecomposeComputeSwipe(pointer2, fromPoint1, toPoint1, TouchOp::SWIPE, options);
143886da342Sopenharmony_ci        } else if (scale_ < 1) {
144886da342Sopenharmony_ci            auto fromPoint0 = Point(rect_.left_ + options.pinchWidgetDeadZone_, rect_.GetCenterY());
145886da342Sopenharmony_ci            auto toPoint0 = Point((fromPoint0.px_ + distanceX0), rect_.GetCenterY());
146886da342Sopenharmony_ci            auto fromPoint1 = Point(rect_.right_ - options.pinchWidgetDeadZone_, rect_.GetCenterY());
147886da342Sopenharmony_ci            auto toPoint1 = Point((fromPoint1.px_- distanceX0), rect_.GetCenterY());
148886da342Sopenharmony_ci            DecomposeComputeSwipe(pointer1, fromPoint0, toPoint0, TouchOp::SWIPE, options);
149886da342Sopenharmony_ci            DecomposeComputeSwipe(pointer2, fromPoint1, toPoint1, TouchOp::SWIPE, options);
150886da342Sopenharmony_ci        }
151886da342Sopenharmony_ci
152886da342Sopenharmony_ci        PointerMatrix pointer3(pointer1.GetFingers() + pointer2.GetFingers(), pointer1.GetSteps());
153886da342Sopenharmony_ci        for (uint32_t index = 0; index < pointer1.GetSize(); index++) {
154886da342Sopenharmony_ci            pointer3.PushAction(pointer1.At(0, index));
155886da342Sopenharmony_ci        }
156886da342Sopenharmony_ci        for (uint32_t index = 0; index < pointer2.GetSize(); index++) {
157886da342Sopenharmony_ci            pointer3.PushAction(pointer2.At(0, index));
158886da342Sopenharmony_ci        }
159886da342Sopenharmony_ci        recv = move(pointer3);
160886da342Sopenharmony_ci    }
161886da342Sopenharmony_ci
162886da342Sopenharmony_ci    void MultiPointerAction::Decompose(PointerMatrix &recv, const UiOpArgs &options) const
163886da342Sopenharmony_ci    {
164886da342Sopenharmony_ci        PointerMatrix matrix(pointers_.GetFingers(), pointers_.GetSteps() + 1);
165886da342Sopenharmony_ci        constexpr int32_t flag = 0x10000; // set the low 16 bits of data as coordinates.
166886da342Sopenharmony_ci        for (uint32_t finger = 0; finger < pointers_.GetFingers(); finger++) {
167886da342Sopenharmony_ci            uint32_t timeOffsetMs = 0;
168886da342Sopenharmony_ci            uint32_t intervalMs = 0;
169886da342Sopenharmony_ci            constexpr uint32_t unitConversionConstant = 1000;
170886da342Sopenharmony_ci            for (uint32_t step = 0; step < pointers_.GetSteps() - 1; step++) {
171886da342Sopenharmony_ci                const int32_t pxTo = (pointers_.At(finger, step + 1).point_.px_) % flag;
172886da342Sopenharmony_ci                const int32_t pxFrom = (pointers_.At(finger, step).point_.px_) % flag;
173886da342Sopenharmony_ci                const int32_t distanceX = pxTo - pxFrom;
174886da342Sopenharmony_ci                const int32_t pyTo = pointers_.At(finger, step + 1).point_.py_;
175886da342Sopenharmony_ci                const int32_t pyFrom = pointers_.At(finger, step).point_.py_;
176886da342Sopenharmony_ci                const int32_t distanceY = pyTo - pyFrom;
177886da342Sopenharmony_ci                auto stayMs = (pointers_.At(finger, step).point_.px_) / flag;
178886da342Sopenharmony_ci                const uint32_t distance = sqrt(distanceX * distanceX + distanceY * distanceY);
179886da342Sopenharmony_ci                intervalMs = (distance * unitConversionConstant) / options.swipeVelocityPps_;
180886da342Sopenharmony_ci                auto holdMs = (stayMs == 0) ? intervalMs : stayMs;
181886da342Sopenharmony_ci                if (step == 0) {
182886da342Sopenharmony_ci                    matrix.PushAction(TouchEvent {ActionStage::DOWN, {pxFrom, pyFrom}, 0, holdMs});
183886da342Sopenharmony_ci                } else {
184886da342Sopenharmony_ci                    timeOffsetMs += intervalMs;
185886da342Sopenharmony_ci                    matrix.PushAction(TouchEvent {ActionStage::MOVE, {pxFrom, pyFrom}, timeOffsetMs, holdMs});
186886da342Sopenharmony_ci                }
187886da342Sopenharmony_ci            }
188886da342Sopenharmony_ci            auto endPx = (pointers_.At(finger, pointers_.GetSteps() - 1).point_.px_) % flag;
189886da342Sopenharmony_ci            auto endPy = pointers_.At(finger, pointers_.GetSteps() - 1).point_.py_;
190886da342Sopenharmony_ci            auto endTime = (pointers_.At(finger, pointers_.GetSteps() - 1).point_.px_) / flag;
191886da342Sopenharmony_ci            auto endStayTime = (endTime == 0) ? intervalMs : endTime;
192886da342Sopenharmony_ci            matrix.PushAction(TouchEvent {ActionStage::MOVE, {endPx, endPy}, timeOffsetMs, endStayTime});
193886da342Sopenharmony_ci            matrix.PushAction(TouchEvent {ActionStage::UP, {endPx, endPy}, timeOffsetMs, intervalMs});
194886da342Sopenharmony_ci        }
195886da342Sopenharmony_ci        recv = move(matrix);
196886da342Sopenharmony_ci    }
197886da342Sopenharmony_ci
198886da342Sopenharmony_ci    PointerMatrix::PointerMatrix() {};
199886da342Sopenharmony_ci
200886da342Sopenharmony_ci    PointerMatrix::PointerMatrix(uint32_t fingersNum, uint32_t stepsNum)
201886da342Sopenharmony_ci    {
202886da342Sopenharmony_ci        this->fingerNum_ = fingersNum;
203886da342Sopenharmony_ci        this->stepNum_ = stepsNum;
204886da342Sopenharmony_ci        this->capacity_ = this->fingerNum_ * this->stepNum_;
205886da342Sopenharmony_ci        this->size_ = 0;
206886da342Sopenharmony_ci        this->data_ = std::make_unique<TouchEvent[]>(this->capacity_);
207886da342Sopenharmony_ci    }
208886da342Sopenharmony_ci
209886da342Sopenharmony_ci    PointerMatrix& PointerMatrix::operator=(PointerMatrix&& other)
210886da342Sopenharmony_ci    {
211886da342Sopenharmony_ci        this->data_ = move(other.data_);
212886da342Sopenharmony_ci        this->fingerNum_ = other.fingerNum_;
213886da342Sopenharmony_ci        this->stepNum_ = other.stepNum_;
214886da342Sopenharmony_ci        this->capacity_ = other.capacity_;
215886da342Sopenharmony_ci        this->size_ = other.size_;
216886da342Sopenharmony_ci        other.fingerNum_ = 0;
217886da342Sopenharmony_ci        other.stepNum_ = 0;
218886da342Sopenharmony_ci        other.capacity_ = 0;
219886da342Sopenharmony_ci        other.size_ = 0;
220886da342Sopenharmony_ci        return *this;
221886da342Sopenharmony_ci    }
222886da342Sopenharmony_ci
223886da342Sopenharmony_ci    PointerMatrix::~PointerMatrix() {}
224886da342Sopenharmony_ci
225886da342Sopenharmony_ci    void PointerMatrix::PushAction(const TouchEvent& ptr)
226886da342Sopenharmony_ci    {
227886da342Sopenharmony_ci        if (this->capacity_ == this->size_) {
228886da342Sopenharmony_ci            return;
229886da342Sopenharmony_ci        }
230886da342Sopenharmony_ci        *(this->data_.get() + this->size_) = ptr;
231886da342Sopenharmony_ci        this->size_++;
232886da342Sopenharmony_ci    }
233886da342Sopenharmony_ci
234886da342Sopenharmony_ci    bool PointerMatrix::Empty() const
235886da342Sopenharmony_ci    {
236886da342Sopenharmony_ci        if (this->size_ == 0) {
237886da342Sopenharmony_ci            return true;
238886da342Sopenharmony_ci        }
239886da342Sopenharmony_ci        return false;
240886da342Sopenharmony_ci    }
241886da342Sopenharmony_ci
242886da342Sopenharmony_ci    TouchEvent& PointerMatrix::At(uint32_t fingerIndex, uint32_t stepIndex) const
243886da342Sopenharmony_ci    {
244886da342Sopenharmony_ci        return *(this->data_.get() + (fingerIndex * this->stepNum_ + stepIndex));
245886da342Sopenharmony_ci    }
246886da342Sopenharmony_ci
247886da342Sopenharmony_ci    uint32_t PointerMatrix::GetCapacity() const
248886da342Sopenharmony_ci    {
249886da342Sopenharmony_ci        return this->capacity_;
250886da342Sopenharmony_ci    }
251886da342Sopenharmony_ci
252886da342Sopenharmony_ci    uint32_t PointerMatrix::GetSize() const
253886da342Sopenharmony_ci    {
254886da342Sopenharmony_ci        return this->size_;
255886da342Sopenharmony_ci    }
256886da342Sopenharmony_ci
257886da342Sopenharmony_ci    uint32_t PointerMatrix::GetSteps() const
258886da342Sopenharmony_ci    {
259886da342Sopenharmony_ci        return this->stepNum_;
260886da342Sopenharmony_ci    }
261886da342Sopenharmony_ci
262886da342Sopenharmony_ci    uint32_t PointerMatrix::GetFingers() const
263886da342Sopenharmony_ci    {
264886da342Sopenharmony_ci        return this->fingerNum_;
265886da342Sopenharmony_ci    }
266886da342Sopenharmony_ci
267886da342Sopenharmony_ci    void PointerMatrix::ConvertToMouseEvents(vector<MouseEvent> &recv) const
268886da342Sopenharmony_ci    {
269886da342Sopenharmony_ci        for (uint32_t finger = 0; finger < fingerNum_; finger++) {
270886da342Sopenharmony_ci            for (uint32_t step = 0; step < stepNum_; step++) {
271886da342Sopenharmony_ci                auto touchEvent = At(finger, step);
272886da342Sopenharmony_ci                recv.push_back(MouseEvent {touchEvent.stage_, touchEvent.point_, MouseButton::BUTTON_LEFT, {},
273886da342Sopenharmony_ci                                           touchEvent.holdMs_});
274886da342Sopenharmony_ci            }
275886da342Sopenharmony_ci        }
276886da342Sopenharmony_ci    }
277886da342Sopenharmony_ci
278886da342Sopenharmony_ci    void MouseMoveTo::Decompose(std::vector<MouseEvent> &recv, const UiOpArgs &opt) const
279886da342Sopenharmony_ci    {
280886da342Sopenharmony_ci        recv.push_back(MouseEvent {ActionStage::MOVE, point_, MouseButton::BUTTON_NONE, {}, 0});
281886da342Sopenharmony_ci    }
282886da342Sopenharmony_ci
283886da342Sopenharmony_ci    void MouseSwipe::Decompose(std::vector<MouseEvent> &recv, const UiOpArgs &opt) const
284886da342Sopenharmony_ci    {
285886da342Sopenharmony_ci        DCHECK(type_ >= TouchOp::SWIPE && type_ <= TouchOp::DRAG);
286886da342Sopenharmony_ci        PointerMatrix touchEvents;
287886da342Sopenharmony_ci        DecomposeComputeSwipe(touchEvents, from_, to_, type_, opt);
288886da342Sopenharmony_ci        touchEvents.ConvertToMouseEvents(recv);
289886da342Sopenharmony_ci        if (type_ == TouchOp::SWIPE) {
290886da342Sopenharmony_ci            recv.front().stage_ = ActionStage::MOVE;
291886da342Sopenharmony_ci            recv.back().stage_ = ActionStage::MOVE;
292886da342Sopenharmony_ci        }
293886da342Sopenharmony_ci    }
294886da342Sopenharmony_ci
295886da342Sopenharmony_ci    void MouseClick::Decompose(std::vector<MouseEvent> &recv, const UiOpArgs &opt) const
296886da342Sopenharmony_ci    {
297886da342Sopenharmony_ci        DCHECK(type_ >= TouchOp::CLICK && type_ <= TouchOp::DOUBLE_CLICK_P);
298886da342Sopenharmony_ci        PointerMatrix touchEvents;
299886da342Sopenharmony_ci        switch (type_) {
300886da342Sopenharmony_ci            case CLICK:
301886da342Sopenharmony_ci                DecomposeClick(touchEvents, point_, opt);
302886da342Sopenharmony_ci                break;
303886da342Sopenharmony_ci            case LONG_CLICK:
304886da342Sopenharmony_ci                DecomposeLongClick(touchEvents, point_, opt);
305886da342Sopenharmony_ci                break;
306886da342Sopenharmony_ci            case DOUBLE_CLICK_P:
307886da342Sopenharmony_ci                DecomposeDoubleClick(touchEvents, point_, opt);
308886da342Sopenharmony_ci                break;
309886da342Sopenharmony_ci            default:
310886da342Sopenharmony_ci                break;
311886da342Sopenharmony_ci        }
312886da342Sopenharmony_ci        touchEvents.ConvertToMouseEvents(recv);
313886da342Sopenharmony_ci        for (size_t index = 0; index < recv.size(); index++) {
314886da342Sopenharmony_ci            recv[index].button_ = button_;
315886da342Sopenharmony_ci        }
316886da342Sopenharmony_ci        vector<KeyEvent> keyAction1;
317886da342Sopenharmony_ci        keyAction1.push_back(KeyEvent {ActionStage::DOWN, key1_, opt.keyHoldMs_});
318886da342Sopenharmony_ci        keyAction1.push_back(KeyEvent {ActionStage::DOWN, key2_, opt.keyHoldMs_});
319886da342Sopenharmony_ci        auto keyDown = MouseEvent {ActionStage::MOVE, point_, MouseButton::BUTTON_NONE, keyAction1, opt.clickHoldMs_};
320886da342Sopenharmony_ci        recv.insert(recv.begin(), keyDown);
321886da342Sopenharmony_ci
322886da342Sopenharmony_ci        vector<KeyEvent> keyAction2;
323886da342Sopenharmony_ci        keyAction2.push_back(KeyEvent {ActionStage::UP, key2_, opt.keyHoldMs_});
324886da342Sopenharmony_ci        keyAction2.push_back(KeyEvent {ActionStage::UP, key1_, opt.keyHoldMs_});
325886da342Sopenharmony_ci        auto keyUp = MouseEvent {ActionStage::UP, point_, MouseButton::BUTTON_NONE, keyAction2, 0};
326886da342Sopenharmony_ci        recv.push_back(keyUp);
327886da342Sopenharmony_ci    }
328886da342Sopenharmony_ci
329886da342Sopenharmony_ci    void MouseScroll::Decompose(std::vector<MouseEvent> &recv, const UiOpArgs &opt) const
330886da342Sopenharmony_ci    {
331886da342Sopenharmony_ci        recv.push_back(MouseEvent {ActionStage::MOVE, point_, MouseButton::BUTTON_NONE, {}, 0});
332886da342Sopenharmony_ci        constexpr int32_t thousandMilliseconds = 1000;
333886da342Sopenharmony_ci        auto focusTimeMs = thousandMilliseconds / speed_ / 2;
334886da342Sopenharmony_ci        auto stage  = (scrollValue_ > 0) ? AXIS_DOWN : AXIS_UP;
335886da342Sopenharmony_ci        vector<KeyEvent> keyAction1;
336886da342Sopenharmony_ci        keyAction1.push_back(KeyEvent {ActionStage::DOWN, key1_, opt.keyHoldMs_});
337886da342Sopenharmony_ci        keyAction1.push_back(KeyEvent {ActionStage::DOWN, key2_, opt.keyHoldMs_});
338886da342Sopenharmony_ci        recv.push_back(MouseEvent {stage, point_, MouseButton::BUTTON_NONE, keyAction1, focusTimeMs});
339886da342Sopenharmony_ci        recv.push_back(MouseEvent {ActionStage::AXIS_STOP, point_, MouseButton::BUTTON_NONE, {}, focusTimeMs});
340886da342Sopenharmony_ci
341886da342Sopenharmony_ci        auto steps = abs(scrollValue_);
342886da342Sopenharmony_ci        for (auto index = 1; index < steps - 1; index++) {
343886da342Sopenharmony_ci            recv.push_back(MouseEvent {stage, point_, MouseButton::BUTTON_NONE, {}, focusTimeMs});
344886da342Sopenharmony_ci            recv.push_back(MouseEvent {ActionStage::AXIS_STOP, point_, MouseButton::BUTTON_NONE, {}, focusTimeMs});
345886da342Sopenharmony_ci        }
346886da342Sopenharmony_ci
347886da342Sopenharmony_ci        vector<KeyEvent> keyAction2;
348886da342Sopenharmony_ci        keyAction2.push_back(KeyEvent {ActionStage::UP, key2_, opt.keyHoldMs_});
349886da342Sopenharmony_ci        keyAction2.push_back(KeyEvent {ActionStage::UP, key1_, opt.keyHoldMs_});
350886da342Sopenharmony_ci        if (steps > 1) {
351886da342Sopenharmony_ci            recv.push_back(MouseEvent {stage, point_, MouseButton::BUTTON_NONE, {}, focusTimeMs});
352886da342Sopenharmony_ci            recv.push_back(MouseEvent {ActionStage::AXIS_STOP, point_, MouseButton::BUTTON_NONE, keyAction2,
353886da342Sopenharmony_ci                                       focusTimeMs});
354886da342Sopenharmony_ci        } else {
355886da342Sopenharmony_ci            recv.push_back(MouseEvent {ActionStage::NONE, point_, MouseButton::BUTTON_NONE, keyAction2, focusTimeMs});
356886da342Sopenharmony_ci        }
357886da342Sopenharmony_ci    }
358886da342Sopenharmony_ci
359886da342Sopenharmony_ci    void GenericAtomicAction::Decompose(PointerMatrix &recv, const UiOpArgs &options) const
360886da342Sopenharmony_ci    {
361886da342Sopenharmony_ci        DCHECK(stage_ >= ActionStage::DOWN && stage_ <= ActionStage::UP);
362886da342Sopenharmony_ci        constexpr uint32_t fingers = 1;
363886da342Sopenharmony_ci        constexpr uint32_t steps = 1;
364886da342Sopenharmony_ci        PointerMatrix pointer(fingers, steps);
365886da342Sopenharmony_ci        pointer.PushAction(TouchEvent {stage_, point_, 0, 0, 0});
366886da342Sopenharmony_ci        recv = move(pointer);
367886da342Sopenharmony_ci    }
368886da342Sopenharmony_ci}
369