Merge branch 'master' of gitee.com:openharmony/inputmethod_imf into master

Signed-off-by: mashaoyin <mashaoyin1@huawei.com>
This commit is contained in:
mashaoyin 2023-10-23 06:16:59 +00:00 committed by Gitee
commit 53d394a719
31 changed files with 1767 additions and 97 deletions

View File

@ -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",

View File

@ -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": [

View File

@ -53,6 +53,7 @@ ohos_shared_library("inputmethod") {
]
external_deps = [
"ability_base:want",
"ability_runtime:abilitykit_native",
"c_utils:utils",
"eventhandler:libeventhandler",

View File

@ -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>();

View File

@ -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(

View 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"
}

View 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);
}

View 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
};

View 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();
})
}
}
}
}

View File

@ -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;

View File

@ -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>

View File

@ -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");

View File

@ -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); });

View File

@ -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));

View File

@ -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",

View File

@ -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",

View File

@ -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.
*

View File

@ -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",

View File

@ -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;

View File

@ -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
};

View 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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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()

View 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

View File

@ -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;
}

View File

@ -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)

View File

@ -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

View File

@ -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);
}

View File

@ -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();
}
});
});