• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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