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