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
24namespace OHOS {
25namespace MMI {
26napi_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
61napi_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
99napi_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
113napi_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
124napi_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
153napi_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
167bool 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