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