1 /*
2 * Copyright (c) 2022-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/key_input_handler.h"
17
18 #include <map>
19 #include "base/log/log.h"
20 #include "core/common/clipboard/clipboard_proxy.h"
21 #include "adapter/preview/entrance/clipboard/clipboard_impl.h"
22 #include "adapter/preview/entrance/clipboard/clipboard_proxy_impl.h"
23 #include "adapter/preview/entrance/event_dispatcher.h"
24
25 namespace OHOS::Ace::Platform {
26 namespace {
27
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
66 }
67
68 #ifndef ENABLE_ROSEN_BACKEND
InitialTextInputCallback(FlutterDesktopWindowControllerRef controller)69 void KeyInputHandler::InitialTextInputCallback(FlutterDesktopWindowControllerRef controller)
70 {
71 // Register clipboard callback functions.
72 auto callbackSetClipboardData = [controller](const std::string& data) {
73 FlutterDesktopSetClipboardData(controller, data.c_str());
74 };
75 auto callbackGetClipboardData = [controller]() {
76 return FlutterDesktopGetClipboardData(controller);
77 };
78 ClipboardProxy::GetInstance()->SetDelegate(
79 std::make_unique<ClipboardProxyImpl>(callbackSetClipboardData, callbackGetClipboardData));
80 // Register key event and input method callback functions.
81 FlutterDesktopAddKeyboardHookHandler(controller, std::make_unique<KeyInputHandler>());
82 }
83 #else
InitialTextInputCallback(const std::shared_ptr<OHOS::Rosen::GlfwRenderContext> & controller)84 void KeyInputHandler::InitialTextInputCallback(const std::shared_ptr<OHOS::Rosen::GlfwRenderContext> &controller)
85 {
86 // clipboard
87 auto callbackSetClipboardData = [controller](const std::string& data) {
88 controller->SetClipboardData(data);
89 };
90 auto callbackGetClipboardData = [controller]() {
91 return controller->GetClipboardData();
92 };
93 ClipboardProxy::GetInstance()->SetDelegate(
94 std::make_unique<ClipboardProxyImpl>(callbackSetClipboardData, callbackGetClipboardData));
95
96 // key: key_event(normal, modifier), char: unicode char input
97 controller->OnKey([](int key, int scancode, int action, int mods) {
98 KeyboardHook(nullptr, key, scancode, action, mods);
99 });
100 controller->OnChar([](unsigned int codepoint) {
101 CharHook(nullptr, codepoint);
102 });
103 }
104 #endif
105
KeyboardHook(GLFWwindow * window,int key,int scancode,int action,int mods)106 void KeyInputHandler::KeyboardHook(GLFWwindow* window, int key, int scancode, int action, int mods)
107 {
108 if (RecognizeKeyEvent(key, action, mods)) {
109 EventDispatcher::GetInstance().DispatchKeyEvent(keyEvent_);
110 } else {
111 LOGW("Unrecognized key type.");
112 }
113 }
114
CharHook(GLFWwindow * window,unsigned int code_point)115 void KeyInputHandler::CharHook(GLFWwindow* window, unsigned int code_point)
116 {
117 EventDispatcher::GetInstance().DispatchInputMethodEvent(code_point);
118 }
119
RecognizeKeyEvent(int key,int action,int mods)120 bool KeyInputHandler::RecognizeKeyEvent(int key, int action, int mods)
121 {
122 auto iterAction = ACTION_MAP.find(action);
123 if (iterAction == ACTION_MAP.end()) {
124 return false;
125 }
126 keyEvent_.action = iterAction->second;
127
128 keyEvent_.pressedCodes.clear();
129 if (mods & GLFW_MOD_CONTROL) {
130 keyEvent_.pressedCodes.push_back(KeyCode::KEY_CTRL_LEFT);
131 }
132 if (mods & GLFW_MOD_SUPER) {
133 keyEvent_.pressedCodes.push_back(KeyCode::KEY_META_LEFT);
134 }
135 if (mods & GLFW_MOD_SHIFT) {
136 keyEvent_.pressedCodes.push_back(KeyCode::KEY_SHIFT_LEFT);
137 }
138 if (mods & GLFW_MOD_ALT) {
139 keyEvent_.pressedCodes.push_back(KeyCode::KEY_ALT_LEFT);
140 }
141
142 auto iterCode = CODE_MAP.find(key);
143 if (iterCode == CODE_MAP.end() && !(key >= GLFW_KEY_A && key <= GLFW_KEY_Z) &&
144 !(key >= GLFW_KEY_0 && key <= GLFW_KEY_9) && !(key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_9)) {
145 return false;
146 }
147 if (iterCode != CODE_MAP.end()) {
148 keyEvent_.code = iterCode->second;
149 }
150 if (key >= GLFW_KEY_A && key <= GLFW_KEY_Z) {
151 keyEvent_.code = static_cast<KeyCode>(static_cast<int32_t>(KeyCode::KEY_A) + key - GLFW_KEY_A);
152 }
153 if (key >= GLFW_KEY_0 && key <= GLFW_KEY_9) {
154 keyEvent_.code = static_cast<KeyCode>(static_cast<int32_t>(KeyCode::KEY_0) + key - GLFW_KEY_0);
155 }
156 if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_9) {
157 keyEvent_.code = static_cast<KeyCode>(static_cast<int32_t>(KeyCode::KEY_0) + key - GLFW_KEY_KP_0);
158 }
159
160 keyEvent_.key = KeyToString(static_cast<int32_t>(keyEvent_.code));
161 keyEvent_.pressedCodes.push_back(keyEvent_.code);
162
163 return true;
164 }
165
166 } // namespace OHOS::Ace::Platform
167