1 /*
2  * Copyright (C) 2021-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 #ifndef FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_METHOD_UTILS_H
17 #define FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_METHOD_UTILS_H
18 
19 #include <stdint.h>
20 #include <variant>
21 
22 #include "global.h"
23 #include "input_attribute.h"
24 #include "panel_info.h"
25 
26 namespace OHOS {
27 namespace MiscServices {
28 constexpr uint32_t INVALID_WINDOW_ID = 0;
29 constexpr int32_t INVALID_VALUE = -1;
30 constexpr size_t MAX_PRIVATE_COMMAND_SIZE = 32 * 1024; // 32K
31 constexpr size_t MAX_PRIVATE_COMMAND_COUNT = 5;
32 const constexpr char *SYSTEM_CMD_KEY = "sys_cmd";
33 enum class EnterKeyType {
34     UNSPECIFIED = 0,
35     NONE,
36     GO,
37     SEARCH,
38     SEND,
39     NEXT,
40     DONE,
41     PREVIOUS,
42     NEW_LINE,
43 };
44 
45 enum class TextInputType {
46     NONE = -1,
47     TEXT = 0,
48     MULTILINE,
49     NUMBER,
50     PHONE,
51     DATETIME,
52     EMAIL_ADDRESS,
53     URL,
54     VISIBLE_PASSWORD,
55     NUMBER_PASSWORD,
56     SCREEN_LOCK_PASSWORD,
57     USER_NAME,
58     NEW_PASSWORD,
59     NUMBER_DECIMAL,
60 };
61 
62 enum class Direction {
63     NONE = 0,
64     UP = 1,
65     DOWN,
66     LEFT,
67     RIGHT,
68 };
69 
70 enum class SecurityMode : int32_t {
71     BASIC = 0,
72     FULL = 1,
73 };
74 
75 enum class ExtendAction {
76     SELECT_ALL = 0,
77     CUT = 3,
78     COPY,
79     PASTE,
80 };
81 
82 class Configuration {
83 public:
GetEnterKeyType() const84     EnterKeyType GetEnterKeyType() const
85     {
86         return enterKeyType;
87     }
88 
SetEnterKeyType(EnterKeyType keyType)89     void SetEnterKeyType(EnterKeyType keyType)
90     {
91         enterKeyType = keyType;
92     }
93 
GetTextInputType() const94     TextInputType GetTextInputType() const
95     {
96         return textInputType;
97     }
98 
SetTextInputType(TextInputType textType)99     void SetTextInputType(TextInputType textType)
100     {
101         textInputType = textType;
102     }
103 
104 private:
105     EnterKeyType enterKeyType = EnterKeyType::UNSPECIFIED;
106     TextInputType textInputType = TextInputType::TEXT;
107 };
108 
109 struct CursorInfo {
110     double left = -1.0;
111     double top = -1.0;
112     double width = -1.0;
113     double height = -1.0;
operator ==OHOS::MiscServices::CursorInfo114     bool operator==(const CursorInfo &info) const
115     {
116         return (left == info.left && top == info.top && width == info.width && height == info.height);
117     }
118 };
119 
120 class KeyEvent {};
121 
122 enum class KeyboardStatus : int32_t { NONE = 0, HIDE, SHOW }; // soft keyboard
123 
124 enum Trigger : int32_t { IME_APP, IMF, END };
125 struct PanelStatusInfo {
126     PanelInfo panelInfo;
127     bool visible{ false };
128     Trigger trigger{ END };
operator ==OHOS::MiscServices::PanelStatusInfo129     bool operator==(const PanelStatusInfo &info) const
130     {
131         return info.panelInfo.panelFlag == panelInfo.panelFlag && info.panelInfo.panelType == panelInfo.panelType &&
132                info.visible == visible && info.trigger == trigger;
133     }
134 };
135 
136 class FunctionKey {
137 public:
GetEnterKeyType() const138     EnterKeyType GetEnterKeyType() const
139     {
140         return enterKeyType;
141     }
142 
SetEnterKeyType(EnterKeyType keyType)143     void SetEnterKeyType(EnterKeyType keyType)
144     {
145         enterKeyType = keyType;
146     }
147 
148 private:
149     EnterKeyType enterKeyType = EnterKeyType::UNSPECIFIED;
150 };
151 
152 struct Range {
153     int32_t start = INVALID_VALUE;
154     int32_t end = INVALID_VALUE;
operator ==OHOS::MiscServices::Range155     bool operator==(const Range &range) const
156     {
157         return start == range.start && end == range.end;
158     }
159 };
160 
161 struct TextSelection {
162     int32_t oldBegin = INVALID_VALUE;
163     int32_t oldEnd = INVALID_VALUE;
164     int32_t newBegin = INVALID_VALUE;
165     int32_t newEnd = INVALID_VALUE;
166 };
167 
168 enum PrivateDataValueType : int32_t { VALUE_TYPE_STRING = 0, VALUE_TYPE_BOOL, VALUE_TYPE_NUMBER };
169 using PrivateDataValue = std::variant<std::string, bool, int32_t>;
170 
171 struct TextTotalConfig {
172 public:
173     InputAttribute inputAttribute = {};
174     CursorInfo cursorInfo = {};
175     TextSelection textSelection = {};
176     uint32_t windowId = INVALID_WINDOW_ID;
177     double positionY = 0;
178     double height = 0;
179     std::unordered_map<std::string, PrivateDataValue> privateCommand = {};
180 
ToStringOHOS::MiscServices::TextTotalConfig181     std::string ToString() const
182     {
183         std::string config;
184         config.append("pattern/enterKey/preview: " + std::to_string(inputAttribute.inputPattern) + "/" +
185                       std::to_string(inputAttribute.enterKeyType) + "/" +
186                       std::to_string(inputAttribute.isTextPreviewSupported));
187         config.append(" windowId/y/height: " + std::to_string(windowId) + "/" + std::to_string(positionY) + "/" +
188                       std::to_string(height));
189         config.append(
190             " oldRange: " + std::to_string(textSelection.oldBegin) + "/" + std::to_string(textSelection.oldEnd));
191         config.append(
192             " newRange: " + std::to_string(textSelection.newBegin) + "/" + std::to_string(textSelection.newEnd));
193         config.append(" cursor: " + std::to_string(cursorInfo.left) + "/" + std::to_string(cursorInfo.top) + "/" +
194                       std::to_string(cursorInfo.width) + "/" + std::to_string(cursorInfo.height));
195         return config;
196     }
197 };
198 struct TextConfig {
199     InputAttribute inputAttribute = {};
200     CursorInfo cursorInfo = {};
201     Range range = {};
202     uint32_t windowId = INVALID_WINDOW_ID;
203     double positionY = 0;
204     double height = 0;
205     std::unordered_map<std::string, PrivateDataValue> privateCommand = {};
206 
ToStringOHOS::MiscServices::TextConfig207     std::string ToString() const
208     {
209         std::string config;
210         config.append("pattern/enterKey/preview: " + std::to_string(inputAttribute.inputPattern) + "/" +
211                       std::to_string(inputAttribute.enterKeyType) + "/" +
212                       std::to_string(inputAttribute.isTextPreviewSupported));
213         config.append(" windowId/y/height: " + std::to_string(windowId) + "/" + std::to_string(positionY) + "/" +
214                       std::to_string(height));
215         config.append(" range: " + std::to_string(range.start) + "/" + std::to_string(range.end));
216         config.append(" cursor: " + std::to_string(cursorInfo.left) + "/" + std::to_string(cursorInfo.top) + "/" +
217                       std::to_string(cursorInfo.width) + "/" + std::to_string(cursorInfo.height));
218         return config;
219     }
220 
IsPrivateCommandValidOHOS::MiscServices::TextConfig221     static bool IsPrivateCommandValid(const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
222     {
223         size_t privateCommandSize = privateCommand.size();
224         size_t maxSize = IsSystemPrivateCommand(privateCommand) ? (MAX_PRIVATE_COMMAND_COUNT + 1)
225                                                                 : MAX_PRIVATE_COMMAND_COUNT;
226         if (privateCommandSize == 0 || privateCommandSize > maxSize) {
227             IMSA_HILOGE("privateCommand size must more than 0 and less than 5.");
228             return false;
229         }
230         size_t totalSize = 0;
231         for (const auto &iter : privateCommand) {
232             size_t keySize = iter.first.size();
233             size_t idx = iter.second.index();
234             size_t valueSize = 0;
235 
236             if (idx == static_cast<size_t>(PrivateDataValueType::VALUE_TYPE_STRING)) {
237                 auto stringValue = std::get_if<std::string>(&iter.second);
238                 if (stringValue == nullptr) {
239                     IMSA_HILOGE("get stringValue failed.");
240                     return false;
241                 }
242                 valueSize = (*stringValue).size();
243             } else if (idx == static_cast<size_t>(PrivateDataValueType::VALUE_TYPE_BOOL)) {
244                 valueSize = sizeof(bool);
245             } else if (idx == static_cast<size_t>(PrivateDataValueType::VALUE_TYPE_NUMBER)) {
246                 valueSize = sizeof(int32_t);
247             }
248             totalSize = totalSize + keySize + valueSize;
249         }
250         if (totalSize > MAX_PRIVATE_COMMAND_SIZE) {
251             IMSA_HILOGE("totalSize : %{public}zu", totalSize);
252             return false;
253         }
254         return true;
255     }
IsSystemPrivateCommandOHOS::MiscServices::TextConfig256     static bool IsSystemPrivateCommand(const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
257     {
258         IMSA_HILOGD("in.");
259         size_t privateCommandSize = privateCommand.size();
260         if (privateCommandSize == 0 || privateCommandSize > MAX_PRIVATE_COMMAND_COUNT) {
261             IMSA_HILOGE("privateCommand size must more than 0 and less than 5.");
262             return false;
263         }
264         auto it = privateCommand.find(SYSTEM_CMD_KEY);
265         if (it != privateCommand.end()) {
266             // if privateCommand has the key system_cmd and value is 1, it's a system privateCommand.
267             if (it->second.index() == static_cast<size_t>(PrivateDataValueType::VALUE_TYPE_NUMBER)) {
268                 auto numberValue = std::get_if<int32_t>(&it->second);
269                 if (numberValue == nullptr) {
270                     IMSA_HILOGE("get stringValue failed.");
271                     return false;
272                 }
273                 return *numberValue == 1;
274             }
275         }
276         return false;
277     }
278 };
279 
280 enum class InputType : int32_t { NONE = -1, CAMERA_INPUT = 0, SECURITY_INPUT, VOICE_INPUT, END };
281 
282 enum class SwitchTrigger : uint32_t { CURRENT_IME = 0, SYSTEM_APP, IMSA, NATIVE_SA};
283 } // namespace MiscServices
284 } // namespace OHOS
285 #endif // FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_METHOD_UTILS_H
286