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 LOGI("Some special shortcut keys are intercepted for performing specific operations.");
81 return;
82 }
83 if (keyEventCallback_ && RecognizeKeyEvent(key, action, mods)) {
84 keyEventCallback_(keyEvent_);
85 } else {
86 LOGW("Unrecognized key type.");
87 }
88 };
89 glfwRenderContext->OnKey(keyboardCbk);
90
91 // mouse button callback
92 auto&& mouseButtonCbk = [this](int button, bool pressed, int mods) {
93 {
94 std::lock_guard lock(mouseMutex_);
95 isMousePressed_ = pressed;
96 }
97 if (pointerEventCallback_) {
98 RecognizePointerEvent(pressed ? TouchType::DOWN : TouchType::UP);
99 pointerEventCallback_(pointerEvent_);
100 }
101 };
102 glfwRenderContext->OnMouseButton(mouseButtonCbk);
103
104 // cursor position callback
105 auto&& cursorPosCbk = [this](double x, double y) {
106 {
107 std::lock_guard lock(mouseMutex_);
108 posX_ = x;
109 posY_ = y;
110 }
111 if (isMousePressed_ && pointerEventCallback_) {
112 RecognizePointerEvent(TouchType::MOVE);
113 pointerEventCallback_(pointerEvent_);
114 }
115 };
116 glfwRenderContext->OnCursorPos(cursorPosCbk);
117 }
118
RegisterKeyEventCallback(MMIKeyEventCallback && callback)119 void EventAdapter::RegisterKeyEventCallback(MMIKeyEventCallback&& callback)
120 {
121 keyEventCallback_ = std::move(callback);
122 }
123
RegisterPointerEventCallback(MMIPointerEventCallback && callback)124 void EventAdapter::RegisterPointerEventCallback(MMIPointerEventCallback&& callback)
125 {
126 pointerEventCallback_ = std::move(callback);
127 }
128
RegisterInspectorCallback(InspectorCallback && callback)129 void EventAdapter::RegisterInspectorCallback(InspectorCallback&& callback)
130 {
131 inspectorCallback_ = std::move(callback);
132 }
133
RecognizeKeyEvent(int key,int action,int mods)134 bool EventAdapter::RecognizeKeyEvent(int key, int action, int mods)
135 {
136 auto iterAction = ACTION_MAP.find(action);
137 if (iterAction == ACTION_MAP.end()) {
138 return false;
139 }
140 keyEvent_->action = iterAction->second;
141
142 keyEvent_->pressedCodes.clear();
143 if (mods & GLFW_MOD_CONTROL) {
144 keyEvent_->pressedCodes.push_back(KeyCode::KEY_CTRL_LEFT);
145 }
146 if (mods & GLFW_MOD_SUPER) {
147 keyEvent_->pressedCodes.push_back(KeyCode::KEY_META_LEFT);
148 }
149 if (mods & GLFW_MOD_SHIFT) {
150 keyEvent_->pressedCodes.push_back(KeyCode::KEY_SHIFT_LEFT);
151 }
152 if (mods & GLFW_MOD_ALT) {
153 keyEvent_->pressedCodes.push_back(KeyCode::KEY_ALT_LEFT);
154 }
155
156 auto iterCode = CODE_MAP.find(key);
157 if (iterCode == CODE_MAP.end() && !(key >= GLFW_KEY_A && key <= GLFW_KEY_Z) &&
158 !(key >= GLFW_KEY_0 && key <= GLFW_KEY_9) && !(key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_9)) {
159 return false;
160 }
161 if (iterCode != CODE_MAP.end()) {
162 keyEvent_->code = iterCode->second;
163 }
164 if (key >= GLFW_KEY_A && key <= GLFW_KEY_Z) {
165 keyEvent_->code = static_cast<KeyCode>(static_cast<int32_t>(KeyCode::KEY_A) + key - GLFW_KEY_A);
166 }
167 if (key >= GLFW_KEY_0 && key <= GLFW_KEY_9) {
168 keyEvent_->code = static_cast<KeyCode>(static_cast<int32_t>(KeyCode::KEY_0) + key - GLFW_KEY_0);
169 }
170 if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_9) {
171 keyEvent_->code = static_cast<KeyCode>(static_cast<int32_t>(KeyCode::KEY_0) + key - GLFW_KEY_KP_0);
172 }
173 keyEvent_->key = "Test";
174 keyEvent_->pressedCodes.push_back(keyEvent_->code);
175
176 return true;
177 }
178
RecognizePointerEvent(const TouchType type)179 void EventAdapter::RecognizePointerEvent(const TouchType type)
180 {
181 std::lock_guard lock(mouseMutex_);
182 pointerEvent_->id = 1;
183 pointerEvent_->x = posX_;
184 pointerEvent_->y = posY_;
185 pointerEvent_->screenX = 0;
186 pointerEvent_->screenY = 0;
187 pointerEvent_->type = type;
188 pointerEvent_->time = std::chrono::high_resolution_clock::now();
189 pointerEvent_->size = sizeof(PointerEvent);
190 pointerEvent_->force = 0;
191 pointerEvent_->deviceId = 0;
192 pointerEvent_->sourceType = SourceType::TOUCH;
193 pointerEvent_->pointers = {};
194 }
195
RunSpecialOperations(int key,int action,int mods)196 bool EventAdapter::RunSpecialOperations(int key, int action, int mods)
197 {
198 // Add specific operations which driven by some special shortcut keys.
199 if (inspectorCallback_ && (action == GLFW_PRESS) && (mods & GLFW_MOD_CONTROL) && (key == GLFW_KEY_I)) {
200 inspectorCallback_();
201 return true;
202 }
203 return false;
204 }
205
206 } // namespace OHOS::Ace::Sample
207