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 "key_event_napi.h"
17 
18 #include "util_napi.h"
19 #include "util_napi_value.h"
20 
21 #undef MMI_LOG_TAG
22 #define MMI_LOG_TAG "KeyEventNapi"
23 
24 namespace OHOS {
25 namespace MMI {
CreateKeyEvent(napi_env env, const std::shared_ptr<KeyEvent> &in, napi_value &out)26 napi_status KeyEventNapi::CreateKeyEvent(napi_env env, const std::shared_ptr<KeyEvent> &in, napi_value &out)
27 {
28     CHKPR(in, napi_invalid_arg);
29     auto status = SetNameProperty(env, out, "action", in->GetKeyAction() - KeyEvent::KEY_ACTION_CANCEL);
30     CHKRR(status, "set action property", status);
31 
32     CHECK_RETURN(in->GetKeyItem(), "get key item", status);
33     auto keyItem = in->GetKeyItem();
34     status = SetNameProperty(env, out, "key", keyItem);
35     CHKRR(status, "set key property", status);
36 
37     status = SetNameProperty(env, out, "unicodeChar", in->GetKeyItem()->GetUnicode());
38     CHKRR(status, "set unicodeChar property", status);
39 
40     auto keyItems = in->GetKeyItems();
41     status = SetNameProperty(env, out, "keys", keyItems);
42     CHKRR(status, "set keys property", status);
43 
44     status = WriteKeyStatusToJs(env, in->GetPressedKeys(), out);
45     CHKRR(status, "set pressed key property", status);
46 
47     status = WriteFunctionKeyStatusToJs(env, in, out);
48     CHKRR(status, "set function key property", status);
49 
50 #ifdef OHOS_BUILD_ENABLE_VKEYBOARD
51     status = SetNameProperty(env, out, "vkeyboardAction", in->GetVKeyboardAction());
52     CHKRR(status, "set vkeyboardAction property", status);
53 
54     status = SetNameProperty(env, out, "keyName", in->GetKeyName());
55     CHKRR(status, "set keyName property", status);
56 #endif // OHOS_BUILD_ENABLE_VKEYBOARD
57 
58     return napi_ok;
59 }
60 
GetKeyEvent(napi_env env, napi_value in, std::shared_ptr<KeyEvent> &out)61 napi_status KeyEventNapi::GetKeyEvent(napi_env env, napi_value in, std::shared_ptr<KeyEvent> &out)
62 {
63     napi_valuetype valueType = napi_undefined;
64     auto status = napi_typeof(env, in, &valueType);
65     CHECK_RETURN((status == napi_ok) && (valueType == napi_object), "object type invalid", status);
66 
67     KeyEvent::KeyItem item = GetNamePropertyKeyItem(env, in, "key");
68     out->SetKeyCode(item.GetKeyCode());
69 
70     uint32_t unicode = GetNamePropertyUint32(env, in, "unicodeChar");
71     out->GetKeyItem()->SetUnicode(unicode);
72 
73     int32_t keyAction = GetNamePropertyInt32(env, in, "action");
74     out->SetKeyAction(keyAction + KeyEvent::KEY_ACTION_CANCEL);
75 
76     std::vector<KeyEvent::KeyItem> keyItems = GetNamePropertyKeyItems(env, in, "keys");
77     for (const auto &keyItem : keyItems) {
78         out->AddKeyItem(keyItem);
79     }
80 
81     bool lock = GetNamePropertyBool(env, in, "capsLock");
82     out->SetFunctionKey(KeyEvent::CAPS_LOCK_FUNCTION_KEY, lock);
83     lock = GetNamePropertyBool(env, in, "numLock");
84     out->SetFunctionKey(KeyEvent::NUM_LOCK_FUNCTION_KEY, lock);
85     lock = GetNamePropertyBool(env, in, "scrollLock");
86     out->SetFunctionKey(KeyEvent::SCROLL_LOCK_FUNCTION_KEY, lock);
87 
88 #ifdef OHOS_BUILD_ENABLE_VKEYBOARD
89     int32_t vkeyboardAction = GetNamePropertyInt32(env, in, "vkeyboardAction");
90     out->SetVKeyboardAction(static_cast<KeyEvent::VKeyboardAction>(vkeyboardAction));
91 
92     std::string keyName = GetNamePropertyString(env, in, "keyName");
93     out->SetKeyName(keyName);
94 #endif // OHOS_BUILD_ENABLE_VKEYBOARD
95 
96     return napi_ok;
97 }
98 
CreateKeyItem(napi_env env, const std::optional<KeyEvent::KeyItem> in, napi_value &out)99 napi_status KeyEventNapi::CreateKeyItem(napi_env env, const std::optional<KeyEvent::KeyItem> in, napi_value &out)
100 {
101     auto status = SetNameProperty(env, out, "code", in->GetKeyCode());
102     CHKRR(status, "set code property", status);
103 
104     status = SetNameProperty(env, out, "pressedTime", in->GetDownTime());
105     CHKRR(status, "set pressedTime property", status);
106 
107     status = SetNameProperty(env, out, "deviceId", in->GetDeviceId());
108     CHKRR(status, "set deviceId property", status);
109 
110     return napi_ok;
111 }
112 
GetKeyItem(napi_env env, napi_value in, KeyEvent::KeyItem &out)113 napi_status KeyEventNapi::GetKeyItem(napi_env env, napi_value in, KeyEvent::KeyItem &out)
114 {
115     int32_t keyCode = GetNamePropertyInt32(env, in, "code");
116     out.SetKeyCode(keyCode);
117     int64_t downTime = GetNamePropertyInt64(env, in, "pressedTime");
118     out.SetDownTime(downTime);
119     int32_t deviceId = GetNamePropertyInt32(env, in, "deviceId");
120     out.SetDeviceId(deviceId);
121     return napi_ok;
122 }
123 
WriteKeyStatusToJs(napi_env env, const std::vector<int32_t> &pressedKeys, napi_value &out)124 napi_status KeyEventNapi::WriteKeyStatusToJs(napi_env env, const std::vector<int32_t> &pressedKeys, napi_value &out)
125 {
126     bool isExists = HasKeyCode(pressedKeys, KeyEvent::KEYCODE_CTRL_LEFT)
127                     || HasKeyCode(pressedKeys, KeyEvent::KEYCODE_CTRL_RIGHT);
128     auto status = SetNameProperty(env, out, "ctrlKey", isExists);
129     CHKRR(status, "set ctrlKey property", status);
130 
131     isExists = HasKeyCode(pressedKeys, KeyEvent::KEYCODE_ALT_LEFT)
132                || HasKeyCode(pressedKeys, KeyEvent::KEYCODE_ALT_RIGHT);
133     status = SetNameProperty(env, out, "altKey", isExists);
134     CHKRR(status, "set altKey property", status);
135 
136     isExists = HasKeyCode(pressedKeys, KeyEvent::KEYCODE_SHIFT_LEFT)
137                || HasKeyCode(pressedKeys, KeyEvent::KEYCODE_SHIFT_RIGHT);
138     status = SetNameProperty(env, out, "shiftKey", isExists);
139     CHKRR(status, "set shiftKey property", status);
140 
141     isExists = HasKeyCode(pressedKeys, KeyEvent::KEYCODE_META_LEFT)
142                || HasKeyCode(pressedKeys, KeyEvent::KEYCODE_META_RIGHT);
143     status = SetNameProperty(env, out, "logoKey", isExists);
144     CHKRR(status, "set logoKey property", status);
145 
146     isExists = HasKeyCode(pressedKeys, KeyEvent::KEYCODE_FN);
147     status = SetNameProperty(env, out, "fnKey", isExists);
148     CHKRR(status, "set fnKey property", status);
149 
150     return napi_ok;
151 }
152 
WriteFunctionKeyStatusToJs(napi_env env, const std::shared_ptr<KeyEvent> &in, napi_value &out)153 napi_status KeyEventNapi::WriteFunctionKeyStatusToJs(napi_env env, const std::shared_ptr<KeyEvent> &in, napi_value &out)
154 {
155     auto status = SetNameProperty(env, out, "capsLock", in->GetFunctionKey(KeyEvent::CAPS_LOCK_FUNCTION_KEY));
156     CHKRR(status, "set capsLock property", status);
157 
158     status = SetNameProperty(env, out, "numLock", in->GetFunctionKey(KeyEvent::NUM_LOCK_FUNCTION_KEY));
159     CHKRR(status, "set numLock property", status);
160 
161     status = SetNameProperty(env, out, "scrollLock", in->GetFunctionKey(KeyEvent::SCROLL_LOCK_FUNCTION_KEY));
162     CHKRR(status, "set scrollLock property", status);
163 
164     return napi_ok;
165 }
166 
HasKeyCode(const std::vector<int32_t> &pressedKeys, int32_t keyCode)167 bool KeyEventNapi::HasKeyCode(const std::vector<int32_t> &pressedKeys, int32_t keyCode)
168 {
169     return std::find(pressedKeys.begin(), pressedKeys.end(), keyCode) != pressedKeys.end();
170 }
171 } // namespace MMI
172 } // namespace OHOS