1 /* 2 * Copyright (c) 2021 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 #include "js_input_method_engine_listener.h" 16 #include "global.h" 17 #include "js_runtime_utils.h" 18 #include "js_input_method_engine_utils.h" 19 20 namespace OHOS { 21 namespace MiscServices { 22 using namespace AbilityRuntime; RegisterListenerWithType(NativeEngine & engine,std::string type,NativeValue * value)23 void JsInputMethodEngineListener::RegisterListenerWithType(NativeEngine& engine, 24 std::string type, NativeValue* value) 25 { 26 // should do type check 27 if (IfCallbackRegistered(type, value)) { 28 IMSA_HILOGI("JsInputMethodEngineListener::RegisterListenerWithType callback already registered!"); 29 return; 30 } 31 std::unique_ptr<NativeReference> callbackRef; 32 callbackRef.reset(engine.CreateReference(value, 1)); 33 34 AddCallback(type, value); 35 } 36 AddCallback(std::string type,NativeValue * jsListenerObject)37 void JsInputMethodEngineListener::AddCallback(std::string type, NativeValue* jsListenerObject) 38 { 39 IMSA_HILOGI("JsInputMethodEngineListener::AddCallback is called"); 40 std::lock_guard<std::mutex> lock(mMutex); 41 std::unique_ptr<NativeReference> callbackRef; 42 callbackRef.reset(engine_->CreateReference(jsListenerObject, 1)); 43 jsCbMap_[type].push_back(std::move(callbackRef)); 44 IMSA_HILOGI("JsInputMethodEngineListener::AddCallback success"); 45 IMSA_HILOGI("jsCbMap_ size: %{public}d, and type[%{public}s] size: %{public}d!", 46 static_cast<uint32_t>(jsCbMap_.size()), type.c_str(), static_cast<uint32_t>(jsCbMap_[type].size())); 47 return; 48 } 49 UnregisterAllListenerWithType(std::string type)50 void JsInputMethodEngineListener::UnregisterAllListenerWithType(std::string type) 51 { 52 IMSA_HILOGI("JsInputMethodEngineListener::UnregisterAllListenerWithType"); 53 // should do type check 54 if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { 55 IMSA_HILOGI("methodName %{public}s not registerted!", type.c_str()); 56 return; 57 } 58 for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) { 59 jsCbMap_[type].erase(it); 60 } 61 // one type with multi jscallback, erase type when there is no callback in one type 62 if (jsCbMap_[type].empty()) { 63 jsCbMap_.erase(type); 64 } 65 return; 66 } 67 UnregisterListenerWithType(std::string type,NativeValue * value)68 void JsInputMethodEngineListener::UnregisterListenerWithType(std::string type, NativeValue* value) 69 { 70 IMSA_HILOGI("JsInputMethodEngineListener::UnregisterListenerWithType"); 71 // should do type check 72 if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { 73 IMSA_HILOGI("methodName %{public}s not registerted!", type.c_str()); 74 return; 75 } 76 for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) { 77 if (value->StrictEquals((*it)->Get())) { 78 jsCbMap_[type].erase(it); 79 break; 80 } 81 } 82 // one type with multi jscallback, erase type when there is no callback in one type 83 if (jsCbMap_[type].empty()) { 84 jsCbMap_.erase(type); 85 } 86 return; 87 } 88 IfCallbackRegistered(std::string type,NativeValue * jsListenerObject)89 bool JsInputMethodEngineListener::IfCallbackRegistered(std::string type, NativeValue* jsListenerObject) 90 { 91 IMSA_HILOGI("JsInputMethodEngineListener::IfCallbackRegistered"); 92 if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { 93 IMSA_HILOGI("methodName %{public}s not registertd!", type.c_str()); 94 return false; 95 } 96 97 for (auto iter = jsCbMap_[type].begin(); iter != jsCbMap_[type].end(); iter++) { 98 if (jsListenerObject->StrictEquals((*iter)->Get())) { 99 IMSA_HILOGI("JsInputMethodEngineListener::IfCallbackRegistered callback already registered!"); 100 return true; 101 } 102 } 103 return false; 104 } 105 CallJsMethod(std::string methodName,NativeValue * const * argv,size_t argc)106 void JsInputMethodEngineListener::CallJsMethod(std::string methodName, NativeValue* const* argv, size_t argc) 107 { 108 IMSA_HILOGI("JsInputMethodEngineListener::CallJsMethod"); 109 if (engine_ == nullptr) { 110 IMSA_HILOGI("engine_ nullptr"); 111 return; 112 } 113 114 if (jsCbMap_.empty() || jsCbMap_.find(methodName) == jsCbMap_.end()) { 115 IMSA_HILOGI("methodName %{public}s not registertd!", methodName.c_str()); 116 return; 117 } 118 119 for (auto iter = jsCbMap_[methodName].begin(); iter != jsCbMap_[methodName].end(); iter++) { 120 engine_->CallFunction(engine_->CreateUndefined(), (*iter)->Get(), argv, argc); 121 } 122 } 123 CallJsMethodReturnBool(std::string methodName,NativeValue * const * argv,size_t argc)124 bool JsInputMethodEngineListener::CallJsMethodReturnBool(std::string methodName, 125 NativeValue* const* argv, size_t argc) 126 { 127 IMSA_HILOGI("JsInputMethodEngineListener::CallJsMethodReturnBool"); 128 if (engine_ == nullptr) { 129 IMSA_HILOGI("engine_ nullptr"); 130 return false; 131 } 132 133 if (jsCbMap_.empty() || jsCbMap_.find(methodName) == jsCbMap_.end()) { 134 IMSA_HILOGI("methodName %{public}s not registertd!", methodName.c_str()); 135 return false; 136 } 137 138 bool result = false; 139 for (auto iter = jsCbMap_[methodName].begin(); iter != jsCbMap_[methodName].end(); iter++) { 140 NativeValue* nativeValue = engine_->CallFunction(engine_->CreateUndefined(), (*iter)->Get(), argv, argc); 141 bool ret = false; 142 if (ConvertFromJsValue(*engine_, nativeValue, ret) && ret) { 143 result = true; 144 } 145 } 146 return result; 147 } 148 OnKeyboardStatus(bool isShow)149 void JsInputMethodEngineListener::OnKeyboardStatus(bool isShow) 150 { 151 std::lock_guard<std::mutex> lock(mMutex); 152 IMSA_HILOGI("JsInputMethodEngineListener::OnKeyboardStatus"); 153 154 auto task = [this, isShow] () { 155 HandleScope handleScope(*engine_); 156 NativeValue* nativeValue = engine_->CreateObject(); 157 NativeObject* object = ConvertNativeValueTo < NativeObject >(nativeValue); 158 if (object == nullptr) { 159 IMSA_HILOGI("Failed to convert rect to jsObject"); 160 return; 161 } 162 NativeValue* argv[] = { nativeValue }; 163 std::string methodName; 164 if (isShow) { 165 methodName = "keyboardShow"; 166 } else { 167 methodName = "keyboardHide"; 168 } 169 CallJsMethod(methodName, argv, ArraySize(argv)); 170 }; 171 mainHandler_->PostTask(task); 172 } 173 OnInputStart()174 void JsInputMethodEngineListener::OnInputStart() 175 { 176 std::lock_guard<std::mutex> lock(mMutex); 177 IMSA_HILOGI("JsInputMethodEngineListener::OnInputStart"); 178 auto task = [this] () { 179 HandleScope handleScope(*engine_); 180 NativeValue *nativeValuekb = CreateKeyboardController(*engine_); 181 NativeValue *nativeValuetx = CreateTextInputClient(*engine_); 182 NativeValue* argv[] = {nativeValuekb, nativeValuetx}; 183 std::string methodName = "inputStart"; 184 CallJsMethod(methodName, argv, ArraySize(argv)); 185 }; 186 mainHandler_->PostTask(task); 187 } 188 OnInputStop(std::string imeId)189 void JsInputMethodEngineListener::OnInputStop(std::string imeId) 190 { 191 std::lock_guard<std::mutex> lock(mMutex); 192 IMSA_HILOGI("JsInputMethodEngineListener::OnInputStop"); 193 194 auto task = [this, imeId] () { 195 HandleScope handleScope(*engine_); 196 NativeValue* nativeValue = CreateJsValue(*engine_, imeId); 197 198 NativeValue* argv[] = { nativeValue }; 199 std::string methodName = "inputStop"; 200 CallJsMethod(methodName, argv, ArraySize(argv)); 201 }; 202 mainHandler_->PostTask(task); 203 } 204 OnSetCallingWindow(uint32_t windowId)205 void JsInputMethodEngineListener::OnSetCallingWindow(uint32_t windowId) 206 { 207 std::lock_guard<std::mutex> lock(mMutex); 208 IMSA_HILOGI("JsInputMethodEngineListener::OnSetCallingWindow"); 209 210 auto task = [this, windowId] () { 211 HandleScope handleScope(*engine_); 212 NativeValue* nativeValue = CreateJsValue(*engine_, windowId); 213 NativeValue* argv[] = { nativeValue }; 214 std::string methodName = "setCallingWindow"; 215 CallJsMethod(methodName, argv, ArraySize(argv)); 216 }; 217 mainHandler_->PostTask(task); 218 } 219 } // namespace MiscServices 220 } // namespace OHOS 221