1 /*
2 * Copyright (c) 2023 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 "adapter/preview/entrance/samples/event_adapter.h"
17
18 #include <GLFW/glfw3.h>
19 #include <map>
20 #include <memory>
21
22 #include "base/utils/utils.h"
23 #include "frameworks/base/log/log.h"
24
25 namespace OHOS::Ace::Sample {
26
27 namespace {
28 const std::map<int, KeyAction> ACTION_MAP = {
29 { GLFW_RELEASE, KeyAction::UP },
30 { GLFW_PRESS, KeyAction::DOWN },
31 { GLFW_REPEAT, KeyAction::LONG_PRESS },
32 };
33
34 const std::map<int, KeyCode> CODE_MAP = {
35 { GLFW_KEY_BACKSPACE, KeyCode::KEY_FORWARD_DEL },
36 { GLFW_KEY_DELETE, KeyCode::KEY_DEL },
37 { GLFW_KEY_ESCAPE, KeyCode::KEY_ESCAPE },
38 { GLFW_KEY_ENTER, KeyCode::KEY_ENTER },
39 { GLFW_KEY_CAPS_LOCK, KeyCode::KEY_CAPS_LOCK },
40 { GLFW_KEY_UP, KeyCode::KEY_DPAD_UP },
41 { GLFW_KEY_DOWN, KeyCode::KEY_DPAD_DOWN },
42 { GLFW_KEY_LEFT, KeyCode::KEY_DPAD_LEFT },
43 { GLFW_KEY_RIGHT, KeyCode::KEY_DPAD_RIGHT },
44 { GLFW_KEY_GRAVE_ACCENT, KeyCode::KEY_GRAVE },
45 { GLFW_KEY_MINUS, KeyCode::KEY_MINUS },
46 { GLFW_KEY_EQUAL, KeyCode::KEY_EQUALS },
47 { GLFW_KEY_TAB, KeyCode::KEY_TAB },
48 { GLFW_KEY_LEFT_BRACKET, KeyCode::KEY_LEFT_BRACKET },
49 { GLFW_KEY_RIGHT_BRACKET, KeyCode::KEY_RIGHT_BRACKET },
50 { GLFW_KEY_BACKSLASH, KeyCode::KEY_BACKSLASH },
51 { GLFW_KEY_SEMICOLON, KeyCode::KEY_SEMICOLON },
52 { GLFW_KEY_APOSTROPHE, KeyCode::KEY_APOSTROPHE },
53 { GLFW_KEY_COMMA, KeyCode::KEY_COMMA },
54 { GLFW_KEY_PERIOD, KeyCode::KEY_PERIOD },
55 { GLFW_KEY_SLASH, KeyCode::KEY_SLASH },
56 { GLFW_KEY_SPACE, KeyCode::KEY_SPACE },
57 { GLFW_KEY_KP_DIVIDE, KeyCode::KEY_NUMPAD_DIVIDE },
58 { GLFW_KEY_KP_MULTIPLY, KeyCode::KEY_NUMPAD_MULTIPLY },
59 { GLFW_KEY_KP_SUBTRACT, KeyCode::KEY_NUMPAD_SUBTRACT },
60 { GLFW_KEY_KP_ADD, KeyCode::KEY_NUMPAD_ADD },
61 { GLFW_KEY_KP_ENTER, KeyCode::KEY_NUMPAD_ENTER },
62 { GLFW_KEY_KP_EQUAL, KeyCode::KEY_NUMPAD_EQUALS },
63 { GLFW_KEY_NUM_LOCK, KeyCode::KEY_NUM_LOCK },
64 };
65 } // namespace
66
EventAdapter()67 EventAdapter::EventAdapter()
68 {
69 keyEvent_ = std::make_shared<KeyEvent>();
70 pointerEvent_ = std::make_shared<PointerEvent>();
71 }
72
73 EventAdapter::~EventAdapter() = default;
74
Initialize(std::shared_ptr<GlfwRenderContext> & glfwRenderContext)75 void EventAdapter::Initialize(std::shared_ptr<GlfwRenderContext>& glfwRenderContext)
76 {
77 // keyboard callback
78 auto&& keyboardCbk = [this](int key, int scancode, int action, int mods) {
79 if (RunSpecialOperations(key, action, mods)) {
80 return;
81 }
82 if (keyEventCallback_ && RecognizeKeyEvent(key, action, mods)) {
83 keyEventCallback_(keyEvent_);
84 } else {
85 LOGW("Unrecognized key type.");
86 }
87 };
88 glfwRenderContext->OnKey(keyboardCbk);
89
90 // mouse button callback
91 auto&& mouseButtonCbk = [this](int button, bool pressed, int mods) {
92 {
93 std::lock_guard lock(mouseMutex_);
94 isMousePressed_ = pressed;
95 }
96 if (pointerEventCallback_) {
97 RecognizePointerEvent(pressed ? TouchType::DOWN : TouchType::UP);
98 pointerEventCallback_(pointerEvent_);
99 }
100 };
101 glfwRenderContext->OnMouseButton(mouseButtonCbk);
102
103 // cursor position callback
104 auto&& cursorPosCbk = [this](double x, double y) {
105 {
106 std::lock_guard lock(mouseMutex_);
107 posX_ = x;
108 posY_ = y;
109 }
110 if (isMousePressed_ && pointerEventCallback_) {
111 RecognizePointerEvent(TouchType::MOVE);
112 pointerEventCallback_(pointerEvent_);
113 }
114 };
115 glfwRenderContext->OnCursorPos(cursorPosCbk);
116 }
117
RegisterKeyEventCallback(MMIKeyEventCallback && callback)118 void EventAdapter::RegisterKeyEventCallback(MMIKeyEventCallback&& callback)
119 {
120 keyEventCallback_ = std::move(callback);
121 }
122
RegisterPointerEventCallback(MMIPointerEventCallback && callback)123 void EventAdapter::RegisterPointerEventCallback(MMIPointerEventCallback&& callback)
124 {
125 pointerEventCallback_ = std::move(callback);
126 }
127
RegisterInspectorCallback(InspectorCallback && callback)128 void EventAdapter::RegisterInspectorCallback(InspectorCallback&& callback)
129 {
130 inspectorCallback_ = std::move(callback);
131 }
132
RecognizeKeyEvent(int key,int action,int mods)133 bool EventAdapter::RecognizeKeyEvent(int key, int action, int mods)
134 {
135 auto iterAction = ACTION_MAP.find(action);
136 if (iterAction == ACTION_MAP.end()) {
137 return false;
138 }
139 keyEvent_->action = iterAction->second;
140
141 keyEvent_->pressedCodes.clear();
142 if (mods & GLFW_MOD_CONTROL) {
143 keyEvent_->pressedCodes.push_back(KeyCode::KEY_CTRL_LEFT);
144 }
145 if (mods & GLFW_MOD_SUPER) {
146 keyEvent_->pressedCodes.push_back(KeyCode::KEY_META_LEFT);
147 }
148 if (mods & GLFW_MOD_SHIFT) {
149 keyEvent_->pressedCodes.push_back(KeyCode::KEY_SHIFT_LEFT);
150 }
151 if (mods & GLFW_MOD_ALT) {
152 keyEvent_->pressedCodes.push_back(KeyCode::KEY_ALT_LEFT);
153 }
154
155 auto iterCode = CODE_MAP.find(key);
156 if (iterCode == CODE_MAP.end() && !(key >= GLFW_KEY_A && key <= GLFW_KEY_Z) &&
157 !(key >= GLFW_KEY_0 && key <= GLFW_KEY_9) && !(key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_9)) {
158 return false;
159 }
160 if (iterCode != CODE_MAP.end()) {
161 keyEvent_->code = iterCode->second;
162 }
163 if (key >= GLFW_KEY_A && key <= GLFW_KEY_Z) {
164 keyEvent_->code = static_cast<KeyCode>(static_cast<int32_t>(KeyCode::KEY_A) + key - GLFW_KEY_A);
165 }
166 if (key >= GLFW_KEY_0 && key <= GLFW_KEY_9) {
167 keyEvent_->code = static_cast<KeyCode>(static_cast<int32_t>(KeyCode::KEY_0) + key - GLFW_KEY_0);
168 }
169 if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_9) {
170 keyEvent_->code = static_cast<KeyCode>(static_cast<int32_t>(KeyCode::KEY_0) + key - GLFW_KEY_KP_0);
171 }
172 keyEvent_->key = "Test";
173 keyEvent_->pressedCodes.push_back(keyEvent_->code);
174
175 return true;
176 }
177
RecognizePointerEvent(const TouchType type)178 void EventAdapter::RecognizePointerEvent(const TouchType type)
179 {
180 std::lock_guard lock(mouseMutex_);
181 pointerEvent_->id = 1;
182 pointerEvent_->x = posX_;
183 pointerEvent_->y = posY_;
184 pointerEvent_->screenX = 0;
185 pointerEvent_->screenY = 0;
186 pointerEvent_->type = type;
187 pointerEvent_->time = std::chrono::high_resolution_clock::now();
188 pointerEvent_->size = sizeof(PointerEvent);
189 pointerEvent_->force = 0;
190 pointerEvent_->deviceId = 0;
191 pointerEvent_->sourceType = static_cast<int32_t>(OHOS::MMI::SourceType::TOUCH);
192 pointerEvent_->pointers = {};
193 }
194
RunSpecialOperations(int key,int action,int mods)195 bool EventAdapter::RunSpecialOperations(int key, int action, int mods)
196 {
197 // Add specific operations which driven by some special shortcut keys.
198 if (inspectorCallback_ && (action == GLFW_PRESS) && (mods & GLFW_MOD_CONTROL) && (key == GLFW_KEY_I)) {
199 inspectorCallback_();
200 return true;
201 }
202 return false;
203 }
204
205 } // namespace OHOS::Ace::Sample
206