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 20namespace OHOS { 21namespace Accessibility { 22struct MouseMoveOffset { 23 int32_t offsetX = 0; 24 int32_t offsetY = 0; 25}; 26namespace { 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 99bool 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 115bool 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 129void AccessibilityMouseKey::UpdateLastMouseEvent(const MMI::PointerEvent &event) 130{ 131 HILOG_DEBUG(); 132 133 lastMouseMoveEvent_ = std::make_shared<MMI::PointerEvent>(event); 134} 135 136bool 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 183int32_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 194bool 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 237void 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 244void 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 284void 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 298int64_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