mirror of
https://gitee.com/openharmony/inputmethod_imf
synced 2024-11-27 00:41:04 +00:00
Merge branch 'master' of gitee.com:openharmony/inputmethod_imf into master
Signed-off-by: mashaoyin <mashaoyin1@huawei.com>
This commit is contained in:
commit
53d394a719
1
BUILD.gn
1
BUILD.gn
@ -23,6 +23,7 @@ group("imf_packages") {
|
||||
"etc/para:inputmethod_para",
|
||||
"frameworks/js/napi/inputmethodability:inputmethodengine",
|
||||
"frameworks/js/napi/inputmethodclient:inputmethod",
|
||||
"frameworks/js/napi/inputmethodlist:inputmethodlist",
|
||||
"interfaces/inner_api/inputmethod_ability:inputmethod_ability",
|
||||
"interfaces/inner_api/inputmethod_controller:inputmethod_client",
|
||||
"profile:inputmethod_inputmethod_sa_profiles",
|
||||
|
@ -60,6 +60,7 @@
|
||||
"fwk_group": [
|
||||
"//base/inputmethod/imf/interfaces/inner_api/inputmethod_controller:inputmethod_client",
|
||||
"//base/inputmethod/imf/frameworks/js/napi/inputmethodclient:inputmethod",
|
||||
"//base/inputmethod/imf/frameworks/js/napi/inputmethodlist:inputmethodlist",
|
||||
"//base/inputmethod/imf/services/dfx:inputmethod_dfx_static"
|
||||
],
|
||||
"service_group": [
|
||||
|
@ -53,6 +53,7 @@ ohos_shared_library("inputmethod") {
|
||||
]
|
||||
|
||||
external_deps = [
|
||||
"ability_base:want",
|
||||
"ability_runtime:abilitykit_native",
|
||||
"c_utils:utils",
|
||||
"eventhandler:libeventhandler",
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "input_method_controller.h"
|
||||
#include "input_method_property.h"
|
||||
#include "napi/native_api.h"
|
||||
#include "js_util.h"
|
||||
#include "napi/native_node_api.h"
|
||||
#include "string_ex.h"
|
||||
|
||||
@ -31,6 +32,8 @@ napi_value JsInputMethod::Init(napi_env env, napi_value exports)
|
||||
DECLARE_NAPI_FUNCTION("switchInputMethod", SwitchInputMethod),
|
||||
DECLARE_NAPI_FUNCTION("getCurrentInputMethod", GetCurrentInputMethod),
|
||||
DECLARE_NAPI_FUNCTION("getCurrentInputMethodSubtype", GetCurrentInputMethodSubtype),
|
||||
DECLARE_NAPI_FUNCTION("getDefaultInputMethod", GetDefaultInputMethod),
|
||||
DECLARE_NAPI_FUNCTION("getSystemInputMethodConfigAbility", GetSystemInputMethodConfigAbility),
|
||||
DECLARE_NAPI_FUNCTION("switchCurrentInputMethodSubtype", SwitchCurrentInputMethodSubtype),
|
||||
DECLARE_NAPI_FUNCTION("switchCurrentInputMethodAndSubtype", SwitchCurrentInputMethodAndSubtype),
|
||||
};
|
||||
@ -172,6 +175,26 @@ napi_value JsInputMethod::GetJsInputMethodSubProperty(napi_env env, const SubPro
|
||||
return prop;
|
||||
}
|
||||
|
||||
napi_value JsInputMethod::GetJsInputConfigElement(napi_env env, const OHOS::AppExecFwk::ElementName &elementName)
|
||||
{
|
||||
napi_value element = nullptr;
|
||||
napi_create_object(env, &element);
|
||||
|
||||
napi_value bundleName = nullptr;
|
||||
napi_create_string_utf8(env, elementName.GetBundleName().c_str(), NAPI_AUTO_LENGTH, &bundleName);
|
||||
napi_set_named_property(env, element, "bundleName", bundleName);
|
||||
|
||||
napi_value moduleName = nullptr;
|
||||
napi_create_string_utf8(env, elementName.GetModuleName().c_str(), NAPI_AUTO_LENGTH, &moduleName);
|
||||
napi_set_named_property(env, element, "moduleName", moduleName);
|
||||
|
||||
napi_value abilityName = nullptr;
|
||||
napi_create_string_utf8(env, elementName.GetAbilityName().c_str(), NAPI_AUTO_LENGTH, &abilityName);
|
||||
napi_set_named_property(env, element, "abilityName", abilityName);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
napi_value JsInputMethod::GetJSInputMethodSubProperties(napi_env env, const std::vector<SubProperty> &subProperties)
|
||||
{
|
||||
uint32_t index = 0;
|
||||
@ -268,6 +291,34 @@ napi_value JsInputMethod::GetCurrentInputMethodSubtype(napi_env env, napi_callba
|
||||
return GetJsInputMethodSubProperty(env, *subProperty);
|
||||
}
|
||||
|
||||
napi_value JsInputMethod::GetDefaultInputMethod(napi_env env, napi_callback_info info)
|
||||
{
|
||||
std::shared_ptr<Property> property;
|
||||
int32_t ret = InputMethodController::GetInstance()->GetDefaultInputMethod(property);
|
||||
if (property == nullptr) {
|
||||
IMSA_HILOGE("get default input method is nullptr");
|
||||
napi_value result = nullptr;
|
||||
napi_get_null(env, &result);
|
||||
return result;
|
||||
}
|
||||
if (ret != ErrorCode::NO_ERROR) {
|
||||
JsUtils::ThrowException(env, JsUtils::Convert(ret), "failed to get default input method", TYPE_NONE);
|
||||
return JsUtil::Const::Null(env);
|
||||
}
|
||||
return GetJsInputMethodProperty(env, *property);
|
||||
}
|
||||
|
||||
napi_value JsInputMethod::GetSystemInputMethodConfigAbility(napi_env env, napi_callback_info info)
|
||||
{
|
||||
OHOS::AppExecFwk::ElementName inputMethodConfig;
|
||||
int32_t ret = InputMethodController::GetInstance()->GetInputMethodConfig(inputMethodConfig);
|
||||
if (ret != ErrorCode::NO_ERROR) {
|
||||
JsUtils::ThrowException(env, JsUtils::Convert(ret), "failed to get input method config", TYPE_NONE);
|
||||
return JsUtil::Const::Null(env);
|
||||
}
|
||||
return GetJsInputConfigElement(env, inputMethodConfig);
|
||||
}
|
||||
|
||||
napi_value JsInputMethod::SwitchCurrentInputMethodSubtype(napi_env env, napi_callback_info info)
|
||||
{
|
||||
auto ctxt = std::make_shared<SwitchInputMethodContext>();
|
||||
|
@ -16,6 +16,7 @@
|
||||
#define INTERFACE_KITS_JS_INPUT_METHOD_H
|
||||
|
||||
#include "async_call.h"
|
||||
#include "element_name.h"
|
||||
#include "global.h"
|
||||
#include "input_method_controller.h"
|
||||
#include "native_engine/native_engine.h"
|
||||
@ -58,10 +59,13 @@ public:
|
||||
static napi_value SwitchCurrentInputMethodAndSubtype(napi_env env, napi_callback_info info);
|
||||
static napi_value GetCurrentInputMethodSubtype(napi_env env, napi_callback_info info);
|
||||
static napi_value GetCurrentInputMethod(napi_env env, napi_callback_info info);
|
||||
static napi_value GetDefaultInputMethod(napi_env env, napi_callback_info info);
|
||||
static napi_value GetSystemInputMethodConfigAbility(napi_env env, napi_callback_info info);
|
||||
static napi_value GetJsInputMethodProperty(napi_env env, const Property &property);
|
||||
static napi_value GetJSInputMethodSubProperties(napi_env env, const std::vector<SubProperty> &subProperties);
|
||||
static napi_value GetJSInputMethodProperties(napi_env env, const std::vector<Property> &properties);
|
||||
static napi_value GetJsInputMethodSubProperty(napi_env env, const SubProperty &subProperty);
|
||||
static napi_value GetJsInputConfigElement(napi_env env, const OHOS::AppExecFwk::ElementName &elementName);
|
||||
|
||||
private:
|
||||
static napi_status GetInputMethodProperty(
|
||||
|
43
frameworks/js/napi/inputmethodlist/BUILD.gn
Normal file
43
frameworks/js/napi/inputmethodlist/BUILD.gn
Normal file
@ -0,0 +1,43 @@
|
||||
# Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//arkcompiler/ets_frontend/es2panda/es2abc_config.gni")
|
||||
import("//build/ohos.gni")
|
||||
import("//foundation/arkui/ace_engine/ace_config.gni")
|
||||
|
||||
es2abc_gen_abc("gen_inputmethodlist_abc") {
|
||||
src_js = rebase_path("inputmethodlist.js")
|
||||
dst_file = rebase_path(target_out_dir + "/inputmethodlist.abc")
|
||||
in_puts = [ "inputmethodlist.js" ]
|
||||
out_puts = [ target_out_dir + "/inputmethodlist.abc" ]
|
||||
extra_args = [ "--module" ]
|
||||
}
|
||||
|
||||
gen_js_obj("inputmethodlist_abc") {
|
||||
input = get_label_info(":gen_inputmethodlist_abc", "target_out_dir") +
|
||||
"/inputmethodlist.abc"
|
||||
output = target_out_dir + "/inputmethodlist_abc.o"
|
||||
dep = ":gen_inputmethodlist_abc"
|
||||
}
|
||||
|
||||
ohos_shared_library("inputmethodlist") {
|
||||
sources = [ "inputmethodlist.cpp" ]
|
||||
|
||||
deps = [ ":inputmethodlist_abc" ]
|
||||
|
||||
external_deps = [ "napi:ace_napi" ]
|
||||
|
||||
relative_install_dir = "module"
|
||||
subsystem_name = "inputmethod"
|
||||
part_name = "imf"
|
||||
}
|
46
frameworks/js/napi/inputmethodlist/inputmethodlist.cpp
Normal file
46
frameworks/js/napi/inputmethodlist/inputmethodlist.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "native_engine/native_engine.h"
|
||||
|
||||
#include "napi/native_api.h"
|
||||
#include "napi/native_node_api.h"
|
||||
|
||||
extern const char _binary_inputmethodlist_abc_start[];
|
||||
extern const char _binary_inputmethodlist_abc_end[];
|
||||
|
||||
extern "C" __attribute__((visibility("default"))) void NAPI_inputMethodList_GetABCCode(const char **buf, int *buflen)
|
||||
{
|
||||
if (buf != nullptr) {
|
||||
*buf = _binary_inputmethodlist_abc_start;
|
||||
}
|
||||
|
||||
if (buf != nullptr) {
|
||||
*buflen = _binary_inputmethodlist_abc_end - _binary_inputmethodlist_abc_start;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" __attribute__((constructor)) void InputMethodListRegisterModule(void)
|
||||
{
|
||||
static napi_module inputMethodListModule = {
|
||||
.nm_version = 1,
|
||||
.nm_flags = 0,
|
||||
.nm_filename = nullptr,
|
||||
.nm_modname = "inputMethodList",
|
||||
.nm_priv = ((void*)0),
|
||||
.reserved = { 0 },
|
||||
};
|
||||
napi_module_register(&inputMethodListModule);
|
||||
}
|
690
frameworks/js/napi/inputmethodlist/inputmethodlist.js
Normal file
690
frameworks/js/napi/inputmethodlist/inputmethodlist.js
Normal file
@ -0,0 +1,690 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
let componentUtils = requireNapi('arkui.componentUtils');
|
||||
let display = requireNapi('display');
|
||||
let inputMethod = requireNapi('inputMethod');
|
||||
let inputMethodEngine = requireNapi('inputMethodEngine');
|
||||
let settings = requireNapi('settings');
|
||||
|
||||
function __Divider__divider() {
|
||||
Divider.height('1px');
|
||||
Divider.color('#10000000');
|
||||
Divider.margin({ left: 12, right: 12 });
|
||||
}
|
||||
|
||||
function __Text__textStyle() {
|
||||
Text.width('100%');
|
||||
Text.fontWeight(400);
|
||||
Text.maxLines(1);
|
||||
}
|
||||
|
||||
const TAG = 'InputMethodListDialog';
|
||||
const BIG_IMAGE_SIZE = 30;
|
||||
const NORMAL_IMAGE_SIZE = 24;
|
||||
const SCREEN_SIZE = 1920;
|
||||
const BIG_SCREEN_DPI = 1280;
|
||||
const NORMAL_SCREEN_DPI = 360;
|
||||
const BIG_DIALOG_WIDTH = 196;
|
||||
const NORMAL_DIALOG_WIDTH = 156;
|
||||
const BIG_FONT_SIZE = 20;
|
||||
const NORMAL_FONT_SIZE = 16;
|
||||
const BIG_ITEM_HEIGHT = 60;
|
||||
const NORMAL_ITEM_HEIGHT = 48;
|
||||
const NORMAL_IMAGE_BUTTON_WIDTH = 40;
|
||||
const NORMAL_IMAGE_BUTTON_HEIGHT = 32;
|
||||
const BIG_IMAGE_BUTTON_WIDTH = 50;
|
||||
const BIG_IMAGE_BUTTON_HEIGHT = 40;
|
||||
const NORMAL_COLUMN_PADDING = 4;
|
||||
const BIG_COLUMN_PADDING = 5;
|
||||
const NORMAL_IMAGE_RADIUS = 8;
|
||||
const BIG_IMAGE_RADIUS = 10;
|
||||
const NORMAL_FONT_PADDING = 12;
|
||||
const BIG_FONT_PADDING = 20;
|
||||
const NORMAL_ITEM_RADIUS = 16;
|
||||
const BIG_ITEM_RADIUS = 12;
|
||||
|
||||
export class InputMethodListDialog extends ViewPU {
|
||||
constructor(t, e, i, o = -1, n = void 0) {
|
||||
super(t, i, o);
|
||||
'function' === typeof n && (this.paramsGenerator_ = n);
|
||||
this.borderBgColor = '#00ffffff';
|
||||
this.listBgColor = '#ffffff';
|
||||
this.pressedColor = '#1A000000';
|
||||
this.selectedColor = '#220A59F7';
|
||||
this.fontColor = '#E6000000';
|
||||
this.selectedFontColor = '#0A59F7';
|
||||
this.__listItemHeight = new ObservedPropertySimplePU(48, this, 'listItemHeight');
|
||||
this.__listItemRadius = new ObservedPropertySimplePU(8, this, 'listItemRadius');
|
||||
this.__inputMethods = new ObservedPropertyObjectPU([], this, 'inputMethods');
|
||||
this.__fontSize = new ObservedPropertySimplePU(16, this, 'fontSize');
|
||||
this.__fontPadding = new ObservedPropertySimplePU(12, this, 'fontPadding');
|
||||
this.__dialogWidth = new ObservedPropertySimplePU(156, this, 'dialogWidth');
|
||||
this.__imageSize = new ObservedPropertySimplePU(24, this, 'imageSize');
|
||||
this.__imageBtnWidth = new ObservedPropertySimplePU(40, this, 'imageBtnWidth');
|
||||
this.__imageBtnHeight = new ObservedPropertySimplePU(32, this, 'imageBtnHeight');
|
||||
this.__columnPadding = new ObservedPropertySimplePU(4, this, 'columnPadding');
|
||||
this.__imageRadius = new ObservedPropertySimplePU(8, this, 'imageRadius');
|
||||
this.__subTypes = new ObservedPropertyObjectPU([], this, 'subTypes');
|
||||
this.__showHand = new ObservedPropertySimplePU(!1, this, 'showHand');
|
||||
this.__inputMethodConfig = new ObservedPropertyObjectPU(void 0, this, 'inputMethodConfig');
|
||||
this.__maxHeight = new ObservedPropertySimplePU(1, this, 'maxHeight');
|
||||
this.__defaultInputMethod = new ObservedPropertyObjectPU(void 0, this, 'defaultInputMethod');
|
||||
this.__currentInputMethod = new ObservedPropertyObjectPU(void 0, this, 'currentInputMethod');
|
||||
this.__currentSub = new ObservedPropertyObjectPU(void 0, this, 'currentSub');
|
||||
this.__viewOpacity = new ObservedPropertySimplePU(0, this, 'viewOpacity');
|
||||
this.__patternMode = this.createStorageLink('patternMode', 0, 'patternMode');
|
||||
this.controller = new CustomDialogController({ builder: void 0 }, this);
|
||||
this.patternOptions = void 0;
|
||||
this.setInitiallyProvidedValue(e);
|
||||
}
|
||||
|
||||
setInitiallyProvidedValue(t) {
|
||||
void 0 !== t.borderBgColor && (this.borderBgColor = t.borderBgColor);
|
||||
void 0 !== t.listBgColor && (this.listBgColor = t.listBgColor);
|
||||
void 0 !== t.pressedColor && (this.pressedColor = t.pressedColor);
|
||||
void 0 !== t.selectedColor && (this.selectedColor = t.selectedColor);
|
||||
void 0 !== t.fontColor && (this.fontColor = t.fontColor);
|
||||
void 0 !== t.selectedFontColor && (this.selectedFontColor = t.selectedFontColor);
|
||||
void 0 !== t.listItemHeight && (this.listItemHeight = t.listItemHeight);
|
||||
void 0 !== t.listItemRadius && (this.listItemRadius = t.listItemRadius);
|
||||
void 0 !== t.inputMethods && (this.inputMethods = t.inputMethods);
|
||||
void 0 !== t.fontSize && (this.fontSize = t.fontSize);
|
||||
void 0 !== t.fontPadding && (this.fontPadding = t.fontPadding);
|
||||
void 0 !== t.dialogWidth && (this.dialogWidth = t.dialogWidth);
|
||||
void 0 !== t.imageSize && (this.imageSize = t.imageSize);
|
||||
void 0 !== t.imageBtnWidth && (this.imageBtnWidth = t.imageBtnWidth);
|
||||
void 0 !== t.imageBtnHeight && (this.imageBtnHeight = t.imageBtnHeight);
|
||||
void 0 !== t.columnPadding && (this.columnPadding = t.columnPadding);
|
||||
void 0 !== t.imageRadius && (this.imageRadius = t.imageRadius);
|
||||
void 0 !== t.subTypes && (this.subTypes = t.subTypes);
|
||||
void 0 !== t.showHand && (this.showHand = t.showHand);
|
||||
void 0 !== t.inputMethodConfig && (this.inputMethodConfig = t.inputMethodConfig);
|
||||
void 0 !== t.maxHeight && (this.maxHeight = t.maxHeight);
|
||||
void 0 !== t.defaultInputMethod && (this.defaultInputMethod = t.defaultInputMethod);
|
||||
void 0 !== t.currentInputMethod && (this.currentInputMethod = t.currentInputMethod);
|
||||
void 0 !== t.currentSub && (this.currentSub = t.currentSub);
|
||||
void 0 !== t.viewOpacity && (this.viewOpacity = t.viewOpacity);
|
||||
void 0 !== t.controller && (this.controller = t.controller);
|
||||
void 0 !== t.patternOptions && (this.patternOptions = t.patternOptions);
|
||||
}
|
||||
|
||||
updateStateVars(t) {
|
||||
}
|
||||
|
||||
purgeVariableDependenciesOnElmtId(t) {
|
||||
this.__listItemHeight.purgeDependencyOnElmtId(t);
|
||||
this.__listItemRadius.purgeDependencyOnElmtId(t);
|
||||
this.__inputMethods.purgeDependencyOnElmtId(t);
|
||||
this.__fontSize.purgeDependencyOnElmtId(t);
|
||||
this.__fontPadding.purgeDependencyOnElmtId(t);
|
||||
this.__dialogWidth.purgeDependencyOnElmtId(t);
|
||||
this.__imageSize.purgeDependencyOnElmtId(t);
|
||||
this.__imageBtnWidth.purgeDependencyOnElmtId(t);
|
||||
this.__imageBtnHeight.purgeDependencyOnElmtId(t);
|
||||
this.__columnPadding.purgeDependencyOnElmtId(t);
|
||||
this.__imageRadius.purgeDependencyOnElmtId(t);
|
||||
this.__subTypes.purgeDependencyOnElmtId(t);
|
||||
this.__showHand.purgeDependencyOnElmtId(t);
|
||||
this.__inputMethodConfig.purgeDependencyOnElmtId(t);
|
||||
this.__maxHeight.purgeDependencyOnElmtId(t);
|
||||
this.__defaultInputMethod.purgeDependencyOnElmtId(t);
|
||||
this.__currentInputMethod.purgeDependencyOnElmtId(t);
|
||||
this.__currentSub.purgeDependencyOnElmtId(t);
|
||||
this.__viewOpacity.purgeDependencyOnElmtId(t);
|
||||
this.__patternMode.purgeDependencyOnElmtId(t);
|
||||
}
|
||||
|
||||
aboutToBeDeleted() {
|
||||
this.__listItemHeight.aboutToBeDeleted();
|
||||
this.__listItemRadius.aboutToBeDeleted();
|
||||
this.__inputMethods.aboutToBeDeleted();
|
||||
this.__fontSize.aboutToBeDeleted();
|
||||
this.__fontPadding.aboutToBeDeleted();
|
||||
this.__dialogWidth.aboutToBeDeleted();
|
||||
this.__imageSize.aboutToBeDeleted();
|
||||
this.__imageBtnWidth.aboutToBeDeleted();
|
||||
this.__imageBtnHeight.aboutToBeDeleted();
|
||||
this.__columnPadding.aboutToBeDeleted();
|
||||
this.__imageRadius.aboutToBeDeleted();
|
||||
this.__subTypes.aboutToBeDeleted();
|
||||
this.__showHand.aboutToBeDeleted();
|
||||
this.__inputMethodConfig.aboutToBeDeleted();
|
||||
this.__maxHeight.aboutToBeDeleted();
|
||||
this.__defaultInputMethod.aboutToBeDeleted();
|
||||
this.__currentInputMethod.aboutToBeDeleted();
|
||||
this.__currentSub.aboutToBeDeleted();
|
||||
this.__viewOpacity.aboutToBeDeleted();
|
||||
this.__patternMode.aboutToBeDeleted();
|
||||
SubscriberManager.Get().delete(this.id__());
|
||||
this.aboutToBeDeletedInternal();
|
||||
}
|
||||
|
||||
get listItemHeight() {
|
||||
return this.__listItemHeight.get();
|
||||
}
|
||||
|
||||
set listItemHeight(t) {
|
||||
this.__listItemHeight.set(t);
|
||||
}
|
||||
|
||||
get listItemRadius() {
|
||||
return this.__listItemRadius.get();
|
||||
}
|
||||
|
||||
set listItemRadius(t) {
|
||||
this.__listItemRadius.set(t);
|
||||
}
|
||||
|
||||
get inputMethods() {
|
||||
return this.__inputMethods.get();
|
||||
}
|
||||
|
||||
set inputMethods(t) {
|
||||
this.__inputMethods.set(t);
|
||||
}
|
||||
|
||||
get fontSize() {
|
||||
return this.__fontSize.get();
|
||||
}
|
||||
|
||||
set fontSize(t) {
|
||||
this.__fontSize.set(t);
|
||||
}
|
||||
|
||||
get fontPadding() {
|
||||
return this.__fontPadding.get();
|
||||
}
|
||||
|
||||
set fontPadding(t) {
|
||||
this.__fontPadding.set(t);
|
||||
}
|
||||
|
||||
get dialogWidth() {
|
||||
return this.__dialogWidth.get();
|
||||
}
|
||||
|
||||
set dialogWidth(t) {
|
||||
this.__dialogWidth.set(t);
|
||||
}
|
||||
|
||||
get imageSize() {
|
||||
return this.__imageSize.get();
|
||||
}
|
||||
|
||||
set imageSize(t) {
|
||||
this.__imageSize.set(t);
|
||||
}
|
||||
|
||||
get imageBtnWidth() {
|
||||
return this.__imageBtnWidth.get();
|
||||
}
|
||||
|
||||
set imageBtnWidth(t) {
|
||||
this.__imageBtnWidth.set(t);
|
||||
}
|
||||
|
||||
get imageBtnHeight() {
|
||||
return this.__imageBtnHeight.get();
|
||||
}
|
||||
|
||||
set imageBtnHeight(t) {
|
||||
this.__imageBtnHeight.set(t);
|
||||
}
|
||||
|
||||
get columnPadding() {
|
||||
return this.__columnPadding.get();
|
||||
}
|
||||
|
||||
set columnPadding(t) {
|
||||
this.__columnPadding.set(t);
|
||||
}
|
||||
|
||||
get imageRadius() {
|
||||
return this.__imageRadius.get();
|
||||
}
|
||||
|
||||
set imageRadius(t) {
|
||||
this.__imageRadius.set(t);
|
||||
}
|
||||
|
||||
get subTypes() {
|
||||
return this.__subTypes.get();
|
||||
}
|
||||
|
||||
set subTypes(t) {
|
||||
this.__subTypes.set(t);
|
||||
}
|
||||
|
||||
get showHand() {
|
||||
return this.__showHand.get();
|
||||
}
|
||||
|
||||
set showHand(t) {
|
||||
this.__showHand.set(t);
|
||||
}
|
||||
|
||||
get inputMethodConfig() {
|
||||
return this.__inputMethodConfig.get();
|
||||
}
|
||||
|
||||
set inputMethodConfig(t) {
|
||||
this.__inputMethodConfig.set(t);
|
||||
}
|
||||
|
||||
get maxHeight() {
|
||||
return this.__maxHeight.get();
|
||||
}
|
||||
|
||||
set maxHeight(t) {
|
||||
this.__maxHeight.set(t);
|
||||
}
|
||||
|
||||
get defaultInputMethod() {
|
||||
return this.__defaultInputMethod.get();
|
||||
}
|
||||
|
||||
set defaultInputMethod(t) {
|
||||
this.__defaultInputMethod.set(t);
|
||||
}
|
||||
|
||||
get currentInputMethod() {
|
||||
return this.__currentInputMethod.get();
|
||||
}
|
||||
|
||||
set currentInputMethod(t) {
|
||||
this.__currentInputMethod.set(t);
|
||||
}
|
||||
|
||||
get currentSub() {
|
||||
return this.__currentSub.get();
|
||||
}
|
||||
|
||||
set currentSub(t) {
|
||||
this.__currentSub.set(t);
|
||||
}
|
||||
|
||||
get viewOpacity() {
|
||||
return this.__viewOpacity.get();
|
||||
}
|
||||
|
||||
set viewOpacity(t) {
|
||||
this.__viewOpacity.set(t);
|
||||
}
|
||||
|
||||
get patternMode() {
|
||||
return this.__patternMode.get();
|
||||
}
|
||||
|
||||
set patternMode(t) {
|
||||
this.__patternMode.set(t);
|
||||
}
|
||||
|
||||
setController(t) {
|
||||
this.controller = t;
|
||||
}
|
||||
|
||||
async getDefaultInputMethodSubType() {
|
||||
console.info(`${TAG} getDefaultInputMethodSubType`);
|
||||
this.inputMethodConfig = inputMethod.getSystemInputMethodConfigAbility();
|
||||
this.inputMethodConfig && console.info(`${TAG} inputMethodConfig: ${JSON.stringify(this.inputMethodConfig)}`);
|
||||
this.inputMethods = await inputMethod.getSetting().getInputMethods(!0);
|
||||
this.defaultInputMethod = inputMethod.getDefaultInputMethod();
|
||||
this.currentInputMethod = inputMethod.getCurrentInputMethod();
|
||||
let t = 0;
|
||||
for (let e = 0; e < this.inputMethods.length; e++) {
|
||||
if (this.inputMethods[e].name === this.defaultInputMethod.name) {
|
||||
t = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.inputMethods.splice(t, 1);
|
||||
this.inputMethods.unshift(this.defaultInputMethod);
|
||||
this.currentSub = inputMethod.getCurrentInputMethodSubtype();
|
||||
console.info(`${TAG} defaultInput: ${JSON.stringify(this.defaultInputMethod)}`);
|
||||
if (this.defaultInputMethod.name === this.currentInputMethod.name && this.patternOptions) {
|
||||
if (void 0 === AppStorage.get('patternMode')) {
|
||||
this.patternOptions.defaultSelected ? this.patternMode = this.patternOptions.defaultSelected :
|
||||
this.patternMode = 0;
|
||||
AppStorage.setOrCreate('patternMode', this.patternMode);
|
||||
} else {
|
||||
this.patternMode = AppStorage.get('patternMode');
|
||||
}
|
||||
this.showHand = !0;
|
||||
}
|
||||
let e = await inputMethod.getSetting().listInputMethodSubtype(this.defaultInputMethod);
|
||||
console.info(`${TAG} defaultSubTypes: ${JSON.stringify(e)}`);
|
||||
let i = getContext(this);
|
||||
try {
|
||||
let t = await settings.getValue(i, settings.input.ACTIVATED_INPUT_METHOD_SUB_MODE);
|
||||
if (t) {
|
||||
console.info(`${TAG} activeSubType: ${t}`);
|
||||
for (let e = 0; e < this.inputMethods.length; e++) {
|
||||
if (this.inputMethods[e].name === this.defaultInputMethod.name) {
|
||||
this.defaultInputMethod = this.inputMethods[e];
|
||||
let i = await inputMethod.getSetting().listInputMethodSubtype(this.inputMethods[e]);
|
||||
for (let e = 0; e < i.length; e++) {
|
||||
-1 !== t.indexOf(i[e].id) && this.subTypes.push(i[e]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (t) {
|
||||
this.subTypes = [];
|
||||
console.info(`${TAG} subTypes is empty, err = ${JSON.stringify(t)}`);
|
||||
}
|
||||
let o = 0 === this.subTypes.length ? this.inputMethods.length : this.subTypes.length + this.inputMethods.length - 1;
|
||||
o += this.inputMethodConfig && this.inputMethodConfig.bundleName.length > 0 ? 1 : 0;
|
||||
o += this.patternOptions && this.showHand ? 1 : 0;
|
||||
let n = o * this.listItemHeight + 2 * this.columnPadding;
|
||||
console.info(`${TAG} height: ${n}`);
|
||||
this.maxHeight > n && (this.maxHeight = n);
|
||||
this.viewOpacity = 1;
|
||||
}
|
||||
|
||||
aboutToAppear() {
|
||||
console.info(`${TAG} aboutToAppear`);
|
||||
let t = display.getDefaultDisplaySync();
|
||||
if (t.width > 1920) {
|
||||
this.dialogWidth = 196 * px2vp(t.width) / 1280;
|
||||
this.fontSize = 20 * px2vp(t.width) / 1280;
|
||||
this.imageSize = 30 * px2vp(t.width) / 1280;
|
||||
this.listItemHeight = 60 * px2vp(t.width) / 360;
|
||||
this.imageBtnWidth = 50 * px2vp(t.width) / 1280;
|
||||
this.imageBtnHeight = 40 * px2vp(t.width) / 1280;
|
||||
this.columnPadding = 5 * px2vp(t.width) / 1280;
|
||||
this.fontPadding = 20 * px2vp(t.width) / 1280;
|
||||
this.listItemRadius = 12 * px2vp(t.width) / 1280;
|
||||
this.imageRadius = 10;
|
||||
} else {
|
||||
this.dialogWidth = 156 * px2vp(t.width) / 360;
|
||||
this.fontSize = 16 * px2vp(t.width) / 360;
|
||||
this.imageSize = 24 * px2vp(t.width) / 360;
|
||||
this.listItemHeight = 48 * px2vp(t.width) / 360;
|
||||
this.imageBtnWidth = 40 * px2vp(t.width) / 360;
|
||||
this.imageBtnHeight = 32 * px2vp(t.width) / 360;
|
||||
this.columnPadding = 4 * px2vp(t.width) / 360;
|
||||
this.fontPadding = 12 * px2vp(t.width) / 360;
|
||||
this.listItemRadius = 16 * px2vp(t.width) / 360;
|
||||
this.imageRadius = 8;
|
||||
}
|
||||
this.getDefaultInputMethodSubType();
|
||||
inputMethodEngine.getInputMethodAbility().on('keyboardHide', (() => {
|
||||
this.controller.close();
|
||||
}));
|
||||
}
|
||||
|
||||
initialRender() {
|
||||
this.observeComponentCreation2(((t, e) => {
|
||||
Stack.create({ alignContent: Alignment.BottomStart });
|
||||
Stack.id('inputDialog');
|
||||
Stack.height('100%');
|
||||
Stack.width('100%');
|
||||
Stack.opacity(this.viewOpacity);
|
||||
Stack.backgroundColor(this.borderBgColor);
|
||||
Stack.transition(TransitionEffect.translate({ y: 400 }).combine(TransitionEffect.scale({
|
||||
x: 1,
|
||||
y: 0
|
||||
})).animation({ duration: 500 }));
|
||||
Stack.onAppear((() => {
|
||||
let t = componentUtils.getRectangleById('inputDialog');
|
||||
this.maxHeight = px2vp(t.size.height + t.windowOffset.y) - 10;
|
||||
}));
|
||||
Stack.onClick((() => {
|
||||
this.controller.close();
|
||||
}))
|
||||
}), Stack);
|
||||
this.observeComponentCreation2(((t, e) => {
|
||||
Column.create();
|
||||
Column.width(this.dialogWidth);
|
||||
Column.margin({ top: this.columnPadding });
|
||||
Column.borderRadius('16vp');
|
||||
Column.backgroundColor(this.listBgColor);
|
||||
Column.height(this.maxHeight);
|
||||
Column.padding(this.columnPadding);
|
||||
Column.shadow(ShadowStyle.OUTER_DEFAULT_SM);
|
||||
}), Column);
|
||||
this.observeComponentCreation2(((t, e) => {
|
||||
If.create();
|
||||
this.inputMethodConfig && this.inputMethodConfig.bundleName.length > 0 ? this.ifElseBranchUpdateFunction(0, (() => {
|
||||
this.observeComponentCreation2(((t, e) => {
|
||||
Text.create({
|
||||
id: -1,
|
||||
type: 10003,
|
||||
params: ['sys.string.ohos_id_input_method_settings'],
|
||||
bundleName: '',
|
||||
moduleName: ''
|
||||
});
|
||||
__Text__textStyle();
|
||||
Text.padding({ left: this.fontPadding, right: this.fontPadding });
|
||||
Text.height(this.listItemHeight);
|
||||
Text.borderRadius(this.listItemRadius);
|
||||
Text.fontSize(this.fontSize);
|
||||
Text.fontColor(this.fontColor);
|
||||
ViewStackProcessor.visualState('pressed');
|
||||
Text.backgroundColor(this.pressedColor);
|
||||
ViewStackProcessor.visualState('normal');
|
||||
Text.backgroundColor(this.listBgColor);
|
||||
ViewStackProcessor.visualState();
|
||||
Text.onClick((() => {
|
||||
if (this.inputMethodConfig) {
|
||||
getContext(this).startAbility({
|
||||
bundleName: this.inputMethodConfig.bundleName,
|
||||
moduleName: this.inputMethodConfig.moduleName,
|
||||
abilityName: this.inputMethodConfig.abilityName
|
||||
});
|
||||
}
|
||||
}));
|
||||
}), Text);
|
||||
Text.pop();
|
||||
this.observeComponentCreation2(((t, e) => {
|
||||
Divider.create();
|
||||
__Divider__divider();
|
||||
}), Divider);
|
||||
})) : this.ifElseBranchUpdateFunction(1, (() => {
|
||||
}));
|
||||
}), If);
|
||||
If.pop();
|
||||
this.observeComponentCreation2(((t, e) => {
|
||||
Scroll.create();
|
||||
Scroll.width('100%');
|
||||
Scroll.scrollBar(BarState.Off);
|
||||
Scroll.layoutWeight(1);
|
||||
}), Scroll);
|
||||
this.observeComponentCreation2(((t, e) => {
|
||||
Column.create();
|
||||
Column.width('100%');
|
||||
}), Column);
|
||||
this.observeComponentCreation2(((t, e) => {
|
||||
ForEach.create();
|
||||
this.forEachUpdateFunction(t, this.subTypes, ((t, e) => {
|
||||
const i = t;
|
||||
this.observeComponentCreation2(((t, e) => {
|
||||
Column.create();
|
||||
Column.width('100%');
|
||||
Column.onClick((() => {
|
||||
this.switchMethodSub(i);
|
||||
}));
|
||||
}), Column);
|
||||
this.observeComponentCreation2(((t, e) => {
|
||||
Text.create(i.label);
|
||||
Text.fontSize(this.fontSize);
|
||||
__Text__textStyle();
|
||||
Text.padding({ left: this.fontPadding, right: this.fontPadding });
|
||||
Text.height(this.listItemHeight);
|
||||
Text.borderRadius(this.listItemRadius);
|
||||
Text.fontColor(this.currentSub && this.currentSub.id === i.id && this.currentSub.name === i.name ?
|
||||
this.selectedFontColor : this.fontColor);
|
||||
ViewStackProcessor.visualState('pressed');
|
||||
Text.backgroundColor(this.pressedColor);
|
||||
ViewStackProcessor.visualState('normal');
|
||||
Text.backgroundColor(this.currentSub && this.currentSub.id === i.id && this.currentSub.name === i.name ?
|
||||
this.selectedColor : this.listBgColor);
|
||||
ViewStackProcessor.visualState();
|
||||
}), Text);
|
||||
Text.pop();
|
||||
this.observeComponentCreation2(((t, i) => {
|
||||
If.create();
|
||||
this.inputMethods.length > 1 || e < this.subTypes.length ? this.ifElseBranchUpdateFunction(0, (() => {
|
||||
this.observeComponentCreation2(((t, e) => {
|
||||
Divider.create();
|
||||
__Divider__divider();
|
||||
}), Divider);
|
||||
})) : this.ifElseBranchUpdateFunction(1, (() => {
|
||||
}));
|
||||
}), If);
|
||||
If.pop();
|
||||
Column.pop();
|
||||
}), (t => JSON.stringify(t)),!0,!1);
|
||||
}), ForEach);
|
||||
ForEach.pop();
|
||||
this.observeComponentCreation2(((t, e) => {
|
||||
ForEach.create();
|
||||
this.forEachUpdateFunction(t, this.inputMethods, ((t, e) => {
|
||||
const i = t;
|
||||
this.observeComponentCreation2(((t, o) => {
|
||||
If.create();
|
||||
0 === this.subTypes.length || this.defaultInputMethod && i.name !== this.defaultInputMethod.name ?
|
||||
this.ifElseBranchUpdateFunction(0, (() => {
|
||||
this.observeComponentCreation2(((t, e) => {
|
||||
Text.create(i.label);
|
||||
Text.fontSize(this.fontSize);
|
||||
__Text__textStyle();
|
||||
Text.padding({ left: this.fontPadding, right: this.fontPadding });
|
||||
Text.height(this.listItemHeight);
|
||||
Text.borderRadius(this.listItemRadius);
|
||||
Text.fontColor(this.currentSub && this.currentSub.id === i.id && this.currentSub.name === i.name ?
|
||||
this.selectedFontColor : this.fontColor);
|
||||
ViewStackProcessor.visualState('pressed');
|
||||
Text.backgroundColor(this.pressedColor);
|
||||
ViewStackProcessor.visualState('normal');
|
||||
Text.backgroundColor(this.currentInputMethod && this.currentInputMethod.name === i.name ?
|
||||
this.selectedColor : this.listBgColor);
|
||||
ViewStackProcessor.visualState();
|
||||
Text.onClick((() => {
|
||||
this.switchMethod(i);
|
||||
}))
|
||||
}), Text);
|
||||
Text.pop();
|
||||
this.observeComponentCreation2(((t, i) => {
|
||||
If.create();
|
||||
e < this.inputMethods.length - 1 ? this.ifElseBranchUpdateFunction(0, (() => {
|
||||
this.observeComponentCreation2(((t, e) => {
|
||||
Divider.create();
|
||||
__Divider__divider();
|
||||
}), Divider);
|
||||
})) : this.ifElseBranchUpdateFunction(1, (() => {
|
||||
}))
|
||||
}), If);
|
||||
If.pop();
|
||||
})) : this.ifElseBranchUpdateFunction(1, (() => {
|
||||
}))
|
||||
}), If);
|
||||
If.pop();
|
||||
}), (t => JSON.stringify(t)),!0,!1);
|
||||
}), ForEach);
|
||||
ForEach.pop();
|
||||
Column.pop();
|
||||
Scroll.pop();
|
||||
this.observeComponentCreation2(((t, e) => {
|
||||
If.create();
|
||||
this.patternOptions && this.showHand ? this.ifElseBranchUpdateFunction(0, (() => {
|
||||
this.observeComponentCreation2(((t, e) => {
|
||||
Divider.create();
|
||||
__Divider__divider();
|
||||
}), Divider);
|
||||
this.observeComponentCreation2(((t, e) => {
|
||||
Row.create();
|
||||
Row.width('100%');
|
||||
Row.height(this.listItemHeight);;
|
||||
Row.justifyContent(FlexAlign.SpaceEvenly);
|
||||
}), Row);
|
||||
this.observeComponentCreation2(((t, e) => {
|
||||
ForEach.create();
|
||||
this.forEachUpdateFunction(t, this.patternOptions.patterns, ((t, e) => {
|
||||
const i = t;
|
||||
this.observeComponentCreation2(((t, i) => {
|
||||
Row.create();
|
||||
Row.justifyContent(FlexAlign.Center);
|
||||
Row.size({ width: this.imageBtnWidth, height: this.imageBtnHeight });
|
||||
Row.borderRadius(this.imageRadius);
|
||||
ViewStackProcessor.visualState('pressed');
|
||||
Row.backgroundColor(this.pressedColor);
|
||||
ViewStackProcessor.visualState('normal');
|
||||
Row.backgroundColor(this.listBgColor);
|
||||
ViewStackProcessor.visualState();
|
||||
Row.onClick((() => {
|
||||
this.switchPositionPattern(e);
|
||||
}))
|
||||
}), Row);
|
||||
this.observeComponentCreation2(((t, o) => {
|
||||
Image.create(e === this.patternMode ? i.selectedIcon : i.icon);
|
||||
Image.size({ width: this.imageSize, height: this.imageSize });
|
||||
Image.objectFit(ImageFit.Contain);
|
||||
}), Image);
|
||||
Row.pop();
|
||||
}), (t => JSON.stringify(t)),!0,!1);
|
||||
}), ForEach);
|
||||
ForEach.pop();
|
||||
Row.pop();
|
||||
})) : this.ifElseBranchUpdateFunction(1, (() => {
|
||||
}));
|
||||
}), If);
|
||||
If.pop();
|
||||
Column.pop();
|
||||
Stack.pop();
|
||||
}
|
||||
|
||||
switchPositionPattern(t) {
|
||||
if (this.patternOptions) {
|
||||
this.patternMode = t;
|
||||
AppStorage.set('patternMode', this.patternMode);
|
||||
console.info(`${TAG} this.handMode = ${this.patternMode}`);
|
||||
this.patternOptions.action(this.patternMode);
|
||||
this.controller.close();
|
||||
}
|
||||
}
|
||||
|
||||
async switchMethod(t) {
|
||||
if (this.currentInputMethod && this.currentInputMethod.name !== t.name) {
|
||||
let e = await inputMethod.getSetting().listInputMethodSubtype(t);
|
||||
inputMethod.switchCurrentInputMethodAndSubtype(t, e[0], ((e, i) => {
|
||||
i && (this.currentInputMethod = t);
|
||||
this.controller.close();
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
switchMethodSub(t) {
|
||||
this.currentInputMethod && this.defaultInputMethod &&
|
||||
(this.currentInputMethod.name !== this.defaultInputMethod.name ?
|
||||
inputMethod.switchCurrentInputMethodAndSubtype(this.defaultInputMethod, t, (() => {
|
||||
this.currentInputMethod = this.defaultInputMethod;
|
||||
this.currentSub = t;
|
||||
this.controller.close();
|
||||
})) : inputMethod.switchCurrentInputMethodSubtype(t, (() => {
|
||||
this.currentSub = t;
|
||||
this.controller.close();
|
||||
})));
|
||||
}
|
||||
|
||||
rerender() {
|
||||
this.updateDirtyElements();
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
InputMethodListDialog
|
||||
};
|
404
frameworks/js/napi/inputmethodlist/source/inputmethodlist.ets
Normal file
404
frameworks/js/napi/inputmethodlist/source/inputmethodlist.ets
Normal file
@ -0,0 +1,404 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import InputMethodSubtype from '@ohos.InputMethodSubtype';
|
||||
import inputMethod from '@ohos.inputMethod';
|
||||
import componentUtils from '@ohos.arkui.componentUtils';
|
||||
import settings from '@ohos.settings';
|
||||
import common from '@ohos.app.ability.common';
|
||||
import display from '@ohos.display';
|
||||
import bundleManager from '@ohos.bundle.bundleManager';
|
||||
import inputMethodEngine from '@ohos.inputMethodEngine';
|
||||
|
||||
export interface PatternOptions {
|
||||
defaultSelected: number;
|
||||
patterns: Array<Pattern>
|
||||
action: (index: number) => void;
|
||||
}
|
||||
|
||||
export interface Pattern {
|
||||
icon: Resource;
|
||||
selectedIcon: Resource;
|
||||
}
|
||||
|
||||
@Extend(Divider)
|
||||
function divider() {
|
||||
.height('1px')
|
||||
.color('#10000000')
|
||||
.margin({ left: 12, right: 12 })
|
||||
}
|
||||
|
||||
@Extend(Text)
|
||||
function textStyle() {
|
||||
.width('100%')
|
||||
.fontWeight(400)
|
||||
.maxLines(1)
|
||||
}
|
||||
|
||||
const TAG: string = 'InputMethodListDialog';
|
||||
const BIG_IMAGE_SIZE: number = 30;
|
||||
const NORMAL_IMAGE_SIZE: number = 24;
|
||||
const SCREEN_SIZE: number = 1920;
|
||||
const BIG_SCREEN_DPI: number = 1280;
|
||||
const NORMAL_SCREEN_DPI: number = 360;
|
||||
const BIG_DIALOG_WIDTH: number = 196;
|
||||
const NORMAL_DIALOG_WIDTH: number = 156;
|
||||
const BIG_FONT_SIZE: number = 20;
|
||||
const NORMAL_FONT_SIZE: number = 16;
|
||||
const BIG_ITEM_HEIGHT: number = 60;
|
||||
const NORMAL_ITEM_HEIGHT: number = 48;
|
||||
const NORMAL_IMAGE_BUTTON_WIDTH: number = 40;
|
||||
const NORMAL_IMAGE_BUTTON_HEIGHT: number = 32;
|
||||
const BIG_IMAGE_BUTTON_WIDTH: number = 50;
|
||||
const BIG_IMAGE_BUTTON_HEIGHT: number = 40;
|
||||
const NORMAL_COLUMN_PADDING: number = 4;
|
||||
const BIG_COLUMN_PADDING: number = 5;
|
||||
const NORMAL_IMAGE_RADIUS: number = 8;
|
||||
const BIG_IMAGE_RADIUS: number = 10;
|
||||
const NORMAL_FONT_PADDING: number = 12;
|
||||
const BIG_FONT_PADDING: number = 20;
|
||||
const NORMAL_ITEM_RADIUS: number = 16;
|
||||
const BIG_ITEM_RADIUS: number = 12;
|
||||
|
||||
@CustomDialog
|
||||
export struct InputMethodListDialog {
|
||||
private borderBgColor: ResourceColor = '#00ffffff';
|
||||
private listBgColor: ResourceColor = '#ffffff';
|
||||
private pressedColor: ResourceColor = '#1A000000'
|
||||
private selectedColor: ResourceColor = '#220A59F7';
|
||||
private fontColor: ResourceColor = '#E6000000';
|
||||
private selectedFontColor: ResourceColor = '#0A59F7';
|
||||
@State listItemHeight: number = NORMAL_ITEM_HEIGHT;
|
||||
@State listItemRadius: number = NORMAL_IMAGE_RADIUS;
|
||||
@State inputMethods: Array<inputMethod.InputMethodProperty> = [];
|
||||
@State fontSize: number = NORMAL_FONT_SIZE;
|
||||
@State fontPadding: number = NORMAL_FONT_PADDING;
|
||||
@State dialogWidth: number = NORMAL_DIALOG_WIDTH;
|
||||
@State imageSize: number = NORMAL_IMAGE_SIZE;
|
||||
@State imageBtnWidth: number = NORMAL_IMAGE_BUTTON_WIDTH;
|
||||
@State imageBtnHeight: number = NORMAL_IMAGE_BUTTON_HEIGHT;
|
||||
@State columnPadding: number = NORMAL_COLUMN_PADDING;
|
||||
@State imageRadius: number = NORMAL_IMAGE_RADIUS;
|
||||
@State subTypes: Array<InputMethodSubtype> = [];
|
||||
@State showHand: boolean = false;
|
||||
@State inputMethodConfig: bundleManager.ElementName | undefined = undefined;
|
||||
@State maxHeight: number = 1;
|
||||
@State defaultInputMethod: inputMethod.InputMethodProperty | undefined = undefined;
|
||||
@State currentInputMethod: inputMethod.InputMethodProperty | undefined = undefined;
|
||||
@State currentSub: InputMethodSubtype | undefined = undefined;
|
||||
@State viewOpacity: number = 0;
|
||||
@StorageLink('patternMode') patternMode: number | undefined = 0;
|
||||
controller: CustomDialogController = new CustomDialogController({ builder: undefined });
|
||||
patternOptions?: PatternOptions;
|
||||
|
||||
async getDefaultInputMethodSubType() {
|
||||
console.info(`${TAG} getDefaultInputMethodSubType`);
|
||||
this.inputMethodConfig = inputMethod.getSystemInputMethodConfigAbility();
|
||||
if (this.inputMethodConfig) {
|
||||
console.info(`${TAG} inputMethodConfig: ${JSON.stringify(this.inputMethodConfig)}`);
|
||||
}
|
||||
this.inputMethods = await inputMethod.getSetting().getInputMethods(true);
|
||||
this.defaultInputMethod = inputMethod.getDefaultInputMethod();
|
||||
this.currentInputMethod = inputMethod.getCurrentInputMethod();
|
||||
let index = 0;
|
||||
for (let k = 0;k < this.inputMethods.length; k++) {
|
||||
if (this.inputMethods[k].name === this.defaultInputMethod.name) {
|
||||
index = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.inputMethods.splice(index, 1);
|
||||
this.inputMethods.unshift(this.defaultInputMethod);
|
||||
this.currentSub = inputMethod.getCurrentInputMethodSubtype();
|
||||
console.info(`${TAG} defaultInput: ${JSON.stringify(this.defaultInputMethod)}`);
|
||||
if (this.defaultInputMethod.name === this.currentInputMethod.name) {
|
||||
if (this.patternOptions) {
|
||||
if (AppStorage.get<number>('patternMode') === undefined) {
|
||||
if (this.patternOptions.defaultSelected) {
|
||||
this.patternMode = this.patternOptions.defaultSelected;
|
||||
} else {
|
||||
this.patternMode = 0;
|
||||
}
|
||||
AppStorage.setOrCreate('patternMode', this.patternMode);
|
||||
} else {
|
||||
this.patternMode = AppStorage.get<number>('patternMode');
|
||||
}
|
||||
this.showHand = true;
|
||||
}
|
||||
}
|
||||
let listSubTypes = await inputMethod.getSetting().listInputMethodSubtype(this.defaultInputMethod);
|
||||
console.info(`${TAG} defaultSubTypes: ${JSON.stringify(listSubTypes)}`);
|
||||
let context = getContext(this) as common.UIAbilityContext;
|
||||
try {
|
||||
let activeSubType = await settings.getValue(context, settings.input.ACTIVATED_INPUT_METHOD_SUB_MODE);
|
||||
if (activeSubType) {
|
||||
console.info(`${TAG} activeSubType: ${activeSubType}`);
|
||||
for (let i = 0;i < this.inputMethods.length; i++) {
|
||||
if (this.inputMethods[i].name === this.defaultInputMethod.name) {
|
||||
this.defaultInputMethod = this.inputMethods[i];
|
||||
let defaultSubTypes = await inputMethod.getSetting().listInputMethodSubtype(this.inputMethods[i]);
|
||||
for (let k = 0;k < defaultSubTypes.length; k++) {
|
||||
if (activeSubType.indexOf(defaultSubTypes[k].id) !== -1) {
|
||||
this.subTypes.push(defaultSubTypes[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
this.subTypes = [];
|
||||
console.info(`${TAG} subTypes is empty, err = ${JSON.stringify(err)}`);
|
||||
}
|
||||
let size = this.subTypes.length == 0 ? this.inputMethods.length : this.subTypes.length + this.inputMethods.length - 1
|
||||
size += (this.inputMethodConfig && this.inputMethodConfig.bundleName.length > 0) ? 1 : 0;
|
||||
size += this.patternOptions && this.showHand ? 1 : 0;
|
||||
let height = size * this.listItemHeight + this.columnPadding * 2;
|
||||
console.info(`${TAG} height: ${height}`);
|
||||
if (this.maxHeight > height) {
|
||||
this.maxHeight = height;
|
||||
}
|
||||
this.viewOpacity = 1;
|
||||
}
|
||||
|
||||
aboutToAppear() {
|
||||
console.info(`${TAG} aboutToAppear`);
|
||||
let defaultDisplay = display.getDefaultDisplaySync();
|
||||
if (defaultDisplay.width > SCREEN_SIZE) {
|
||||
this.dialogWidth = px2vp(defaultDisplay.width) * BIG_DIALOG_WIDTH / BIG_SCREEN_DPI;
|
||||
this.fontSize = px2vp(defaultDisplay.width) * BIG_FONT_SIZE / BIG_SCREEN_DPI;
|
||||
this.imageSize = px2vp(defaultDisplay.width) * BIG_IMAGE_SIZE / BIG_SCREEN_DPI;
|
||||
this.listItemHeight = px2vp(defaultDisplay.width) * BIG_ITEM_HEIGHT / NORMAL_SCREEN_DPI;
|
||||
this.imageBtnWidth = px2vp(defaultDisplay.width) * BIG_IMAGE_BUTTON_WIDTH / BIG_SCREEN_DPI;
|
||||
this.imageBtnHeight = px2vp(defaultDisplay.width) * BIG_IMAGE_BUTTON_HEIGHT / BIG_SCREEN_DPI;
|
||||
this.columnPadding = px2vp(defaultDisplay.width) * BIG_COLUMN_PADDING / BIG_SCREEN_DPI;
|
||||
this.fontPadding = px2vp(defaultDisplay.width) * BIG_FONT_PADDING / BIG_SCREEN_DPI;
|
||||
this.listItemRadius = px2vp(defaultDisplay.width) * BIG_ITEM_RADIUS / BIG_SCREEN_DPI;
|
||||
this.imageRadius = BIG_IMAGE_RADIUS;
|
||||
|
||||
} else {
|
||||
this.dialogWidth = px2vp(defaultDisplay.width) * NORMAL_DIALOG_WIDTH / NORMAL_SCREEN_DPI;
|
||||
this.fontSize = px2vp(defaultDisplay.width) * NORMAL_FONT_SIZE / NORMAL_SCREEN_DPI;
|
||||
this.imageSize = px2vp(defaultDisplay.width) * NORMAL_IMAGE_SIZE / NORMAL_SCREEN_DPI;
|
||||
this.listItemHeight = px2vp(defaultDisplay.width) * NORMAL_ITEM_HEIGHT / NORMAL_SCREEN_DPI;
|
||||
this.imageBtnWidth = px2vp(defaultDisplay.width) * NORMAL_IMAGE_BUTTON_WIDTH / NORMAL_SCREEN_DPI;
|
||||
this.imageBtnHeight = px2vp(defaultDisplay.width) * NORMAL_IMAGE_BUTTON_HEIGHT / NORMAL_SCREEN_DPI;
|
||||
this.columnPadding = px2vp(defaultDisplay.width) * NORMAL_COLUMN_PADDING / NORMAL_SCREEN_DPI;
|
||||
this.fontPadding = px2vp(defaultDisplay.width) * NORMAL_FONT_PADDING / NORMAL_SCREEN_DPI;
|
||||
this.listItemRadius = px2vp(defaultDisplay.width) * NORMAL_ITEM_RADIUS / NORMAL_SCREEN_DPI;
|
||||
this.imageRadius = NORMAL_IMAGE_RADIUS;
|
||||
}
|
||||
this.getDefaultInputMethodSubType();
|
||||
let inputMethodAbility = inputMethodEngine.getInputMethodAbility();
|
||||
inputMethodAbility.on('keyboardHide', () => {
|
||||
this.controller.close();
|
||||
});
|
||||
}
|
||||
|
||||
@Styles
|
||||
listItemStyle(){
|
||||
.padding({ left: this.fontPadding, right: this.fontPadding })
|
||||
.height(this.listItemHeight)
|
||||
.borderRadius(this.listItemRadius)
|
||||
}
|
||||
|
||||
build() {
|
||||
Stack({ alignContent: Alignment.BottomStart }) {
|
||||
Column() {
|
||||
if (this.inputMethodConfig && this.inputMethodConfig.bundleName.length > 0) {
|
||||
Text($r('sys.string.ohos_id_input_method_settings'))
|
||||
.textStyle()
|
||||
.listItemStyle()
|
||||
.fontSize(this.fontSize)
|
||||
.fontColor(this.fontColor)
|
||||
.stateStyles({
|
||||
pressed: {
|
||||
.backgroundColor(this.pressedColor)
|
||||
},
|
||||
normal: {
|
||||
.backgroundColor(this.listBgColor)
|
||||
}
|
||||
})
|
||||
.onClick(() => {
|
||||
if (this.inputMethodConfig) {
|
||||
let context = getContext(this) as common.UIAbilityContext;
|
||||
context.startAbility({
|
||||
bundleName: this.inputMethodConfig.bundleName,
|
||||
moduleName: this.inputMethodConfig.moduleName,
|
||||
abilityName: this.inputMethodConfig.abilityName
|
||||
});
|
||||
}
|
||||
})
|
||||
Divider()
|
||||
.divider()
|
||||
}
|
||||
Scroll() {
|
||||
Column() {
|
||||
ForEach(this.subTypes, (item: InputMethodSubtype, index: number) => {
|
||||
Column() {
|
||||
Text(item.label)
|
||||
.fontSize(this.fontSize)
|
||||
.textStyle()
|
||||
.listItemStyle()
|
||||
.fontColor((this.currentSub && this.currentSub.id === item.id && this.currentSub.name === item.name)
|
||||
? this.selectedFontColor : this.fontColor)
|
||||
.stateStyles({
|
||||
pressed: {
|
||||
.backgroundColor(this.pressedColor)
|
||||
},
|
||||
normal: {
|
||||
.backgroundColor(
|
||||
(this.currentSub && this.currentSub.id === item.id && this.currentSub.name === item.name)
|
||||
? this.selectedColor : this.listBgColor)
|
||||
}
|
||||
})
|
||||
if (this.inputMethods.length > 1 || index < this.subTypes.length) {
|
||||
Divider()
|
||||
.divider()
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.onClick(() => {
|
||||
this.switchMethodSub(item);
|
||||
})
|
||||
}, (item: inputMethod.InputMethodProperty) => JSON.stringify(item));
|
||||
|
||||
ForEach(this.inputMethods, (item: inputMethod.InputMethodProperty, index: number) => {
|
||||
if (this.subTypes.length === 0 || (this.defaultInputMethod && item.name !== this.defaultInputMethod.name)) {
|
||||
Text(item.label)
|
||||
.fontSize(this.fontSize)
|
||||
.textStyle()
|
||||
.listItemStyle()
|
||||
.fontColor((this.currentSub && this.currentSub.id === item.id && this.currentSub.name === item.name)
|
||||
? this.selectedFontColor : this.fontColor)
|
||||
.stateStyles({
|
||||
pressed: {
|
||||
.backgroundColor(this.pressedColor)
|
||||
},
|
||||
normal: {
|
||||
.backgroundColor((this.currentInputMethod && this.currentInputMethod.name === item.name)
|
||||
? this.selectedColor : this.listBgColor)
|
||||
}
|
||||
})
|
||||
.onClick(() => {
|
||||
this.switchMethod(item);
|
||||
})
|
||||
if (index < this.inputMethods.length - 1) {
|
||||
Divider()
|
||||
.divider()
|
||||
}
|
||||
}
|
||||
}, (item: inputMethod.InputMethodProperty) => JSON.stringify(item));
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
.width('100%')
|
||||
.scrollBar(BarState.Off)
|
||||
.layoutWeight(1)
|
||||
|
||||
if (this.patternOptions && this.showHand) {
|
||||
Divider()
|
||||
.divider()
|
||||
Row() {
|
||||
ForEach(this.patternOptions.patterns, (item: Pattern, index: number) => {
|
||||
Row() {
|
||||
Image(index === this.patternMode ? item.selectedIcon : item.icon)
|
||||
.size({ width: this.imageSize, height: this.imageSize })
|
||||
.objectFit(ImageFit.Contain)
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.size({ width: this.imageBtnWidth, height: this.imageBtnHeight })
|
||||
.borderRadius(this.imageRadius)
|
||||
.stateStyles({
|
||||
pressed: {
|
||||
.backgroundColor(this.pressedColor)
|
||||
},
|
||||
normal: {
|
||||
.backgroundColor(this.listBgColor)
|
||||
}
|
||||
})
|
||||
.onClick(() => {
|
||||
this.switchPositionPattern(index);
|
||||
})
|
||||
}, (item: Resource) => JSON.stringify(item));
|
||||
}
|
||||
.width('100%')
|
||||
.height(this.listItemHeight)
|
||||
.justifyContent(FlexAlign.SpaceEvenly)
|
||||
}
|
||||
}
|
||||
.width(this.dialogWidth)
|
||||
.margin({ top: this.columnPadding })
|
||||
.borderRadius('16vp')
|
||||
.backgroundColor(this.listBgColor)
|
||||
.height(this.maxHeight)
|
||||
.padding(this.columnPadding)
|
||||
.shadow(ShadowStyle.OUTER_DEFAULT_SM)
|
||||
}
|
||||
.id('inputDialog')
|
||||
.height('100%')
|
||||
.width('100%')
|
||||
.opacity(this.viewOpacity)
|
||||
.backgroundColor(this.borderBgColor)
|
||||
.transition(TransitionEffect.translate({ y: 400 })
|
||||
.combine(TransitionEffect.scale({ x: 1, y: 0 }))
|
||||
.animation({ duration: 500 }))
|
||||
.onAppear(() => {
|
||||
let component = componentUtils.getRectangleById('inputDialog');
|
||||
this.maxHeight = px2vp(component.size.height + component.windowOffset.y) - 10;
|
||||
})
|
||||
.onClick(() => {
|
||||
this.controller.close();
|
||||
})
|
||||
}
|
||||
|
||||
switchPositionPattern(mode: number) {
|
||||
if (this.patternOptions) {
|
||||
this.patternMode = mode;
|
||||
AppStorage.set('patternMode', this.patternMode);
|
||||
console.info(`${TAG} this.handMode = ${this.patternMode}`);
|
||||
this.patternOptions.action(this.patternMode);
|
||||
this.controller.close();
|
||||
}
|
||||
}
|
||||
|
||||
async switchMethod(inputProperty: inputMethod.InputMethodProperty) {
|
||||
if (this.currentInputMethod && this.currentInputMethod.name !== inputProperty.name) {
|
||||
let subTypes = await inputMethod.getSetting().listInputMethodSubtype(inputProperty);
|
||||
inputMethod.switchCurrentInputMethodAndSubtype(inputProperty, subTypes[0], (err: Error, result: boolean) => {
|
||||
if (result) {
|
||||
this.currentInputMethod = inputProperty;
|
||||
}
|
||||
this.controller.close();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
switchMethodSub(inputSub: InputMethodSubtype) {
|
||||
if (this.currentInputMethod && this.defaultInputMethod) {
|
||||
if (this.currentInputMethod.name !== this.defaultInputMethod.name) {
|
||||
inputMethod.switchCurrentInputMethodAndSubtype(this.defaultInputMethod, inputSub, () => {
|
||||
this.currentInputMethod = this.defaultInputMethod;
|
||||
this.currentSub = inputSub;
|
||||
this.controller.close();
|
||||
})
|
||||
} else {
|
||||
inputMethod.switchCurrentInputMethodSubtype(inputSub, () => {
|
||||
this.currentSub = inputSub;
|
||||
this.controller.close();
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "global.h"
|
||||
#include "element_name.h"
|
||||
#include "i_input_method_system_ability.h"
|
||||
#include "input_attribute.h"
|
||||
#include "input_client_stub.h"
|
||||
@ -52,6 +53,8 @@ public:
|
||||
int32_t ReleaseInput(sptr<IInputClient> client) override;
|
||||
std::shared_ptr<Property> GetCurrentInputMethod() override;
|
||||
std::shared_ptr<SubProperty> GetCurrentInputMethodSubtype() override;
|
||||
int32_t GetDefaultInputMethod(std::shared_ptr<Property> &prop) override;
|
||||
int32_t GetInputMethodConfig(OHOS::AppExecFwk::ElementName &inputMethodConfig) override;
|
||||
int32_t ListInputMethod(InputMethodStatus status, std::vector<Property> &props) override;
|
||||
int32_t SwitchInputMethod(const std::string &name, const std::string &subName) override;
|
||||
int32_t DisplayOptionalInputMethod() override;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "element_name.h"
|
||||
#include "event_status_manager.h"
|
||||
#include "global.h"
|
||||
#include "input_client_info.h"
|
||||
@ -84,6 +85,9 @@ public:
|
||||
static bool Marshalling(InputType input, MessageParcel &data);
|
||||
static bool Unmarshalling(InputType &output, MessageParcel &data);
|
||||
|
||||
static bool Marshalling(const OHOS::AppExecFwk::ElementName &input, MessageParcel &data);
|
||||
static bool Unmarshalling(OHOS::AppExecFwk::ElementName &output, MessageParcel &data);
|
||||
|
||||
template<class T>
|
||||
static bool Marshalling(const std::vector<T> &val, MessageParcel &parcel);
|
||||
template<class T>
|
||||
|
@ -365,6 +365,28 @@ int32_t InputMethodController::ListInputMethod(bool enable, std::vector<Property
|
||||
return ListInputMethodCommon(enable ? ENABLE : DISABLE, props);
|
||||
}
|
||||
|
||||
int32_t InputMethodController::GetDefaultInputMethod(std::shared_ptr<Property> &property)
|
||||
{
|
||||
IMSA_HILOGD("InputMethodController::GetDefaultInputMethod");
|
||||
auto proxy = GetSystemAbilityProxy();
|
||||
if (proxy == nullptr) {
|
||||
IMSA_HILOGE("proxy is nullptr");
|
||||
return ErrorCode::ERROR_SERVICE_START_FAILED;
|
||||
}
|
||||
return proxy->GetDefaultInputMethod(property);
|
||||
}
|
||||
|
||||
int32_t InputMethodController::GetInputMethodConfig(OHOS::AppExecFwk::ElementName &inputMethodConfig)
|
||||
{
|
||||
IMSA_HILOGD("InputMethodController::inputMethodConfig");
|
||||
auto proxy = GetSystemAbilityProxy();
|
||||
if (proxy == nullptr) {
|
||||
IMSA_HILOGE("proxy is nullptr");
|
||||
return ErrorCode::ERROR_SERVICE_START_FAILED;
|
||||
}
|
||||
return proxy->GetInputMethodConfig(inputMethodConfig);
|
||||
}
|
||||
|
||||
std::shared_ptr<Property> InputMethodController::GetCurrentInputMethod()
|
||||
{
|
||||
IMSA_HILOGD("InputMethodController::GetCurrentInputMethod");
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "input_method_system_ability_proxy.h"
|
||||
|
||||
#include "element_name.h"
|
||||
#include "global.h"
|
||||
#include "inputmethod_service_ipc_interface_code.h"
|
||||
#include "itypes_util.h"
|
||||
@ -87,6 +88,23 @@ int32_t InputMethodSystemAbilityProxy::SetCoreAndAgent(
|
||||
});
|
||||
}
|
||||
|
||||
int32_t InputMethodSystemAbilityProxy::GetDefaultInputMethod(std::shared_ptr<Property> &property)
|
||||
{
|
||||
return SendRequest(static_cast<uint32_t>(InputMethodInterfaceCode::GET_DEFAULT_INPUT_METHOD), nullptr,
|
||||
[&property](MessageParcel& reply) {
|
||||
property = std::make_shared<Property>();
|
||||
return ITypesUtil::Unmarshal(reply, *property);
|
||||
});
|
||||
}
|
||||
|
||||
int32_t InputMethodSystemAbilityProxy::GetInputMethodConfig(OHOS::AppExecFwk::ElementName &inputMethodConfig)
|
||||
{
|
||||
return SendRequest(static_cast<uint32_t>(InputMethodInterfaceCode::GET_INPUT_METHOD_SETTINGS), nullptr,
|
||||
[&inputMethodConfig](MessageParcel& reply) {
|
||||
return ITypesUtil::Unmarshal(reply, inputMethodConfig);
|
||||
});
|
||||
}
|
||||
|
||||
int32_t InputMethodSystemAbilityProxy::UnRegisteredProxyIme(UnRegisteredType type, const sptr<IInputMethodCore> &core)
|
||||
{
|
||||
return SendRequest(
|
||||
@ -155,7 +173,8 @@ int32_t InputMethodSystemAbilityProxy::ListCurrentInputMethodSubtype(std::vector
|
||||
[&subProps](MessageParcel &reply) { return ITypesUtil::Unmarshal(reply, subProps); });
|
||||
}
|
||||
|
||||
int32_t InputMethodSystemAbilityProxy::SwitchInputMethod(const std::string &name, const std::string &subName)
|
||||
int32_t InputMethodSystemAbilityProxy::SwitchInputMethod(const std::string& name,
|
||||
const std::string& subName)
|
||||
{
|
||||
return SendRequest(static_cast<uint32_t>(InputMethodInterfaceCode::SWITCH_INPUT_METHOD),
|
||||
[&name, &subName](MessageParcel &data) { return ITypesUtil::Marshal(data, name, subName); });
|
||||
|
@ -281,6 +281,27 @@ bool ITypesUtil::Unmarshalling(EventType &output, MessageParcel &data)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ITypesUtil::Marshalling(const OHOS::AppExecFwk::ElementName &input, MessageParcel &data)
|
||||
{
|
||||
return data.WriteString(input.GetBundleName().c_str()) && data.WriteString(input.GetModuleName().c_str()) &&
|
||||
data.WriteString(input.GetAbilityName().c_str());
|
||||
}
|
||||
|
||||
bool ITypesUtil::Unmarshalling(OHOS::AppExecFwk::ElementName &output, MessageParcel &data)
|
||||
{
|
||||
std::string bundleName;
|
||||
std::string moduleName;
|
||||
std::string abilityName;
|
||||
if (data.ReadString(bundleName) && data.ReadString(moduleName) && data.ReadString(abilityName)) {
|
||||
output.SetBundleName(bundleName);
|
||||
output.SetModuleName(moduleName);
|
||||
output.SetAbilityName(abilityName);
|
||||
return true;
|
||||
}
|
||||
IMSA_HILOGE("read ElementName from message parcel failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ITypesUtil::Marshalling(InputType input, MessageParcel &data)
|
||||
{
|
||||
return data.WriteInt32(static_cast<int32_t>(input));
|
||||
|
@ -67,6 +67,7 @@ ohos_shared_library("inputmethod_ability") {
|
||||
|
||||
external_deps = [
|
||||
"ability_base:configuration",
|
||||
"ability_base:want",
|
||||
"ability_runtime:ability_context_native",
|
||||
"c_utils:utils",
|
||||
"graphic_2d:window_animation",
|
||||
|
@ -72,6 +72,7 @@ ohos_shared_library("inputmethod_client") {
|
||||
public_deps = [ "${inputmethod_path}/services/dfx:inputmethod_dfx_static" ]
|
||||
|
||||
external_deps = [
|
||||
"ability_base:want",
|
||||
"c_utils:utils",
|
||||
"eventhandler:libeventhandler",
|
||||
"ffrt:libffrt",
|
||||
@ -111,6 +112,7 @@ ohos_static_library("inputmethod_client_static") {
|
||||
public_deps = [ "${inputmethod_path}/services/dfx:inputmethod_dfx_static" ]
|
||||
|
||||
external_deps = [
|
||||
"ability_base:want",
|
||||
"c_utils:utils",
|
||||
"eventhandler:libeventhandler",
|
||||
"ffrt:libffrt",
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <thread>
|
||||
|
||||
#include "controller_listener.h"
|
||||
#include "element_name.h"
|
||||
#include "event_handler.h"
|
||||
#include "event_status_manager.h"
|
||||
#include "global.h"
|
||||
@ -312,6 +313,26 @@ public:
|
||||
*/
|
||||
IMF_API std::shared_ptr<SubProperty> GetCurrentInputMethodSubtype();
|
||||
|
||||
/**
|
||||
* @brief Get default input method property.
|
||||
*
|
||||
* This function is used to get default input method property.
|
||||
*
|
||||
* @return The property of default input method.
|
||||
* @since 10
|
||||
*/
|
||||
IMF_API int32_t GetDefaultInputMethod(std::shared_ptr<Property> &prop);
|
||||
|
||||
/**
|
||||
* @brief get input method config ability.
|
||||
*
|
||||
* This function is used to get input method config ability.
|
||||
*
|
||||
* @return The info of input settings.
|
||||
* @since 10
|
||||
*/
|
||||
IMF_API int32_t GetInputMethodConfig(AppExecFwk::ElementName &inputMethodConfig);
|
||||
|
||||
/**
|
||||
* @brief Set calling window id.
|
||||
*
|
||||
|
@ -48,6 +48,7 @@ ohos_shared_library("inputmethod_service") {
|
||||
"src/input_channel.cpp",
|
||||
"src/input_control_channel_proxy.cpp",
|
||||
"src/input_control_channel_stub.cpp",
|
||||
"src/input_method_config_parser.cpp",
|
||||
"src/input_method_info.cpp",
|
||||
"src/input_method_system_ability.cpp",
|
||||
"src/input_method_system_ability_stub.cpp",
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "element_name.h"
|
||||
#include "event_status_manager.h"
|
||||
#include "global.h"
|
||||
#include "i_input_client.h"
|
||||
@ -48,6 +49,8 @@ public:
|
||||
virtual int32_t ShowInput(sptr<IInputClient> client) = 0;
|
||||
virtual int32_t HideInput(sptr<IInputClient> client) = 0;
|
||||
virtual int32_t ReleaseInput(sptr<IInputClient> client) = 0;
|
||||
virtual int32_t GetDefaultInputMethod(std::shared_ptr<Property> &prop) = 0;
|
||||
virtual int32_t GetInputMethodConfig(AppExecFwk::ElementName &inputMethodConfig) = 0;
|
||||
virtual std::shared_ptr<Property> GetCurrentInputMethod() = 0;
|
||||
virtual std::shared_ptr<SubProperty> GetCurrentInputMethodSubtype() = 0;
|
||||
virtual int32_t ListInputMethod(InputMethodStatus status, std::vector<Property> &props) = 0;
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include "bundle_mgr_proxy.h"
|
||||
#include "enable_ime_data_parser.h"
|
||||
#include "element_name.h"
|
||||
#include "input_method_info.h"
|
||||
#include "input_method_property.h"
|
||||
#include "input_method_status.h"
|
||||
@ -48,6 +49,11 @@ enum class Condition {
|
||||
CHINESE,
|
||||
};
|
||||
|
||||
struct ImeConfig {
|
||||
std::string systemInputMethodConfigAbility;
|
||||
std::string defaultInputMethod;
|
||||
};
|
||||
|
||||
class ImeInfoInquirer {
|
||||
public:
|
||||
using CompareHandler = std::function<bool(const SubProperty &)>;
|
||||
@ -63,7 +69,9 @@ public:
|
||||
void SetCurrentImeInfo(std::shared_ptr<ImeInfo> info);
|
||||
void RefreshCurrentImeInfo(int32_t userId);
|
||||
std::shared_ptr<SubProperty> FindTargetSubtypeByCondition(
|
||||
const std::vector<SubProperty> &subProps, const Condition &condition);
|
||||
const std::vector<SubProperty> &subProps, const Condition &condition);
|
||||
int32_t GetDefaultInputMethod(const int32_t userId, std::shared_ptr<Property> &prop);
|
||||
int32_t GetInputMethodConfig(const int32_t userId, AppExecFwk::ElementName &inputMethodConfig);
|
||||
int32_t ListInputMethod(int32_t userId, InputMethodStatus status, std::vector<Property> &props, bool enableOn);
|
||||
int32_t ListInputMethodSubtype(int32_t userId, const std::string &bundleName, std::vector<SubProperty> &subProps);
|
||||
int32_t ListCurrentInputMethodSubtype(int32_t userId, std::vector<SubProperty> &subProps);
|
||||
@ -100,6 +108,7 @@ private:
|
||||
void ParseLanguage(const std::string &locale, std::string &language);
|
||||
bool QueryImeExtInfos(const int32_t userId, std::vector<OHOS::AppExecFwk::ExtensionAbilityInfo> &infos);
|
||||
|
||||
ImeConfig imeConfig_;
|
||||
std::mutex currentImeInfoLock_;
|
||||
std::shared_ptr<ImeInfo> currentImeInfo_{ nullptr }; // current imeInfo of current user
|
||||
};
|
||||
|
139
services/include/input_method_config_parser.h
Normal file
139
services/include/input_method_config_parser.h
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SERVICES_INCLUDE_IME_CONFIG_PARSE_H
|
||||
#define SERVICES_INCLUDE_IME_CONFIG_PARSE_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "global.h"
|
||||
#include "config_policy_utils.h"
|
||||
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
namespace OHOS {
|
||||
namespace MiscServices {
|
||||
class ImeConfigParse {
|
||||
public:
|
||||
static std::string ReadFile(const std::string &path);
|
||||
static CfgFiles* ParseFromCustom();
|
||||
static bool parseJson(const std::string &cfgPath, const std::string &parseKey, nlohmann::json &jsonCfg);
|
||||
template<typename T>
|
||||
static bool ParseFromCustomSystem(const std::string &parseKey, T &data);
|
||||
template<typename T>
|
||||
static bool ParseFromCustomSystem(const std::string &parseKey, std::vector<T> &data);
|
||||
template<typename T>
|
||||
static bool GetCfgsFromFile(const std::string &cfgPath, const std::string &parseKey, T &data);
|
||||
template<typename T>
|
||||
static bool GetCfgsFromFile(const std::string &cfgPath, const std::string &parseKey, std::vector<T> &data);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
bool ImeConfigParse::ParseFromCustomSystem(const std::string &parseKey, T &data)
|
||||
{
|
||||
CfgFiles* cfgFiles = ParseFromCustom();
|
||||
if (cfgFiles == nullptr) {
|
||||
IMSA_HILOGE("cfgFiles is nullptr");
|
||||
return false;
|
||||
}
|
||||
bool isSuccess = true;
|
||||
// parse config files, ordered by priority from high to low
|
||||
for (int32_t i = MAX_CFG_POLICY_DIRS_CNT - 1; i >= 0; i--) {
|
||||
auto path = cfgFiles->paths[i];
|
||||
if (path == nullptr || *path == '\0') {
|
||||
continue;
|
||||
}
|
||||
isSuccess = false;
|
||||
char realPath[PATH_MAX + 1] = { 0x00 };
|
||||
if (strlen(path) == 0 || strlen(path) > PATH_MAX || realpath(path, realPath) == nullptr) {
|
||||
IMSA_HILOGE("failed to get realpath");
|
||||
break;
|
||||
}
|
||||
std::string cfgPath(realPath);
|
||||
if (!GetCfgsFromFile(cfgPath, parseKey, data)) {
|
||||
break;
|
||||
}
|
||||
isSuccess = true;
|
||||
}
|
||||
FreeCfgFiles(cfgFiles);
|
||||
IMSA_HILOGI("parse result: %{public}d", isSuccess);
|
||||
return isSuccess;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool ImeConfigParse::ParseFromCustomSystem(const std::string &parseKey, std::vector<T> &data)
|
||||
{
|
||||
CfgFiles* cfgFiles = ParseFromCustom();
|
||||
if (cfgFiles == nullptr) {
|
||||
IMSA_HILOGE("cfgFiles is nullptr");
|
||||
return false;
|
||||
}
|
||||
bool isSuccess = true;
|
||||
// parse config files, ordered by priority from high to low
|
||||
for (int32_t i = MAX_CFG_POLICY_DIRS_CNT - 1; i >= 0; i--) {
|
||||
auto path = cfgFiles->paths[i];
|
||||
if (path == nullptr || *path == '\0') {
|
||||
continue;
|
||||
}
|
||||
isSuccess = false;
|
||||
char realPath[PATH_MAX + 1] = { 0x00 };
|
||||
if (strlen(path) == 0 || strlen(path) > PATH_MAX || realpath(path, realPath) == nullptr) {
|
||||
IMSA_HILOGE("failed to get realpath");
|
||||
break;
|
||||
}
|
||||
std::string cfgPath(realPath);
|
||||
if (!GetCfgsFromFile(cfgPath, parseKey, data)) {
|
||||
break;
|
||||
}
|
||||
isSuccess = true;
|
||||
}
|
||||
FreeCfgFiles(cfgFiles);
|
||||
IMSA_HILOGI("parse result: %{public}d", isSuccess);
|
||||
return isSuccess;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool ImeConfigParse::GetCfgsFromFile(const std::string &cfgPath, const std::string &parseKey, T &data)
|
||||
{
|
||||
nlohmann::json jsonCfg;
|
||||
if (parseJson(cfgPath, parseKey, jsonCfg)) {
|
||||
data = jsonCfg.at(parseKey).get<T>();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool ImeConfigParse::GetCfgsFromFile(const std::string &cfgPath, const std::string &parseKey, std::vector<T> &data)
|
||||
{
|
||||
nlohmann::json jsonCfg;
|
||||
if (parseJson(cfgPath, parseKey, jsonCfg)) {
|
||||
if (!jsonCfg.at(parseKey).is_array()) {
|
||||
IMSA_HILOGE("%{public}s is not array", parseKey.c_str());
|
||||
return false;
|
||||
}
|
||||
data = jsonCfg.at(parseKey).get<std::vector<T>>();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace MiscServices
|
||||
} // namespace OHOS
|
||||
#endif // SERVICES_INCLUDE_IME_CONFIG_PARSE_H
|
@ -24,6 +24,7 @@
|
||||
#include "block_queue.h"
|
||||
#include "bundle_mgr_proxy.h"
|
||||
#include "enable_ime_data_parser.h"
|
||||
#include "element_name.h"
|
||||
#include "event_handler.h"
|
||||
#include "identity_checker_impl.h"
|
||||
#include "ime_info_inquirer.h"
|
||||
@ -41,7 +42,6 @@ using AbilityType = AppExecFwk::ExtensionAbilityType;
|
||||
using namespace AppExecFwk;
|
||||
using namespace Security::AccessToken;
|
||||
enum class ServiceRunningState { STATE_NOT_START, STATE_RUNNING };
|
||||
|
||||
class InputMethodSystemAbility : public SystemAbility, public InputMethodSystemAbilityStub {
|
||||
DECLARE_SYSTEM_ABILITY(InputMethodSystemAbility);
|
||||
|
||||
@ -58,6 +58,8 @@ public:
|
||||
int32_t HideInput(sptr<IInputClient> client) override;
|
||||
int32_t StopInputSession() override;
|
||||
int32_t ReleaseInput(sptr<IInputClient> client) override;
|
||||
int32_t GetDefaultInputMethod(std::shared_ptr<Property> &prop) override;
|
||||
int32_t GetInputMethodConfig(OHOS::AppExecFwk::ElementName &inputMethodConfig) override;
|
||||
std::shared_ptr<Property> GetCurrentInputMethod() override;
|
||||
std::shared_ptr<SubProperty> GetCurrentInputMethodSubtype() override;
|
||||
int32_t ListInputMethod(InputMethodStatus status, std::vector<Property> &props) override;
|
||||
|
@ -82,6 +82,10 @@ private:
|
||||
|
||||
int32_t ShowCurrentInputOnRemoteDeprecated(MessageParcel &data, MessageParcel &reply);
|
||||
|
||||
int32_t GetDefaultInputMethodOnRemote(MessageParcel &data, MessageParcel &reply);
|
||||
|
||||
int32_t GetInputMethodConfigOnRemote(MessageParcel &data, MessageParcel &reply);
|
||||
|
||||
using RequestHandler = int32_t (InputMethodSystemAbilityStub::*)(MessageParcel &, MessageParcel &);
|
||||
static constexpr RequestHandler HANDLERS[static_cast<uint32_t>(InputMethodInterfaceCode::IMS_CMD_LAST)] = {
|
||||
[static_cast<uint32_t>(InputMethodInterfaceCode::START_INPUT)] =
|
||||
@ -134,6 +138,10 @@ private:
|
||||
&InputMethodSystemAbilityStub::StartInputTypeOnRemote,
|
||||
[static_cast<uint32_t>(InputMethodInterfaceCode::EXIT_CURRENT_INPUT_TYPE)] =
|
||||
&InputMethodSystemAbilityStub::ExitCurrentInputTypeOnRemote,
|
||||
[static_cast<uint32_t>(InputMethodInterfaceCode::GET_DEFAULT_INPUT_METHOD)] =
|
||||
&InputMethodSystemAbilityStub::GetDefaultInputMethodOnRemote,
|
||||
[static_cast<uint32_t>(InputMethodInterfaceCode::GET_INPUT_METHOD_SETTINGS)] =
|
||||
&InputMethodSystemAbilityStub::GetInputMethodConfigOnRemote,
|
||||
};
|
||||
};
|
||||
} // namespace OHOS::MiscServices
|
||||
|
@ -45,7 +45,9 @@ enum class InputMethodInterfaceCode {
|
||||
IS_INPUT_TYPE_SUPPORTED,
|
||||
START_INPUT_TYPE,
|
||||
EXIT_CURRENT_INPUT_TYPE,
|
||||
IMS_CMD_LAST
|
||||
GET_DEFAULT_INPUT_METHOD,
|
||||
GET_INPUT_METHOD_SETTINGS,
|
||||
IMS_CMD_LAST,
|
||||
};
|
||||
} // namespace MiscServices
|
||||
} // namespace OHOS
|
||||
|
@ -20,9 +20,11 @@
|
||||
|
||||
#include "application_info.h"
|
||||
#include "bundle_mgr_client_impl.h"
|
||||
#include "config_policy_utils.h"
|
||||
#include "global.h"
|
||||
#include "if_system_ability_manager.h"
|
||||
#include "ime_cfg_manager.h"
|
||||
#include "input_method_config_parser.h"
|
||||
#include "input_method_info.h"
|
||||
#include "input_type_manager.h"
|
||||
#include "iservice_registry.h"
|
||||
@ -37,6 +39,9 @@ namespace {
|
||||
using json = nlohmann::json;
|
||||
using namespace OHOS::AppExecFwk;
|
||||
constexpr const char *SUBTYPE_PROFILE_METADATA_NAME = "ohos.extension.input_method";
|
||||
const std::string SYSTEM_CONFIG = "systemConfig";
|
||||
const std::string SYSTEM_INPUT_METHOD_CONFIG_ABILITY = "systemInputMethodConfigAbility";
|
||||
const std::string DEFAULT_INPUT_METHOD = "defaultInputMethod";
|
||||
constexpr uint32_t SUBTYPE_PROFILE_NUM = 1;
|
||||
constexpr uint32_t MAX_SUBTYPE_NUM = 256;
|
||||
constexpr const char *DEFAULT_IME_KEY = "persist.sys.default_ime";
|
||||
@ -44,6 +49,19 @@ constexpr int32_t CONFIG_LEN = 128;
|
||||
constexpr uint32_t RETRY_INTERVAL = 100;
|
||||
constexpr uint32_t BLOCK_RETRY_TIMES = 1000;
|
||||
} // namespace
|
||||
|
||||
void from_json(const nlohmann::json &jsonConfigs, ImeConfig &config)
|
||||
{
|
||||
json jsonCfg = jsonConfigs[SYSTEM_CONFIG];
|
||||
if (jsonConfigs.find(SYSTEM_INPUT_METHOD_CONFIG_ABILITY) != jsonConfigs.end() &&
|
||||
jsonConfigs[SYSTEM_INPUT_METHOD_CONFIG_ABILITY].is_string()) {
|
||||
jsonConfigs.at(SYSTEM_INPUT_METHOD_CONFIG_ABILITY).get_to(config.systemInputMethodConfigAbility);
|
||||
}
|
||||
if (jsonConfigs.find(DEFAULT_INPUT_METHOD) != jsonConfigs.end() && jsonConfigs[DEFAULT_INPUT_METHOD].is_string()) {
|
||||
jsonConfigs.at(DEFAULT_INPUT_METHOD).get_to(config.defaultInputMethod);
|
||||
}
|
||||
}
|
||||
|
||||
ImeInfoInquirer &ImeInfoInquirer::GetInstance()
|
||||
{
|
||||
static ImeInfoInquirer instance;
|
||||
@ -621,6 +639,54 @@ std::string ImeInfoInquirer::GetImeToBeStarted(int32_t userId)
|
||||
return currentImeCfg->imeId;
|
||||
}
|
||||
|
||||
int32_t ImeInfoInquirer::GetInputMethodConfig(const int32_t userId, AppExecFwk::ElementName &inputMethodConfig)
|
||||
{
|
||||
IMSA_HILOGD("userId: %{public}d", userId);
|
||||
if (!ImeConfigParse::ParseFromCustomSystem(SYSTEM_CONFIG, imeConfig_)) {
|
||||
return ErrorCode::ERROR_NULL_POINTER;
|
||||
}
|
||||
if (imeConfig_.systemInputMethodConfigAbility.empty()) {
|
||||
IMSA_HILOGE("inputMethodConfig systemInputMethodConfigAbility is null");
|
||||
return ErrorCode::NO_ERROR;
|
||||
}
|
||||
IMSA_HILOGD("inputMethodConfig: %{public}s", imeConfig_.systemInputMethodConfigAbility.c_str());
|
||||
auto pos = imeConfig_.systemInputMethodConfigAbility.find('/');
|
||||
if (pos == std::string::npos || pos + 1 >= imeConfig_.systemInputMethodConfigAbility.size()) {
|
||||
IMSA_HILOGE("inputMethodConfig: %{public}s is abnormal", imeConfig_.systemInputMethodConfigAbility.c_str());
|
||||
return ErrorCode::ERROR_NULL_POINTER;
|
||||
}
|
||||
std::string bundleName = imeConfig_.systemInputMethodConfigAbility.substr(0, pos);
|
||||
std::string abilityName = imeConfig_.systemInputMethodConfigAbility.substr(pos + 1);
|
||||
std::string moduleName;
|
||||
auto pos1 = abilityName.find('/');
|
||||
if (pos1 == std::string::npos || pos1 + 1 >= abilityName.size()) {
|
||||
IMSA_HILOGD("inputMethodConfig moduleName is abnormal, abilityName is %{public}s", abilityName.c_str());
|
||||
} else {
|
||||
moduleName = abilityName.substr(0, pos1);
|
||||
abilityName = abilityName.substr(pos1 + 1);
|
||||
}
|
||||
inputMethodConfig.SetBundleName(bundleName);
|
||||
inputMethodConfig.SetModuleName(moduleName);
|
||||
inputMethodConfig.SetAbilityName(abilityName);
|
||||
return ErrorCode::NO_ERROR;
|
||||
}
|
||||
|
||||
int32_t ImeInfoInquirer::GetDefaultInputMethod(const int32_t userId, std::shared_ptr<Property>& prop)
|
||||
{
|
||||
IMSA_HILOGD("userId: %{public}d", userId);
|
||||
auto imeInfo = GetDefaultImeInfo(userId);
|
||||
if (imeInfo == nullptr) {
|
||||
return ErrorCode::ERROR_NULL_POINTER;
|
||||
}
|
||||
IMSA_HILOGD("getDefaultInputMethod name: %{public}s", imeInfo->prop.name.c_str());
|
||||
prop->name = imeInfo->prop.name;
|
||||
prop->id = imeInfo->prop.id;
|
||||
prop->label = imeInfo->prop.label;
|
||||
prop->labelId = imeInfo->prop.labelId;
|
||||
prop->iconId = imeInfo->prop.iconId;
|
||||
return ErrorCode::NO_ERROR;
|
||||
}
|
||||
|
||||
std::shared_ptr<ImeInfo> ImeInfoInquirer::GetDefaultImeInfo(int32_t userId)
|
||||
{
|
||||
auto ime = GetDefaultIme();
|
||||
@ -650,9 +716,16 @@ std::shared_ptr<ImeInfo> ImeInfoInquirer::GetDefaultImeInfo(int32_t userId)
|
||||
|
||||
std::string ImeInfoInquirer::GetDefaultIme()
|
||||
{
|
||||
char value[CONFIG_LEN] = { 0 };
|
||||
auto code = GetParameter(DEFAULT_IME_KEY, "", value, CONFIG_LEN);
|
||||
return code > 0 ? value : "";
|
||||
if (!ImeConfigParse::ParseFromCustomSystem(SYSTEM_CONFIG, imeConfig_)) {
|
||||
return "";
|
||||
}
|
||||
IMSA_HILOGI("defaultInputMethod: %{public}s", imeConfig_.defaultInputMethod.c_str());
|
||||
if (imeConfig_.defaultInputMethod.empty()) {
|
||||
char value[CONFIG_LEN] = { 0 };
|
||||
auto code = GetParameter(DEFAULT_IME_KEY, "", value, CONFIG_LEN);
|
||||
return code > 0 ? value : "";
|
||||
}
|
||||
return imeConfig_.defaultInputMethod;
|
||||
}
|
||||
|
||||
sptr<OHOS::AppExecFwk::IBundleMgr> ImeInfoInquirer::GetBundleMgr()
|
||||
|
82
services/src/input_method_config_parser.cpp
Normal file
82
services/src/input_method_config_parser.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "input_method_config_parser.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <fcntl.h>
|
||||
#include <ios>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <fstream>
|
||||
|
||||
#include "file_ex.h"
|
||||
#include "global.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace MiscServices {
|
||||
namespace {
|
||||
constexpr const char *IME_INPUT_TYPE_CFG_FILE_PATH = "etc/inputmethod/inputmethod_framework_config.json";
|
||||
using json = nlohmann::json;
|
||||
} // namespace
|
||||
|
||||
CfgFiles* ImeConfigParse::ParseFromCustom()
|
||||
{
|
||||
return GetCfgFiles(IME_INPUT_TYPE_CFG_FILE_PATH);
|
||||
}
|
||||
|
||||
bool ImeConfigParse::parseJson(const std::string &cfgPath, const std::string &parseKey, nlohmann::json &jsonCfg)
|
||||
{
|
||||
IMSA_HILOGD("in");
|
||||
std::string jsonStr = ImeConfigParse::ReadFile(cfgPath);
|
||||
if (jsonStr.empty()) {
|
||||
IMSA_HILOGE("json config size is invalid");
|
||||
return false;
|
||||
}
|
||||
jsonCfg = json::parse(jsonStr, nullptr, false);
|
||||
if (jsonCfg.is_discarded()) {
|
||||
IMSA_HILOGE("jsonStr parse failed");
|
||||
return false;
|
||||
}
|
||||
if (!jsonCfg.contains(parseKey)) {
|
||||
IMSA_HILOGE("%{public}s not find or abnormal", parseKey.c_str());
|
||||
return false;
|
||||
}
|
||||
IMSA_HILOGD("get json: %{public}s", jsonCfg.dump().c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string ImeConfigParse::ReadFile(const std::string &path)
|
||||
{
|
||||
std::ifstream infile;
|
||||
std::string sLine;
|
||||
std::string sAll = "";
|
||||
infile.open(path);
|
||||
if (!infile.is_open()) {
|
||||
IMSA_HILOGE("path: %s Readfile fail", path.c_str());
|
||||
return sAll;
|
||||
}
|
||||
|
||||
while (getline(infile, sLine)) {
|
||||
sAll.append(sLine);
|
||||
}
|
||||
infile.close();
|
||||
return sAll;
|
||||
}
|
||||
} // namespace MiscServices
|
||||
} // namespace OHOS
|
@ -137,7 +137,6 @@ int32_t InputMethodSystemAbility::Init()
|
||||
return -1;
|
||||
}
|
||||
state_ = ServiceRunningState::STATE_RUNNING;
|
||||
ImeCfgManager::GetInstance().Init();
|
||||
std::vector<int32_t> userIds;
|
||||
if (BlockRetry(RETRY_INTERVAL, BLOCK_RETRY_TIMES, [&userIds]() -> bool {
|
||||
return OsAccountManager::QueryActiveOsAccountIds(userIds) == ERR_OK && !userIds.empty();
|
||||
@ -616,6 +615,16 @@ std::shared_ptr<SubProperty> InputMethodSystemAbility::GetCurrentInputMethodSubt
|
||||
return ImeInfoInquirer::GetInstance().GetCurrentSubtype(userId_);
|
||||
}
|
||||
|
||||
int32_t InputMethodSystemAbility::GetDefaultInputMethod(std::shared_ptr<Property> &prop)
|
||||
{
|
||||
return ImeInfoInquirer::GetInstance().GetDefaultInputMethod(userId_, prop);
|
||||
}
|
||||
|
||||
int32_t InputMethodSystemAbility::GetInputMethodConfig(OHOS::AppExecFwk::ElementName &inputMethodConfig)
|
||||
{
|
||||
return ImeInfoInquirer::GetInstance().GetInputMethodConfig(userId_, inputMethodConfig);
|
||||
}
|
||||
|
||||
int32_t InputMethodSystemAbility::ListInputMethod(InputMethodStatus status, std::vector<Property> &props)
|
||||
{
|
||||
return ImeInfoInquirer::GetInstance().ListInputMethod(userId_, status, props, enableImeOn_);
|
||||
@ -929,17 +938,28 @@ int32_t InputMethodSystemAbility::UnRegisteredProxyIme(UnRegisteredType type, co
|
||||
return userSession_->OnUnRegisteredProxyIme(type, core);
|
||||
}
|
||||
|
||||
bool InputMethodSystemAbility::IsSwitchPermitted(const SwitchInfo &switchInfo)
|
||||
bool InputMethodSystemAbility::IsSwitchPermitted(const SwitchInfo& switchInfo)
|
||||
{
|
||||
auto currentBundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName;
|
||||
// if currentIme is switching subtype, permission verification is not performed.
|
||||
if (identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(), PERMISSION_CONNECT_IME_ABILITY)
|
||||
|| (identityChecker_->IsBundleNameValid(IPCSkeleton::GetCallingTokenID(), currentBundleName)
|
||||
&& switchInfo.bundleName == currentBundleName && !switchInfo.subName.empty())) {
|
||||
if (identityChecker_->IsBundleNameValid(IPCSkeleton::GetCallingTokenID(), currentBundleName) &&
|
||||
switchInfo.bundleName == currentBundleName && !switchInfo.subName.empty()) {
|
||||
return true;
|
||||
}
|
||||
InputMethodSysEvent::GetInstance().InputmethodFaultReporter(
|
||||
ErrorCode::ERROR_STATUS_PERMISSION_DENIED, switchInfo.bundleName, "switch inputmethod failed!");
|
||||
if (!identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(), PERMISSION_CONNECT_IME_ABILITY)) {
|
||||
InputMethodSysEvent::GetInstance().InputmethodFaultReporter(
|
||||
ErrorCode::ERROR_STATUS_PERMISSION_DENIED, switchInfo.bundleName, "switch inputmethod failed!");
|
||||
return false;
|
||||
}
|
||||
if (switchInfo.subName.empty()) {
|
||||
return true;
|
||||
}
|
||||
if (identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID()) ||
|
||||
identityChecker_->IsBundleNameValid(IPCSkeleton::GetCallingTokenID(), currentBundleName)) {
|
||||
return true;
|
||||
}
|
||||
InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ErrorCode::ERROR_STATUS_PERMISSION_DENIED,
|
||||
switchInfo.bundleName, "switch inputmethod failed!");
|
||||
IMSA_HILOGE("not permitted");
|
||||
return false;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "element_name.h"
|
||||
#include "input_client_proxy.h"
|
||||
#include "input_data_channel_proxy.h"
|
||||
#include "input_method_agent_proxy.h"
|
||||
@ -130,6 +131,22 @@ int32_t InputMethodSystemAbilityStub::SetCoreAndAgentOnRemote(MessageParcel &dat
|
||||
return reply.WriteInt32(ret) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
|
||||
}
|
||||
|
||||
int32_t InputMethodSystemAbilityStub::GetDefaultInputMethodOnRemote(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
std::shared_ptr<Property> prop = std::make_shared<Property>();
|
||||
auto ret = GetDefaultInputMethod(prop);
|
||||
return ITypesUtil::Marshal(reply, ret, *prop) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
|
||||
}
|
||||
|
||||
int32_t InputMethodSystemAbilityStub::GetInputMethodConfigOnRemote(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
OHOS::AppExecFwk::ElementName inputMethodConfig;
|
||||
auto ret = GetInputMethodConfig(inputMethodConfig);
|
||||
IMSA_HILOGD("GetInputMethodConfigOnRemote inputMethodConfig is %{public}s, %{public}s ",
|
||||
inputMethodConfig.GetBundleName().c_str(), inputMethodConfig.GetAbilityName().c_str());
|
||||
return ITypesUtil::Marshal(reply, ret, inputMethodConfig) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
|
||||
}
|
||||
|
||||
int32_t InputMethodSystemAbilityStub::GetCurrentInputMethodOnRemote(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
auto property = GetCurrentInputMethod();
|
||||
@ -203,7 +220,7 @@ int32_t InputMethodSystemAbilityStub::ListCurrentInputMethodSubtypeOnRemote(Mess
|
||||
return ErrorCode::NO_ERROR;
|
||||
}
|
||||
|
||||
int32_t InputMethodSystemAbilityStub::SwitchInputMethodOnRemote(MessageParcel &data, MessageParcel &reply)
|
||||
int32_t InputMethodSystemAbilityStub::SwitchInputMethodOnRemote(MessageParcel& data, MessageParcel& reply)
|
||||
{
|
||||
std::string name;
|
||||
std::string subName;
|
||||
@ -211,7 +228,8 @@ int32_t InputMethodSystemAbilityStub::SwitchInputMethodOnRemote(MessageParcel &d
|
||||
IMSA_HILOGE("Unmarshal failed");
|
||||
return ErrorCode::ERROR_EX_PARCELABLE;
|
||||
}
|
||||
return reply.WriteInt32(SwitchInputMethod(name, subName)) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
|
||||
return reply.WriteInt32(SwitchInputMethod(name, subName)) ? ErrorCode::NO_ERROR
|
||||
: ErrorCode::ERROR_EX_PARCELABLE;
|
||||
}
|
||||
|
||||
int32_t InputMethodSystemAbilityStub::PanelStatusChangeOnRemote(MessageParcel &data, MessageParcel &reply)
|
||||
|
@ -30,13 +30,13 @@
|
||||
|
||||
#include "climits"
|
||||
#include "config_policy_utils.h"
|
||||
#include "input_method_config_parser.h"
|
||||
#include "global.h"
|
||||
#include "ime_cfg_manager.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace MiscServices {
|
||||
namespace {
|
||||
constexpr const char *IME_INPUT_TYPE_CFG_FILE_PATH = "etc/inputmethod/inputmethod_framework_config.json";
|
||||
const std::string SUPPORTED_INPUT_TYPE_LIST = "supportedInputTypeList";
|
||||
const std::string INPUT_TYPE = "inputType";
|
||||
const std::string BUNDLE_NAME = "bundleName";
|
||||
@ -133,10 +133,15 @@ bool InputTypeManager::Init()
|
||||
}
|
||||
isInitInProgress_.store(true);
|
||||
isInitSuccess_.Clear(false);
|
||||
bool isSuccess = ParseFromCustomSystem();
|
||||
std::vector<InputTypeCfg> configs;
|
||||
bool isSuccess = ImeConfigParse::ParseFromCustomSystem(SUPPORTED_INPUT_TYPE_LIST, configs);
|
||||
IMSA_HILOGD("ParseFromCustomSystem end isSuccess %{public}d", isSuccess);
|
||||
if (isSuccess) {
|
||||
std::lock_guard<std::mutex> lk(typesLock_);
|
||||
for (const auto &cfg : inputTypes_) {
|
||||
for (const auto& config : configs) {
|
||||
inputTypes_.insert({ config.type, config.ime });
|
||||
}
|
||||
for (const auto& cfg : inputTypes_) {
|
||||
std::lock_guard<std::mutex> lock(listLock_);
|
||||
inputTypeImeList_.insert(cfg.second);
|
||||
}
|
||||
@ -149,80 +154,5 @@ bool InputTypeManager::Init()
|
||||
isInitInProgress_.store(false);
|
||||
return isSuccess;
|
||||
}
|
||||
|
||||
bool InputTypeManager::ParseFromCustomSystem()
|
||||
{
|
||||
CfgFiles *cfgFiles = GetCfgFiles(IME_INPUT_TYPE_CFG_FILE_PATH);
|
||||
if (cfgFiles == nullptr) {
|
||||
IMSA_HILOGE("cfgFiles is nullptr");
|
||||
return false;
|
||||
}
|
||||
bool isSuccess = true;
|
||||
// parse config files, ordered by priority from high to low
|
||||
for (int32_t i = MAX_CFG_POLICY_DIRS_CNT - 1; i >= 0; i--) {
|
||||
auto path = cfgFiles->paths[i];
|
||||
if (path == nullptr || *path == '\0') {
|
||||
continue;
|
||||
}
|
||||
isSuccess = false;
|
||||
char realPath[PATH_MAX + 1] = { 0x00 };
|
||||
if (strlen(path) == 0 || strlen(path) > PATH_MAX || realpath(path, realPath) == nullptr) {
|
||||
IMSA_HILOGE("failed to get realpath");
|
||||
break;
|
||||
}
|
||||
std::string cfgPath(realPath);
|
||||
if (!GetCfgsFromFile(cfgPath)) {
|
||||
break;
|
||||
}
|
||||
isSuccess = true;
|
||||
}
|
||||
FreeCfgFiles(cfgFiles);
|
||||
IMSA_HILOGI("parse result: %{public}d", isSuccess);
|
||||
return isSuccess;
|
||||
}
|
||||
|
||||
bool InputTypeManager::GetCfgsFromFile(const std::string &cfgPath)
|
||||
{
|
||||
IMSA_HILOGD("in");
|
||||
std::string jsonStr = ReadFile(cfgPath);
|
||||
if (jsonStr.empty()) {
|
||||
IMSA_HILOGE("json config size is invalid");
|
||||
return false;
|
||||
}
|
||||
auto jsonCfg = json::parse(jsonStr, nullptr, false);
|
||||
if (jsonCfg.is_discarded()) {
|
||||
IMSA_HILOGE("jsonStr parse failed");
|
||||
return false;
|
||||
}
|
||||
if (!jsonCfg.contains(SUPPORTED_INPUT_TYPE_LIST) || !jsonCfg[SUPPORTED_INPUT_TYPE_LIST].is_array()) {
|
||||
IMSA_HILOGE("%{public}s not find or abnormal", SUPPORTED_INPUT_TYPE_LIST.c_str());
|
||||
return false;
|
||||
}
|
||||
IMSA_HILOGD("get json: %{public}s", jsonCfg.dump().c_str());
|
||||
std::vector<InputTypeCfg> configs = jsonCfg.at(SUPPORTED_INPUT_TYPE_LIST).get<std::vector<InputTypeCfg>>();
|
||||
std::lock_guard<std::mutex> lock(typesLock_);
|
||||
for (const auto &config : configs) {
|
||||
inputTypes_.insert({ config.type, config.ime });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string InputTypeManager::ReadFile(const std::string &path)
|
||||
{
|
||||
std::ifstream infile;
|
||||
std::string sLine;
|
||||
std::string sAll = "";
|
||||
infile.open(path);
|
||||
if (!infile.is_open()) {
|
||||
IMSA_HILOGE("path: %s Readfile fail", path.c_str());
|
||||
return sAll;
|
||||
}
|
||||
|
||||
while (getline(infile, sLine)) {
|
||||
sAll.append(sLine);
|
||||
}
|
||||
infile.close();
|
||||
return sAll;
|
||||
}
|
||||
} // namespace MiscServices
|
||||
} // namespace OHOS
|
@ -681,8 +681,7 @@ HWTEST_F(IdentityCheckerTest, testSwitchInputMethod_001, TestSize.Level0)
|
||||
*/
|
||||
HWTEST_F(IdentityCheckerTest, testSwitchInputMethod_002, TestSize.Level0)
|
||||
{
|
||||
IMSA_HILOGI("IdentityCheckerTest testSwitchInputMethod_001 start");
|
||||
EXPECT_CALL(*IdentityCheckerTest::identityCheckerMock_, HasPermission(_, _)).Times(1).WillRepeatedly(Return(false));
|
||||
IMSA_HILOGI("IdentityCheckerTest testSwitchInputMethod_002 start");
|
||||
EXPECT_CALL(*IdentityCheckerTest::identityCheckerMock_, IsBundleNameValid(_, _))
|
||||
.Times(1)
|
||||
.WillRepeatedly(Return(true));
|
||||
@ -700,8 +699,11 @@ HWTEST_F(IdentityCheckerTest, testSwitchInputMethod_002, TestSize.Level0)
|
||||
HWTEST_F(IdentityCheckerTest, testSwitchInputMethod_003, TestSize.Level0)
|
||||
{
|
||||
IMSA_HILOGI("IdentityCheckerTest testSwitchInputMethod_003 start");
|
||||
EXPECT_CALL(*IdentityCheckerTest::identityCheckerMock_, IsBundleNameValid(_, _))
|
||||
.Times(1)
|
||||
.WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(*IdentityCheckerTest::identityCheckerMock_, HasPermission(_, _)).Times(1).WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(*IdentityCheckerTest::identityCheckerMock_, IsBundleNameValid(_, _)).WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(*IdentityCheckerTest::identityCheckerMock_, IsSystemApp(_)).Times(1).WillRepeatedly(Return(true));
|
||||
int32_t ret = IdentityCheckerTest::service_->SwitchInputMethod(CURRENT_BUNDLENAME, CURRENT_SUBNAME);
|
||||
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
|
||||
}
|
||||
|
@ -1191,4 +1191,51 @@ describe('InputMethodTest', function () {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* @tc.number inputmethod_test_getDefaultInputMethod_001
|
||||
* @tc.name Test Indicates the getDefaultInputMethod.
|
||||
* @tc.desc Function test
|
||||
* @tc.level 1
|
||||
*/
|
||||
it('inputmethod_test_getDefaultInputMethod_001', 0, async function (done) {
|
||||
console.info('************* inputmethod_test_getDefaultInputMethod_001 Test start*************');
|
||||
try {
|
||||
let property = inputMethod.getDefaultInputMethod();
|
||||
if (property.name.length > 0) {
|
||||
expect(true).assertTrue();
|
||||
}
|
||||
console.info('************* inputmethod_test_getDefaultInputMethod_001 Test end*************');
|
||||
} catch (error) {
|
||||
if(error) {
|
||||
console.info(`inputmethod_test_getDefaultInputMethod_001 error, result: ${JSON.stringify(error)}`);
|
||||
expect().assertFail();
|
||||
}
|
||||
} finally {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* @tc.number inputmethod_test_getSystemInputMethodConfigAbility_001
|
||||
* @tc.name Test Indicates the getSystemInputMethodConfigAbility.
|
||||
* @tc.desc Function test
|
||||
* @tc.level 1
|
||||
*/
|
||||
it('inputmethod_test_getSystemInputMethodConfigAbility_001', 0, async function (done) {
|
||||
console.info('************* inputmethod_test_getSystemInputMethodConfigAbility_001 Test start*************');
|
||||
try {
|
||||
let systemInputMethodConfigAbility = inputMethod.getSystemInputMethodConfigAbility();
|
||||
console.info('************* inputmethod_test_getSystemInputMethodConfigAbility_001 Test end*************');
|
||||
expect(true).assertTrue();
|
||||
done();
|
||||
} catch (error) {
|
||||
if(error) {
|
||||
console.info(`inputmethod_test_getSystemInputMethodConfigAbility_001 error, result: ${JSON.stringify(error)}`);
|
||||
expect().assertFail();
|
||||
}
|
||||
} finally {
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user