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_key.h"
17 #include "hilog_wrapper.h"
18 #include "utils.h"
19 
20 namespace OHOS {
21 namespace Accessibility {
22 struct MouseMoveOffset {
23     int32_t offsetX = 0;
24     int32_t offsetY = 0;
25 };
26 namespace {
27     // item count
28     constexpr size_t ITEM_COUNT_1 = 1;
29     constexpr size_t ITEM_COUNT_2 = 2;
30     constexpr size_t ITEM_COUNT_3 = 3;
31     // move offset
32     constexpr int32_t MOVE_LEFT_STEP = -5;
33     constexpr int32_t MOVE_RIGHT_STEP = 5;
34     constexpr int32_t MOVE_UP_STEP = -5;
35     constexpr int32_t MOVE_DOWN_STEP = 5;
36     // speed multiple
37     constexpr float SPEED_UP_MULTIPLE = 5.0f;
38     constexpr float SLOW_DOWN_MULTIPLE = 0.5f;
39     // result of parsing meta key
40     constexpr int32_t INVALID_KEY = -1;
41     constexpr int32_t NONE_KEY = 0;
42     constexpr int32_t CTRL_KEY = 1;
43     constexpr int32_t SHIFT_KEY = 2;
44     constexpr int32_t CTRL_SHIFT_KEY = 3;
45     // array(PRESSED_METAKEYS_TBL)'s length
46     constexpr int32_t ROW_COUNT = 21;
47     constexpr int32_t COLUMN_COUNT = 3;
48     const std::vector<int32_t> MOUSE_KEYCODE_V = {
49         MMI::KeyEvent::KEYCODE_NUMPAD_1, MMI::KeyEvent::KEYCODE_NUMPAD_2, MMI::KeyEvent::KEYCODE_NUMPAD_3,
50         MMI::KeyEvent::KEYCODE_NUMPAD_4, MMI::KeyEvent::KEYCODE_NUMPAD_5, MMI::KeyEvent::KEYCODE_NUMPAD_6,
51         MMI::KeyEvent::KEYCODE_NUMPAD_7, MMI::KeyEvent::KEYCODE_NUMPAD_8, MMI::KeyEvent::KEYCODE_NUMPAD_9,
52         MMI::KeyEvent::KEYCODE_NUMPAD_DIVIDE, MMI::KeyEvent::KEYCODE_NUMPAD_MULTIPLY,
53         MMI::KeyEvent::KEYCODE_NUMPAD_SUBTRACT, MMI::KeyEvent::KEYCODE_NUMPAD_ADD};
54     const std::vector<int32_t> MOUSE_MOVE_KEYCODE_V = {
55         MMI::KeyEvent::KEYCODE_NUMPAD_1, MMI::KeyEvent::KEYCODE_NUMPAD_2, MMI::KeyEvent::KEYCODE_NUMPAD_3,
56         MMI::KeyEvent::KEYCODE_NUMPAD_4, MMI::KeyEvent::KEYCODE_NUMPAD_6, MMI::KeyEvent::KEYCODE_NUMPAD_7,
57         MMI::KeyEvent::KEYCODE_NUMPAD_8, MMI::KeyEvent::KEYCODE_NUMPAD_9};
58     const std::vector<int32_t> CTRL_SHIFT_KEYCODE_V = {
59         MMI::KeyEvent::KEYCODE_CTRL_LEFT, MMI::KeyEvent::KEYCODE_CTRL_RIGHT,
60         MMI::KeyEvent::KEYCODE_SHIFT_LEFT, MMI::KeyEvent::KEYCODE_SHIFT_RIGHT};
61     const std::map<int32_t, MouseMoveOffset> MOUSE_MOVE_OFFSET_M = {
62         {MMI::KeyEvent::KEYCODE_NUMPAD_1, {MOVE_LEFT_STEP, MOVE_DOWN_STEP}},
63         {MMI::KeyEvent::KEYCODE_NUMPAD_2, {0, MOVE_DOWN_STEP}},
64         {MMI::KeyEvent::KEYCODE_NUMPAD_3, {MOVE_RIGHT_STEP, MOVE_DOWN_STEP}},
65         {MMI::KeyEvent::KEYCODE_NUMPAD_4, {MOVE_LEFT_STEP, 0}},
66         {MMI::KeyEvent::KEYCODE_NUMPAD_6, {MOVE_RIGHT_STEP, 0}},
67         {MMI::KeyEvent::KEYCODE_NUMPAD_7, {MOVE_LEFT_STEP, MOVE_UP_STEP}},
68         {MMI::KeyEvent::KEYCODE_NUMPAD_8, {0, MOVE_UP_STEP}},
69         {MMI::KeyEvent::KEYCODE_NUMPAD_9, {MOVE_RIGHT_STEP, MOVE_UP_STEP}}};
70     const int32_t PRESSED_METAKEYS_TBL[ROW_COUNT][COLUMN_COUNT] = {
71         {MMI::KeyEvent::KEYCODE_UNKNOWN, MMI::KeyEvent::KEYCODE_UNKNOWN, NONE_KEY},
72         {MMI::KeyEvent::KEYCODE_UNKNOWN, MMI::KeyEvent::KEYCODE_CTRL_LEFT, CTRL_KEY},
73         {MMI::KeyEvent::KEYCODE_UNKNOWN, MMI::KeyEvent::KEYCODE_CTRL_RIGHT, CTRL_KEY},
74         {MMI::KeyEvent::KEYCODE_UNKNOWN, MMI::KeyEvent::KEYCODE_SHIFT_LEFT, SHIFT_KEY},
75         {MMI::KeyEvent::KEYCODE_UNKNOWN, MMI::KeyEvent::KEYCODE_SHIFT_RIGHT, SHIFT_KEY},
76 
77         {MMI::KeyEvent::KEYCODE_CTRL_LEFT, MMI::KeyEvent::KEYCODE_UNKNOWN, CTRL_KEY},
78         {MMI::KeyEvent::KEYCODE_CTRL_LEFT, MMI::KeyEvent::KEYCODE_CTRL_RIGHT, CTRL_KEY},
79         {MMI::KeyEvent::KEYCODE_CTRL_LEFT, MMI::KeyEvent::KEYCODE_SHIFT_LEFT, CTRL_SHIFT_KEY},
80         {MMI::KeyEvent::KEYCODE_CTRL_LEFT, MMI::KeyEvent::KEYCODE_SHIFT_RIGHT, CTRL_SHIFT_KEY},
81 
82         {MMI::KeyEvent::KEYCODE_CTRL_RIGHT, MMI::KeyEvent::KEYCODE_UNKNOWN, CTRL_KEY},
83         {MMI::KeyEvent::KEYCODE_CTRL_RIGHT, MMI::KeyEvent::KEYCODE_CTRL_LEFT, CTRL_KEY},
84         {MMI::KeyEvent::KEYCODE_CTRL_RIGHT, MMI::KeyEvent::KEYCODE_SHIFT_LEFT, CTRL_SHIFT_KEY},
85         {MMI::KeyEvent::KEYCODE_CTRL_RIGHT, MMI::KeyEvent::KEYCODE_SHIFT_RIGHT, CTRL_SHIFT_KEY},
86 
87         {MMI::KeyEvent::KEYCODE_SHIFT_LEFT, MMI::KeyEvent::KEYCODE_UNKNOWN, SHIFT_KEY},
88         {MMI::KeyEvent::KEYCODE_SHIFT_LEFT, MMI::KeyEvent::KEYCODE_CTRL_LEFT, CTRL_SHIFT_KEY},
89         {MMI::KeyEvent::KEYCODE_SHIFT_LEFT, MMI::KeyEvent::KEYCODE_CTRL_RIGHT, CTRL_SHIFT_KEY},
90         {MMI::KeyEvent::KEYCODE_SHIFT_LEFT, MMI::KeyEvent::KEYCODE_SHIFT_RIGHT, SHIFT_KEY},
91 
92         {MMI::KeyEvent::KEYCODE_SHIFT_RIGHT, MMI::KeyEvent::KEYCODE_UNKNOWN, SHIFT_KEY},
93         {MMI::KeyEvent::KEYCODE_SHIFT_RIGHT, MMI::KeyEvent::KEYCODE_CTRL_LEFT, CTRL_SHIFT_KEY},
94         {MMI::KeyEvent::KEYCODE_SHIFT_RIGHT, MMI::KeyEvent::KEYCODE_CTRL_RIGHT, CTRL_SHIFT_KEY},
95         {MMI::KeyEvent::KEYCODE_SHIFT_RIGHT, MMI::KeyEvent::KEYCODE_SHIFT_LEFT, SHIFT_KEY},
96     };
97 } // namespace
98 
OnPointerEvent(MMI::PointerEvent & event)99 bool AccessibilityMouseKey::OnPointerEvent(MMI::PointerEvent &event)
100 {
101     HILOG_DEBUG();
102 
103     int32_t sourceType = event.GetSourceType();
104     int32_t action = event.GetPointerAction();
105     std::vector<int32_t> pointers = event.GetPointerIds();
106     size_t pointerCount = pointers.size();
107     if ((sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE) &&
108         (action == MMI::PointerEvent::POINTER_ACTION_MOVE) &&
109         (pointerCount == ITEM_COUNT_1)) {
110         UpdateLastMouseEvent(event);
111     }
112     return false;
113 }
114 
OnKeyEvent(MMI::KeyEvent & event)115 bool AccessibilityMouseKey::OnKeyEvent(MMI::KeyEvent &event)
116 {
117     HILOG_DEBUG();
118 
119     int32_t actionKey = MMI::KeyEvent::KEYCODE_UNKNOWN;
120     int32_t metaKey1 = MMI::KeyEvent::KEYCODE_UNKNOWN;
121     int32_t metaKey2 = MMI::KeyEvent::KEYCODE_UNKNOWN;
122     std::vector<int32_t> pressedKeys = event.GetPressedKeys();
123     if (IsMouseKey(pressedKeys, actionKey, metaKey1, metaKey2)) {
124         return ExecuteMouseKey(actionKey, metaKey1, metaKey2);
125     }
126     return false;
127 }
128 
UpdateLastMouseEvent(const MMI::PointerEvent & event)129 void AccessibilityMouseKey::UpdateLastMouseEvent(const MMI::PointerEvent &event)
130 {
131     HILOG_DEBUG();
132 
133     lastMouseMoveEvent_ = std::make_shared<MMI::PointerEvent>(event);
134 }
135 
IsMouseKey(const std::vector<int32_t> & pressedKeys,int32_t & actionKey,int32_t & metaKey1,int32_t & metaKey2) const136 bool AccessibilityMouseKey::IsMouseKey(const std::vector<int32_t> &pressedKeys, int32_t &actionKey,
137     int32_t &metaKey1, int32_t &metaKey2) const
138 {
139     HILOG_DEBUG();
140 
141     size_t pressedKeyCount = pressedKeys.size();
142     if (pressedKeyCount == ITEM_COUNT_1) {
143         if (std::find(MOUSE_KEYCODE_V.begin(), MOUSE_KEYCODE_V.end(), pressedKeys[0]) != MOUSE_KEYCODE_V.end()) {
144             actionKey = pressedKeys[0];
145             return true;
146         }
147     } else if (pressedKeyCount == ITEM_COUNT_2) {
148         for (size_t i = 0; i < ITEM_COUNT_2; i++) {
149             if (std::find(MOUSE_MOVE_KEYCODE_V.begin(), MOUSE_MOVE_KEYCODE_V.end(), pressedKeys[i]) ==
150                 MOUSE_MOVE_KEYCODE_V.end()) {
151                 continue;
152             }
153             actionKey = pressedKeys[i];
154             size_t Index = (i + 1) % ITEM_COUNT_2;
155             if (std::find(CTRL_SHIFT_KEYCODE_V.begin(), CTRL_SHIFT_KEYCODE_V.end(), pressedKeys[Index]) !=
156                 CTRL_SHIFT_KEYCODE_V.end()) {
157                 metaKey1 = pressedKeys[Index];
158                 return true;
159             }
160         }
161     } else if (pressedKeyCount == ITEM_COUNT_3) {
162         for (size_t i = 0; i < ITEM_COUNT_3; i++) {
163             if (std::find(MOUSE_MOVE_KEYCODE_V.begin(), MOUSE_MOVE_KEYCODE_V.end(), pressedKeys[i]) ==
164                 MOUSE_MOVE_KEYCODE_V.end()) {
165                 continue;
166             }
167             actionKey = pressedKeys[i];
168             size_t Index1 = (i + 1) % ITEM_COUNT_3;
169             size_t Index2 = (i + 2) % ITEM_COUNT_3;
170             if ((std::find(CTRL_SHIFT_KEYCODE_V.begin(), CTRL_SHIFT_KEYCODE_V.end(), pressedKeys[Index1]) !=
171                 CTRL_SHIFT_KEYCODE_V.end()) &&
172                 (std::find(CTRL_SHIFT_KEYCODE_V.begin(), CTRL_SHIFT_KEYCODE_V.end(), pressedKeys[Index2]) !=
173                 CTRL_SHIFT_KEYCODE_V.end())) {
174                 metaKey1 = pressedKeys[Index1];
175                 metaKey2 = pressedKeys[Index2];
176                 return true;
177             }
178         }
179     }
180     return false;
181 }
182 
ParseMetaKey(int32_t metaKey1,int32_t metaKey2) const183 int32_t AccessibilityMouseKey::ParseMetaKey(int32_t metaKey1, int32_t metaKey2) const
184 {
185     HILOG_DEBUG();
186     for (int32_t i = 0; i < ROW_COUNT; i++) {
187         if ((metaKey1 == PRESSED_METAKEYS_TBL[i][0]) && (metaKey2 == PRESSED_METAKEYS_TBL[i][1])) {
188             return PRESSED_METAKEYS_TBL[i][COLUMN_COUNT - 1];
189         }
190     }
191     return INVALID_KEY;
192 }
193 
ExecuteMouseKey(int32_t actionKey,int32_t metaKey1,int32_t metaKey2)194 bool AccessibilityMouseKey::ExecuteMouseKey(int32_t actionKey, int32_t metaKey1, int32_t metaKey2)
195 {
196     HILOG_DEBUG("actionKey:%{public}d, metaKey1:%{public}d, metaKey2:%{public}d", actionKey, metaKey1, metaKey2);
197 
198     if ((actionKey == MMI::KeyEvent::KEYCODE_NUMPAD_1) ||
199         (actionKey == MMI::KeyEvent::KEYCODE_NUMPAD_2) ||
200         (actionKey == MMI::KeyEvent::KEYCODE_NUMPAD_3) ||
201         (actionKey == MMI::KeyEvent::KEYCODE_NUMPAD_4) ||
202         (actionKey == MMI::KeyEvent::KEYCODE_NUMPAD_6) ||
203         (actionKey == MMI::KeyEvent::KEYCODE_NUMPAD_7) ||
204         (actionKey == MMI::KeyEvent::KEYCODE_NUMPAD_8) ||
205         (actionKey == MMI::KeyEvent::KEYCODE_NUMPAD_9)) {
206         auto iter = MOUSE_MOVE_OFFSET_M.find(actionKey);
207         if (iter != MOUSE_MOVE_OFFSET_M.end()) {
208             int32_t offsetX = iter->second.offsetX;
209             int32_t offsetY = iter->second.offsetY;
210             int32_t result = ParseMetaKey(metaKey1, metaKey2);
211             if ((result == INVALID_KEY) || (result == CTRL_SHIFT_KEY)) {
212                 return false;
213             }
214             if (result == CTRL_KEY) {
215                 offsetX = static_cast<int32_t>(iter->second.offsetX * SPEED_UP_MULTIPLE);
216                 offsetY = static_cast<int32_t>(iter->second.offsetY * SPEED_UP_MULTIPLE);
217             } else if (result == SHIFT_KEY) {
218                 offsetX = static_cast<int32_t>(iter->second.offsetX * SLOW_DOWN_MULTIPLE);
219                 offsetY = static_cast<int32_t>(iter->second.offsetY * SLOW_DOWN_MULTIPLE);
220             }
221             MoveMousePointer(offsetX, offsetY);
222         }
223     } else if (actionKey == MMI::KeyEvent::KEYCODE_NUMPAD_5) {
224         SendMouseClickEvent(SINGLE_CLICK);
225     } else if (actionKey == MMI::KeyEvent::KEYCODE_NUMPAD_DIVIDE) {
226         selectedKeyType_ = LEFT_KEY;
227     } else if (actionKey == MMI::KeyEvent::KEYCODE_NUMPAD_MULTIPLY) {
228         selectedKeyType_ = BOOTH_KEY;
229     } else if (actionKey == MMI::KeyEvent::KEYCODE_NUMPAD_SUBTRACT) {
230         selectedKeyType_ = RIGHT_KEY;
231     } else if (actionKey == MMI::KeyEvent::KEYCODE_NUMPAD_ADD) {
232         SendMouseClickEvent(DOUBLE_CLICK);
233     }
234     return true;
235 }
236 
MoveMousePointer(int32_t offsetX,int32_t offsetY)237 void AccessibilityMouseKey::MoveMousePointer(int32_t offsetX, int32_t offsetY)
238 {
239     HILOG_DEBUG("offsetX:%{public}d, offsetY:%{public}d", offsetX, offsetY);
240 
241     EventTransmission::OnMoveMouse(offsetX, offsetY);
242 }
243 
SendMouseClickEvent(CLICK_TYPE clickType)244 void AccessibilityMouseKey::SendMouseClickEvent(CLICK_TYPE clickType)
245 {
246     HILOG_DEBUG();
247 
248     if (!lastMouseMoveEvent_) {
249         HILOG_DEBUG("No mouse event to be sent.");
250         return;
251     }
252 
253     int64_t nowTime = GetSystemTime();
254     // Update event information.
255     lastMouseMoveEvent_->SetActionTime(nowTime);
256     lastMouseMoveEvent_->SetActionStartTime(nowTime);
257 
258     // Update pointer item information.
259     int32_t pointerId = lastMouseMoveEvent_->GetPointerId();
260     MMI::PointerEvent::PointerItem item;
261     lastMouseMoveEvent_->GetPointerItem(pointerId, item);
262     item.SetDownTime(nowTime);
263     item.SetPressed(true);
264     lastMouseMoveEvent_->UpdatePointerItem(pointerId, item);
265 
266     for (uint32_t clickCount = 0; clickCount < clickType; clickCount ++) {
267         HILOG_DEBUG("selectedKeyType:%{public}u", selectedKeyType_);
268         if (selectedKeyType_ == LEFT_KEY) {
269             PerformMouseAction(MMI::PointerEvent::MOUSE_BUTTON_LEFT, MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN);
270             PerformMouseAction(MMI::PointerEvent::MOUSE_BUTTON_LEFT, MMI::PointerEvent::POINTER_ACTION_BUTTON_UP);
271         } else if (selectedKeyType_ == RIGHT_KEY) {
272             PerformMouseAction(MMI::PointerEvent::MOUSE_BUTTON_RIGHT, MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN);
273             PerformMouseAction(MMI::PointerEvent::MOUSE_BUTTON_RIGHT, MMI::PointerEvent::POINTER_ACTION_BUTTON_UP);
274         } else if (selectedKeyType_ == BOOTH_KEY) {
275             PerformMouseAction(MMI::PointerEvent::MOUSE_BUTTON_LEFT, MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN);
276             PerformMouseAction(MMI::PointerEvent::MOUSE_BUTTON_RIGHT, MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN);
277 
278             PerformMouseAction(MMI::PointerEvent::MOUSE_BUTTON_LEFT, MMI::PointerEvent::POINTER_ACTION_BUTTON_UP);
279             PerformMouseAction(MMI::PointerEvent::MOUSE_BUTTON_RIGHT, MMI::PointerEvent::POINTER_ACTION_BUTTON_UP);
280         }
281     }
282 }
283 
PerformMouseAction(int32_t buttonId,int32_t actionType)284 void AccessibilityMouseKey::PerformMouseAction(int32_t buttonId, int32_t actionType)
285 {
286     HILOG_DEBUG();
287 
288     if (!lastMouseMoveEvent_) {
289         HILOG_DEBUG("No mouse event to be sent.");
290         return;
291     }
292     lastMouseMoveEvent_->SetButtonId(buttonId);
293     lastMouseMoveEvent_->SetButtonPressed(buttonId);
294     lastMouseMoveEvent_->SetPointerAction(actionType);
295     EventTransmission::OnPointerEvent(*lastMouseMoveEvent_);
296 }
297 
GetSystemTime() const298 int64_t AccessibilityMouseKey::GetSystemTime() const
299 {
300     HILOG_DEBUG();
301 
302     int64_t microsecond = Utils::GetSystemTime() * 1000;
303     return microsecond;
304 }
305 } // namespace Accessibility
306 } // namespace OHOS