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