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 "core/common/ime/text_input_client.h"
17
18 #include "core/pipeline_ng/pipeline_context.h"
19
20 namespace OHOS::Ace {
21 namespace {
22 using tic = TextInputClient; // give it a shorter name to maintain a good code layout
23 }
24
25 // Here declares function keys which can be handled by TextInputClient.
26 std::map<KeyComb, std::function<bool(TextInputClient*)>> TextInputClient::functionKeys_ = {
27 { KeyComb(KeyCode::KEY_ESCAPE), &tic::HandleOnEscape },
__anon5f7860540202() 28 { KeyComb(KeyCode::KEY_TAB), [](tic* c) -> bool { return c->HandleOnTab(false); } },
__anon5f7860540302() 29 { KeyComb(KeyCode::KEY_TAB, KEY_SHIFT), [](tic* c) -> bool { return c->HandleOnTab(true); } },
30 };
31
32 // Here declares keyboard shortcuts which should be handled and consumed by TextInputClient.
33 std::map<KeyComb, std::function<void(TextInputClient*)>> TextInputClient::keyboardShortCuts_ = {
34 // actions
35 #if defined(MAC_PLATFORM)
36 { KeyComb(KeyCode::KEY_A, KEY_META), &tic::HandleOnSelectAll },
__anon5f7860540402() 37 { KeyComb(KeyCode::KEY_C, KEY_META), [](tic* c) -> void { c->HandleOnCopy(true); } },
__anon5f7860540502() 38 { KeyComb(KeyCode::KEY_D, KEY_META), [](tic* c) -> void { c->HandleOnDelete(true); } },
39 { KeyComb(KeyCode::KEY_V, KEY_META), &tic::HandleOnPaste },
40 { KeyComb(KeyCode::KEY_X, KEY_META), &tic::HandleOnCut },
41 { KeyComb(KeyCode::KEY_Y, KEY_META), &tic::HandleOnRedoAction },
42 { KeyComb(KeyCode::KEY_Z, KEY_META), &tic::HandleOnUndoAction },
43 { KeyComb(KeyCode::KEY_Z, KEY_META | KEY_SHIFT), &tic::HandleOnRedoAction },
44 #else
45 { KeyComb(KeyCode::KEY_A, KEY_CTRL), &tic::HandleOnSelectAll },
46 { KeyComb(KeyCode::KEY_C, KEY_CTRL), [](tic* c) -> void { c->HandleOnCopy(true); } },
47 { KeyComb(KeyCode::KEY_D, KEY_CTRL), [](tic* c) -> void { c->HandleOnDelete(true); } },
48 { KeyComb(KeyCode::KEY_V, KEY_CTRL), &tic::HandleOnPaste },
49 { KeyComb(KeyCode::KEY_X, KEY_CTRL), &tic::HandleOnCut },
50 { KeyComb(KeyCode::KEY_Y, KEY_CTRL), &tic::HandleOnRedoAction },
51 { KeyComb(KeyCode::KEY_Z, KEY_CTRL), &tic::HandleOnUndoAction },
52 { KeyComb(KeyCode::KEY_Z, KEY_CTRL | KEY_SHIFT), &tic::HandleOnRedoAction },
53 #endif
__anon5f7860540602() 54 { KeyComb(KeyCode::KEY_DEL), [](tic* c) -> void { c->HandleOnDelete(true); } },
__anon5f7860540702() 55 { KeyComb(KeyCode::KEY_FORWARD_DEL), [](tic* c) -> void { c->HandleOnDelete(false); } },
__anon5f7860540802() 56 { KeyComb(KeyCode::KEY_DEL, KEY_CTRL), [](tic* c) -> void { c->HandleOnDeleteComb(true); } },
__anon5f7860540902() 57 { KeyComb(KeyCode::KEY_FORWARD_DEL, KEY_CTRL), [](tic* c) -> void { c->HandleOnDeleteComb(false); } },
__anon5f7860540a02() 58 { KeyComb(KeyCode::KEY_INSERT, KEY_CTRL), [](tic* c) -> void { c->HandleOnCopy(true); } },
59 { KeyComb(KeyCode::KEY_INSERT, KEY_SHIFT), &tic::HandleOnPaste },
60 { KeyComb(KeyCode::KEY_PASTE), &tic::HandleOnPaste },
61 { KeyComb(KeyCode::KEY_F10, KEY_SHIFT), &tic::HandleOnShowMenu },
62 { KeyComb(KeyCode::KEY_MENU), &tic::HandleOnShowMenu },
63 { KeyComb(KeyCode::KEY_ENTER), &tic::HandleOnEnter },
64 { KeyComb(KeyCode::KEY_NUMPAD_ENTER), &tic::HandleOnEnter },
65 { KeyComb(KeyCode::KEY_DPAD_CENTER), &tic::HandleOnEnter },
66 { KeyComb(KeyCode::KEY_ENTER, KEY_CTRL), &tic::HandleOnEnter },
67 { KeyComb(KeyCode::KEY_NUMPAD_ENTER, KEY_CTRL), &tic::HandleOnEnter },
68 { KeyComb(KeyCode::KEY_DPAD_CENTER, KEY_CTRL), &tic::HandleOnEnter },
69 { KeyComb(KeyCode::KEY_PAGE_UP), &tic::HandleOnPageUp },
70 { KeyComb(KeyCode::KEY_PAGE_DOWN), &tic::HandleOnPageDown },
71 // caret move keys
__anon5f7860540b02() 72 { KeyComb(KeyCode::KEY_DPAD_LEFT), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::Left); } },
__anon5f7860540c02() 73 { KeyComb(KeyCode::KEY_DPAD_RIGHT), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::Right); } },
__anon5f7860540d02() 74 { KeyComb(KeyCode::KEY_DPAD_UP), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::Up); } },
__anon5f7860540e02() 75 { KeyComb(KeyCode::KEY_DPAD_DOWN), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::Down); } },
__anon5f7860540f02() 76 { KeyComb(KeyCode::KEY_MOVE_HOME), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::LineBegin); } },
__anon5f7860541002() 77 { KeyComb(KeyCode::KEY_MOVE_END), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::LineEnd); } },
__anon5f7860541102() 78 { KeyComb(KeyCode::KEY_DPAD_LEFT, KEY_CTRL), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::LeftWord); } },
__anon5f7860541202() 79 { KeyComb(KeyCode::KEY_DPAD_RIGHT, KEY_CTRL), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::RightWord); } },
__anon5f7860541302() 80 { KeyComb(KeyCode::KEY_DPAD_UP, KEY_CTRL), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::ParagraghBegin); } },
__anon5f7860541402() 81 { KeyComb(KeyCode::KEY_DPAD_DOWN, KEY_CTRL), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::ParagraghEnd); } },
__anon5f7860541502() 82 { KeyComb(KeyCode::KEY_MOVE_HOME, KEY_CTRL), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::Home); } },
__anon5f7860541602() 83 { KeyComb(KeyCode::KEY_MOVE_END, KEY_CTRL), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::End); } },
84 // select key combinations
__anon5f7860541702() 85 { KeyComb(KeyCode::KEY_DPAD_LEFT, KEY_SHIFT), [](tic* c) -> void { c->HandleSelect(CaretMoveIntent::Left); } },
__anon5f7860541802() 86 { KeyComb(KeyCode::KEY_DPAD_RIGHT, KEY_SHIFT), [](tic* c) -> void { c->HandleSelect(CaretMoveIntent::Right); } },
__anon5f7860541902() 87 { KeyComb(KeyCode::KEY_DPAD_UP, KEY_SHIFT), [](tic* c) -> void { c->HandleSelect(CaretMoveIntent::Up); } },
__anon5f7860541a02() 88 { KeyComb(KeyCode::KEY_DPAD_DOWN, KEY_SHIFT), [](tic* c) -> void { c->HandleSelect(CaretMoveIntent::Down); } },
__anon5f7860541b02() 89 { KeyComb(KeyCode::KEY_MOVE_HOME, KEY_SHIFT), [](tic* c) -> void { c->HandleSelect(CaretMoveIntent::LineBegin); } },
__anon5f7860541c02() 90 { KeyComb(KeyCode::KEY_MOVE_END, KEY_SHIFT), [](tic* c) -> void { c->HandleSelect(CaretMoveIntent::LineEnd); } },
91 { KeyComb(KeyCode::KEY_DPAD_LEFT, KEY_CTRL | KEY_SHIFT),
__anon5f7860541d02() 92 [](tic* c) -> void { c->HandleSelect(CaretMoveIntent::LeftWord); } },
93 { KeyComb(KeyCode::KEY_DPAD_RIGHT, KEY_CTRL | KEY_SHIFT),
__anon5f7860541e02() 94 [](tic* c) -> void { c->HandleSelect(CaretMoveIntent::RightWord); } },
95 { KeyComb(KeyCode::KEY_DPAD_UP, KEY_CTRL | KEY_SHIFT),
__anon5f7860541f02() 96 [](tic* c) -> void { c->CursorMove(CaretMoveIntent::ParagraghBegin); } },
97 { KeyComb(KeyCode::KEY_DPAD_DOWN, KEY_CTRL | KEY_SHIFT),
__anon5f7860542002() 98 [](tic* c) -> void { c->CursorMove(CaretMoveIntent::ParagraghEnd); } },
99 { KeyComb(KeyCode::KEY_MOVE_HOME, KEY_CTRL | KEY_SHIFT),
__anon5f7860542102() 100 [](tic* c) -> void { c->CursorMove(CaretMoveIntent::Home); } },
101 { KeyComb(KeyCode::KEY_MOVE_END, KEY_CTRL | KEY_SHIFT),
__anon5f7860542202() 102 [](tic* c) -> void { c->CursorMove(CaretMoveIntent::End); } },
__anon5f7860542302() 103 { KeyComb(KeyCode::KEY_B, KEY_CTRL), [](tic* c) -> void { c->HandleSelectFontStyle(KeyCode::KEY_B); } },
__anon5f7860542402() 104 { KeyComb(KeyCode::KEY_I, KEY_CTRL), [](tic* c) -> void { c->HandleSelectFontStyle(KeyCode::KEY_I); } },
__anon5f7860542502() 105 { KeyComb(KeyCode::KEY_U, KEY_CTRL), [](tic* c) -> void { c->HandleSelectFontStyle(KeyCode::KEY_U); } },
106 // when numLock off, KEY_NUMPAD_0 perform as KEY_INSERT
__anon5f7860542602() 107 { KeyComb(KeyCode::KEY_NUMPAD_0, KEY_CTRL), [](tic* c) -> void { c->HandleOnCopy(true); } },
108 { KeyComb(KeyCode::KEY_NUMPAD_0, KEY_SHIFT), &tic::HandleOnPaste },
109 // when numLock off, KEY_NUMPAD_1 perform as KEY_MOVE_END
__anon5f7860542702() 110 { KeyComb(KeyCode::KEY_NUMPAD_1), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::LineEnd); } },
__anon5f7860542802() 111 { KeyComb(KeyCode::KEY_NUMPAD_1, KEY_CTRL), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::End); } },
__anon5f7860542902() 112 { KeyComb(KeyCode::KEY_NUMPAD_1, KEY_SHIFT), [](tic* c) -> void { c->HandleSelect(CaretMoveIntent::LineEnd); } },
113 { KeyComb(KeyCode::KEY_NUMPAD_1, KEY_CTRL | KEY_SHIFT),
__anon5f7860542a02() 114 [](tic* c) -> void { c->CursorMove(CaretMoveIntent::End); } },
115 // when numLock off, KEY_NUMPAD_2 perform as KEY_DPAD_DOWN
__anon5f7860542b02() 116 { KeyComb(KeyCode::KEY_NUMPAD_2), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::Down); } },
__anon5f7860542c02() 117 { KeyComb(KeyCode::KEY_NUMPAD_2, KEY_CTRL), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::ParagraghEnd); } },
__anon5f7860542d02() 118 { KeyComb(KeyCode::KEY_NUMPAD_2, KEY_SHIFT), [](tic* c) -> void { c->HandleSelect(CaretMoveIntent::Down); } },
119 { KeyComb(KeyCode::KEY_NUMPAD_2, KEY_CTRL | KEY_SHIFT),
__anon5f7860542e02() 120 [](tic* c) -> void { c->CursorMove(CaretMoveIntent::ParagraghEnd); } },
121 // when numLock off, KEY_NUMPAD_3 perform as KEY_PAGE_DOWN
122 { KeyComb(KeyCode::KEY_NUMPAD_3), &tic::HandleOnPageDown },
123 // when numLock off, KEY_NUMPAD_4 perform as KEY_DPAD_LEFT
__anon5f7860542f02() 124 { KeyComb(KeyCode::KEY_NUMPAD_4), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::Left); } },
__anon5f7860543002() 125 { KeyComb(KeyCode::KEY_NUMPAD_4, KEY_CTRL), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::LeftWord); } },
__anon5f7860543102() 126 { KeyComb(KeyCode::KEY_NUMPAD_4, KEY_SHIFT), [](tic* c) -> void { c->HandleSelect(CaretMoveIntent::Left); } },
127 { KeyComb(KeyCode::KEY_NUMPAD_4, KEY_CTRL | KEY_SHIFT),
__anon5f7860543202() 128 [](tic* c) -> void { c->HandleSelect(CaretMoveIntent::LeftWord); } },
129 // when numLock off, KEY_NUMPAD_5 perform as none
130 // when numLock off, KEY_NUMPAD_6 perform as KEY_DPAD_RIGHT
__anon5f7860543302() 131 { KeyComb(KeyCode::KEY_NUMPAD_6), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::Right); } },
__anon5f7860543402() 132 { KeyComb(KeyCode::KEY_NUMPAD_6, KEY_CTRL), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::RightWord); } },
__anon5f7860543502() 133 { KeyComb(KeyCode::KEY_NUMPAD_6, KEY_SHIFT), [](tic* c) -> void { c->HandleSelect(CaretMoveIntent::Right); } },
134 { KeyComb(KeyCode::KEY_NUMPAD_6, KEY_CTRL | KEY_SHIFT),
__anon5f7860543602() 135 [](tic* c) -> void { c->HandleSelect(CaretMoveIntent::RightWord); } },
136 // when numLock off, KEY_NUMPAD_7 perform as KEY_MOVE_HOME
__anon5f7860543702() 137 { KeyComb(KeyCode::KEY_NUMPAD_7), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::LineBegin); } },
__anon5f7860543802() 138 { KeyComb(KeyCode::KEY_NUMPAD_7, KEY_CTRL), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::Home); } },
__anon5f7860543902() 139 { KeyComb(KeyCode::KEY_NUMPAD_7, KEY_SHIFT), [](tic* c) -> void { c->HandleSelect(CaretMoveIntent::LineBegin); } },
140 { KeyComb(KeyCode::KEY_NUMPAD_7, KEY_CTRL | KEY_SHIFT),
__anon5f7860543a02() 141 [](tic* c) -> void { c->CursorMove(CaretMoveIntent::Home); } },
142 // when numLock off, KEY_NUMPAD_8 perform as KEY_DPAD_UP
__anon5f7860543b02() 143 { KeyComb(KeyCode::KEY_NUMPAD_8), [](tic* c) -> void { c->CursorMove(CaretMoveIntent::Up); } },
144 { KeyComb(KeyCode::KEY_NUMPAD_8, KEY_CTRL),
__anon5f7860543c02() 145 [](tic* c) -> void { c->CursorMove(CaretMoveIntent::ParagraghBegin); } },
__anon5f7860543d02() 146 { KeyComb(KeyCode::KEY_NUMPAD_8, KEY_SHIFT), [](tic* c) -> void { c->HandleSelect(CaretMoveIntent::Up); } },
147 { KeyComb(KeyCode::KEY_NUMPAD_8, KEY_CTRL | KEY_SHIFT),
__anon5f7860543e02() 148 [](tic* c) -> void { c->CursorMove(CaretMoveIntent::ParagraghBegin); } },
149 // when numLock off, KEY_NUMPAD_9 perform as KEY_PAGE_UP
150 { KeyComb(KeyCode::KEY_NUMPAD_9), &tic::HandleOnPageUp },
151 // when numLock off, KEY_NUMPAD_DOT perform as KEY_FORWARD_DEL
__anon5f7860543f02() 152 { KeyComb(KeyCode::KEY_NUMPAD_DOT), [](tic* c) -> void { c->HandleOnDelete(false); } },
__anon5f7860544002() 153 { KeyComb(KeyCode::KEY_NUMPAD_DOT, KEY_CTRL), [](tic* c) -> void { c->HandleOnDeleteComb(false); } },
154 };
155
NotifyKeyboardHeight(uint32_t height)156 void TextInputClient::NotifyKeyboardHeight(uint32_t height)
157 {
158 auto pipeline = NG::PipelineContext::GetCurrentContext();
159 CHECK_NULL_VOID(pipeline);
160 auto manager = pipeline->GetSafeAreaManager();
161 CHECK_NULL_VOID(manager);
162 manager->SetkeyboardHeightConsideringUIExtension(height);
163 }
164
HandleKeyEvent(const KeyEvent & keyEvent)165 bool TextInputClient::HandleKeyEvent(const KeyEvent& keyEvent)
166 {
167 UpdateShiftFlag(keyEvent);
168 if (keyEvent.action != KeyAction::DOWN) {
169 return false;
170 }
171 uint32_t ctrlFlag =
172 (keyEvent.HasKey(KeyCode::KEY_CTRL_LEFT) || keyEvent.HasKey(KeyCode::KEY_CTRL_RIGHT) ? KEY_CTRL : KEY_NULL);
173 bool vFlag = keyEvent.HasKey(KeyCode::KEY_V);
174 if (!keyEvent.msg.empty() && ctrlFlag == KEY_CTRL && vFlag) {
175 InsertValue(keyEvent.msg);
176 return true;
177 }
178 uint32_t modKeyFlags =
179 (keyEvent.HasKey(KeyCode::KEY_ALT_LEFT) || keyEvent.HasKey(KeyCode::KEY_ALT_RIGHT) ? KEY_ALT : KEY_NULL) |
180 (keyEvent.HasKey(KeyCode::KEY_SHIFT_LEFT) || keyEvent.HasKey(KeyCode::KEY_SHIFT_RIGHT) ? KEY_SHIFT : KEY_NULL) |
181 (keyEvent.HasKey(KeyCode::KEY_CTRL_LEFT) || keyEvent.HasKey(KeyCode::KEY_CTRL_RIGHT) ? KEY_CTRL : KEY_NULL) |
182 (keyEvent.HasKey(KeyCode::KEY_META_LEFT) || keyEvent.HasKey(KeyCode::KEY_META_RIGHT) ? KEY_META : KEY_NULL);
183 if (modKeyFlags == KEY_NULL || modKeyFlags == KEY_SHIFT) {
184 auto value = keyEvent.ConvertCodeToString();
185 if (value != "") {
186 InsertValue(value, true);
187 return true;
188 }
189 }
190 auto iterFunctionKeys = functionKeys_.find(KeyComb(keyEvent.code, modKeyFlags));
191 if (iterFunctionKeys != functionKeys_.end()) {
192 this->ResetOriginCaretPosition();
193 return iterFunctionKeys->second(this);
194 }
195 auto iterKeyboardShortCuts = keyboardShortCuts_.find(KeyComb(keyEvent.code, modKeyFlags));
196 if (iterKeyboardShortCuts != keyboardShortCuts_.end()) {
197 if (KeyComb(keyEvent.code, modKeyFlags) == KeyComb(KeyCode::KEY_DPAD_UP, KEY_SHIFT) ||
198 KeyComb(keyEvent.code, modKeyFlags) == KeyComb(KeyCode::KEY_DPAD_DOWN, KEY_SHIFT)) {
199 this->RecordOriginCaretPosition();
200 } else {
201 this->ResetOriginCaretPosition();
202 }
203 iterKeyboardShortCuts->second(this);
204 return true;
205 }
206 return false;
207 }
208 } // namespace OHOS::Ace
209