From 74d2897d468aefe9ecded8548ee219189e1173f4 Mon Sep 17 00:00:00 2001 From: KangPeng Date: Fri, 5 Sep 2025 14:11:39 +0800 Subject: [PATCH 1/4] =?UTF-8?q?imf=20arkts1.2=20inputMethodEngine=E6=A8=A1?= =?UTF-8?q?=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: KangPeng --- frameworks/ets/taihe/inputMethod/BUILD.gn | 27 +- .../idl/ohos.inputMethodEngine.taihe | 620 ++++++++++++++++++ .../inputMethod/include/ani_callback_object.h | 57 ++ .../inputMethod/include/ani_message_handler.h | 37 ++ .../include/input_method_ability_impl.h | 172 +++++ .../input_method_keyboard_delegate_impl.h | 132 ++++ .../include/input_method_panel_impl.h | 200 ++++++ .../include/input_method_panel_listener.h | 45 ++ .../inputMethod/src/ani_callback_object.cpp | 99 +++ .../taihe/inputMethod/src/ani_constructor.cpp | 48 +- .../inputMethod/src/ani_message_handler.cpp | 51 ++ .../src/input_method_ability_impl.cpp | 319 +++++++++ .../input_method_keyboard_delegate_impl.cpp | 264 ++++++++ .../src/input_method_panel_impl.cpp | 456 +++++++++++++ .../src/input_method_panel_listener.cpp | 119 ++++ .../src/ohos.inputMethodEngine.impl.cpp | 541 +++++++++++++++ 16 files changed, 3175 insertions(+), 12 deletions(-) create mode 100644 frameworks/ets/taihe/inputMethod/idl/ohos.inputMethodEngine.taihe create mode 100644 frameworks/ets/taihe/inputMethod/include/ani_callback_object.h create mode 100644 frameworks/ets/taihe/inputMethod/include/ani_message_handler.h create mode 100644 frameworks/ets/taihe/inputMethod/include/input_method_ability_impl.h create mode 100644 frameworks/ets/taihe/inputMethod/include/input_method_keyboard_delegate_impl.h create mode 100644 frameworks/ets/taihe/inputMethod/include/input_method_panel_impl.h create mode 100644 frameworks/ets/taihe/inputMethod/include/input_method_panel_listener.h create mode 100644 frameworks/ets/taihe/inputMethod/src/ani_callback_object.cpp create mode 100644 frameworks/ets/taihe/inputMethod/src/ani_message_handler.cpp create mode 100644 frameworks/ets/taihe/inputMethod/src/input_method_ability_impl.cpp create mode 100644 frameworks/ets/taihe/inputMethod/src/input_method_keyboard_delegate_impl.cpp create mode 100644 frameworks/ets/taihe/inputMethod/src/input_method_panel_impl.cpp create mode 100644 frameworks/ets/taihe/inputMethod/src/input_method_panel_listener.cpp create mode 100644 frameworks/ets/taihe/inputMethod/src/ohos.inputMethodEngine.impl.cpp diff --git a/frameworks/ets/taihe/inputMethod/BUILD.gn b/frameworks/ets/taihe/inputMethod/BUILD.gn index 6bc740450..ed2f7a1be 100644 --- a/frameworks/ets/taihe/inputMethod/BUILD.gn +++ b/frameworks/ets/taihe/inputMethod/BUILD.gn @@ -24,10 +24,13 @@ copy_taihe_idl("copy_taihe") { sources = [ "idl/ohos.inputMethod.Panel.taihe", "idl/ohos.inputMethod.taihe", - "idl/ohos.InputMethodSubtype.taihe" + "idl/ohos.InputMethodSubtype.taihe", + "idl/ohos.inputMethodEngine.taihe", ] - external_deps = [] + external_deps = [ + "input:key_event_taihe" + ] } ohos_taihe("run_taihe") { @@ -40,6 +43,8 @@ ohos_taihe("run_taihe") { "$taihe_generated_file_path/src/ohos.inputMethod.Panel.abi.c", "$taihe_generated_file_path/src/ohos.InputMethodSubtype.ani.cpp", "$taihe_generated_file_path/src/ohos.InputMethodSubtype.abi.c", + "$taihe_generated_file_path/src/ohos.inputMethodEngine.ani.cpp", + "$taihe_generated_file_path/src/ohos.inputMethodEngine.abi.c", ] } @@ -142,6 +147,24 @@ ohos_prebuilt_etc("inputmethod_subtype_etc") { deps = [ ":inputmethod_subtype_abc"] } +generate_static_abc("inputmethod_engine_abc") { + base_url = "$taihe_generated_file_path" + files = [ + "$taihe_generated_file_path/@ohos.inputMethodEngine.ets" + ] + is_boot_abc = "True" + device_dst_file = "/system/framework/inputmethod_engine_abc.abc" + dependencies = [ ":run_taihe" ] +} + +ohos_prebuilt_etc("inputmethod_engine_etc") { + source = "$target_out_dir/inputmethod_engine_abc.abc" + module_install_dir = "framework" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + deps = [ ":inputmethod_engine_abc"] +} + group("inputmethod_taihe") { deps = [ ":inputmethod_taihe_native", diff --git a/frameworks/ets/taihe/inputMethod/idl/ohos.inputMethodEngine.taihe b/frameworks/ets/taihe/inputMethod/idl/ohos.inputMethodEngine.taihe new file mode 100644 index 000000000..946d0ca8c --- /dev/null +++ b/frameworks/ets/taihe/inputMethod/idl/ohos.inputMethodEngine.taihe @@ -0,0 +1,620 @@ +/* + * Copyright (c) 2025 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. + */ + +@!sts_inject_into_module(""" +import BaseContext from 'application.BaseContext'; +import window from '@ohos.window'; +""") +@!sts_inject_into_module("import * as ohos_InputMethodSubtype from './@ohos.InputMethodSubtype';") +@!sts_inject_into_module("import * as ohos_keyEvent from './@ohos.multimodalInput.keyEvent';") + +@!namespace("@ohos.inputMethodEngine", "inputMethodEngine") + +from ohos.InputMethodSubtype use InputMethodSubtype; +from ohos.multimodalInput.keyEvent use KeyEvent as InputKeyEvent; + +enum Direction: i32 { + CURSOR_UP = 1, + CURSOR_DOWN = 2, + CURSOR_LEFT = 3, + CURSOR_RIGHT = 4 +} + +struct Movement { + direction: Direction; +} + +struct Range { + start: i32; + end: i32; +} + +enum ImmersiveMode: i32 { + NONE_IMMERSIVE = 0, + IMMERSIVE = 1, + LIGHT_IMMERSIVE = 2, + DARK_IMMERSIVE = 3 +} + +enum CapitalizeMode: i32 { + NONE = 0, + SENTENCES = 1, + WORDS = 2, + CHARACTERS = 3 +} + +enum GradientMode: i32 { + NONE = 0, + LINEAR_GRADIENT = 1 +} + +enum FluidLightMode: i32 { + NONE = 0, + BACKGROUND_FLUID_LIGHT = 1 +} + +union CommandDataType { + type_Int: i32; + type_String: String; + type_Bool: bool; +} + +struct EditorAttribute { + @readonly inputPattern: i32; + @readonly enterKeyType: i32; + isTextPreviewSupported: bool; + @readonly bundleName: Optional; + @readonly immersiveMode: Optional; + @readonly windowId: Optional; + @readonly displayId: Optional; + @readonly placeholder: Optional; + @readonly abilityName: Optional; + @readonly capitalizeMode: Optional; + @readonly gradientMode: Optional; + @readonly fluidLightMode: Optional; +} + +struct WindowInfo { + rect: @sts_type("window.Rect") Opaque; + status: @sts_type("window.WindowStatusType") Opaque; +} + +enum PanelType: i32 { + SOFT_KEYBOARD = 0, + STATUS_BAR = 1 +} + +enum PanelFlag: i32 { + FLG_FIXED = 0, + FLG_FLOATING = 1, + FLAG_CANDIDATE = 2 +} + +enum SecurityMode: i32 { + BASIC = 0, + FULL = 1 +} + +enum ExtendAction: i32 { + SELECT_ALL = 0, + CUT = 3, + COPY = 4, + PASTE = 5 +} + +struct PanelInfo { + type: PanelType; + flag: Optional; +} + +@const +enum EnterKeyType: u32 { + ENTER_KEY_TYPE_UNSPECIFIED = 0, + ENTER_KEY_TYPE_GO = 2, + ENTER_KEY_TYPE_SEARCH = 3, + ENTER_KEY_TYPE_SEND = 4, + ENTER_KEY_TYPE_NEXT = 5, + ENTER_KEY_TYPE_DONE = 6, + ENTER_KEY_TYPE_PREVIOUS = 7, + ENTER_KEY_TYPE_NEWLINE = 8 +} + +@const +enum PatternType: i32 { + PATTERN_NULL = -1, + PATTERN_TEXT = 0, + PATTERN_NUMBER = 2, + PATTERN_PHONE = 3, + PATTERN_DATETIME = 4, + PATTERN_EMAIL = 5, + PATTERN_URI = 6, + PATTERN_PASSWORD = 7, + PATTERN_PASSWORD_NUMBER = 8, + PATTERN_PASSWORD_SCREEN_LOCK = 9, + PATTERN_USER_NAME = 10, + PATTERN_NEW_PASSWORD = 11, + PATTERN_NUMBER_DECIMAL = 12, + PATTERN_ONE_TIME_CODE = 13 +} + +@const +enum FlagType: u32 { + DISPLAY_MODE_PART = 0, + DISPLAY_MODE_FULL = 1, + FLAG_SINGLE_LINE = 1, + FLAG_SELECTING = 2 +} + +@const +enum OptionType: u32 { + OPTION_NONE = 0, + OPTION_MULTI_LINE = 1, + OPTION_AUTO_CAP_CHARACTERS = 2, + OPTION_AUTO_WORDS = 4, + OPTION_AUTO_CAP_SENTENCES = 8, + OPTION_NO_FULLSCREEN = 10, + OPTION_ASCII = 20, +} + +@const +enum CursorType: u32 { + CURSOR_UP = 1, + CURSOR_DOWN = 2, + CURSOR_LEFT = 3, + CURSOR_RIGHT = 4 +} + +@const +enum WindowType: u32 { + WINDOW_TYPE_INPUT_METHOD_FLOAT = 2105 +} + +struct PanelRect { + landscapeRect: @sts_type("window.Rect") Opaque; + portraitRect: @sts_type("window.Rect") Opaque; +} + +struct KeyboardArea { + top: i32; + bottom: i32; + left: i32; + right: i32; +} + +struct EnhancedPanelRect { + landscapeRect: Optional<@sts_type("window.Rect") Opaque>; + portraitRect: Optional<@sts_type("window.Rect") Opaque>; + landscapeAvoidY: Optional; + landscapeInputRegion: Optional>; + portraitAvoidY: Optional; + portraitInputRegion: Optional>; + fullScreenMode: Optional; +} + +struct KeyEventType { + @readonly keyCode: i32; + @readonly keyAction: i32; +} + +interface TextInputClient { + +} + +interface InputMethodEngine { + @!sts_inject_into_interface(""" + on(type: string, callback: (data1: Object, data2: Object) => void): void; + off(type: string, callback?: (data1: Object, data2: Object) => void): void; + """) + @!sts_inject_into_class(""" + on(type: string, callback: (data1: Object, data2: Object) => void) { + switch(type) { + case "inputStart": return this.onInputStart(callback as (data1: KeyboardController, data2: TextInputClient) => void, callback); + default: throw new Error(`Unknown type: ${type}`); + } + } + off(type: string, callback?: (data1: Object, data2: Object) => void) { + switch(type) { + case "inputStart": return this.offInputStart(callback); + default: throw new Error(`Unknown type: ${type}`); + } + } + """) + OnInputStart(callback: (kbController: KeyboardController, textInputClient: TextInputClient) => void, opq: Opaque); + OffInputStart(opq: Optional); + + @!sts_inject_into_interface(""" + on(type: string, callback: () => void): void; + off(type: string, callback?: () => void): void; + """) + @!sts_inject_into_class(""" + on(type: string, callback: () => void) { + switch(type) { + case "keyboardShow": + case "keyboardHide": return this.onKeyboard(type, callback, callback); + default: throw new Error(`Unknown type: ${type}`); + } + } + off(type: string, callback?: () => void) { + switch(type) { + case "keyboardShow": + case "keyboardHide": return this.offKeyboard(type, callback); + default: throw new Error(`Unknown type: ${type}`); + } + } + """) + OnKeyboard(type: String, callback: () => void, opq: Opaque); + OffKeyboard(type: String, opq: Optional); +} + +interface InputClient { + @gen_async("selectByMovement") + @gen_promise("selectByMovement") + SelectByMovementAsync(movement: Movement): void; + + @gen_async("selectByRange") + @gen_promise("selectByRange") + SelectByRangeAsync(range: Range): void; + + @gen_async("moveCursor") + @gen_promise("moveCursor") + MoveCursorAsync(direction: i32): void; + + @gen_async("getBackward") + @gen_promise("getBackward") + GetBackwardAsync(length: i32): String; + + @gen_async("getForward") + @gen_promise("getForward") + GetForwardAsync(length: i32): String; + + @gen_async("insertText") + @gen_promise("insertText") + InsertTextAsync(text: String): bool; + + @gen_async("deleteBackward") + @gen_promise("deleteBackward") + DeleteBackwardAsync(length: i32): bool; + + @gen_async("deleteForward") + @gen_promise("deleteForward") + DeleteForwardAsync(length: i32): bool; + + @gen_async("sendKeyFunction") + @gen_promise("sendKeyFunction") + SendKeyFunctionAsync(action: i32): bool; + + @gen_async("getTextIndexAtCursor") + @gen_promise("getTextIndexAtCursor") + GetTextIndexAtCursorAsync(): i32; + + @gen_async("getEditorAttribute") + @gen_promise("getEditorAttribute") + GetEditorAttributeAsync(): EditorAttribute; + + @gen_promise("sendMessage") + SendMessageAsync(msgId: String, msgParam: Optional<@typedarray Array>): void; + + RecvMessage(msgHandler: Optional): void; + + @gen_promise("setPreviewText") + SetPreviewTextAsync(text: String, range: Range): void; + + FinishTextPreviewSync(): void; + + @gen_promise("getCallingWindowInfo") + GetCallingWindowInfoAsync(): WindowInfo; + + @gen_promise("sendPrivateCommand") + SendPrivateCommandAsync(commandData: @record Map): void; + + @gen_promise("finishTextPreview") + FinishTextPreviewAsync(): void; + + SetPreviewTextSync(text: String, range: Range): void; + + @gen_async("createPanel") + @gen_promise("createPanel") + CreatePanelAsync(ctx: @sts_type("BaseContext") Opaque, info: PanelInfo): Panel; + + @gen_async("sendExtendAction") + @gen_promise("sendExtendAction") + SendExtendActionAsync(action: ExtendAction): void; + + SelectByMovementSync(movement: Movement): void; + SelectByRangeSync(range: Range): void; + MoveCursorSync(direction: i32): void; + GetBackwardSync(length: i32): String; + GetForwardSync(length: i32): String; + InsertTextSync(text: String): void; + DeleteBackwardSync(length: i32): void; + DeleteForwardSync(length: i32): void; + GetEditorAttributeSync(): EditorAttribute; + GetTextIndexAtCursorSync(): i32; +} + +interface KeyboardDelegate { + + @!sts_inject_into_interface(""" + on(type: string, callback: (data1: Object, data2: Object, data3: Object) => void): void; + off(type: string, callback?: (data1: Object, data2: Object, data3: Object) => void): void; + on(type: string, callback: (data1: Object, data2: Object, data3: Object, data4: Object) => void): void; + off(type: string, callback?: (data1: Object, data2: Object, data3: Object, data4: Object) => void): void; + """) + @!sts_inject_into_class(""" + on(type: string, callback: (data1: Object, data2: Object, data3: Object) => void) { + switch(type) { + case "cursorContextChange": return this.onCursorContextChange(callback as (data1: int, data2: int, data3: int) => void, callback); + default: throw new Error(`Unknown type: ${type}`); + } + } + off(type: string, callback?: () => void) { + switch(type) { + case "cursorContextChange": return this.offCursorContextChange(callback); + default: throw new Error(`Unknown type: ${type}`); + } + } + on(type: string, callback: (data1: Object, data2: Object, data3: Object, data4: Object) => void) { + switch(type) { + case "selectionChange": return this.onSelectionChange(callback as (data1: int, data2: int, data3: int, data4: int) => void, callback); + default: throw new Error(`Unknown type: ${type}`); + } + } + off(type: string, callback?: (data1: Object, data2: Object, data3: Object, data4: Object) => void) { + switch(type) { + case "selectionChange": return this.offSelectionChange(callback); + default: throw new Error(`Unknown type: ${type}`); + } + } + """) + OnCursorContextChange(callback: (x: i32, y: i32, height: i32) => void, opq: Opaque); + OffCursorContextChange(opq: Optional); + OnSelectionChange(callback: (oldBegin: i32, oldEnd: i32, newBegin: i32, newEnd: i32) => void, opq: Opaque); + OffSelectionChange(opq: Optional); + + @!sts_inject_into_interface(""" + on(type: string, callback: (data: object) => object): void; + off(type: string, callback?: (data: object) => object): void; + """) + @!sts_inject_into_class(""" + on(type: string, callback: object) { + switch(type) { + case "keyDown": + case "keyUp": return this.onKeyEventType(type, callback as (data: KeyEventType) => boolean, callback); + case "keyEvent": return this.onKeyEvent(callback as (data: ohos_keyEvent.KeyEvent) => boolean, callback); + case "textChange": return this.onTextChange(callback as (data: string) => void, callback); + case "editorAttributeChanged": return this.onEditorAttributeChanged(callback as (data: EditorAttribute) => void, callback); + default: throw new Error(`Unknown type: ${type}`); + } + } + off(type: string, callback?: Object) { + switch(type) { + case "keyDown": + case "keyUp": return this.offKeyEventType(type, callback); + case "keyEvent": return this.offKeyEvent(callback); + case "textChange": return this.offTextChange(callback); + case "editorAttributeChanged": return this.offEditorAttributeChanged(callback); + default: throw new Error(`Unknown type: ${type}`); + } + } + """) + OnKeyEventType(type: String, callback: (event: KeyEventType) => bool, opq: Opaque); + OffKeyEventType(type: String, opq: Optional); + OnKeyEvent(callback: (event: InputKeyEvent) => bool, opq: Opaque); + OffKeyEvent(opq: Optional); + OnTextChange(callback: (text: String) => void, opq: Opaque); + OffTextChange(opq: Optional); + OnEditorAttributeChanged(callback: (attr: EditorAttribute) => void, opq: Opaque); + OffEditorAttributeChanged(opq: Optional); +} + +interface KeyboardController { + @gen_async("hide") + @gen_promise("hide") + HideAsync(): void; + + @gen_async("exitCurrentInputType") + @gen_promise("exitCurrentInputType") + ExitCurrentInputTypeAsync(): void; +} + +interface InputMethodAbility { + GetSecurityMode(): SecurityMode; + + @gen_async("destroyPanel") + @gen_promise("destroyPanel") + DestroyPanelAsync(panel: Panel): void; + + @!sts_inject_into_interface(""" + on(type: string, callback: () => void): void; + off(type: string, callback?: () => void): void; + """) + @!sts_inject_into_class(""" + on(type: string, callback: () => void) { + switch(type) { + case "keyboardShow": + case "keyboardHide": return this.onKeyboard(type, callback, callback); + case "inputStop": return this.onInputStop(callback as () => void, callback); + case "discardTypingText": return this.onDiscardTypingText(callback as () => void, callback); + default: throw new Error(`Unknown type: ${type}`); + } + } + off(type: string, callback?: () => void) { + switch(type) { + case "keyboardShow": + case "keyboardHide": return this.offKeyboard(type, callback); + case "inputStop": return this.offInputStop(callback); + case "discardTypingText": return this.offDiscardTypingText(callback); + default: throw new Error(`Unknown type: ${type}`); + } + } + """) + OnKeyboard(type: String, callback: () => void, opq: Opaque); + OffKeyboard(type: String, opq: Optional); + OnInputStop(callback: () => void, opq: Opaque); + OffInputStop(opq: Optional); + OnDiscardTypingText(callback: () => void, opq: Opaque); + OffDiscardTypingText(opq: Optional); + + @!sts_inject_into_interface(""" + on(type: string, callback: (data: Object) => void): void; + off(type: string, callback?: (data: Object) => void): void; + """) + @!sts_inject_into_class(""" + on(type: string, callback: (data: Object) => void) { + switch(type) { + case "privateCommand": return this.onPrivateCommand(callback as (data: Record) => void, callback); + case "setCallingWindow": return this.onSetCallingWindow(callback as (data: long) => void, callback); + case "callingDisplayDidChange": return this.onCallingDisplayDidChange(callback as (data: bigint) => void, callback); + case "securityModeChange": return this.onSecurityModeChange(callback as (data: SecurityMode) => void, callback); + case "setSubtype": return this.onSetSubtype(callback as (data: ohos_InputMethodSubtype.InputMethodSubtype) => void, callback); + default: throw new Error(`Unknown type: ${type}`); + } + } + off(type: string, callback?: (data: Object) => void) { + switch(type) { + case "privateCommand": return this.offPrivateCommand(callback); + case "setCallingWindow": return this.offSetCallingWindow(callback); + case "callingDisplayDidChange": return this.offCallingDisplayDidChange(callback); + case "securityModeChange": return this.offSecurityModeChange(callback); + case "setSubtype": return this.offSetSubtype(callback); + default: throw new Error(`Unknown type: ${type}`); + } + } + """) + OnPrivateCommand(callback: (data: @record Map) => void, opq: Opaque); + OffPrivateCommand(opq: Optional); + OnSetCallingWindow(callback: (wid: i64) => void, opq: Opaque); + OffSetCallingWindow(opq: Optional); + OnCallingDisplayDidChange(callback: (callingDisplayId: @bigint Array) => void, opq: Opaque); + OffCallingDisplayDidChange(opq: Optional); + OnSecurityModeChange(callback: (mode: SecurityMode) => void, opq: Opaque); + OffSecurityModeChange(opq: Optional); + OnSetSubtype(callback: (inputMethodSubtype: InputMethodSubtype) => void, opq: Opaque); + OffSetSubtype(opq: Optional); + + @!sts_inject_into_interface(""" + on(type: string, callback: (data1: Object, data2: Object) => void): void; + off(type: string, callback?: (data1: Object, data2: Object) => void): void; + """) + @!sts_inject_into_class(""" + on(type: string, callback: (data1: Object, data2: Object) => void) { + switch(type) { + case "inputStart": return this.onInputStart(callback as (data1: KeyboardController, data2: InputClient) => void, callback); + default: throw new Error(`Unknown type: ${type}`); + } + } + off(type: string, callback?: (data1: Object, data2: Object) => void) { + switch(type) { + case "inputStart": return this.offInputStart(callback); + default: throw new Error(`Unknown type: ${type}`); + } + } + """) + OnInputStart(callback: (kbController: KeyboardController, inputClient: InputClient) => void, opq: Opaque); + OffInputStart(opq: Optional); +} + +interface Panel { + GetImplPtr(): i64; + + StartMoving(): void; + UpdateRegion(inputRegion: Array<@sts_type("window.Rect") Opaque>): void; + + @overload("adjustPanelRect") + AdjustPanelRect(flag: PanelFlag, rect: PanelRect): void; + @overload("adjustPanelRect") + AdjustPanelRectEnhanced(flag: PanelFlag, rect: EnhancedPanelRect): void; + + @gen_promise("getDisplayId") + GetDisplayIdSync(): u32; + + GetImmersiveMode(): ImmersiveMode; + SetImmersiveMode(mode: ImmersiveMode): void; + SetPrivacyMode(isPrivacyMode: bool): void; + ChangeFlag(flag: PanelFlag): void; + + @gen_async("moveTo") + @gen_promise("moveTo") + MoveToAsync(x: i32, y: i32): void; + + @gen_async("resize") + @gen_promise("resize") + ResizeAsync(width: u32, height: u32): void; + + @gen_async("setUiContent") + @gen_promise("setUiContent") + //@overload("setUiContentSync") + SetUiContentAsync(path: String): void; + + // @gen_async("setUiContent") + // @gen_promise("setUiContent") + // @overload("setUiContentSync") + // SetUiContentStorage(path: String, storage: @sts_type("LocalStorage") Opaque): void; + + @gen_async("hide") + @gen_promise("hide") + HideAsync(): void; + + @gen_async("show") + @gen_promise("show") + ShowAsync(): void; + + + @!sts_inject_into_interface(""" + on(type: string, callback: () => void): void; + off(type: string, callback?: () => void): void; + on(type: string, callback: (data1: Object, data2: Object) => void): void; + off(type: string, callback?: (data1: Object, data2: Object) => void): void; + on(type: string, callback: (data1: Object, data2?: Object) => void): void; + off(type: string, callback?: (data1: Object, data2?: Object) => void): void; + """) + @!sts_inject_into_class(""" + on(type: string, callback: Object) { + switch(type) { + case "show": return this.onShow(callback as () => void, callback); + case "hide": return this.onHide(callback as () => void, callback); + case "sizeChange": return this.onSizeChange(callback as (data1: window.Size, data2?: KeyboardArea) => void, callback); + case "sizeUpdate": return this.onSizeUpdate(callback as (data1: window.Size, data2: KeyboardArea) => void, callback); + default: throw new Error(`Unknown type: ${type}`); + } + } + off(type: string, callback?: Object) { + switch(type) { + case "show": return this.offShow(callback); + case "hide": return this.offHide(callback); + case "sizeChange": return this.offSizeChange(callback); + case "sizeUpdate": return this.offSizeUpdate(callback); + default: throw new Error(`Unknown type: ${type}`); + } + } + """) + OnShow(callback: () => void, opq: Opaque); + OffShow(opq: Optional); + OnHide(callback: () => void, opq: Opaque); + OffHide(opq: Optional); + OnSizeChange(callback: (size: @sts_type("window.Size") Opaque, keyboardArea: Optional) => void, opq: Opaque): void; + OffSizeChange(opq: Optional); + OnSizeUpdate(callback: (size: @sts_type("window.Size") Opaque, keyboardArea: KeyboardArea) => void, opq: Opaque): void; + OffSizeUpdate(opq: Optional); +} + +interface MessageHandler { + OnMessage(msgId: String, msgParam: Optional<@arraybuffer Array>): void; + OnTerminated(): void; +} + +function GetKeyboardDelegate(): KeyboardDelegate; + +function GetInputMethodAbility(): InputMethodAbility; \ No newline at end of file diff --git a/frameworks/ets/taihe/inputMethod/include/ani_callback_object.h b/frameworks/ets/taihe/inputMethod/include/ani_callback_object.h new file mode 100644 index 000000000..1e0a6042c --- /dev/null +++ b/frameworks/ets/taihe/inputMethod/include/ani_callback_object.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 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 ANI_CALLBACK_OBJECT_H +#define ANI_CALLBACK_OBJECT_H + +#include +#include + +#include "block_data.h" +#include "event_handler.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace MiscServices { +class AniCallbackObject { +public: + AniCallbackObject(ani_env* env, uintptr_t callback, std::thread::id threadId, + std::shared_ptr aniHandler); + ~AniCallbackObject(); + ani_ref callback_ = nullptr; + ani_env env_{}; + std::thread::id threadId_; + std::shared_ptr> isDone_; + std::shared_ptr aniHandler_; +}; + +// Ensure this object abstract in constract thread. +class AniMsgHandlerCallbackObject { +public: + AniMsgHandlerCallbackObject(ani_env* env, uintptr_t onTerminated, uintptr_t onMessage); + ~AniMsgHandlerCallbackObject(); + ani_env env_{}; + ani_ref onTerminatedCallback_ = nullptr; + ani_ref onMessageCallback_ = nullptr; + std::shared_ptr GetEventHandler(); + +private: + std::mutex eventHandlerMutex_; + std::shared_ptr handler_ = nullptr; + std::thread::id threadId_; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // ANI_CALLBACK_OBJECT_H diff --git a/frameworks/ets/taihe/inputMethod/include/ani_message_handler.h b/frameworks/ets/taihe/inputMethod/include/ani_message_handler.h new file mode 100644 index 000000000..907bbfdbf --- /dev/null +++ b/frameworks/ets/taihe/inputMethod/include/ani_message_handler.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 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 ANI_MESSAGE_HANDLER_H +#define ANI_MESSAGE_HANDLER_H + +#include +#include "msg_handler_callback_interface.h" +#include "ani_callback_object.h" + +namespace OHOS { +namespace MiscServices { +class AniMessageHandler : public MsgHandlerCallbackInterface { +public: + explicit AniMessageHandler(ani_env* env, uintptr_t onTerminated, uintptr_t onMessage) + : AniMessageHandler_(std::make_shared(env, onTerminated, onMessage)) {}; + virtual ~AniMessageHandler() {}; + int32_t OnTerminated() override; + int32_t OnMessage(const ArrayBuffer &arrayBuffer) override; +private: + std::mutex callbackObjectMutex_; + std::shared_ptr aniMessageHandler_ = nullptr; +} +} // namespace MiscServices +} // namespace OHOS +#endif // ANI_MESSAGE_HANDLER_H \ No newline at end of file diff --git a/frameworks/ets/taihe/inputMethod/include/input_method_ability_impl.h b/frameworks/ets/taihe/inputMethod/include/input_method_ability_impl.h new file mode 100644 index 000000000..a80e090e9 --- /dev/null +++ b/frameworks/ets/taihe/inputMethod/include/input_method_ability_impl.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2025 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 TAIHE_INPUT_METHOD_ABILITY_IMPL_H +#define TAIHE_INPUT_METHOD_ABILITY_IMPL_H + +#include +#include +#include +#include +#include + +#include "ani_common.h" +#include "ohos.inputMethodEngine.proj.hpp" +#include "ohos.inputMethodEngine.impl.hpp" + +using SecurityMode_t = ohos::inputMethodEngine::SecurityMode; +namespace OHOS { +namespace MiscServices { +class InputMethodAbilityImpl : public InputMethodEngineListener { +public: + static std::shared_ptr GetInstance(); + SecurityMode_t GetSecurityMode(); + void DestroyPanelAsync(::ohos::inputMethodEngine::weak::Panel panel); + void RegisterListener(std::string const &type, callbackType &&cb, uintptr_t opq); + void UnRegisterListener(std::string const &type, taihe::optional_view opq); + + void OnKeyboardStatus(bool isShow) override; + void OnInputStart() override; + int32_t OnInputStop() override; + int32_t OnDiscardTypingText() override; + void OnSecurityChange(int32_t security) override; + void OnSetCallingWindow(uint32_t windowId) override; + void OnSetSubtype(const SubProperty &property) override; + void OnCallingDisplayIdChanged(uint64_t callingDisplayId) override; + void ReceivePrivateCommand(const std::unordered_map &privateCommand) override; + +private: + SecurityMode_t ConvertSecurityMode(SecurityMode mode); + std::mutex mutex_; + std::map>> jsCbMap_; + std::mutex engineMutex_; + std::shared_ptr inputMethodEngine_; +} + +class IMFAbilityImpl { +public: + IMFAbilityImpl() + { + } + SecurityMode_t GetSecurityMode() + { + return InputMethodAbilityImpl::GetInstance()->GetSecurityMode(); + } + + void DestroyPanelAsync(ohos::inputMethodEngine::weak::Panel panel) + { + InputMethodAbilityImpl::GetInstance()->DestroyPanelAsync(panel); + } + + void OnKeyboard(taihe::string_view type, taihe::callback_view callback, uintptr_t opq) + { + if (type == "keyboardShow") { + InputMethodAbilityImpl::GetInstance()->RegisterListener("keyboardShow", callback, opq); + } else { + InputMethodAbilityImpl::GetInstance()->RegisterListener("keyboardHide", callback, opq); + } + } + + void OffKeyboard(taihe::string_view type, taihe::optional_view opq) + { + if (type == "keyboardShow") { + InputMethodAbilityImpl::GetInstance()->UnRegisterListener("keyboardShow", opq); + } else { + InputMethodAbilityImpl::GetInstance()->UnRegisterListener("keyboardHide", opq); + } + } + + void OnInputStop(taihe::callback_view callback, uintptr_t opq) + { + InputMethodAbilityImpl::GetInstance()->RegisterListener("inputStop", callback, opq); + } + + void OffInputStop(taihe::optional_view opq) + { + InputMethodAbilityImpl::GetInstance()->UnRegisterListener("inputStop", opq); + } + + void OnDiscardTypingText(taihe::callback_view callback, uintptr_t opq) + { + InputMethodAbilityImpl::GetInstance()->RegisterListener("discardTypingText", callback, opq); + } + + void OffDiscardTypingText(taihe::optional_view opq) + { + InputMethodAbilityImpl::GetInstance()->UnRegisterListener("discardTypingText", opq); + } + + void OnPrivateCommand(taihe::callback_view)> callback, uintptr_t opq) + { + InputMethodAbilityImpl::GetInstance()->RegisterListener("privateCommand", callback, opq); + } + + void OffPrivateCommand(taihe::optional_view opq) + { + InputMethodAbilityImpl::GetInstance()->UnRegisterListener("privateCommand", opq); + } + + void OnSetCallingWindow(taihe::callback_view callback, uintptr_t opq) + { + InputMethodAbilityImpl::GetInstance()->RegisterListener("setCallingWindow", callback, opq); + } + + void OffSetCallingWindow(taihe::optional_view opq) + { + InputMethodAbilityImpl::GetInstance()->UnRegisterListener("setCallingWindow", opq); + } + + void OnCallingDisplayDidChange(taihe::callback_view)> callback, uintptr_t opq) + { + InputMethodAbilityImpl::GetInstance()->RegisterListener("callingDisplayDidChange", callback, opq); + } + + void OffCallingDisplayDidChange(taihe::optional_view opq) + { + InputMethodAbilityImpl::GetInstance()->UnRegisterListener("callingDisplayDidChange", opq); + } + + void OnSecurityModeChange(taihe::callback_view callback, uintptr_t opq) + { + InputMethodAbilityImpl::GetInstance()->RegisterListener("securityModeChange", callback, opq); + } + + void OffSecurityModeChange(taihe::optional_view opq) + { + InputMethodAbilityImpl::GetInstance()->UnRegisterListener("securityModeChange", opq); + } + + void OnSetSubtype(taihe::callback_view callback, uintptr_t opq) + { + InputMethodAbilityImpl::GetInstance()->RegisterListener("setSubtype", callback, opq); + } + + void OffSetSubtype(taihe::optional_view opq) + { + InputMethodAbilityImpl::GetInstance()->UnRegisterListener("setSubtype", opq); + } + + void OnInputStart(taihe::callback_view callback, uintptr_t opq) + { + InputMethodAbilityImpl::GetInstance()->RegisterListener("inputStart", callback, opq); + } + + void OffInputStart(taihe::optional_view opq) + { + InputMethodAbilityImpl::GetInstance()->UnRegisterListener("inputStart", opq); + } +} +} // namespace MiscServices +} // namespace OHOS +#endif // TAIHE_INPUT_METHOD_ABILITY_IMPL_H \ No newline at end of file diff --git a/frameworks/ets/taihe/inputMethod/include/input_method_keyboard_delegate_impl.h b/frameworks/ets/taihe/inputMethod/include/input_method_keyboard_delegate_impl.h new file mode 100644 index 000000000..93b72dd41 --- /dev/null +++ b/frameworks/ets/taihe/inputMethod/include/input_method_keyboard_delegate_impl.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2025 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 TAIHE_INPUT_METHOD_KEYBOARD_DELEGATE_IMPL_H +#define TAIHE_INPUT_METHOD_KEYBOARD_DELEGATE_IMPL_H + +#include +#include +#include +#include +#include + +#include "ani_common.h" +#include "ohos.inputMethodEngine.proj.hpp" +#include "ohos.inputMethodEngine.impl.hpp" + +using KeyEventType_t = ohos::inputMethodEngine::KeyEventType; +using KeyEvent_t = ohos::multimodalInput::keyEvent::KeyEvent; +namespace OHOS { +namespace MiscServices { +class KeyboardDelegateImpl : public KeyboardListener { +public: + static std::shared_ptr GetInstance(); + void RegisterListener(std::string const &type, callbackType &&cb, uintptr_t opq); + void UnRegisterListener(std::string const &type, taihe::optional_view opq); + bool OnKeyEvent(int32_t keyCode, int32_t keyStatus, sptr &consumer) override; + bool OnKeyEvent(const std::shared_ptr &keyEvent, sptr &consumer) override; + void OnCursorUpdate(int32_t positionX, int32_t positionY, int32_t height) override; + void OnSelectionChange(int32_t oldBegin, int32_t oldEnd, int32_t newBegin, int32_t newEnd) override; + void OnTextChange(const std::string &text) override; + void OnEditorAttributeChange(const InputAttribute &inputAttribute) override; + bool OnDealKeyEvent(const std::shared_ptr &keyEvent, sptr &consumer) override; +private: + std::mutex mutex_; + std::map>> jsCbMap_; + static std::mutex keyboardMutex_; + static std::shared_ptr keyboardDelegate_; + + bool keyEventConsume_ = false; + bool keyCodeConsume_ = false; + bool keyEventResult_ = false; + bool keyCodeResult_ = false; +}; + +class IMFKeyboardDelegateImpl { + public: + IMFKeyboardDelegateImpl() + { + } + + void OnCursorContextChange(taihe::callback_view callback, uintptr_t opq) + { + KeyboardDelegateImpl::GetInstance()->RegisterListener("cursorContextChange", callback, opq); + } + + void OffCursorContextChange(taihe::optional_view opq) + { + KeyboardDelegateImpl::GetInstance()->UnRegisterListener("cursorContextChange", opq); + } + + void OnSelectionChange(taihe::callback_view callback, uintptr_t opq) + { + KeyboardDelegateImpl::GetInstance()->RegisterListener("selectionChange", callback, opq); + } + + void OffSelectionChange(taihe::optional_view opq) + { + KeyboardDelegateImpl::GetInstance()->UnRegisterListener("selectionChange", opq); + } + + void OnKeyEventType(taihe::string_view type, taihe::callback_view callback, uintptr_t opq) + { + if (type == "keyUp") { + KeyboardDelegateImpl::GetInstance()->RegisterListener("keyUp", callback, opq); + } else { + KeyboardDelegateImpl::GetInstance()->RegisterListener("keyDown", callback, opq); + } + } + + void OffKeyEventType(taihe::string_view type, taihe::optional_view opq) + { + if (type == "keyUp") { + KeyboardDelegateImpl::GetInstance()->UnRegisterListener("keyUp", opq); + } else { + KeyboardDelegateImpl::GetInstance()->UnRegisterListener("keyDown", opq); + } + } + + void OnKeyEvent(taihe::callback_view callback, uintptr_t opq) + { + KeyboardDelegateImpl::GetInstance()->RegisterListener("keyEvent", callback, opq); + } + + void OffKeyEvent(taihe::optional_view opq) + { + KeyboardDelegateImpl::GetInstance()-> UnRegisterListener("keyEvent", opq); + } + + void OnTextChange(taihe::callback_view callback, uintptr_t opq) + { + KeyboardDelegateImpl::GetInstance()->RegisterListener("textChange", callback, opq); + } + + void OffTextChange(taihe::optional_view opq) + { + KeyboardDelegateImpl::GetInstance()->UnRegisterListener("textChange", opq); + } + + void OnEditorAttributeChanged(taihe::callback_view callback, uintptr_t opq) + { + KeyboardDelegateImpl::GetInstance()->RegisterListener("editorAttributeChanged", callback, opq); + } + + void OffEditorAttributeChanged(taihe::optional_view opq) + { + KeyboardDelegateImpl::GetInstance()->UnRegisterListener("editorAttributeChanged", opq); + } +} +} // namespace MiscServices +} // namespace OHOS +#endif // TAIHE_INPUT_METHOD_KEYBOARD_DELEGATE_IMPL_H \ No newline at end of file diff --git a/frameworks/ets/taihe/inputMethod/include/input_method_panel_impl.h b/frameworks/ets/taihe/inputMethod/include/input_method_panel_impl.h new file mode 100644 index 000000000..7ecbaa655 --- /dev/null +++ b/frameworks/ets/taihe/inputMethod/include/input_method_panel_impl.h @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2025 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 TAIHE_INPUT_METHOD_PANEL_IMPL_H +#define TAIHE_INPUT_METHOD_PANEL_IMPL_H + +#include +#include +#include +#include +#include + +#include "ani_common.h" +#include "ohos.inputMethodEngine.proj.hpp" +#include "ohos.inputMethodEngine.impl.hpp" + +using PanelFlag_t = ohos::inputMethodEngine::PanelFlag; +using PanelRect_t = ohos::inputMethodEngine::PanelRect; +using EnhancedPanelRect_t = ohos::inputMethodEngine::EnhancedPanelRect; +using ImmersiveMode_t = ohos::inputMethodEngine::ImmersiveMode; +using KeyboardArea_t = ohos::inputMethodEngine::KeyboardArea; +namespace OHOS { +namespace MiscServices { +class PanelImpl { +public: + static std::shared_ptr GetInstance(); + ~PanelImpl(); + void CreatePanel(uintptr_t ctx, ohos::inputMethodEngine::PanelInfo const& info, std::shared_ptr &panel); + void StartMoving(); + void UpdateRegion(taihe::array_view inputRegion); + void AdjustPanelRect(PanelFlag_t flag, PanelRect_t const& rect); + void AdjustPanelRectEnhanced(PanelFlag_t flag, EnhancedPanelRect_t const& rect); + uint32_t GetDisplayIdSync(); + ImmersiveMode_t GetImmersiveMode(); + void SetImmersiveMode(ImmersiveMode_t mode); + void SetPrivacyMode(bool isPrivacyMode); + void ChangeFlag(PanelFlag_t flag); + void MoveToAsync(int32_t x, int32_t y); + void ResizeAsync(uint32_t width, uint32_t height); + void SetUiContentAsync(taihe::string_view path); + void HideAsync(); + void ShowAsync(); + void RegisterListener(std::string const &type, callbackType &&cb, uintptr_t opq); + void UnRegisterListener(std::string const &type, taihe::optional_view opq); +private: + bool IsPanelFlagValid(PanelFlag panelFlag, bool isEnhancedCalled); + ImmersiveMode_t ConvertMode(ImmersiveMode mode); + bool IsVaildImmersiveMode(ImmersiveMode mode); + void SetNative(const std::shared_ptr &panel); + std::shared_ptr GetNative(); + static std::mutex PanelImpl::panelMutex_; + static std::shared_ptr panel_; + static std::shared_ptr inputMethodPanel_; +} + +class IMFPanelImpl { +public: + + int64_t GetImplPtr() + { + return reinterpret_cast(this); + } + + std::shared_ptr GetNativePtr() + { + return value_; + } + + IMFPanelImpl(uintptr_t ctx, ohos::inputMethodEngine::PanelInfo const& info) + { + value_ = std::shared_ptr(); + PanelImpl::GetInstance()->CreatePanel(ctx, info, value_); + } + + void StartMoving() + { + PanelImpl::GetInstance()->StartMoving(); + } + + void UpdateRegion(taihe::array_view inputRegion) + { + PanelImpl::GetInstance()->UpdateRegion(inputRegion); + } + + void AdjustPanelRect(PanelFlag_t flag, PanelRect_t const& rect) + { + PanelImpl::GetInstance()->AdjustPanelRect(flag, rect); + } + + void AdjustPanelRectEnhanced(PanelFlag_t flag, EnhancedPanelRect_t const& rect) + { + PanelImpl::GetInstance()->AdjustPanelRectEnhanced(flag, rect); + } + + uint32_t GetDisplayIdSync() + { + return PanelImpl::GetInstance()->GetDisplayIdSync(); + } + + ImmersiveMode_t GetImmersiveMode() + { + return PanelImpl::GetInstance()->GetImmersiveMode(); + } + + void SetImmersiveMode(ImmersiveMode_t mode) + { + PanelImpl::GetInstance()->SetImmersiveMode(mode); + } + + void SetPrivacyMode(bool isPrivacyMode) + { + PanelImpl::GetInstance()->SetPrivacyMode(isPrivacyMode); + } + + void ChangeFlag(PanelFlag_t flag) + { + PanelImpl::GetInstance()->ChangeFlag(flag); + } + + void MoveToAsync(int32_t x, int32_t y) + { + PanelImpl::GetInstance()->MoveToAsync(x, y); + } + + void ResizeAsync(uint32_t width, uint32_t height) + { + PanelImpl::GetInstance()->ResizeAsync(width, height); + } + + void SetUiContentAsync(taihe::string_view path) + { + PanelImpl::GetInstance()->SetUiContentAsync(path); + } + + void HideAsync() + { + PanelImpl::GetInstance()->HideAsync(); + } + + void ShowAsync() + { + PanelImpl::GetInstance()->ShowAsync(); + } + + void OnShow(taihe::callback_view callback, uintptr_t opq) + { + PanelImpl::GetInstance()->RegisterListener("show", callback, opq); + } + + void OffShow(taihe::optional_view opq) + { + PanelImpl::GetInstance()->UnRegisterListener("show", opq); + } + + void OnHide(taihe::callback_view callback, uintptr_t opq) + { + PanelImpl::GetInstance()->RegisterListener("hide", callback, opq); + } + + void OffHide(taihe::optional_view opq) + { + PanelImpl::GetInstance()->UnRegisterListener("hide", opq); + } + + void OnSizeChange(taihe::callback_view)> callback, uintptr_t opq) + { + PanelImpl::GetInstance()->RegisterListener("sizeChange", callback, opq); + } + + void OffSizeChange(taihe::optional_view opq) + { + PanelImpl::GetInstance()->UnRegisterListener("sizeChange", opq); + } + + void OnSizeUpdate(taihe::callback_view callback, uintptr_t opq) + { + PanelImpl::GetInstance()->RegisterListener("sizeUpdate", callback, opq); + } + + void OffSizeUpdate(taihe::optional_view opq) + { + PanelImpl::GetInstance()->UnRegisterListener("sizeUpdate", opq); + } +private: + std::shared_ptr value_; +} +} // namespace MiscServices +} // namespace OHOS +#endif // TAIHE_INPUT_METHOD_PANEL_IMPL_H \ No newline at end of file diff --git a/frameworks/ets/taihe/inputMethod/include/input_method_panel_listener.h b/frameworks/ets/taihe/inputMethod/include/input_method_panel_listener.h new file mode 100644 index 000000000..46b951525 --- /dev/null +++ b/frameworks/ets/taihe/inputMethod/include/input_method_panel_listener.h @@ -0,0 +1,45 @@ +/* + * 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 INPUTMETHOD_PANEL_LISTENER_H +#define INPUTMETHOD_PANEL_LISTENER_H + +#include + +#include "ani_common.h" +#include "concurrent_map.h" +#include "panel_status_listener.h" +namespace OHOS { +namespace MiscServices { +class InputMethodPanelListener : public PanelStatusListener { +public: + static std::shared_ptr GetInstance(); + ~InputMethodPanelListener(); + void OnPanelStatus(uint32_t windowId, bool isShow) override; + void OnSizeChange(uint32_t windowId, const WindowSize &size) override; + void OnSizeChange(uint32_t windowId, const WindowSize &size, const PanelAdjustInfo &keyboardArea, + const std::string &event) override; + void Subscribe(uint32_t windowId, const std::string &type, callbackType &&cb, uintptr_t opq); + void RemoveInfo(const std::string &type, uint32_t windowId, taihe::optional_view opq); + + std::mutex mutex_; + ConcurrentMap>> jsCbMap_; + static std::mutex listenerMutex_; + static std::shared_ptr instance_; +} +} // namespace MiscServices +} // namespace OHOS + +#endif //INPUTMETHOD_PANEL_LISTENER_H \ No newline at end of file diff --git a/frameworks/ets/taihe/inputMethod/src/ani_callback_object.cpp b/frameworks/ets/taihe/inputMethod/src/ani_callback_object.cpp new file mode 100644 index 000000000..5686166d9 --- /dev/null +++ b/frameworks/ets/taihe/inputMethod/src/ani_callback_object.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2022 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 "ani_callback_object.h" +#include "global.h" + +#include + +namespace OHOS { +namespace MiscServices { +constexpr int32_t MAX_TIMEOUT = 2000; +AniCallbackObject::AniCallbackObject(ani_env* env, uintptr_t callback, std::thread::id threadId, + std::shared_ptr aniHandler) + : env_(env), threadId_(threadId), aniHandler_(aniHandler) +{ + ani_object callbackObj = reinterpret_cast(callback); + if (ANI_OK != env->GlobalReference_Create(callbackObj, &callback_)) { + IMSA_HILOGE(UDMF_ANI, "GlobalReference_Create callback_ failed."); + return; + } +} + +AniCallbackObject::~AniCallbackObject() +{ + if (callback_ != nullptr) { + if (threadId_ == std::this_thread::get_id()) { + env_->GlobalReference_Delete(env_, callback_); + env_ = nullptr; + return; + } + isDone_ = std::make_shared>(MAX_TIMEOUT, false); + std::string type = "~AniCallbackObject"; + auto eventHandler = aniHandler_; + if (eventHandler == nullptr) { + IMSA_HILOGE("eventHandler is nullptr!"); + return; + } + auto task = [env = env_, callback = callback_, isDone = isDone_]() { + env->GlobalReference_Delete(env, callback); + bool isFinish = true; + isDone->SetValue(isFinish); + }; + eventHandler->PostTask(task, type); + isDone_->GetValue(); + } + env_ = nullptr; +} + + +AniMsgHandlerCallbackObject::AniMsgHandlerCallbackObject(ani_env *env, uintptr_t onTerminated, uintptr_t onMessage) + : env_(env), handler_(AppExecFwk::EventHandler::Current()), threadId_(std::this_thread::get_id()) +{ + ani_object onTerminatedObj = reinterpret_cast(onTerminated); + ani_object onMessageObj = reinterpret_cast(onMessage); + if (ANI_OK != env->GlobalReference_Create(onTerminatedObj, &onTerminatedCallback_)) { + IMSA_HILOGE(UDMF_ANI, "GlobalReference_Create onTerminated failed."); + return; + } + if (ANI_OK != env->GlobalReference_Create(onMessageObj, &onMessageCallback_)) { + IMSA_HILOGE(UDMF_ANI, "GlobalReference_Create onMessage failed."); + return; + } +} + +AniMsgHandlerCallbackObject::~AniMsgHandlerCallbackObject() +{ + if (threadId_ == std::this_thread::get_id()) { + if (onTerminatedCallback_ != nullptr) { + env_->GlobalReference_Delete(env_, onTerminatedCallback_); + } + if (onMessageCallback_ != nullptr) { + env_->GlobalReference_Delete(env_, onMessageCallback_); + } + env_ = nullptr; + return; + } + IMSA_HILOGW("Thread id is not same, abstract destructor is run in muti-thread!"); + env_ = nullptr; +} + +std::shared_ptr AniMsgHandlerCallbackObject::GetEventHandler() +{ + std::lock_guard lock(eventHandlerMutex_); + return handler_; +} +} // namespace MiscServices +} // namespace OHOS diff --git a/frameworks/ets/taihe/inputMethod/src/ani_constructor.cpp b/frameworks/ets/taihe/inputMethod/src/ani_constructor.cpp index b3719ccb2..1f5c1fd87 100644 --- a/frameworks/ets/taihe/inputMethod/src/ani_constructor.cpp +++ b/frameworks/ets/taihe/inputMethod/src/ani_constructor.cpp @@ -13,27 +13,55 @@ * limitations under the License. */ +#include "ohos.InputMethodSubtype.ani.hpp" #include "ohos.inputMethod.Panel.ani.hpp" +#include "ohos.multimodalInput.keyEvent.ani.hpp" #include "ohos.inputMethod.ani.hpp" -#include "ohos.InputMethodSubtype.ani.hpp" -ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) -{ +#include "ohos.multimodalInput.keyCode.ani.hpp" +#include "ohos.multimodalInput.inputEvent.ani.hpp" +#include "taihe.platform.ani.ani.hpp" +#include "ohos.inputMethodEngine.ani.hpp" +#if __has_include() +#include +#elif __has_include() +#include +#else +#error "ani.h not found. Please ensure the Ani SDK is correctly installed." +#endif +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) { ani_env *env; if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { return ANI_ERROR; } - if (ANI_OK != ohos::inputMethod::ANIRegister(env)) { - std::cerr << "Error from ohos::inputMethod::ANIRegister" << std::endl; - return ANI_ERROR; - } + ani_status status = ANI_OK; if (ANI_OK != ohos::InputMethodSubtype::ANIRegister(env)) { std::cerr << "Error from ohos::InputMethodSubtype::ANIRegister" << std::endl; - return ANI_ERROR; + status = ANI_ERROR; } if (ANI_OK != ohos::inputMethod::Panel::ANIRegister(env)) { std::cerr << "Error from ohos::inputMethod::Panel::ANIRegister" << std::endl; - return ANI_ERROR; + status = ANI_ERROR; + } + if (ANI_OK != ohos::multimodalInput::keyEvent::ANIRegister(env)) { + std::cerr << "Error from ohos::multimodalInput::keyEvent::ANIRegister" << std::endl; + status = ANI_ERROR; + } + if (ANI_OK != ohos::inputMethod::ANIRegister(env)) { + std::cerr << "Error from ohos::inputMethod::ANIRegister" << std::endl; + status = ANI_ERROR; + } + if (ANI_OK != ohos::multimodalInput::keyCode::ANIRegister(env)) { + std::cerr << "Error from ohos::multimodalInput::keyCode::ANIRegister" << std::endl; + status = ANI_ERROR; + } + if (ANI_OK != ohos::multimodalInput::inputEvent::ANIRegister(env)) { + std::cerr << "Error from ohos::multimodalInput::inputEvent::ANIRegister" << std::endl; + status = ANI_ERROR; + } + if (ANI_OK != ohos::inputMethodEngine::ANIRegister(env)) { + std::cerr << "Error from ohos::inputMethodEngine::ANIRegister" << std::endl; + status = ANI_ERROR; } *result = ANI_VERSION_1; - return ANI_OK; + return status; } diff --git a/frameworks/ets/taihe/inputMethod/src/ani_message_handler.cpp b/frameworks/ets/taihe/inputMethod/src/ani_message_handler.cpp new file mode 100644 index 000000000..245239617 --- /dev/null +++ b/frameworks/ets/taihe/inputMethod/src/ani_message_handler.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2025 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 "ani_message_handler.h" + +namespace OHOS { +namespace MiscServices { +int32_t AniMessageHandler::OnTerminated() +{ + std::lock_guard lock(callbackObjectMutex_); + if (aniMessageHandler_ == nullptr) { + IMSA_HILOGI("aniMessageHandler_ is nullptr, can not call OnTerminated!."); + return ErrorCode::ERROR_NULL_POINTER; + } + auto func = aniMessageHandler_->onTerminatedCallback_; + std::shared_ptr>cacheCallback = std::reinterpret_pointer_cast>(func); + (*cacheCallback); + return ErrorCode::NO_ERROR; +} + +int32_t AniMessageHandler::OnMessage(const ArrayBuffer &arrayBuffer) +{ + std::lock_guard lock(callbackObjectMutex_); + if (aniMessageHandler_ == nullptr) { + IMSA_HILOGE("MessageHandler was not regist!."); + return ErrorCode::ERROR_MSG_HANDLER_NOT_REGIST; + } + if (!ArrayBuffer::IsSizeValid(arrayBuffer)) { + IMSA_HILOGE("msgId limit 256B and msgParam limit 128KB."); + return ErrorCode::ERROR_PARAMETER_CHECK_FAILED; + } + auto func = aniMessageHandler_->onMessageCallback_; + std::shared_ptr>)>>cacheCallback = std::reinterpret_pointer_cast>(func); + (*cacheCallback)(taihe::string_view(arrayBuffer.msgId), ::taihe::optional<::taihe::array>::make( + ::taihe::array(arrayBuffer.msgParam))); + return ErrorCode::NO_ERROR; +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/taihe/inputMethod/src/input_method_ability_impl.cpp b/frameworks/ets/taihe/inputMethod/src/input_method_ability_impl.cpp new file mode 100644 index 000000000..41e0ee119 --- /dev/null +++ b/frameworks/ets/taihe/inputMethod/src/input_method_ability_impl.cpp @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2025 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_ability_impl.h" +#include "input_method_panel_impl.h" + +using ValueMap = std::unordered_map; +using CommandDataType_t = ohos::inputMethodEngine::CommandDataType; + +namespace OHOS { +namespace MiscServices { +using namespace taihe; +std::mutex InputMethodAbilityImpl::engineMutex_; +std::shared_ptr InputMethodAbilityImpl::inputMethodEngine_{ nullptr }; + +std::shared_ptr InputMethodAbilityImpl::GetInstance() +{ + if (inputMethodEngine_ == nullptr) { + std::lock_guard lock(engineMutex_); + if (inputMethodEngine_ == nullptr) { + auto engine = std::make_shared(); + if (engine == nullptr) { + IMSA_HILOGE("create engine failed!"); + return nullptr; + } + inputMethodEngine_ = engine; + } + } + return inputMethodEngine_; +} + +SecurityMode_t InputMethodAbilityImpl::ConvertSecurityMode(SecurityMode mode) +{ + switch (mode) { + case SecurityMode::BASIC: + return SecurityMode_t::key_t::BASIC; + case SecurityMode::FULL: + return SecurityMode_t::key_t::FULL; + default: + return SecurityMode_t::key_t::BASIC; + } +} + +CommandDataType_t ConvertToDataType(const PrivateDataValue &value) +{ + size_t idx = value.index(); + if (idx == static_cast(PrivateDataValueType::VALUE_TYPE_STRING)) { + auto stringValue = std::get_if(&value); + if (stringValue != nullptr) { + return CommandDataType_t::make_type_String(*stringValue); + } + } else if (idx == static_cast(PrivateDataValueType::VALUE_TYPE_BOOL)) { + auto boolValue = std::get_if(&value); + if (boolValue != nullptr) { + return CommandDataType_t::make_type_Bool(*boolValue); + } + } else if (idx == static_cast(PrivateDataValueType::VALUE_TYPE_NUMBER)) { + auto numberValue = std::get_if(&value); + if (numberValue != nullptr) { + return CommandDataType_t::make_type_Int(*numberValue); + } + } + return CommandDataType_t::make_type_Bool(true); +} + +taihe::map InputMethodAbilityImpl::NativeConvertPCommandToAni(ValueMap &valueMap) +{ + taihe::map result(valueMap.size()); + for (const auto &[key, value] : valueMap) { + result.emplace(key, ConvertToDataType(value)); + } + return result; +} + +SecurityMode_t InputMethodAbilityImpl::GetSecurityMode() +{ + int32_t security = 0; + int32_t ret = InputMethodAbility::GetInstance().GetSecurityMode(security); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed to get security mode"); + set_business_error(JsUtils::Convert(ret), "failed to get security mode"); + return ConvertSecurityMode(security); + } + IMSA_HILOGI("GetSecurityMode success!"); + return ConvertSecurityMode(security); +} + +void InputMethodAbilityImpl::DestroyPanelAsync(::ohos::inputMethodEngine::weak::Panel panel) +{ + // ohos::inputMethodEngine::weak::Panel -> panel + IMFPanelImpl* panelImpl = reinterpret_castpanel->GetImplPtr(); + if (panelImpl == nullptr) { + IMSA_HILOGE("Failed to unwrap IMFPanelImpl"); + set_business_error(IMFErrorCode::EXCEPTION_PARAMCHECK, "Failed to unwrap IMFPanelImpl"); + return; + } + auto panelNative = panelImpl->GetNativePtr(); + if (panelNative == nullptr) { + IMSA_HILOGE("get panelNative failed"); + } + auto errCode = InputMethodAbility::GetInstance().DestroyPanel(panelNative); + if (errCode != ErrorCode::NO_ERROR) { + IMSA_HILOGE("DestroyPanel failed, errCode: %{public}d!", errCode); + set_business_error(JsUtils::Convert(ret), "DestroyPanel failed"); + return; + } + IMSA_HILOGI("DestroyPanel success!"); +} + +void InputMethodAbilityImpl::RegisterListener(std::string const &type, callbackType &&cb, uintptr_t opq) +{ + if (!EventChecker::IsValidEventType(EventSubscribeModule::INPUT_METHOD_ABILITY, type)) { + IMSA_HILOGE("subscribe failed, type: %{public}s.", type.c_str()); + return; + } + if (type == "privateCommand" && !InputMethodAbility::GetInstance().IsDefaultIme()) { + set_business_error(JsUtils::Convert(ErrorCode::ERROR_NOT_DEFAULT_IME), "default ime check failed"); + return; + } +#ifndef SCENE_BOARD_ENABLE + if (type == "callingDisplayDidChange") { + set_business_error(JsUtils::Convert(ErrorCode::ERROR_DEVICE_UNSUPPORTED), "capability not supported."); + return; + } +#endif + std::lock_guard lock(mutex_); + ani_object callbackObj = reinterpret_cast(opq); + ani_ref callbackRef; + ani_env *env = taihe::get_env(); + if (env == nullptr || ANI_OK != env->GlobalReference_Create(callbackObj, &callbackRef)) { + IMSA_HILOGE("Failed to register %{public}s", type.c_str()); + return; + } + auto &cbVec = jsCbMap_[type]; + bool isDuplicate = + std::any_of(cbVec.begin(), cbVec.end(), [env, callbackRef](std::unique_ptr &obj) { + ani_boolean isEqual = false; + return (ANI_OK == env->Reference_StrictEquals(callbackRef, obj->ref, &isEqual)) && isEqual; + }); + if (isDuplicate) { + env->GlobalReference_Delete(callbackRef); + IMSA_HILOGD("%{public}s is already registered", type.c_str()); + return; + } + cbVec.emplace_back(std::make_unique(cb, callbackRef)); + IMSA_HILOGI("Registered success type: %{public}s", type.c_str()); +} + +void InputMethodAbilityImpl::UnRegisterListener(std::string const &type, taihe::optional_view opq) +{ + if (!EventChecker::IsValidEventType(EventSubscribeModule::INPUT_METHOD_ABILITY, type)) { + IMSA_HILOGE("subscribe failed, type: %{public}s.", type.c_str()); + return; + } + if (type == "privateCommand" && !InputMethodAbility::GetInstance().IsDefaultIme()) { + set_business_error(JsUtils::Convert(ErrorCode::ERROR_NOT_DEFAULT_IME), "default ime check failed"); + return; + } + std::lock_guard lock(mutex_); + const auto iter = jsCbMap_.find(type); + if (iter == jsCbMap_.end()) { + IMSA_HILOGE("%{public}s is not registered", type.c_str()); + return; + } + + if (!opq.has_value()) { + jsCbMap_.erase(iter); + return; + } + + ani_env *env = taihe::get_env(); + if (env == nullptr) { + IMSA_HILOGE("Failed to unregister %{public}s, env is nullptr", type.c_str()); + return; + } + + GlobalRefGuard guard(env, reinterpret_cast(opq.value())); + if (!guard) { + IMSA_HILOGE("Failed to unregister %{public}s, GlobalRefGuard is false!", type.c_str()); + return; + } + + const auto pred = [env, targetRef = guard.get()](std::unique_ptr &obj) { + ani_boolean is_equal = false; + return (ANI_OK == env->Reference_StrictEquals(targetRef, obj->ref, &is_equal)) && is_equal; + }; + auto &callbacks = iter->second; + const auto it = std::find_if(callbacks.begin(), callbacks.end(), pred); + if (it != callbacks.end()) { + callbacks.erase(it); + } + if (callbacks.empty()) { + jsCbMap_.erase(iter); + } +} + +void InputMethodAbilityImpl::OnKeyboardStatus(bool isShow) +{ + std::string type = isShow ? "keyboardShow" : "keyboardHide"; + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_[type]; + for (auto &cb : cbVec) { + auto &func = std::get>(cb->callback); + func(); + } +} + +void InputMethodAbilityImpl::OnInputStart() +{ + IMSA_HILOGI("OnInputStart start."); + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_["inputStart"]; + for (auto &cb : cbVec) { + auto &func = std::get>(cb->callback); + // 解析kbController, inputClient + func(); + } +} + +int32_t InputMethodAbilityImpl::OnInputStop() +{ + IMSA_HILOGI("OnInputStop start."); + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_["inputStop"]; + for (auto &cb : cbVec) { + auto &func = std::get>(cb->callback); + func(); + } + return 0; +} + +int32_t InputMethodAbilityImpl::OnDiscardTypingText() +{ + IMSA_HILOGI("DiscardTypingText start."); + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_["discardTypingText"]; + for (auto &cb : cbVec) { + auto &func = std::get>(cb->callback); + func(); + } + return 0; +} + +void InputMethodAbilityImpl::OnSecurityChange(int32_t security) +{ + IMSA_HILOGI("OnSecurityChange start."); + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_["securityModeChange"]; + for (auto &cb : cbVec) { + auto &func = std::get>(cb->callback); + SecurityMode_t modeType = ConvertSecurityMode(static_cast(security)); + func(modeType); + } +} + +void InputMethodAbilityImpl::OnSetCallingWindow(uint32_t windowId) +{ + IMSA_HILOGI("OnSetCallingWindow start."); + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_["setCallingWindow"]; + for (auto &cb : cbVec) { + // uint32 int64_t ? + auto &func = std::get>(cb->callback); + int64_t wid = static_cast(windowId); + func(wid); + } +} + +void InputMethodAbilityImpl::OnSetSubtype(const SubProperty &property) +{ + IMSA_HILOGI("OnSetSubtype start."); + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_["setSubtype"]; + for (auto &cb : cbVec) { + auto &func = std::get>(cb->callback); + func(PropertyConverter::ConvertSubProperty(property)); + } +} + +void InputMethodAbilityImpl::OnCallingDisplayIdChanged(uint64_t callingDisplayId) +{ + IMSA_HILOGI("OnCallingDisplayIdChanged start."); + if (callingDisplayId > UINT32_MAX) { + IMSA_HILOGE("callingDisplayId over range!"); + return; + } + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_["callingDisplayDidChange"]; + for (auto &cb : cbVec) { + auto &func = std::get)>>(cb->callback); + // callingDisplayId-> array_view + func(); + } +} + +void InputMethodAbilityImpl::ReceivePrivateCommand(const std::unordered_map &privateCommand) +{ + IMSA_HILOGD("start."); + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_["privateCommand"]; + for (auto &cb : cbVec) { + auto &func = std::get)>>(cb->callback); + func(NativeConvertPCommandToAni(privateCommand)); + } +} + +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/taihe/inputMethod/src/input_method_keyboard_delegate_impl.cpp b/frameworks/ets/taihe/inputMethod/src/input_method_keyboard_delegate_impl.cpp new file mode 100644 index 000000000..cacbfa6b1 --- /dev/null +++ b/frameworks/ets/taihe/inputMethod/src/input_method_keyboard_delegate_impl.cpp @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2025 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_keyboard_delegate_impl.h" + +namespace OHOS { +namespace MiscServices { +constexpr size_t ARGC_TWO = 2; +using namespace taihe; +std::mutex KeyboardDelegateImpl::keyboardMutex_; +std::shared_ptr KeyboardDelegateImpl::keyboardDelegate_{ nullptr }; + +std::shared_ptr KeyboardDelegateImpl::GetInstance() +{ + if (keyboardDelegate_ == nullptr) { + std::lock_guard lock(keyboardMutex_); + if (keyboardDelegate_ == nullptr) { + auto delegate = std::make_shared(); + if (delegate == nullptr) { + IMSA_HILOGE("keyboard delegate is nullptr!"); + return nullptr; + } + keyboardDelegate_ = delegate; + } + } + return keyboardDelegate_; +} + +void KeyboardDelegateImpl::RegisterListener(std::string const &type, callbackType &&cb, uintptr_t opq) +{ + if (!EventChecker::IsValidEventType(EventSubscribeModule::KEYBOARD_DELEGATE, type)) { + IMSA_HILOGE("subscribe failed, type: %{public}s.", type.c_str()); + return; + } + std::lock_guard lock(mutex_); + ani_object callbackObj = reinterpret_cast(opq); + ani_ref callbackRef; + ani_env *env = taihe::get_env(); + if (env == nullptr || ANI_OK != env->GlobalReference_Create(callbackObj, &callbackRef)) { + IMSA_HILOGE("Failed to register %{public}s", type.c_str()); + return; + } + auto &cbVec = jsCbMap_[type]; + bool isDuplicate = + std::any_of(cbVec.begin(), cbVec.end(), [env, callbackRef](std::unique_ptr &obj) { + ani_boolean isEqual = false; + return (ANI_OK == env->Reference_StrictEquals(callbackRef, obj->ref, &isEqual)) && isEqual; + }); + if (isDuplicate) { + env->GlobalReference_Delete(callbackRef); + IMSA_HILOGD("%{public}s is already registered", type.c_str()); + return; + } + cbVec.emplace_back(std::make_unique(cb, callbackRef)); + IMSA_HILOGI("Registered success type: %{public}s", type.c_str()); +} + +void KeyboardDelegateImpl::UnRegisterListener(std::string const &type, taihe::optional_view opq) +{ + if (!EventChecker::IsValidEventType(EventSubscribeModule::KEYBOARD_DELEGATE, type)) { + IMSA_HILOGE("subscribe failed, type: %{public}s.", type.c_str()); + return; + } + std::lock_guard lock(mutex_); + const auto iter = jsCbMap_.find(type); + if (iter == jsCbMap_.end()) { + IMSA_HILOGE("%{public}s is not registered", type.c_str()); + return; + } + + if (!opq.has_value()) { + jsCbMap_.erase(iter); + return; + } + + ani_env *env = taihe::get_env(); + if (env == nullptr) { + IMSA_HILOGE("Failed to unregister %{public}s, env is nullptr", type.c_str()); + return; + } + + GlobalRefGuard guard(env, reinterpret_cast(opq.value())); + if (!guard) { + IMSA_HILOGE("Failed to unregister %{public}s, GlobalRefGuard is false!", type.c_str()); + return; + } + + const auto pred = [env, targetRef = guard.get()](std::unique_ptr &obj) { + ani_boolean is_equal = false; + return (ANI_OK == env->Reference_StrictEquals(targetRef, obj->ref, &is_equal)) && is_equal; + }; + auto &callbacks = iter->second; + const auto it = std::find_if(callbacks.begin(), callbacks.end(), pred); + if (it != callbacks.end()) { + callbacks.erase(it); + } + if (callbacks.empty()) { + jsCbMap_.erase(iter); + } +} + +bool KeyboardDelegateImpl::OnKeyEvent(int32_t keyCode, int32_t keyStatus, sptr &consumer) +{ + std::string type = (keyStatus == ARGC_TWO ? "keyDown" : "keyUp"); + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_[type]; + for (auto &cb : cbVec) { + auto &func = std::get>(cb->callback); + KeyEventType_t event { + .keyCode = keyCode, + .keyAction = keyStatus, + }; + bool isConsumed = false; + isConsumed = func(event); + if (consumer != nullptr) { + IMSA_HILOGE("consumer result: %{public}d!", isConsumed); + OnKeyCodeConsumeResult(isConsumed, consumer); + } + } + return true; +} + +void KeyboardDelegateImpl::OnKeyCodeConsumeResult(bool isConsumed, sptr consumer) +{ + IMSA_HILOGI("result: %{public}d.", isConsumed); + keyCodeConsume_ = true; + keyCodeResult_ = isConsumed; + if (keyEventConsume_) { + consumer->OnKeyEventResult(keyCodeResult_ || keyEventResult_); + keyCodeConsume_ = false; + keyCodeResult_ = false; + } +} + +bool KeyboardDelegateImpl::OnKeyEvent(const std::shared_ptr &keyEvent, sptr &consumer) +{ + std::string type = "keyEvent"; + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_[type]; + for (auto &cb : cbVec) { + auto &func = std::get>(cb->callback); + KeyEvent_t event; + // 转换 依赖keyEvent + int32_t ret = ErrorCode::ERROR_BAD_PARAMETERS; + ret = TaiheKeyEvnet(*keyEvent, event); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("create key event failed"); + return false; + } + // 后续增加 + bool isConsumed = false; + isConsumed = func(event); + if (consumer != nullptr) { + IMSA_HILOGE("consumer result: %{public}d!", isConsumed); + OnKeyEventConsumeResult(isConsumed, consumer); + } + } + return true; +} + +void KeyboardDelegateImpl::OnCursorUpdate(int32_t positionX, int32_t positionY, int32_t height) +{ + std::string type = "cursorContextChange"; + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_[type]; + for (auto &cb : cbVec) { + auto &func = std::get>(cb->callback); + func(positionX, positionY, height); + } +} + +void KeyboardDelegateImpl::OnSelectionChange(int32_t oldBegin, int32_t oldEnd, int32_t newBegin, int32_t newEnd) +{ + std::string type = "selectionChange"; + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_[type]; + for (auto &cb : cbVec) { + auto &func = std::get>(cb->callback); + func(oldBegin, oldEnd, newBegin, newEnd); + } +} + +void KeyboardDelegateImpl::OnTextChange(const std::string &text) +{ + std::string type = "textChange"; + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_[type]; + for (auto &cb : cbVec) { + auto &func = std::get>(cb->callback); + func(taihe::string_view(text)); + } +} + +void KeyboardDelegateImpl::OnEditorAttributeChange(const InputAttribute &inputAttribute) +{ + std::string type = "editorAttributeChanged"; + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_[type]; + for (auto &cb : cbVec) { + auto &func = std::get>(cb->callback); + func(NativeAttributeToAni(inputAttribute)); + } +} + +bool KeyboardDelegateImpl::OnDealKeyEvent(const std::shared_ptr &keyEvent, sptr &consumer) +{ + // ??? + if (keyEvent == nullptr) { + IMSA_HILOGE("keyEvent is nullptr"); + return false; + } + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_["keyEvent"]; + for (auto &cb : cbVec) { + auto &func = std::get>(cb->callback); + // keyevent转换 + bool isKeyEventConsumed = func(); + if (consumer != nullptr) { + if (!isKeyEventConsumed) { + if (keyEvent != nullptr && keyEvent->GetKeyAction() == MMI::KeyEvent::KEY_ACTION_DOWN) { + IMSA_HILOGW("keyEvent is not consumed by ime"); + } + isKeyEventConsumed = InputMethodAbility::GetInstance().HandleUnconsumedKey(keyEvent); + } + IMSA_HILOGD("final consumed result: %{public}d.", isKeyEventConsumed); + consumer->OnKeyEventResult(isKeyEventConsumed); + } + } + std::string type = (keyEvent->GetKeyAction() == ARGC_TWO ? "keyDown" : "keyUp"); + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_[type]; + for (auto &cb : cbVec) { + auto &func = std::get>(cb->callback); + KeyEventType_t event { + .keyCode = keyEvent->GetKeyCode(), + .keyAction = keyEvent->GetKeyAction(), + }; + bool isKeyCodeConsumed = false; + isKeyCodeConsumed = func(event); + if (consumer != nullptr) { + if (!isKeyCodeConsumed) { + if (keyEvent != nullptr && keyEvent->GetKeyAction() == MMI::KeyEvent::KEY_ACTION_DOWN) { + IMSA_HILOGW("keyEvent is not consumed by ime"); + } + isKeyCodeConsumed = InputMethodAbility::GetInstance().HandleUnconsumedKey(keyEvent); + } + IMSA_HILOGD("final consumed result: %{public}d.", isKeyCodeConsumed); + consumer->OnKeyEventResult(isKeyCodeConsumed); + } + } +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/taihe/inputMethod/src/input_method_panel_impl.cpp b/frameworks/ets/taihe/inputMethod/src/input_method_panel_impl.cpp new file mode 100644 index 000000000..126462bd8 --- /dev/null +++ b/frameworks/ets/taihe/inputMethod/src/input_method_panel_impl.cpp @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2025 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_panel_impl.h" + +#include "input_method_panel_listener.h" + +namespace OHOS { +namespace MiscServices { +using namespace taihe; +std::mutex PanelImpl::panelMutex_; +std::shared_ptr PanelImpl::panel_{ nullptr }; +std::shared_ptr PanelImpl::inputMethodPanel_{ nullptr }; +std::shared_ptr PanelImpl::GetInstance() +{ + std::shared_ptr panelImpl = InputMethodPanelListener::GetInstance(); + if (panelImpl != nullptr) { + IMSA_HILOGD("set eventHandler."); + panelImpl->SetEventHandler(AppExecFwk::EventHandler::Current()); + } + if (panel_ == nullptr) { + std::lock_guard lock(panelMutex_); + if (panel_ == nullptr) { + auto panel = std::make_shared(); + panel_ = panel; + } + } + return panel_; +} + +PanelImpl::~PanelImpl() +{ + inputMethodPanel_ = nullptr; +} + +void PanelImpl::SetNative(const std::shared_ptr &panel) +{ + inputMethodPanel_ = panel; +} +std::shared_ptr PanelImpl::GetNative() +{ + return inputMethodPanel_; +} + +void PanelImpl::CreatePanel(uintptr_t ctx, ohos::inputMethodEngine::PanelInfo const& info, std::shared_ptr &panel) +{ + auto ret = InputMethodAbility::GetInstance().CreatePanel(ctx, info, panel); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("panel create failed!"); + set_business_error(IMFErrorCode::EXCEPTION_IME, "panel create failed!"); + return; + } + if (panel != nullptr) { + inputMethodPanel_ = panel; + IMSA_HILOGI("panel create success!"); + } +} + +void PanelImpl::StartMoving() +{ + if (inputMethodPanel_ == nullptr) { + IMSA_HILOGE("panel is nullptr!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to start moving, panel is nullptr"); + return; + } + auto ret = inputMethodPanel_->StartMoving(); + if (ret != ErrorCode::NO_ERROR) { + set_business_error(JsUtils::Convert(ret), "failed to start moving"); + } +} + +bool PanelImpl::IsPanelFlagValid(PanelFlag panelFlag, bool isEnhancedCalled) +{ + bool isValid = false; + if (InputMethodAbility::GetInstance().IsDefaultIme()) { + isValid = panelFlag == FLG_FIXED || panelFlag == FLG_FLOATING || panelFlag == FLG_CANDIDATE_COLUMN; + } else { + isValid = panelFlag == FLG_FIXED || panelFlag == FLG_FLOATING; + } + IMSA_HILOGI("flag: %{public}d, isEnhanced: %{public}d, isValid: %{public}d", panelFlag, isEnhancedCalled, isValid); + if (!isEnhancedCalled && !isValid) { + IMSA_HILOGE("invalid panelFlag!"); + return false; + } + return true; +} + +void PanelImpl::UpdateRegion(taihe::array_view inputRegion) +{ + if (inputMethodPanel_ == nullptr) { + IMSA_HILOGE("panel is nullptr!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "panel is nullptr!"); + return; + } + if (inputMethodPanel_->GetPanelType() != PanelType::SOFT_KEYBOARD) { + set_business_error(JsUtils::Convert(ErrorCode::ERROR_INVALID_PANEL_TYPE), + "only used for SOFT_KEYBOARD panel"); + return; + } + if (!IsPanelFlagValid(inputMethodPanel_->GetPanelFlag(), true)) { + IMSA_HILOGE("invalid panelFlag!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_INVALID_PANEL_FLAG), + "param flag should be FIXED or FLOATING"); + return; + } + // inputRegion -> vector hotArea + std::vector hotArea; + int32_t code = inputMethodPanel_->UpdateRegion(hotArea); + if (ret == ErrorCode::NO_ERROR) { + IMSA_HILOGI("UpdateRegion success!"); + return; + } else if (code == ErrorCode::ERROR_INVALID_PANEL_TYPE) { + IMSA_HILOGE("only used for SOFT_KEYBOARD panel!"); + set_business_error(JsUtils::Convert(code), "only used for SOFT_KEYBOARD panel!"); + return; + } else if (code == ErrorCode::ERROR_INVALID_PANEL_FLAG) { + IMSA_HILOGE("only used for fixed or floating panel!"); + set_business_error(JsUtils::Convert(code), "only used for fixed or floating panel!"); + return; + } + IMSA_HILOGE("UpdateRegion failed!"); + set_business_error(JsUtils::Convert(code), "UpdateRegion failed!"); + return; +} + +void PanelImpl::AdjustPanelRect(PanelFlag_t flag, PanelRect_t const& rect) +{ + if (inputMethodPanel_ == nullptr) { + IMSA_HILOGE("panel is nullptr!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "panel is nullptr!"); + return; + } + // PanelFlag_t -> PanelFlag PanelRect_t -> LayoutParams + PanelFlag panelFlag = static_cast(flag.get_value()); + LayoutParams layoutParams; + int32_t ret = inputMethodPanel_->AdjustPanelRect(panelFlag, layoutParams); + if (ret == ErrorCode::NO_ERROR) { + IMSA_HILOGI("AdjustPanelRect success!"); + return; + } else if (ret == ErrorCode::ERROR_PARAMETER_CHECK_FAILED) { + IMSA_HILOGE("invalid param"); + set_business_error(JsUtils::Convert(ret), + "width limit:[0, displayWidth], height limit:[0, 70 percent of displayHeight]!"); + return; + } + IMSA_HILOGE("AdjustPanelRect failed!"); + set_business_error(JsUtils::Convert(ret), "AdjustPanelRect failed!"); +} + +void PanelImpl::AdjustPanelRectEnhanced(PanelFlag_t flag, EnhancedPanelRect_t const& rect) +{ + if (inputMethodPanel_ == nullptr) { + IMSA_HILOGE("panel is nullptr!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "panel is nullptr!"); + return; + } + // PanelFlag_t -> PanelFlag EnhancedPanelRect_t -> EnhancedLayoutParams 、HotAreas + // portraitInputRegion -> hotAreas.portrait.keyboardHotArea 、 landscapeInputRegion -> hotAreas.landscape.keyboardHotArea + PanelFlag panelFlag = static_cast(flag.get_value()); + EnhancedLayoutParams enhancedLayoutParams; + HotAreas hotAreas; + int32_t ret = inputMethodPanel_->AdjustPanelRect(panelFlag, enhancedLayoutParams, hotAreas); + if (ret == ErrorCode::NO_ERROR) { + IMSA_HILOGI("AdjustPanelRect success!"); + return; + } else if (ret == ErrorCode::ERROR_PARAMETER_CHECK_FAILED) { + IMSA_HILOGE("invalid param"); + set_business_error(JsUtils::Convert(ret), + "width limit:[0, displayWidth], height limit:[0, 70 percent of displayHeight]!"); + return; + } else if (ret == ErrorCode::ERROR_INVALID_PANEL_TYPE) { + IMSA_HILOGE("only used for SOFT_KEYBOARD panel"); + set_business_error(JsUtils::Convert(ret), "only used for SOFT_KEYBOARD panel"); + return; + } + +} + +uint32_t PanelImpl::GetDisplayIdSync() +{ + uint64_t displayId = 0; + if (inputMethodPanel_ == nullptr) { + IMSA_HILOGE("panel is nullptr!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "panel is nullptr!"); + return static_cast(displayId); + } + auto ret = inputMethodPanel_->GetDisplayId(displayId); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed get displayId!"); + set_business_error(JsUtils::Convert(ret), "failed get displayId!"); + return static_cast(displayId); + } + if (displayId > UINT32_MAX) { + IMSA_HILOGE("displayId is too large, displayId: %{public}" PRIu64 "", ctxt->displayId); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_WINDOW_MANAGER), "displayId is too large"); + return static_cast(displayId); + } + IMSA_HILOGI("get displayId success!"); + return static_cast(displayId); +} + +ImmersiveMode_t PanelImpl::ConvertMode(ImmersiveMode mode) +{ + switch (mode) { + case ImmersiveMode::NONE_IMMERSIVE: + return ImmersiveMode_t::key_t::NONE_IMMERSIVE; + case ImmersiveMode::IMMERSIVE: + return ImmersiveMode_t::key_t::IMMERSIVE; + case ImmersiveMode::LIGHT_IMMERSIVE: + return ImmersiveMode_t::key_t::LIGHT_IMMERSIVE; + case ImmersiveMode::DARK_IMMERSIVE: + return ImmersiveMode_t::key_t::DARK_IMMERSIVE; + default: + return ImmersiveMode_t::key_t::NONE_IMMERSIVE; + } +} + +ImmersiveMode_t PanelImpl::GetImmersiveMode() +{ + if (inputMethodPanel_ == nullptr) { + IMSA_HILOGE("panel is nullptr!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to get ImmersiveMode, panel is nullptr!"); + return ImmersiveMode::key_t::NONE_IMMERSIVE; + } + auto immersiveMode = inputMethodPanel_->GetImmersiveMode(); + IMSA_HILOGI("get Immersive mode success!"); + return ConvertMode(immersiveMode); +} + +bool PanelImpl::IsVaildImmersiveMode(ImmersiveMode mode) +{ + if (mode == ImmersiveMode::NONE_IMMERSIVE || + mode == ImmersiveMode::LIGHT_IMMERSIVE || + mode == ImmersiveMode::DARK_IMMERSIVE) { + return true; + } + return false; +} + +void PanelImpl::SetImmersiveMode(ImmersiveMode_t mode) +{ + if (inputMethodPanel_ == nullptr) { + IMSA_HILOGE("panel is nullptr!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to set ImmersiveMode, panel is nullptr!"); + return; + } + ImmersiveMode immersiveMode = static_cast(mode.get_value()); + if (!IsVaildImmersiveMode(immersiveMode)) { + IMSA_HILOGE("immersiveMode type must be ImmersiveMode and can not be IMMERSIVE"); + set_business_error(IMFErrorCode::EXCEPTION_PARAMCHECK, + "immersiveMode type must be ImmersiveMode and can not be IMMERSIVE"); + return; + } + auto ret = inputMethodPanel_->SetImmersiveMode(immersiveMode); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("SetImmersiveMode failed!"); + set_business_error(JsUtils::Convert(ret), "SetImmersiveMode failed!"); + return; + } + IMSA_HILOGI("set Immersive mode success!"); +} + +void PanelImpl::SetPrivacyMode(bool isPrivacyMode) +{ + if (inputMethodPanel_ == nullptr) { + IMSA_HILOGE("panel is nullptr!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to set PrivacyMode, panel is nullptr!"); + return; + } + auto ret = inputMethodPanel_->SetPrivacyMode(isPrivacyMode); + if (ret == static_cast(WMError::WM_ERROR_INVALID_PERMISSION)) { + IMSA_HILOGE("permission denied"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_STATUS_PERMISSION_DENIED), + "ohos.permission.PRIVACY_WINDOW permission denied"); + return; + } else if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed to SetPrivacyMode!"); + return; + } + IMSA_HILOGI("set Privacy mode success!"); +} + +void PanelImpl::ChangeFlag(PanelFlag_t flag) +{ + if (inputMethodPanel_ == nullptr) { + IMSA_HILOGE("panel is nullptr!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to ChangeFlag, panel is nullptr!"); + return; + } + PanelFlag panelFlag = static_cast(flag.get_value()); + if (panelFlag != PanelFlag::FLG_FIXED || + panelFlag != PanelFlag::FLG_FLOATING || + panelFlag != PanelFlag::FLG_CANDIDATE_COLUMN) { + IMSA_HILOGE("invaild panelFlag!"); + set_business_error(IMFErrorCode::EXCEPTION_PARAMCHECK, "flag type must be one of PanelFlag!"); + return; + } + auto ret = inputMethodPanel_->ChangePanelFlag(panelFlag); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed to ChangePanelFlag!"); + return; + } + IMSA_HILOGI("change flag success!"); +} + +void PanelImpl::MoveToAsync(int32_t x, int32_t y) +{ + if (inputMethodPanel_ == nullptr) { + IMSA_HILOGE("panel is nullptr!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to MoveTo, panel is nullptr!"); + return; + } + auto code = inputMethodPanel_->MoveTo(x, y); + if (code == ErrorCode::ERROR_PARAMETER_CHECK_FAILED) { + IMSA_HILOGE("moveTo failed!"); + set_business_error(JsUtils::Convert(code), "failed to moveTo!"); + return; + } + IMSA_HILOGI("moveTo success!"); +} + +void PanelImpl::ResizeAsync(uint32_t width, uint32_t height) +{ + if (inputMethodPanel_ == nullptr) { + IMSA_HILOGE("panel is nullptr!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to Resize, panel is nullptr!"); + return; + } + auto code = inputMethodPanel_->Resize(width, height); + if (code != ErrorCode::NO_ERROR) { + IMSA_HILOGE("Resize failed!"); + set_business_error(JsUtils::Convert(code), "failed to Resize!"); + return; + } + IMSA_HILOGE("Resize success!"); +} + +void PanelImpl::SetUiContentAsync(taihe::string_view path) +{ + if (inputMethodPanel_ == nullptr) { + IMSA_HILOGE("panel is nullptr!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to SetUiContent, panel is nullptr!"); + return; + } + // env 类型有问题 lmq 方案 + ani_env *env = taihe::get_env(); + std::string contentInfo = std::string(path); + auto code = inputMethodPanel_->SetUiContent(contentInfo, env, nullptr); + if (code == ErrorCode::ERROR_PARAMETER_CHECK_FAILED) { + IMSA_HILOGE("path should be a path to specific page."); + set_business_error(JsUtils::Convert(code), "path should be a path to specific page."); + return; + } else if (code != ErrorCode::NO_ERROR) { + IMSA_HILOGE("SetUiContent failed!"); + set_business_error(JsUtils::Convert(code), "SetUiContent failed!"); + return; + } + IMSA_HILOGI("SetUiContent success!"); +} + +void PanelImpl::HideAsync() +{ + InputMethodSyncTrace tracer("Hide"); + if (inputMethodPanel_ == nullptr) { + IMSA_HILOGE("panel is nullptr!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to Hide, panel is nullptr!"); + return; + } + auto code = InputMethodAbility::GetInstance().HidePanel(inputMethodPanel_); + if (code != ErrorCode::NO_ERROR) { + IMSA_HILOGE("Hide failed!"); + set_business_error(JsUtils::Convert(code), "Hide failed!"); + return; + } + IMSA_HILOGI("Hide success!"); +} + +void PanelImpl::ShowAsync() +{ + InputMethodSyncTrace tracer("Show"); + if (inputMethodPanel_ == nullptr) { + IMSA_HILOGE("panel is nullptr!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to Show, panel is nullptr!"); + return; + } + auto code = InputMethodAbility::GetInstance().ShowPanel(inputMethodPanel_); + if (code != ErrorCode::NO_ERROR) { + IMSA_HILOGE("Show failed!"); + set_business_error(JsUtils::Convert(code), "Show failed!"); + return; + } + IMSA_HILOGI("Show success!"); +} + +void PanelImpl::RegisterListener(std::string const &type, callbackType &&cb, uintptr_t opq) +{ + IMSA_HILOGD("PanelImpl start."); + if (!EventChecker::IsValidEventType(EventSubscribeModule::PANEL, type)) { + IMSA_HILOGE("RegisterListener failed, type: %{public}s!", type.c_str()); + return; + } + IMSA_HILOGD("RegisterListener type: %{public}s.", type.c_str()); + if (type == "sizeUpdate") { + if (!InputMethodAbility::GetInstance().IsSystemApp()) { + set_business_error(IMFErrorCode::EXCEPTION_SYSTEM_PERMISSION, "not system application.") + return; + } + } + if (inputMethodPanel_ == nullptr) { + IMSA_HILOGE("inputMethodPanel is nullptr!"); + return; + } + std::shared_ptr observer = PanelListener::GetInstance(); + observer->Subscribe(inputMethodPanel_->windowId_, type, cb, opq); + bool ret = inputMethodPanel_->SetPanelStatusListener(observer, type); + if (!ret) { + IMSA_HILOGE("failed to subscribe %{public}s!", type.c_str()); + observer->RemoveInfo(type, inputMethodPanel_->windowId_); + return; + } +} + +void PanelImpl::UnRegisterListener(std::string const &type, taihe::optional_view opq) +{ + if (!EventChecker::IsValidEventType(EventSubscribeModule::PANEL, type)) { + IMSA_HILOGE("RegisterListener failed, type: %{public}s!", type.c_str()); + return; + } + IMSA_HILOGD("RegisterListener type: %{public}s.", type.c_str()); + if (type == "sizeUpdate") { + if (!InputMethodAbility::GetInstance().IsSystemApp()) { + set_business_error(IMFErrorCode::EXCEPTION_SYSTEM_PERMISSION, "not system application.") + return; + } + } + if (inputMethodPanel_ == nullptr) { + IMSA_HILOGE("inputMethodPanel is nullptr!"); + return; + } + std::shared_ptr observer = PanelListener::GetInstance(); + observer->RemoveInfo(inputMethodPanel_->windowId_, type, cb, opq); + inputMethodPanel_->ClearPanelListener(type); +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/taihe/inputMethod/src/input_method_panel_listener.cpp b/frameworks/ets/taihe/inputMethod/src/input_method_panel_listener.cpp new file mode 100644 index 000000000..55f3829d5 --- /dev/null +++ b/frameworks/ets/taihe/inputMethod/src/input_method_panel_listener.cpp @@ -0,0 +1,119 @@ +/* + * 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_panel_listener.h" + +namespace OHOS { +namespace MiscServices { +std::mutex InputMethodPanelListener::listenerMutex_; +std::shared_ptr InputMethodPanelListener::instance_{ nullptr }; + +std::shared_ptr InputMethodPanelListener::GetInstance() +{ + if (instance_ == nullptr) { + std::lock_guard lock(listenerMutex_); + if (instance_ == nullptr) { + instance_ = std::make_shared(); + } + } + return instance_; +} + +InputMethodPanelListener::~InputMethodPanelListener() {} + +void InputMethodPanelListener::Subscribe(uint32_t windowId, const std::string &type, callbackType &&cb, uintptr_t opq) +{ + std::lock_guard lock(mutex_); + ani_object callbackObj = reinterpret_cast(opq); + ani_ref callbackRef; + ani_env *env = taihe::get_env(); + if (env == nullptr || ANI_OK != env->GlobalReference_Create(callbackObj, &callbackRef)) { + IMSA_HILOGE("ani_env is nullptr or GlobalReference_Create failed, type: %{public}s!", type.c_str()); + return; + } + // 1 : n : n -> 1: n(1: 1)[] + auto subscriptionAction = [&type](uint32_t windowId, + std::map> &cbs) -> bool { + if (cbs.find(type) != cbs.end()) { + env->GlobalReference_Delete(callbackRef); + IMSA_HILOGI("callback already registered, type: %{public}s!", type.c_str()); + return true; + } + auto result = cbs.try_emplace(type, std::make_unique(cb, callbackRef)); + bool inserted = result.second; + + if (inserted) { + IMSA_HILOGI("start to subscribe type: %{public}s of windowId: %{public}u.", + type.c_str(), windowId); + } else { + IMSA_HILOGD("type: %{public}s of windowId: %{public}u already subscribed.", + type.c_str(), windowId); + } + return !cbs.empty(); + }; + jsCbMap_.Compute(windowId, subscriptionAction); +} + +void InputMethodPanelListener::RemoveInfo(const std::string &type, uint32_t windowId, taihe::optional_view opq) +{ + std::lock_guard lock(mutex_); + jsCbMap_.ComputeIfPresent(windowId, + [&type](auto windowId, std::map> &cbs) { + cbs.erase(type); + return !cbs.empty(); + }); +} + +void InputMethodPanelListener::OnPanelStatus(uint32_t windowId, bool isShow) +{ + std::string type = isShow ? "show" : "hide"; + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_[windowId]; + for (auto &cb : cbVec) { + auto cbObj = cb[type]; + auto &func = std::get>(cbObj->callback); + func(); + } +} + +void InputMethodPanelListener::OnSizeChange(uint32_t windowId, const WindowSize &size) +{ + std::string type = "sizeChange"; + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_[windowId]; + for (auto &cb : cbVec) { + auto cbObj = cb[type]; + auto &func = std::get)>>(cbObj->callback); + // WindowSize -> uintptr_t(taihe window.size) 、keyboardArea(空) + func(); + } +} + +void InputMethodPanelListener::OnSizeChange(uint32_t windowId, const WindowSize &size, + const PanelAdjustInfo &keyboardArea, const std::string &event) +{ + std::string type = "sizeUpdate"; + std::lock_guard lock(mutex_); + auto &cbVec = jsCbMap_[windowId]; + for (auto &cb : cbVec) { + auto cbObj = cb[type]; + auto &func = std::get>(cbObj->callback); + // WindowSize -> uintptr_t 、PanelAdjustInfo -> KeyboardArea_t + func(); + } +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/taihe/inputMethod/src/ohos.inputMethodEngine.impl.cpp b/frameworks/ets/taihe/inputMethod/src/ohos.inputMethodEngine.impl.cpp new file mode 100644 index 000000000..25b2ed469 --- /dev/null +++ b/frameworks/ets/taihe/inputMethod/src/ohos.inputMethodEngine.impl.cpp @@ -0,0 +1,541 @@ +#include "ohos.inputMethodEngine.proj.hpp" +#include "ohos.inputMethodEngine.impl.hpp" +#include "taihe/runtime.hpp" +#include "stdexcept" + +#include "panel_info.h" +#include "input_attribute.h" +#include "input_method_utils.h" +#include "js_utils.h" +#include "inputmethod_trace.h" + +using namespace OHOS::MiscServices; +using Movement_t = ohos::inputMethodEngine::Movement; +using Range_t = ohos::inputMethodEngine::Range; +using EditorAttribute_t = ohos::inputMethodEngine::EditorAttribute; +using CapitalizeMode_t = ohos::inputMethodEngine::CapitalizeMode; +using GradientMode_t = ohos::inputMethodEngine::GradientMode; +using FluidLightMode_t = ohos::inputMethodEngine::FluidLightMode; +using ValueMap = std::unordered_map; +using CommandDataType_t = ohos::inputMethodEngine::CommandDataType; +namespace { +// To be implemented. +class CommonConvert { +public: + CapitalizeMode_t ConvertCapMode(CapitalizeMode mode) + { + switch (mode) { + case CapitalizeMode::NONE: + return CapitalizeMode_t::key_t::NONE; + case CapitalizeMode::SENTENCES: + return CapitalizeMode_t::key_t::SENTENCES; + case CapitalizeMode::WORDS: + return CapitalizeMode_t::key_t::WORDS; + case CapitalizeMode::CHARACTERS: + return CapitalizeMode_t::key_t::CHARACTERS; + default: + return CapitalizeMode_t::key_t::NONE; + } + } + + GradientMode_t ConvertGraMode(GradientMode mode) + { + switch (mode) { + case GradientMode::NONE: + return GradientMode_t::key_t::NONE; + case GradientMode::LINEAR_GRADIENT: + return GradientMode_t::key_t::LINEAR_GRADIENT; + default: + return GradientMode_t::key_t::NONE; + } + } + + FluidLightMode_t ConvertFLMode(FluidLightMode mode) + { + switch (mode) { + case FluidLightMode::NONE: + return FluidLightMode_t::key_t::NONE; + case FluidLightMode::BACKGROUND_FLUID_LIGHT: + return FluidLightMode_t::key_t::BACKGROUND_FLUID_LIGHT; + default: + return FluidLightMode_t::key_t::NONE; + } + } + + EditorAttribute_t NativeAttributeToAni(InputAttribute inputAttribute) + { + EditorAttribute_t result {}; + result.inputPattern = inputAttribute.inputPattern; + result.enterKeyType = inputAttribute.enterKeyType; + result.isTextPreviewSupported = inputAttribute.isTextPreviewSupported; + result.bundleName = inputAttribute.bundleName; + // Panel ConvertMode 提出去 + result.immersiveMode = ConvertMode(static_cast(inputAttribute.immersiveMode)); + result.windowId = inputAttribute.windowId; + result.displayId = inputAttribute.callingDisplayId; + result.placeholder = std::string(Str16ToStr8(inputAttribute.placeholder)); + result.abilityName = std::string(Str16ToStr8(inputAttribute.abilityName)); + result.capitalizeMode = ConvertCapMode(static_castinputAttribute.capitalizeMode); + result.gradientMode = ConvertGraMode(static_cast(inputAttribute.gradientMode)); + result.fluidLightMode = ConvertFLMode(static_cast(inputAttribute.fluidLightMode)); + return result; + } + + ValueMap AniConvertPCommandToNative(taihe::map_view commandData) + { + ValueMap valueMap; + for (auto &item : commandData) { + if (item.first.empty()) { + continue; + } + PrivateDataValue value; + switch (item.second.get_tag()) { + case CommandDataType_t::tag_t::type_Int: + value = item.second.get_type_Int_ref(); + break; + case CommandDataType_t::tag_t::type_String: + value = std::string(item.second.get_type_String_ref()); + break; + case CommandDataType_t::tag_t::type_Bool: + value = item.second.get_type_Bool_ref(); + break; + default: + break; + } + + valueMap.insert(std::make_pair(std::string(item.first), value)); + } + return valueMap; + } +} + + +class TextInputClientImpl { + public: + TextInputClientImpl() { + // Don't forget to implement the constructor. + } +}; + +class InputMethodEngineImpl { + public: + InputMethodEngineImpl() { + // Don't forget to implement the constructor. + } + + void OnInputStart(taihe::callback_view callback, uintptr_t opq) { + TH_THROW(std::runtime_error, "OnInputStart not implemented"); + } + + void OffInputStart(taihe::optional_view opq) { + TH_THROW(std::runtime_error, "OffInputStart not implemented"); + } + + void OnKeyboard(taihe::string_view type, taihe::callback_view callback, uintptr_t opq) { + TH_THROW(std::runtime_error, "OnKeyboard not implemented"); + } + + void OffKeyboard(taihe::string_view type, taihe::optional_view opq) { + TH_THROW(std::runtime_error, "OffKeyboard not implemented"); + } +}; + +class InputClientImpl { +public: + InputClientImpl() + { + } + + void SelectByMovementAsync(Movement_t const& movement) + { + } + + void SelectByRangeAsync(Range_t const& range) + { + + } + + void MoveCursorAsync(int32_t direction) + { + } + + taihe::string GetBackwardAsync(int32_t length) + { + } + + taihe::string GetForwardAsync(int32_t length) + { + } + + bool InsertTextAsync(taihe::string_view text) + { + } + + bool DeleteBackwardAsync(int32_t length) + { + } + + bool DeleteForwardAsync(int32_t length) + { + } + + bool SendKeyFunctionAsync(int32_t action) + { + } + + int32_t GetTextIndexAtCursorAsync() + { + } + + EditorAttribute_t GetEditorAttributeAsync() + { + EditorAttribute_t result {}; + TextTotalConfig config; + int32_t ret = InputMethodAbility::GetInstance().GetTextConfig(config); + if (ret == ErrorCode::NO_ERROR) { + IMSA_HILOGD("inputPattern: %{public}d, enterKeyType: %{public}d, isTextPreviewSupported: %{public}d", + config.inputAttribute.inputPattern, config.inputAttribute.enterKeyType, + config.inputAttribute.isTextPreviewSupported); + } else { + IMSA_HILOGE("failed to get text config: %{public}d!", ret); + set_business_error(IMFErrorCode::EXCEPTION_IMCLIENT, "failed to get text config!"); + return result; + } + result = NativeAttributeToAni(config.inputAttribute); + return result; + } + + void SendMessageAsync(taihe::string_view msgId, taihe::optional_view> msgParam) + { + ArrayBuffer arrayBuffer {}; + arrayBuffer.msgId = std::string(msgId); + arrayBuffer.jsArgc = 1; + if (msgParam.has_value()) { + arrayBuffer.jsArgc = 2; + auto const &value = msgParam.value(); + arrayBuffer.msgParam(value.size()); + for (size_t i = 0; i < value.size(); ++i) { + arrayBuffer.msgParam[i] = value[i]; + } + } + if (!ArrayBuffer::IsSizeValid(arrayBuffer)) { + IMSA_HILOGE("msgId limit 256B and msgParam limit 128KB."); + set_business_error(IMFErrorCode::EXCEPTION_PARAMCHECK, "msgId limit 256B and msgParam limit 128KB."); + return; + } + int32_t ret = InputMethodAbility::GetInstance().SendMessage(arrayBuffer); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed to get text config: %{public}d!", ret); + set_business_error(IMFErrorCode::EXCEPTION_IMCLIENT, "failed to get text config!"); + } + } + + void RecvMessage(taihe::optional_view<::ohos::inputMethodEngine::MessageHandler> msgHandler) + { + if (msgHandler.has_value()) { + IMSA_HILOGI("RecvMessage on."); + ani_env *env = get_env(); + std::shared_ptr()>taiheCallbackOnTerminated = std::make_shared()>(msgHandler.OnTerminated); + std::shared_ptr onTerminatedCB = std::reinterpret_pointer_cast(taiheCallbackOnTerminated); + std::shared_ptr()>taiheCallbackOnMessage = std::make_shared()>(msgHandler.onMessage); + std::shared_ptr onMessageCB = std::reinterpret_pointer_cast(taiheCallbackOnMessage); + std::shared_ptr callback = std::make_shared(env, onTerminatedCB, onMessageCB); + InputMethodAbility::GetInstance().RegisterMsgHandler(callback); + } else { + IMSA_HILOGI("RecvMessage off."); + InputMethodAbility::GetInstance().RegisterMsgHandler(); + } + } + + void SetPreviewTextAsync(taihe::string_view text, Range_t const& range) + { + } + + void FinishTextPreviewSync() + { + InputMethodSyncTrace tracer("Taihe_FinishTextPreviewSync", GenerateTraceId()); + IMSA_HILOGD("Taihe TextInputClientEngine in"); + int32_t ret = InputMethodAbility::GetInstance().FinishTextPreview(); + if (ret != ErrorCode::NO_ERROR) { + set_business_error(JsUtils::Convert(ret), "failed to finish text preview!"); + } + } + + ::ohos::inputMethodEngine::WindowInfo GetCallingWindowInfoAsync() + { + ::ohos::inputMethodEngine::WindowInfo result {}; + CallingWindowInfo windowInfo {}; + int32_t ret = InputMethodAbility::GetInstance().GetCallingWindowInfo(windowInfo); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGI("GetCallingWindowInfo failed."); + set_business_error(JsUtils::Convert(ret), "GetCallingWindowInfo failed."); + return result; + } + // windowInfo -> ohos::inputMethodEngine::WindowInfo; + return result; + } + + void SendPrivateCommandAsync(taihe::map_view commandData) + { + ValueMap privateCommand = AniConvertPCommandToNative(commandData); + if (!TextConfig::IsPrivateCommandValid(privateCommand)) { + IMSA_HILOGE("privateCommand invaild."); + set_business_error(IMFErrorCode::EXCEPTION_PARAMCHECK, "commandData size limit 32KB, count limit 5."); + return; + } + int32_t ret = InputMethodAbility::GetInstance().SendPrivateCommand(privateCommand); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("SendPrivateCommand failed."); + set_business_error(JsUtils::Convert(ret), "SendPrivateCommand failed."); + return; + } + IMSA_HILOGI("SendPrivateCommand success."); + } + + void FinishTextPreviewAsync() + { + } + + void SetPreviewTextSync(taihe::string_view text, Range_t const& range) + { + } + + ::ohos::inputMethodEngine::Panel CreatePanelAsync(uintptr_t ctx, ohos::inputMethodEngine::PanelInfo const& info) + { + // The parameters in the make_holder function should be of the same type + // as the parameters in the constructor of the actual implementation class. + return taihe::make_holder(ctx, info); + } + + void SendExtendActionAsync(ohos::inputMethodEngine::ExtendAction action) + { + } + + void SelectByMovementSync(Movement_t const& movement) + { + IMSA_HILOGD("run in"); + int32_t direction = movement.direction.get_value(); + IMSA_HILOGD("direction: %{public}d.", direction); + int32_t ret = InputMethodAbility::GetInstance().SelectByMovement(direction); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGI("failed to select by movement!"); + set_business_error(JsUtils::Convert(ret), "failed to select by movement!"); + } + } + + void SelectByRangeSync(Range_t const& range) + { + IMSA_HILOGD("SelectByRangeSync"); + Range tmpRange {}; + tmpRange.start = range.start; + tmpRange.end = range.end; + int32_t ret = InputMethodAbility::GetInstance().SelectByRange(tmpRange.start, tmpRange.end); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGI("failed to select by range!"); + set_business_error(JsUtils::Convert(ret), "failed to select by range!"); + } + } + + void MoveCursorSync(int32_t direction) + { + if (direction < 0) { + IMSA_HILOGE("direction should be no less than 0!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_PARAMETER_CHECK_FAILED), + "direction should be no less than 0!"); + return; + } + IMSA_HILOGD("moveCursor, direction: %{public}d", direction); + int32_t ret = InputMethodAbility::GetInstance().MoveCursor(direction); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGI("failed to move cursor!"); + set_business_error(JsUtils::Convert(ret), "failed to move cursor!"); + } + } + + taihe::string GetBackwardSync(int32_t length) + { + if (length < 0) { + IMSA_HILOGE("length should be no less than 0!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_PARAMETER_CHECK_FAILED), + "length should be no less than 0!"); + return; + } + IMSA_HILOGD("get backward, length: %{public}d.", length); + std::u16string text; + taihe::string result; + int32_t ret = InputMethodAbility::GetInstance().GetTextAfterCursor(length, text); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed to get backward!"); + set_business_error(JsUtils::Convert(ret), "failed to get backward!"); + return result; + } + IMSA_HILOGI("get backward success!"); + result = std::string(Str16ToStr8(text)); + return result; + } + + taihe::string GetForwardSync(int32_t length) + { + InputMethodSyncTrace tracer("GetForwardSync", GenerateTraceId()); + if (length < 0) { + IMSA_HILOGE("length should be no less than 0!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_PARAMETER_CHECK_FAILED), + "length should be no less than 0!"); + return; + } + IMSA_HILOGD("get forward, length: %{public}d.", length); + std::u16string text; + taihe::string result; + int32_t ret = InputMethodAbility::GetInstance().GetTextBeforeCursor(length, text); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed to get forward!"); + set_business_error(JsUtils::Convert(ret), "failed to get forward!"); + return result; + } + IMSA_HILOGI("get forward success!"); + result = std::string(Str16ToStr8(text)); + return result; + } + + void InsertTextSync(taihe::string_view text) + { + InputMethodSyncTrace tracer("InsertTextSync", GenerateTraceId()); + std::string tmpText = std::string(text); + int32_t ret = InputMethodAbility::GetInstance().InsertText(tmpText); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed to insert text!"); + set_business_error(JsUtils::Convert(ret), "failed to insert text!"); + } + IMSA_HILOGI("insert text success!"); + } + + void DeleteBackwardSync(int32_t length) + { + if (length < 0) { + IMSA_HILOGE("length should be no less than 0!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_PARAMETER_CHECK_FAILED), + "length should be no less than 0!"); + return; + } + IMSA_HILOGD("delete backward, length: %{public}d.", length); + int32_t ret = InputMethodAbility::GetInstance().DeleteBackward(length); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed to delete backward"); + set_business_error(JsUtils::Convert(ret), "failed to delete backward"); + } + IMSA_HILOGI("delete backward success!"); + } + + void DeleteForwardSync(int32_t length) + { + InputMethodSyncTrace tracer("DeleteForwardSync", GenerateTraceId()); + if (length < 0) { + IMSA_HILOGE("length should be no less than 0!"); + set_business_error(JsUtils::Convert(ErrorCode::ERROR_PARAMETER_CHECK_FAILED), + "length should be no less than 0!"); + return; + } + IMSA_HILOGD("delete forward, length: %{public}d.", length); + int32_t ret = InputMethodAbility::GetInstance().DeleteForward(length); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed to delete forward"); + set_business_error(JsUtils::Convert(ret), "failed to delete forward"); + } + IMSA_HILOGI("delete forward success!"); + } + + EditorAttribute_t GetEditorAttributeSync() + { + TextTotalConfig config; + EditorAttribute_t result; + int32_t ret = InputMethodAbility::GetInstance().GetTextConfig(config); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed to get text config: %{public}d!", ret); + set_business_error(IMFErrorCode::EXCEPTION_IMCLIENT, "failed to get text config!"); + return result; + } + IMSA_HILOGD("inputPattern: %{public}d, enterKeyType: %{public}d, isTextPreviewSupported: %{public}d.", + config.inputAttribute.inputPattern, config.inputAttribute.enterKeyType, + config.inputAttribute.isTextPreviewSupported); + IMSA_HILOGI("get editor attribute success!"); + result = NativeAttributeToAni(config.inputAttribute); + return result; + } + + int32_t GetTextIndexAtCursorSync() + { + IMSA_HILOGD("start."); + int32_t index = 0; + int32_t ret = InputMethodAbility::GetInstance().GetTextIndexAtCursor(index); + if (ret != ErrorCode::NO_ERROR) { + JsUtils::ThrowException(env, JsUtils::Convert(ret), "failed to get text index at cursor!", TYPE_NONE); + IMSA_HILOGE("failed to get text index at cursor: %{public}d!", ret); + set_business_error(JsUtils::Convert(ret), "failed to get text index at cursor!"); + return index; + } + IMSA_HILOGI("get text index at cursor success"); + return index; + } +}; + +class KeyboardControllerImpl { + public: + KeyboardControllerImpl() + { + // Don't forget to implement the constructor. + } + + void HideAsync() + { + int32_t ret = InputMethodAbility::GetInstance().HideKeyboardSelf(); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed to hide keyboard self: %{public}d!", ret); + set_business_error(JsUtils::Convert(ret), "failed to hide keyboard self!"); + return; + } + } + + void ExitCurrentInputTypeAsync() + { + int32_t ret = InputMethodAbility::GetInstance().ExitCurrentInputType(); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("failed to exit current input type: %{public}d!", ret); + set_business_error(JsUtils::Convert(ret), "failed to exit current input type!"); + return; + } + } +}; + +class MessageHandlerImpl { + public: + MessageHandlerImpl() + { + } + + void OnMessage(taihe::string_view msgId, taihe::optional_view> msgParam) + { + } + + void OnTerminated() + { + } +}; + +ohos::inputMethodEngine::KeyboardDelegate GetKeyboardDelegate() { + // The parameters in the make_holder function should be of the same type + // as the parameters in the constructor of the actual implementation class. + return taihe::make_holder(); +} + +ohos::inputMethodEngine::InputMethodAbility GetInputMethodAbility() { + // The parameters in the make_holder function should be of the same type + // as the parameters in the constructor of the actual implementation class. + return taihe::make_holder(); +} +} // namespace + +// Since these macros are auto-generate, lint will cause false positive. +// NOLINTBEGIN +TH_EXPORT_CPP_API_GetKeyboardDelegate(GetKeyboardDelegate); +TH_EXPORT_CPP_API_GetInputMethodAbility(GetInputMethodAbility); +// NOLINTEND -- Gitee From 223233f14390818c133993e63545ca1abe4a40d8 Mon Sep 17 00:00:00 2001 From: KangPeng Date: Fri, 5 Sep 2025 17:05:41 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E4=BC=98=E5=8C=96engine=20taihe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: KangPeng --- .../inputMethod/include/ani_callback_object.h | 3 +- .../inputMethod/include/ani_common_engine.h | 278 ++++++++++++++++++ .../include/input_method_ability_impl.h | 15 +- .../input_method_keyboard_delegate_impl.h | 9 +- .../include/input_method_panel_impl.h | 16 +- .../include/input_method_panel_listener.h | 7 +- .../inputMethod/src/ani_callback_object.cpp | 2 - .../src/input_method_ability_impl.cpp | 72 +---- .../input_method_keyboard_delegate_impl.cpp | 14 +- .../src/input_method_panel_impl.cpp | 25 +- .../src/input_method_panel_listener.cpp | 8 +- .../src/ohos.inputMethodEngine.impl.cpp | 99 +------ 12 files changed, 331 insertions(+), 217 deletions(-) create mode 100644 frameworks/ets/taihe/inputMethod/include/ani_common_engine.h diff --git a/frameworks/ets/taihe/inputMethod/include/ani_callback_object.h b/frameworks/ets/taihe/inputMethod/include/ani_callback_object.h index 1e0a6042c..406a36f12 100644 --- a/frameworks/ets/taihe/inputMethod/include/ani_callback_object.h +++ b/frameworks/ets/taihe/inputMethod/include/ani_callback_object.h @@ -18,10 +18,9 @@ #include #include +#include "ani.h" #include "block_data.h" #include "event_handler.h" -#include "napi/native_api.h" -#include "napi/native_node_api.h" namespace OHOS { namespace MiscServices { diff --git a/frameworks/ets/taihe/inputMethod/include/ani_common_engine.h b/frameworks/ets/taihe/inputMethod/include/ani_common_engine.h new file mode 100644 index 000000000..905b4a12a --- /dev/null +++ b/frameworks/ets/taihe/inputMethod/include/ani_common_engine.h @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2025 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 INPUT_METHOD_TAIHE_ANI_COMMON_ENGINE_H +#define INPUT_METHOD_TAIHE_ANI_COMMON_ENGINE_H + +#include "input_method_property.h" +#include "input_method_utils.h" +#include "ohos.inputMethod.impl.hpp" +#include "ohos.inputMethod.proj.hpp" +#include "ohos.inputMethodEngine.proj.hpp" +#include "ohos.inputMethodEngine.impl.hpp" +#include "taihe/runtime.hpp" + +using InputMethodSubtype_t = ohos::InputMethodSubtype::InputMethodSubtype; +using EnhancedPanelRect_t = ohos::inputMethodEngine::EnhancedPanelRect; +using ImmersiveMode_t = ohos::inputMethodEngine::ImmersiveMode; +using KeyboardArea_t = ohos::inputMethodEngine::KeyboardArea; +using Movement_t = ohos::inputMethodEngine::Movement; +using Range_t = ohos::inputMethodEngine::Range; +using EditorAttribute_t = ohos::inputMethodEngine::EditorAttribute; +using CapitalizeMode_t = ohos::inputMethodEngine::CapitalizeMode; +using GradientMode_t = ohos::inputMethodEngine::GradientMode; +using FluidLightMode_t = ohos::inputMethodEngine::FluidLightMode; +using ValueMap = std::unordered_map; +using CommandDataType_t = ohos::inputMethodEngine::CommandDataType; +using SecurityMode_t = ohos::inputMethodEngine::SecurityMode; +using KeyEventType_t = ohos::inputMethodEngine::KeyEventType; +using KeyEvent_t = ohos::multimodalInput::keyEvent::KeyEvent; +using PanelInfo_t = ohos::inputMethodEngine::PanelInfo; +using PanelFlag_t = ohos::inputMethodEngine::PanelFlag; +using PanelRect_t = ohos::inputMethodEngine::PanelRect; +using KeyboardController_t = ohos::inputMethodEngine::weak::KeyboardController; +using InputClient_t = ohos::inputMethodEngine::weak::InputClient; +using Panel_t =ohos::inputMethodEngine::weak::Panel; +using TextInputClient_t = ohos::inputMethodEngine::weak::TextInputClient; // 大概率废弃 +namespace OHOS { +namespace MiscServices { + +class TaiheConverter { +public: + static InputMethodSubtype_t ConvertSubProperty(const SubProperty &property) + { + return ConvertSubPropertyImpl(property); + } + +private: + static InputMethodSubtype_t ConvertSubPropertyImpl(SubProperty &property) + { + InputMethodSubtype_t result {}; + result.name = property.name; + result.id = property.id; + result.locale = property.locale; + result.language = property.language; + result.label = taihe::optional(std::in_place_t{}, property.label); + result.labelId = taihe::optional(std::in_place_t{}, property.labelId); + result.icon = taihe::optional(std::in_place_t{}, property.icon); + result.iconId = taihe::optional(std::in_place_t{}, property.iconId); + return result; + } +}; + +using callbackTypes = std::variant, + taihe::callback, taihe::callback)>>, + taihe::callback)>, taihe::callback, + taihe::callback, taihe::callback, + taihe::callback, taihe::callback, + taihe::callback, taihe::callback, + taihe::callback, taihe::callback, + taihe::callback)>, taihe::callback + ; + +struct CallbackObjects { + CallbackObjects(callbackTypes cb, ani_ref ref) : callback(cb), ref(ref) + { + } + void Release() + { + taihe::env_guard guard; + if (auto *env = guard.get_env()) { + env->GlobalReference_Delete(ref); + } + } + callbackTypes callback; + ani_ref ref; +}; + +class GlobalRefGuards { + ani_env *env_ = nullptr; + ani_ref ref_ = nullptr; + +public: + GlobalRefGuards(ani_env *env, ani_object obj) : env_(env) + { + if (!env_) + return; + if (ANI_OK != env_->GlobalReference_Create(obj, &ref_)) { + ref_ = nullptr; + } + } + explicit operator bool() const + { + return ref_ != nullptr; + } + ani_ref get() const + { + return ref_; + } + ~GlobalRefGuards() + { + if (env_ && ref_) { + env_->GlobalReference_Delete(ref_); + } + } + + GlobalRefGuards(const GlobalRefGuard &) = delete; + GlobalRefGuards &operator=(const GlobalRefGuard &) = delete; +}; + +class CommonConvert { +public: + static SecurityMode_t ConvertSecurityMode(SecurityMode mode) + { + switch (mode) { + case SecurityMode::BASIC: + return SecurityMode_t::key_t::BASIC; + case SecurityMode::FULL: + return SecurityMode_t::key_t::FULL; + default: + return SecurityMode_t::key_t::BASIC; + } + } + static ImmersiveMode_t ConvertMode(ImmersiveMode mode) + { + switch (mode) { + case ImmersiveMode::NONE_IMMERSIVE: + return ImmersiveMode_t::key_t::NONE_IMMERSIVE; + case ImmersiveMode::IMMERSIVE: + return ImmersiveMode_t::key_t::IMMERSIVE; + case ImmersiveMode::LIGHT_IMMERSIVE: + return ImmersiveMode_t::key_t::LIGHT_IMMERSIVE; + case ImmersiveMode::DARK_IMMERSIVE: + return ImmersiveMode_t::key_t::DARK_IMMERSIVE; + default: + return ImmersiveMode_t::key_t::NONE_IMMERSIVE; + } + } + static CapitalizeMode_t ConvertCapMode(CapitalizeMode mode) + { + switch (mode) { + case CapitalizeMode::NONE: + return CapitalizeMode_t::key_t::NONE; + case CapitalizeMode::SENTENCES: + return CapitalizeMode_t::key_t::SENTENCES; + case CapitalizeMode::WORDS: + return CapitalizeMode_t::key_t::WORDS; + case CapitalizeMode::CHARACTERS: + return CapitalizeMode_t::key_t::CHARACTERS; + default: + return CapitalizeMode_t::key_t::NONE; + } + } + + static GradientMode_t ConvertGraMode(GradientMode mode) + { + switch (mode) { + case GradientMode::NONE: + return GradientMode_t::key_t::NONE; + case GradientMode::LINEAR_GRADIENT: + return GradientMode_t::key_t::LINEAR_GRADIENT; + default: + return GradientMode_t::key_t::NONE; + } + } + + static FluidLightMode_t ConvertFLMode(FluidLightMode mode) + { + switch (mode) { + case FluidLightMode::NONE: + return FluidLightMode_t::key_t::NONE; + case FluidLightMode::BACKGROUND_FLUID_LIGHT: + return FluidLightMode_t::key_t::BACKGROUND_FLUID_LIGHT; + default: + return FluidLightMode_t::key_t::NONE; + } + } + + static EditorAttribute_t NativeAttributeToAni(InputAttribute inputAttribute) + { + EditorAttribute_t result {}; + result.inputPattern = inputAttribute.inputPattern; + result.enterKeyType = inputAttribute.enterKeyType; + result.isTextPreviewSupported = inputAttribute.isTextPreviewSupported; + result.bundleName = inputAttribute.bundleName; + result.immersiveMode = ConvertMode(static_cast(inputAttribute.immersiveMode)); + result.windowId = inputAttribute.windowId; + result.displayId = inputAttribute.callingDisplayId; + result.placeholder = std::string(Str16ToStr8(inputAttribute.placeholder)); + result.abilityName = std::string(Str16ToStr8(inputAttribute.abilityName)); + result.capitalizeMode = ConvertCapMode(static_castinputAttribute.capitalizeMode); + result.gradientMode = ConvertGraMode(static_cast(inputAttribute.gradientMode)); + result.fluidLightMode = ConvertFLMode(static_cast(inputAttribute.fluidLightMode)); + return result; + } + + static ValueMap AniConvertPCommandToNative(taihe::map_view commandData) + { + ValueMap valueMap; + for (auto &item : commandData) { + if (item.first.empty()) { + continue; + } + PrivateDataValue value; + switch (item.second.get_tag()) { + case CommandDataType_t::tag_t::type_Int: + value = item.second.get_type_Int_ref(); + break; + case CommandDataType_t::tag_t::type_String: + value = std::string(item.second.get_type_String_ref()); + break; + case CommandDataType_t::tag_t::type_Bool: + value = item.second.get_type_Bool_ref(); + break; + default: + break; + } + + valueMap.insert(std::make_pair(std::string(item.first), value)); + } + return valueMap; + } + + static CommandDataType_t ConvertToDataType(const PrivateDataValue &value) + { + size_t idx = value.index(); + if (idx == static_cast(PrivateDataValueType::VALUE_TYPE_STRING)) { + auto stringValue = std::get_if(&value); + if (stringValue != nullptr) { + return CommandDataType_t::make_type_String(*stringValue); + } + } else if (idx == static_cast(PrivateDataValueType::VALUE_TYPE_BOOL)) { + auto boolValue = std::get_if(&value); + if (boolValue != nullptr) { + return CommandDataType_t::make_type_Bool(*boolValue); + } + } else if (idx == static_cast(PrivateDataValueType::VALUE_TYPE_NUMBER)) { + auto numberValue = std::get_if(&value); + if (numberValue != nullptr) { + return CommandDataType_t::make_type_Int(*numberValue); + } + } + return CommandDataType_t::make_type_Bool(true); + } + + static taihe::map NativeConvertPCommandToAni(ValueMap &valueMap) + { + taihe::map result(valueMap.size()); + for (const auto &[key, value] : valueMap) { + result.emplace(key, ConvertToDataType(value)); + } + return result; + } +}; +} // namespace MiscServices +} // namespace OHOS +#endif // INPUT_METHOD_TAIHE_ANI_COMMON_ENGINE_H \ No newline at end of file diff --git a/frameworks/ets/taihe/inputMethod/include/input_method_ability_impl.h b/frameworks/ets/taihe/inputMethod/include/input_method_ability_impl.h index a80e090e9..d862ad9bd 100644 --- a/frameworks/ets/taihe/inputMethod/include/input_method_ability_impl.h +++ b/frameworks/ets/taihe/inputMethod/include/input_method_ability_impl.h @@ -21,21 +21,19 @@ #include #include -#include "ani_common.h" +#include "ani_common_engine.h" #include "ohos.inputMethodEngine.proj.hpp" #include "ohos.inputMethodEngine.impl.hpp" -using SecurityMode_t = ohos::inputMethodEngine::SecurityMode; namespace OHOS { namespace MiscServices { class InputMethodAbilityImpl : public InputMethodEngineListener { public: static std::shared_ptr GetInstance(); SecurityMode_t GetSecurityMode(); - void DestroyPanelAsync(::ohos::inputMethodEngine::weak::Panel panel); - void RegisterListener(std::string const &type, callbackType &&cb, uintptr_t opq); + void DestroyPanelAsync(Panel_t panel); + void RegisterListener(std::string const &type, callbackTypes &&cb, uintptr_t opq); void UnRegisterListener(std::string const &type, taihe::optional_view opq); - void OnKeyboardStatus(bool isShow) override; void OnInputStart() override; int32_t OnInputStop() override; @@ -47,9 +45,8 @@ public: void ReceivePrivateCommand(const std::unordered_map &privateCommand) override; private: - SecurityMode_t ConvertSecurityMode(SecurityMode mode); std::mutex mutex_; - std::map>> jsCbMap_; + std::map>> jsCbMap_; std::mutex engineMutex_; std::shared_ptr inputMethodEngine_; } @@ -137,7 +134,7 @@ public: InputMethodAbilityImpl::GetInstance()->UnRegisterListener("callingDisplayDidChange", opq); } - void OnSecurityModeChange(taihe::callback_view callback, uintptr_t opq) + void OnSecurityModeChange(taihe::callback_view callback, uintptr_t opq) { InputMethodAbilityImpl::GetInstance()->RegisterListener("securityModeChange", callback, opq); } @@ -157,7 +154,7 @@ public: InputMethodAbilityImpl::GetInstance()->UnRegisterListener("setSubtype", opq); } - void OnInputStart(taihe::callback_view callback, uintptr_t opq) + void OnInputStart(taihe::callback_view callback, uintptr_t opq) { InputMethodAbilityImpl::GetInstance()->RegisterListener("inputStart", callback, opq); } diff --git a/frameworks/ets/taihe/inputMethod/include/input_method_keyboard_delegate_impl.h b/frameworks/ets/taihe/inputMethod/include/input_method_keyboard_delegate_impl.h index 93b72dd41..d294f8a1b 100644 --- a/frameworks/ets/taihe/inputMethod/include/input_method_keyboard_delegate_impl.h +++ b/frameworks/ets/taihe/inputMethod/include/input_method_keyboard_delegate_impl.h @@ -21,18 +21,17 @@ #include #include -#include "ani_common.h" +#include "ani_common_engine.h" #include "ohos.inputMethodEngine.proj.hpp" #include "ohos.inputMethodEngine.impl.hpp" -using KeyEventType_t = ohos::inputMethodEngine::KeyEventType; -using KeyEvent_t = ohos::multimodalInput::keyEvent::KeyEvent; + namespace OHOS { namespace MiscServices { class KeyboardDelegateImpl : public KeyboardListener { public: static std::shared_ptr GetInstance(); - void RegisterListener(std::string const &type, callbackType &&cb, uintptr_t opq); + void RegisterListener(std::string const &type, callbackTypes &&cb, uintptr_t opq); void UnRegisterListener(std::string const &type, taihe::optional_view opq); bool OnKeyEvent(int32_t keyCode, int32_t keyStatus, sptr &consumer) override; bool OnKeyEvent(const std::shared_ptr &keyEvent, sptr &consumer) override; @@ -43,7 +42,7 @@ public: bool OnDealKeyEvent(const std::shared_ptr &keyEvent, sptr &consumer) override; private: std::mutex mutex_; - std::map>> jsCbMap_; + std::map>> jsCbMap_; static std::mutex keyboardMutex_; static std::shared_ptr keyboardDelegate_; diff --git a/frameworks/ets/taihe/inputMethod/include/input_method_panel_impl.h b/frameworks/ets/taihe/inputMethod/include/input_method_panel_impl.h index 7ecbaa655..b94b47813 100644 --- a/frameworks/ets/taihe/inputMethod/include/input_method_panel_impl.h +++ b/frameworks/ets/taihe/inputMethod/include/input_method_panel_impl.h @@ -21,22 +21,17 @@ #include #include -#include "ani_common.h" +#include "ani_common_engine.h" #include "ohos.inputMethodEngine.proj.hpp" #include "ohos.inputMethodEngine.impl.hpp" -using PanelFlag_t = ohos::inputMethodEngine::PanelFlag; -using PanelRect_t = ohos::inputMethodEngine::PanelRect; -using EnhancedPanelRect_t = ohos::inputMethodEngine::EnhancedPanelRect; -using ImmersiveMode_t = ohos::inputMethodEngine::ImmersiveMode; -using KeyboardArea_t = ohos::inputMethodEngine::KeyboardArea; namespace OHOS { namespace MiscServices { class PanelImpl { public: static std::shared_ptr GetInstance(); ~PanelImpl(); - void CreatePanel(uintptr_t ctx, ohos::inputMethodEngine::PanelInfo const& info, std::shared_ptr &panel); + void CreatePanel(uintptr_t ctx, PanelInfo_t const& info, std::shared_ptr &panel); void StartMoving(); void UpdateRegion(taihe::array_view inputRegion); void AdjustPanelRect(PanelFlag_t flag, PanelRect_t const& rect); @@ -51,7 +46,7 @@ public: void SetUiContentAsync(taihe::string_view path); void HideAsync(); void ShowAsync(); - void RegisterListener(std::string const &type, callbackType &&cb, uintptr_t opq); + void RegisterListener(std::string const &type, callbackTypes &&cb, uintptr_t opq); void UnRegisterListener(std::string const &type, taihe::optional_view opq); private: bool IsPanelFlagValid(PanelFlag panelFlag, bool isEnhancedCalled); @@ -59,7 +54,7 @@ private: bool IsVaildImmersiveMode(ImmersiveMode mode); void SetNative(const std::shared_ptr &panel); std::shared_ptr GetNative(); - static std::mutex PanelImpl::panelMutex_; + static std::mutex panelMutex_; static std::shared_ptr panel_; static std::shared_ptr inputMethodPanel_; } @@ -77,7 +72,7 @@ public: return value_; } - IMFPanelImpl(uintptr_t ctx, ohos::inputMethodEngine::PanelInfo const& info) + IMFPanelImpl(uintptr_t ctx, PanelInfo_t const& info) { value_ = std::shared_ptr(); PanelImpl::GetInstance()->CreatePanel(ctx, info, value_); @@ -192,6 +187,7 @@ public: { PanelImpl::GetInstance()->UnRegisterListener("sizeUpdate", opq); } + private: std::shared_ptr value_; } diff --git a/frameworks/ets/taihe/inputMethod/include/input_method_panel_listener.h b/frameworks/ets/taihe/inputMethod/include/input_method_panel_listener.h index 46b951525..4a264c794 100644 --- a/frameworks/ets/taihe/inputMethod/include/input_method_panel_listener.h +++ b/frameworks/ets/taihe/inputMethod/include/input_method_panel_listener.h @@ -18,9 +18,10 @@ #include -#include "ani_common.h" +#include "ani_common_engine.h" #include "concurrent_map.h" #include "panel_status_listener.h" +#include "panel_common.h" namespace OHOS { namespace MiscServices { class InputMethodPanelListener : public PanelStatusListener { @@ -31,11 +32,11 @@ public: void OnSizeChange(uint32_t windowId, const WindowSize &size) override; void OnSizeChange(uint32_t windowId, const WindowSize &size, const PanelAdjustInfo &keyboardArea, const std::string &event) override; - void Subscribe(uint32_t windowId, const std::string &type, callbackType &&cb, uintptr_t opq); + void Subscribe(uint32_t windowId, const std::string &type, callbackTypes &&cb, uintptr_t opq); void RemoveInfo(const std::string &type, uint32_t windowId, taihe::optional_view opq); std::mutex mutex_; - ConcurrentMap>> jsCbMap_; + ConcurrentMap>> jsCbMap_; static std::mutex listenerMutex_; static std::shared_ptr instance_; } diff --git a/frameworks/ets/taihe/inputMethod/src/ani_callback_object.cpp b/frameworks/ets/taihe/inputMethod/src/ani_callback_object.cpp index 5686166d9..42ac5c292 100644 --- a/frameworks/ets/taihe/inputMethod/src/ani_callback_object.cpp +++ b/frameworks/ets/taihe/inputMethod/src/ani_callback_object.cpp @@ -16,8 +16,6 @@ #include "ani_callback_object.h" #include "global.h" -#include - namespace OHOS { namespace MiscServices { constexpr int32_t MAX_TIMEOUT = 2000; diff --git a/frameworks/ets/taihe/inputMethod/src/input_method_ability_impl.cpp b/frameworks/ets/taihe/inputMethod/src/input_method_ability_impl.cpp index 41e0ee119..8f4c7f632 100644 --- a/frameworks/ets/taihe/inputMethod/src/input_method_ability_impl.cpp +++ b/frameworks/ets/taihe/inputMethod/src/input_method_ability_impl.cpp @@ -15,9 +15,6 @@ #include "input_method_ability_impl.h" #include "input_method_panel_impl.h" -using ValueMap = std::unordered_map; -using CommandDataType_t = ohos::inputMethodEngine::CommandDataType; - namespace OHOS { namespace MiscServices { using namespace taihe; @@ -29,7 +26,7 @@ std::shared_ptr InputMethodAbilityImpl::GetInstance() if (inputMethodEngine_ == nullptr) { std::lock_guard lock(engineMutex_); if (inputMethodEngine_ == nullptr) { - auto engine = std::make_shared(); + auto engine = std::make_shared(); if (engine == nullptr) { IMSA_HILOGE("create engine failed!"); return nullptr; @@ -40,49 +37,6 @@ std::shared_ptr InputMethodAbilityImpl::GetInstance() return inputMethodEngine_; } -SecurityMode_t InputMethodAbilityImpl::ConvertSecurityMode(SecurityMode mode) -{ - switch (mode) { - case SecurityMode::BASIC: - return SecurityMode_t::key_t::BASIC; - case SecurityMode::FULL: - return SecurityMode_t::key_t::FULL; - default: - return SecurityMode_t::key_t::BASIC; - } -} - -CommandDataType_t ConvertToDataType(const PrivateDataValue &value) -{ - size_t idx = value.index(); - if (idx == static_cast(PrivateDataValueType::VALUE_TYPE_STRING)) { - auto stringValue = std::get_if(&value); - if (stringValue != nullptr) { - return CommandDataType_t::make_type_String(*stringValue); - } - } else if (idx == static_cast(PrivateDataValueType::VALUE_TYPE_BOOL)) { - auto boolValue = std::get_if(&value); - if (boolValue != nullptr) { - return CommandDataType_t::make_type_Bool(*boolValue); - } - } else if (idx == static_cast(PrivateDataValueType::VALUE_TYPE_NUMBER)) { - auto numberValue = std::get_if(&value); - if (numberValue != nullptr) { - return CommandDataType_t::make_type_Int(*numberValue); - } - } - return CommandDataType_t::make_type_Bool(true); -} - -taihe::map InputMethodAbilityImpl::NativeConvertPCommandToAni(ValueMap &valueMap) -{ - taihe::map result(valueMap.size()); - for (const auto &[key, value] : valueMap) { - result.emplace(key, ConvertToDataType(value)); - } - return result; -} - SecurityMode_t InputMethodAbilityImpl::GetSecurityMode() { int32_t security = 0; @@ -96,7 +50,7 @@ SecurityMode_t InputMethodAbilityImpl::GetSecurityMode() return ConvertSecurityMode(security); } -void InputMethodAbilityImpl::DestroyPanelAsync(::ohos::inputMethodEngine::weak::Panel panel) +void InputMethodAbilityImpl::DestroyPanelAsync(Panel_t panel) { // ohos::inputMethodEngine::weak::Panel -> panel IMFPanelImpl* panelImpl = reinterpret_castpanel->GetImplPtr(); @@ -118,7 +72,7 @@ void InputMethodAbilityImpl::DestroyPanelAsync(::ohos::inputMethodEngine::weak:: IMSA_HILOGI("DestroyPanel success!"); } -void InputMethodAbilityImpl::RegisterListener(std::string const &type, callbackType &&cb, uintptr_t opq) +void InputMethodAbilityImpl::RegisterListener(std::string const &type, callbackTypes &&cb, uintptr_t opq) { if (!EventChecker::IsValidEventType(EventSubscribeModule::INPUT_METHOD_ABILITY, type)) { IMSA_HILOGE("subscribe failed, type: %{public}s.", type.c_str()); @@ -144,7 +98,7 @@ void InputMethodAbilityImpl::RegisterListener(std::string const &type, callbackT } auto &cbVec = jsCbMap_[type]; bool isDuplicate = - std::any_of(cbVec.begin(), cbVec.end(), [env, callbackRef](std::unique_ptr &obj) { + std::any_of(cbVec.begin(), cbVec.end(), [env, callbackRef](std::unique_ptr &obj) { ani_boolean isEqual = false; return (ANI_OK == env->Reference_StrictEquals(callbackRef, obj->ref, &isEqual)) && isEqual; }); @@ -153,7 +107,7 @@ void InputMethodAbilityImpl::RegisterListener(std::string const &type, callbackT IMSA_HILOGD("%{public}s is already registered", type.c_str()); return; } - cbVec.emplace_back(std::make_unique(cb, callbackRef)); + cbVec.emplace_back(std::make_unique(cb, callbackRef)); IMSA_HILOGI("Registered success type: %{public}s", type.c_str()); } @@ -185,13 +139,13 @@ void InputMethodAbilityImpl::UnRegisterListener(std::string const &type, taihe:: return; } - GlobalRefGuard guard(env, reinterpret_cast(opq.value())); + GlobalRefGuards guard(env, reinterpret_cast(opq.value())); if (!guard) { IMSA_HILOGE("Failed to unregister %{public}s, GlobalRefGuard is false!", type.c_str()); return; } - const auto pred = [env, targetRef = guard.get()](std::unique_ptr &obj) { + const auto pred = [env, targetRef = guard.get()](std::unique_ptr &obj) { ani_boolean is_equal = false; return (ANI_OK == env->Reference_StrictEquals(targetRef, obj->ref, &is_equal)) && is_equal; }; @@ -222,8 +176,8 @@ void InputMethodAbilityImpl::OnInputStart() std::lock_guard lock(mutex_); auto &cbVec = jsCbMap_["inputStart"]; for (auto &cb : cbVec) { - auto &func = std::get>(cb->callback); - // 解析kbController, inputClient + auto &func = std::get>(cb->callback); + // 获取kbController, inputClient func(); } } @@ -284,7 +238,7 @@ void InputMethodAbilityImpl::OnSetSubtype(const SubProperty &property) auto &cbVec = jsCbMap_["setSubtype"]; for (auto &cb : cbVec) { auto &func = std::get>(cb->callback); - func(PropertyConverter::ConvertSubProperty(property)); + func(TaiheConverter::ConvertSubProperty(property)); } } @@ -300,7 +254,9 @@ void InputMethodAbilityImpl::OnCallingDisplayIdChanged(uint64_t callingDisplayId for (auto &cb : cbVec) { auto &func = std::get)>>(cb->callback); // callingDisplayId-> array_view - func(); + std::vector displayId = {callingDisplayId}; + taihe::array_view displayIdView = taihe::array_view(displayId); + func(displayIdView); } } @@ -311,7 +267,7 @@ void InputMethodAbilityImpl::ReceivePrivateCommand(const std::unordered_map)>>(cb->callback); - func(NativeConvertPCommandToAni(privateCommand)); + func(CommonConvert::NativeConvertPCommandToAni(privateCommand)); } } diff --git a/frameworks/ets/taihe/inputMethod/src/input_method_keyboard_delegate_impl.cpp b/frameworks/ets/taihe/inputMethod/src/input_method_keyboard_delegate_impl.cpp index cacbfa6b1..ed2d974df 100644 --- a/frameworks/ets/taihe/inputMethod/src/input_method_keyboard_delegate_impl.cpp +++ b/frameworks/ets/taihe/inputMethod/src/input_method_keyboard_delegate_impl.cpp @@ -26,7 +26,7 @@ std::shared_ptr KeyboardDelegateImpl::GetInstance() if (keyboardDelegate_ == nullptr) { std::lock_guard lock(keyboardMutex_); if (keyboardDelegate_ == nullptr) { - auto delegate = std::make_shared(); + auto delegate = std::make_shared(); if (delegate == nullptr) { IMSA_HILOGE("keyboard delegate is nullptr!"); return nullptr; @@ -37,7 +37,7 @@ std::shared_ptr KeyboardDelegateImpl::GetInstance() return keyboardDelegate_; } -void KeyboardDelegateImpl::RegisterListener(std::string const &type, callbackType &&cb, uintptr_t opq) +void KeyboardDelegateImpl::RegisterListener(std::string const &type, callbackTypes &&cb, uintptr_t opq) { if (!EventChecker::IsValidEventType(EventSubscribeModule::KEYBOARD_DELEGATE, type)) { IMSA_HILOGE("subscribe failed, type: %{public}s.", type.c_str()); @@ -53,7 +53,7 @@ void KeyboardDelegateImpl::RegisterListener(std::string const &type, callbackTyp } auto &cbVec = jsCbMap_[type]; bool isDuplicate = - std::any_of(cbVec.begin(), cbVec.end(), [env, callbackRef](std::unique_ptr &obj) { + std::any_of(cbVec.begin(), cbVec.end(), [env, callbackRef](std::unique_ptr &obj) { ani_boolean isEqual = false; return (ANI_OK == env->Reference_StrictEquals(callbackRef, obj->ref, &isEqual)) && isEqual; }); @@ -62,7 +62,7 @@ void KeyboardDelegateImpl::RegisterListener(std::string const &type, callbackTyp IMSA_HILOGD("%{public}s is already registered", type.c_str()); return; } - cbVec.emplace_back(std::make_unique(cb, callbackRef)); + cbVec.emplace_back(std::make_unique(cb, callbackRef)); IMSA_HILOGI("Registered success type: %{public}s", type.c_str()); } @@ -90,13 +90,13 @@ void KeyboardDelegateImpl::UnRegisterListener(std::string const &type, taihe::op return; } - GlobalRefGuard guard(env, reinterpret_cast(opq.value())); + GlobalRefGuards guard(env, reinterpret_cast(opq.value())); if (!guard) { IMSA_HILOGE("Failed to unregister %{public}s, GlobalRefGuard is false!", type.c_str()); return; } - const auto pred = [env, targetRef = guard.get()](std::unique_ptr &obj) { + const auto pred = [env, targetRef = guard.get()](std::unique_ptr &obj) { ani_boolean is_equal = false; return (ANI_OK == env->Reference_StrictEquals(targetRef, obj->ref, &is_equal)) && is_equal; }; @@ -215,7 +215,7 @@ void KeyboardDelegateImpl::OnEditorAttributeChange(const InputAttribute &inputAt bool KeyboardDelegateImpl::OnDealKeyEvent(const std::shared_ptr &keyEvent, sptr &consumer) { - // ??? + // 正确? if (keyEvent == nullptr) { IMSA_HILOGE("keyEvent is nullptr"); return false; diff --git a/frameworks/ets/taihe/inputMethod/src/input_method_panel_impl.cpp b/frameworks/ets/taihe/inputMethod/src/input_method_panel_impl.cpp index 126462bd8..c83bb01e6 100644 --- a/frameworks/ets/taihe/inputMethod/src/input_method_panel_impl.cpp +++ b/frameworks/ets/taihe/inputMethod/src/input_method_panel_impl.cpp @@ -19,6 +19,7 @@ namespace OHOS { namespace MiscServices { using namespace taihe; +using WMError = OHOS::Rosen::WMError; std::mutex PanelImpl::panelMutex_; std::shared_ptr PanelImpl::panel_{ nullptr }; std::shared_ptr PanelImpl::inputMethodPanel_{ nullptr }; @@ -53,8 +54,9 @@ std::shared_ptr PanelImpl::GetNative() return inputMethodPanel_; } -void PanelImpl::CreatePanel(uintptr_t ctx, ohos::inputMethodEngine::PanelInfo const& info, std::shared_ptr &panel) +void PanelImpl::CreatePanel(uintptr_t ctx, PanelInfo_t const& info, std::shared_ptr &panel) { + // ctx转换 auto ret = InputMethodAbility::GetInstance().CreatePanel(ctx, info, panel); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("panel create failed!"); @@ -184,7 +186,6 @@ void PanelImpl::AdjustPanelRectEnhanced(PanelFlag_t flag, EnhancedPanelRect_t co set_business_error(JsUtils::Convert(ret), "only used for SOFT_KEYBOARD panel"); return; } - } uint32_t PanelImpl::GetDisplayIdSync() @@ -202,7 +203,7 @@ uint32_t PanelImpl::GetDisplayIdSync() return static_cast(displayId); } if (displayId > UINT32_MAX) { - IMSA_HILOGE("displayId is too large, displayId: %{public}" PRIu64 "", ctxt->displayId); + IMSA_HILOGE("displayId is too large, displayId: %{public}" PRIu64 "", displayId); set_business_error(JsUtils::Convert(ErrorCode::ERROR_WINDOW_MANAGER), "displayId is too large"); return static_cast(displayId); } @@ -210,22 +211,6 @@ uint32_t PanelImpl::GetDisplayIdSync() return static_cast(displayId); } -ImmersiveMode_t PanelImpl::ConvertMode(ImmersiveMode mode) -{ - switch (mode) { - case ImmersiveMode::NONE_IMMERSIVE: - return ImmersiveMode_t::key_t::NONE_IMMERSIVE; - case ImmersiveMode::IMMERSIVE: - return ImmersiveMode_t::key_t::IMMERSIVE; - case ImmersiveMode::LIGHT_IMMERSIVE: - return ImmersiveMode_t::key_t::LIGHT_IMMERSIVE; - case ImmersiveMode::DARK_IMMERSIVE: - return ImmersiveMode_t::key_t::DARK_IMMERSIVE; - default: - return ImmersiveMode_t::key_t::NONE_IMMERSIVE; - } -} - ImmersiveMode_t PanelImpl::GetImmersiveMode() { if (inputMethodPanel_ == nullptr) { @@ -403,7 +388,7 @@ void PanelImpl::ShowAsync() IMSA_HILOGI("Show success!"); } -void PanelImpl::RegisterListener(std::string const &type, callbackType &&cb, uintptr_t opq) +void PanelImpl::RegisterListener(std::string const &type, callbackTypes &&cb, uintptr_t opq) { IMSA_HILOGD("PanelImpl start."); if (!EventChecker::IsValidEventType(EventSubscribeModule::PANEL, type)) { diff --git a/frameworks/ets/taihe/inputMethod/src/input_method_panel_listener.cpp b/frameworks/ets/taihe/inputMethod/src/input_method_panel_listener.cpp index 55f3829d5..4f026d187 100644 --- a/frameworks/ets/taihe/inputMethod/src/input_method_panel_listener.cpp +++ b/frameworks/ets/taihe/inputMethod/src/input_method_panel_listener.cpp @@ -34,7 +34,7 @@ std::shared_ptr InputMethodPanelListener::GetInstance() InputMethodPanelListener::~InputMethodPanelListener() {} -void InputMethodPanelListener::Subscribe(uint32_t windowId, const std::string &type, callbackType &&cb, uintptr_t opq) +void InputMethodPanelListener::Subscribe(uint32_t windowId, const std::string &type, callbackTypes &&cb, uintptr_t opq) { std::lock_guard lock(mutex_); ani_object callbackObj = reinterpret_cast(opq); @@ -46,13 +46,13 @@ void InputMethodPanelListener::Subscribe(uint32_t windowId, const std::string &t } // 1 : n : n -> 1: n(1: 1)[] auto subscriptionAction = [&type](uint32_t windowId, - std::map> &cbs) -> bool { + std::map> &cbs) -> bool { if (cbs.find(type) != cbs.end()) { env->GlobalReference_Delete(callbackRef); IMSA_HILOGI("callback already registered, type: %{public}s!", type.c_str()); return true; } - auto result = cbs.try_emplace(type, std::make_unique(cb, callbackRef)); + auto result = cbs.try_emplace(type, std::make_unique(cb, callbackRef)); bool inserted = result.second; if (inserted) { @@ -71,7 +71,7 @@ void InputMethodPanelListener::RemoveInfo(const std::string &type, uint32_t wind { std::lock_guard lock(mutex_); jsCbMap_.ComputeIfPresent(windowId, - [&type](auto windowId, std::map> &cbs) { + [&type](auto windowId, std::map> &cbs) { cbs.erase(type); return !cbs.empty(); }); diff --git a/frameworks/ets/taihe/inputMethod/src/ohos.inputMethodEngine.impl.cpp b/frameworks/ets/taihe/inputMethod/src/ohos.inputMethodEngine.impl.cpp index 25b2ed469..ed35c099b 100644 --- a/frameworks/ets/taihe/inputMethod/src/ohos.inputMethodEngine.impl.cpp +++ b/frameworks/ets/taihe/inputMethod/src/ohos.inputMethodEngine.impl.cpp @@ -10,104 +10,9 @@ #include "inputmethod_trace.h" using namespace OHOS::MiscServices; -using Movement_t = ohos::inputMethodEngine::Movement; -using Range_t = ohos::inputMethodEngine::Range; -using EditorAttribute_t = ohos::inputMethodEngine::EditorAttribute; -using CapitalizeMode_t = ohos::inputMethodEngine::CapitalizeMode; -using GradientMode_t = ohos::inputMethodEngine::GradientMode; -using FluidLightMode_t = ohos::inputMethodEngine::FluidLightMode; -using ValueMap = std::unordered_map; -using CommandDataType_t = ohos::inputMethodEngine::CommandDataType; namespace { // To be implemented. -class CommonConvert { -public: - CapitalizeMode_t ConvertCapMode(CapitalizeMode mode) - { - switch (mode) { - case CapitalizeMode::NONE: - return CapitalizeMode_t::key_t::NONE; - case CapitalizeMode::SENTENCES: - return CapitalizeMode_t::key_t::SENTENCES; - case CapitalizeMode::WORDS: - return CapitalizeMode_t::key_t::WORDS; - case CapitalizeMode::CHARACTERS: - return CapitalizeMode_t::key_t::CHARACTERS; - default: - return CapitalizeMode_t::key_t::NONE; - } - } - - GradientMode_t ConvertGraMode(GradientMode mode) - { - switch (mode) { - case GradientMode::NONE: - return GradientMode_t::key_t::NONE; - case GradientMode::LINEAR_GRADIENT: - return GradientMode_t::key_t::LINEAR_GRADIENT; - default: - return GradientMode_t::key_t::NONE; - } - } - - FluidLightMode_t ConvertFLMode(FluidLightMode mode) - { - switch (mode) { - case FluidLightMode::NONE: - return FluidLightMode_t::key_t::NONE; - case FluidLightMode::BACKGROUND_FLUID_LIGHT: - return FluidLightMode_t::key_t::BACKGROUND_FLUID_LIGHT; - default: - return FluidLightMode_t::key_t::NONE; - } - } - - EditorAttribute_t NativeAttributeToAni(InputAttribute inputAttribute) - { - EditorAttribute_t result {}; - result.inputPattern = inputAttribute.inputPattern; - result.enterKeyType = inputAttribute.enterKeyType; - result.isTextPreviewSupported = inputAttribute.isTextPreviewSupported; - result.bundleName = inputAttribute.bundleName; - // Panel ConvertMode 提出去 - result.immersiveMode = ConvertMode(static_cast(inputAttribute.immersiveMode)); - result.windowId = inputAttribute.windowId; - result.displayId = inputAttribute.callingDisplayId; - result.placeholder = std::string(Str16ToStr8(inputAttribute.placeholder)); - result.abilityName = std::string(Str16ToStr8(inputAttribute.abilityName)); - result.capitalizeMode = ConvertCapMode(static_castinputAttribute.capitalizeMode); - result.gradientMode = ConvertGraMode(static_cast(inputAttribute.gradientMode)); - result.fluidLightMode = ConvertFLMode(static_cast(inputAttribute.fluidLightMode)); - return result; - } - - ValueMap AniConvertPCommandToNative(taihe::map_view commandData) - { - ValueMap valueMap; - for (auto &item : commandData) { - if (item.first.empty()) { - continue; - } - PrivateDataValue value; - switch (item.second.get_tag()) { - case CommandDataType_t::tag_t::type_Int: - value = item.second.get_type_Int_ref(); - break; - case CommandDataType_t::tag_t::type_String: - value = std::string(item.second.get_type_String_ref()); - break; - case CommandDataType_t::tag_t::type_Bool: - value = item.second.get_type_Bool_ref(); - break; - default: - break; - } - valueMap.insert(std::make_pair(std::string(item.first), value)); - } - return valueMap; - } -} class TextInputClientImpl { @@ -123,7 +28,7 @@ class InputMethodEngineImpl { // Don't forget to implement the constructor. } - void OnInputStart(taihe::callback_view callback, uintptr_t opq) { + void OnInputStart(taihe::callback_view callback, uintptr_t opq) { TH_THROW(std::runtime_error, "OnInputStart not implemented"); } @@ -201,7 +106,7 @@ public: set_business_error(IMFErrorCode::EXCEPTION_IMCLIENT, "failed to get text config!"); return result; } - result = NativeAttributeToAni(config.inputAttribute); + result = CommonConvert::NativeAttributeToAni(config.inputAttribute); return result; } -- Gitee From 43ebbcec578c9b67a01a8ac29ded78fdb4b9682b Mon Sep 17 00:00:00 2001 From: KangPeng Date: Mon, 8 Sep 2025 19:22:28 +0800 Subject: [PATCH 3/4] =?UTF-8?q?imf=20=E7=BC=96=E8=AF=91=E9=80=9A=E8=BF=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: KangPeng --- frameworks/ets/taihe/inputMethod/BUILD.gn | 11 +- .../idl/ohos.inputMethodEngine.taihe | 4 +- .../inputMethod/include/ani_common_engine.h | 109 ++++++++++++--- .../include/input_method_ability_impl.h | 11 +- .../input_method_keyboard_delegate_impl.h | 7 +- .../include/input_method_panel_impl.h | 5 +- .../include/input_method_panel_listener.h | 14 +- .../taihe/inputMethod/src/ani_constructor.cpp | 12 -- .../src/input_method_ability_impl.cpp | 27 ++-- .../input_method_keyboard_delegate_impl.cpp | 41 +++--- .../src/input_method_panel_impl.cpp | 127 +++++++++--------- .../src/input_method_panel_listener.cpp | 68 +++++++--- .../src/ohos.inputMethodEngine.impl.cpp | 101 +++++++------- 13 files changed, 330 insertions(+), 207 deletions(-) diff --git a/frameworks/ets/taihe/inputMethod/BUILD.gn b/frameworks/ets/taihe/inputMethod/BUILD.gn index ed2f7a1be..4f008280a 100644 --- a/frameworks/ets/taihe/inputMethod/BUILD.gn +++ b/frameworks/ets/taihe/inputMethod/BUILD.gn @@ -75,11 +75,19 @@ taihe_shared_library("inputmethod_taihe_native") { "src/input_method_event_listener.cpp", "src/input_method_text_changed_listener.cpp", "${inputmethod_path}/frameworks/js/napi/inputmethodclient/js_utils.cpp", + #"src/ani_callback_object.cpp", + #"src/ani_message_handler.cpp", + "src/input_method_ability_impl.cpp", + "src/input_method_keyboard_delegate_impl.cpp", + "src/input_method_panel_impl.cpp", + "src/input_method_panel_listener.cpp", + "src/ohos.inputMethodEngine.impl.cpp" ] deps = [ ":run_taihe", "${inputmethod_path}/frameworks/js/napi/common:inputmethod_js_common", "${inputmethod_path}/interfaces/inner_api/inputmethod_controller:inputmethod_client", + "${inputmethod_path}/interfaces/inner_api/inputmethod_ability:inputmethod_ability", ] external_deps = [ "ability_base:want", @@ -170,6 +178,7 @@ group("inputmethod_taihe") { ":inputmethod_taihe_native", ":inputmethod_etc", ":inputmethod_panel_etc", - ":inputmethod_subtype_etc" + ":inputmethod_subtype_etc", + ":inputmethod_engine_etc" ] } diff --git a/frameworks/ets/taihe/inputMethod/idl/ohos.inputMethodEngine.taihe b/frameworks/ets/taihe/inputMethod/idl/ohos.inputMethodEngine.taihe index 946d0ca8c..203d1bb31 100644 --- a/frameworks/ets/taihe/inputMethod/idl/ohos.inputMethodEngine.taihe +++ b/frameworks/ets/taihe/inputMethod/idl/ohos.inputMethodEngine.taihe @@ -18,7 +18,7 @@ import BaseContext from 'application.BaseContext'; import window from '@ohos.window'; """) @!sts_inject_into_module("import * as ohos_InputMethodSubtype from './@ohos.InputMethodSubtype';") -@!sts_inject_into_module("import * as ohos_keyEvent from './@ohos.multimodalInput.keyEvent';") +@!sts_inject_into_module("import * as ohos_multimodalInput_keyEvent from './@ohos.multimodalInput.keyEvent';") @!namespace("@ohos.inputMethodEngine", "inputMethodEngine") @@ -392,7 +392,7 @@ interface KeyboardDelegate { switch(type) { case "keyDown": case "keyUp": return this.onKeyEventType(type, callback as (data: KeyEventType) => boolean, callback); - case "keyEvent": return this.onKeyEvent(callback as (data: ohos_keyEvent.KeyEvent) => boolean, callback); + case "keyEvent": return this.onKeyEvent(callback as (data: ohos_multimodalInput_keyEvent.KeyEvent) => boolean, callback); case "textChange": return this.onTextChange(callback as (data: string) => void, callback); case "editorAttributeChanged": return this.onEditorAttributeChanged(callback as (data: EditorAttribute) => void, callback); default: throw new Error(`Unknown type: ${type}`); diff --git a/frameworks/ets/taihe/inputMethod/include/ani_common_engine.h b/frameworks/ets/taihe/inputMethod/include/ani_common_engine.h index 905b4a12a..202299831 100644 --- a/frameworks/ets/taihe/inputMethod/include/ani_common_engine.h +++ b/frameworks/ets/taihe/inputMethod/include/ani_common_engine.h @@ -23,6 +23,9 @@ #include "ohos.inputMethodEngine.proj.hpp" #include "ohos.inputMethodEngine.impl.hpp" #include "taihe/runtime.hpp" +#include "ani.h" +#include "string_ex.h" +#include "panel_info.h" using InputMethodSubtype_t = ohos::InputMethodSubtype::InputMethodSubtype; using EnhancedPanelRect_t = ohos::inputMethodEngine::EnhancedPanelRect; @@ -34,11 +37,14 @@ using EditorAttribute_t = ohos::inputMethodEngine::EditorAttribute; using CapitalizeMode_t = ohos::inputMethodEngine::CapitalizeMode; using GradientMode_t = ohos::inputMethodEngine::GradientMode; using FluidLightMode_t = ohos::inputMethodEngine::FluidLightMode; -using ValueMap = std::unordered_map; using CommandDataType_t = ohos::inputMethodEngine::CommandDataType; using SecurityMode_t = ohos::inputMethodEngine::SecurityMode; using KeyEventType_t = ohos::inputMethodEngine::KeyEventType; using KeyEvent_t = ohos::multimodalInput::keyEvent::KeyEvent; +using Action_t = ohos::multimodalInput::keyEvent::Action; +using InputEvent_t = ohos::multimodalInput::inputEvent::InputEvent; +using Key_t = ohos::multimodalInput::keyEvent::Key; +using KeyCode_t = ohos::multimodalInput::keyCode::KeyCode; using PanelInfo_t = ohos::inputMethodEngine::PanelInfo; using PanelFlag_t = ohos::inputMethodEngine::PanelFlag; using PanelRect_t = ohos::inputMethodEngine::PanelRect; @@ -48,6 +54,7 @@ using Panel_t =ohos::inputMethodEngine::weak::Panel; using TextInputClient_t = ohos::inputMethodEngine::weak::TextInputClient; // 大概率废弃 namespace OHOS { namespace MiscServices { +using ValueMap = std::unordered_map; class TaiheConverter { public: @@ -57,7 +64,7 @@ public: } private: - static InputMethodSubtype_t ConvertSubPropertyImpl(SubProperty &property) + static InputMethodSubtype_t ConvertSubPropertyImpl(const SubProperty &property) { InputMethodSubtype_t result {}; result.name = property.name; @@ -73,14 +80,13 @@ private: }; using callbackTypes = std::variant, - taihe::callback, taihe::callback)>>, + taihe::callback, taihe::callback)>, taihe::callback)>, taihe::callback, taihe::callback, taihe::callback, taihe::callback, taihe::callback, taihe::callback, taihe::callback, taihe::callback, taihe::callback, - taihe::callback)>, taihe::callback - ; + taihe::callback)>, taihe::callback>; struct CallbackObjects { CallbackObjects(callbackTypes cb, ani_ref ref) : callback(cb), ref(ref) @@ -125,12 +131,13 @@ public: } } - GlobalRefGuards(const GlobalRefGuard &) = delete; - GlobalRefGuards &operator=(const GlobalRefGuard &) = delete; + GlobalRefGuards(const GlobalRefGuards &) = delete; + GlobalRefGuards &operator=(const GlobalRefGuards &) = delete; }; class CommonConvert { public: + static constexpr int KEYEVENT_ACTION_JS_NATIVE_DELTA = 1; static SecurityMode_t ConvertSecurityMode(SecurityMode mode) { switch (mode) { @@ -203,15 +210,15 @@ public: result.inputPattern = inputAttribute.inputPattern; result.enterKeyType = inputAttribute.enterKeyType; result.isTextPreviewSupported = inputAttribute.isTextPreviewSupported; - result.bundleName = inputAttribute.bundleName; - result.immersiveMode = ConvertMode(static_cast(inputAttribute.immersiveMode)); - result.windowId = inputAttribute.windowId; - result.displayId = inputAttribute.callingDisplayId; - result.placeholder = std::string(Str16ToStr8(inputAttribute.placeholder)); - result.abilityName = std::string(Str16ToStr8(inputAttribute.abilityName)); - result.capitalizeMode = ConvertCapMode(static_castinputAttribute.capitalizeMode); - result.gradientMode = ConvertGraMode(static_cast(inputAttribute.gradientMode)); - result.fluidLightMode = ConvertFLMode(static_cast(inputAttribute.fluidLightMode)); + result.bundleName = taihe::optional(std::in_place_t{}, inputAttribute.bundleName); + result.immersiveMode = taihe::optional(std::in_place_t{}, ConvertMode(static_cast(inputAttribute.immersiveMode))); + result.windowId = taihe::optional(std::in_place_t{}, inputAttribute.windowId); + result.displayId = taihe::optional(std::in_place_t{}, inputAttribute.callingDisplayId); + result.placeholder = taihe::optional(std::in_place_t{}, std::string(Str16ToStr8(inputAttribute.placeholder))); + result.abilityName = taihe::optional(std::in_place_t{}, std::string(Str16ToStr8(inputAttribute.abilityName))); + result.capitalizeMode = taihe::optional(std::in_place_t{}, ConvertCapMode(static_cast(inputAttribute.capitalizeMode))); + result.gradientMode = taihe::optional(std::in_place_t{}, ConvertGraMode(static_cast(inputAttribute.gradientMode))); + result.fluidLightMode = taihe::optional(std::in_place_t{}, ConvertFLMode(static_cast(inputAttribute.fluidLightMode))); return result; } @@ -264,7 +271,7 @@ public: return CommandDataType_t::make_type_Bool(true); } - static taihe::map NativeConvertPCommandToAni(ValueMap &valueMap) + static taihe::map NativeConvertPCommandToAni(const ValueMap &valueMap) { taihe::map result(valueMap.size()); for (const auto &[key, value] : valueMap) { @@ -272,6 +279,74 @@ public: } return result; } + + static PanelInfo AniConvertPanelInfoToNative(PanelInfo_t panel) + { + PanelInfo info{}; + info.panelType = static_cast(panel.type.get_value()); + if (panel.flag.has_value()) { + info.panelFlag = static_cast(panel.flag.value().get_value()); + } + return info; + } + + static Key_t ToTaiheKey(const std::optional &in) + { + bool isNull = (in == std::nullopt); + int32_t keyCode = isNull ? OHOS::MMI::KeyEvent::KEYCODE_UNKNOWN : in->GetKeyCode(); + Key_t out = { + .code = KeyCode_t::from_value(keyCode), + .pressedTime = isNull ? 0 : in->GetDownTime(), + .deviceId = isNull ? 0 : in->GetDeviceId(), + }; + return out; + } + + static taihe::array ToTaiheKeys(const std::vector &in) + { + std::vector resultVec; + for (const auto &item : in) { + Key_t result = ToTaiheKey(item); + resultVec.emplace_back(result); + } + return taihe::array(resultVec); + } + + static InputEvent_t ToTaiheInputEvent(const std::shared_ptr &in) + { + auto key = in->GetKeyItem(); + bool isNull = (key == std::nullopt); + InputEvent_t out = { + .id = isNull ? 0 : in->GetKeyItem()->GetKeyCode(), + .deviceId = isNull ? 0 : in->GetKeyItem()->GetDeviceId(), + .actionTime = isNull ? 0 : in->GetKeyItem()->GetDownTime(), + .screenId = 0, + .windowId = 0, + }; + return out; + } + + static KeyEvent_t ToTaiheKeyEvent(const std::shared_ptr &in) + { + auto key = in->GetKeyItem(); + int32_t unicodeChar = (key == std::nullopt) ? 0 : static_cast(key->GetUnicode()); + KeyEvent_t out = { + .base = ToTaiheInputEvent(in), + .action = Action_t::from_value(in->GetKeyAction()), + .key = ToTaiheKey(key), + .unicodeChar = unicodeChar, + .keys = ToTaiheKeys(in->GetKeyItems()), + .ctrlKey = in->GetKeyItem(MMI::KeyEvent::KEYCODE_CTRL_RIGHT).has_value(), + .altKey = in->GetKeyItem(MMI::KeyEvent::KEYCODE_ALT_RIGHT).has_value(), + .shiftKey = in->GetKeyItem(MMI::KeyEvent::KEYCODE_SHIFT_RIGHT).has_value(), + .logoKey = in->GetKeyItem(MMI::KeyEvent::KEYCODE_META_RIGHT).has_value(), + .fnKey = in->GetKeyItem(MMI::KeyEvent::KEYCODE_FN).has_value(), + .capsLock = in->GetFunctionKey(OHOS::MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY), + .numLock = in->GetFunctionKey(OHOS::MMI::KeyEvent::NUM_LOCK_FUNCTION_KEY), + .scrollLock = in->GetFunctionKey(OHOS::MMI::KeyEvent::SCROLL_LOCK_FUNCTION_KEY), + }; + return out; + } }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/ets/taihe/inputMethod/include/input_method_ability_impl.h b/frameworks/ets/taihe/inputMethod/include/input_method_ability_impl.h index d862ad9bd..6eac1cb74 100644 --- a/frameworks/ets/taihe/inputMethod/include/input_method_ability_impl.h +++ b/frameworks/ets/taihe/inputMethod/include/input_method_ability_impl.h @@ -24,6 +24,7 @@ #include "ani_common_engine.h" #include "ohos.inputMethodEngine.proj.hpp" #include "ohos.inputMethodEngine.impl.hpp" +#include "input_method_engine_listener.h" namespace OHOS { namespace MiscServices { @@ -43,13 +44,13 @@ public: void OnSetSubtype(const SubProperty &property) override; void OnCallingDisplayIdChanged(uint64_t callingDisplayId) override; void ReceivePrivateCommand(const std::unordered_map &privateCommand) override; - + private: std::mutex mutex_; std::map>> jsCbMap_; - std::mutex engineMutex_; - std::shared_ptr inputMethodEngine_; -} + static std::mutex engineMutex_; + static std::shared_ptr inputMethodEngine_; +}; class IMFAbilityImpl { public: @@ -163,7 +164,7 @@ public: { InputMethodAbilityImpl::GetInstance()->UnRegisterListener("inputStart", opq); } -} +}; } // namespace MiscServices } // namespace OHOS #endif // TAIHE_INPUT_METHOD_ABILITY_IMPL_H \ No newline at end of file diff --git a/frameworks/ets/taihe/inputMethod/include/input_method_keyboard_delegate_impl.h b/frameworks/ets/taihe/inputMethod/include/input_method_keyboard_delegate_impl.h index d294f8a1b..b0eef79e9 100644 --- a/frameworks/ets/taihe/inputMethod/include/input_method_keyboard_delegate_impl.h +++ b/frameworks/ets/taihe/inputMethod/include/input_method_keyboard_delegate_impl.h @@ -24,7 +24,8 @@ #include "ani_common_engine.h" #include "ohos.inputMethodEngine.proj.hpp" #include "ohos.inputMethodEngine.impl.hpp" - +#include "key_event_consumer_proxy.h" +#include "keyboard_listener.h" namespace OHOS { namespace MiscServices { @@ -40,6 +41,8 @@ public: void OnTextChange(const std::string &text) override; void OnEditorAttributeChange(const InputAttribute &inputAttribute) override; bool OnDealKeyEvent(const std::shared_ptr &keyEvent, sptr &consumer) override; + void OnKeyEventConsumeResult(bool isConsumed, sptr consumer); + void OnKeyCodeConsumeResult(bool isConsumed, sptr consumer); private: std::mutex mutex_; std::map>> jsCbMap_; @@ -125,7 +128,7 @@ class IMFKeyboardDelegateImpl { { KeyboardDelegateImpl::GetInstance()->UnRegisterListener("editorAttributeChanged", opq); } -} +}; } // namespace MiscServices } // namespace OHOS #endif // TAIHE_INPUT_METHOD_KEYBOARD_DELEGATE_IMPL_H \ No newline at end of file diff --git a/frameworks/ets/taihe/inputMethod/include/input_method_panel_impl.h b/frameworks/ets/taihe/inputMethod/include/input_method_panel_impl.h index b94b47813..10c344230 100644 --- a/frameworks/ets/taihe/inputMethod/include/input_method_panel_impl.h +++ b/frameworks/ets/taihe/inputMethod/include/input_method_panel_impl.h @@ -24,6 +24,7 @@ #include "ani_common_engine.h" #include "ohos.inputMethodEngine.proj.hpp" #include "ohos.inputMethodEngine.impl.hpp" +#include "input_method_ability.h" namespace OHOS { namespace MiscServices { @@ -57,7 +58,7 @@ private: static std::mutex panelMutex_; static std::shared_ptr panel_; static std::shared_ptr inputMethodPanel_; -} +}; class IMFPanelImpl { public: @@ -190,7 +191,7 @@ public: private: std::shared_ptr value_; -} +}; } // namespace MiscServices } // namespace OHOS #endif // TAIHE_INPUT_METHOD_PANEL_IMPL_H \ No newline at end of file diff --git a/frameworks/ets/taihe/inputMethod/include/input_method_panel_listener.h b/frameworks/ets/taihe/inputMethod/include/input_method_panel_listener.h index 4a264c794..8a478014c 100644 --- a/frameworks/ets/taihe/inputMethod/include/input_method_panel_listener.h +++ b/frameworks/ets/taihe/inputMethod/include/input_method_panel_listener.h @@ -17,11 +17,16 @@ #define INPUTMETHOD_PANEL_LISTENER_H #include +#include +#include +#include +#include #include "ani_common_engine.h" #include "concurrent_map.h" #include "panel_status_listener.h" #include "panel_common.h" +#include "event_handler.h" namespace OHOS { namespace MiscServices { class InputMethodPanelListener : public PanelStatusListener { @@ -33,13 +38,18 @@ public: void OnSizeChange(uint32_t windowId, const WindowSize &size, const PanelAdjustInfo &keyboardArea, const std::string &event) override; void Subscribe(uint32_t windowId, const std::string &type, callbackTypes &&cb, uintptr_t opq); - void RemoveInfo(const std::string &type, uint32_t windowId, taihe::optional_view opq); + void RemoveInfo(uint32_t windowId, const std::string &type); + void SetEventHandler(std::shared_ptr handler); +private: + std::unique_ptr GetCallback(uint32_t windowId, const std::string &type); std::mutex mutex_; ConcurrentMap>> jsCbMap_; static std::mutex listenerMutex_; static std::shared_ptr instance_; -} + mutable std::shared_mutex eventHandlerMutex_; + std::shared_ptr handler_; +}; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/ets/taihe/inputMethod/src/ani_constructor.cpp b/frameworks/ets/taihe/inputMethod/src/ani_constructor.cpp index 1f5c1fd87..10962456d 100644 --- a/frameworks/ets/taihe/inputMethod/src/ani_constructor.cpp +++ b/frameworks/ets/taihe/inputMethod/src/ani_constructor.cpp @@ -42,22 +42,10 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) { std::cerr << "Error from ohos::inputMethod::Panel::ANIRegister" << std::endl; status = ANI_ERROR; } - if (ANI_OK != ohos::multimodalInput::keyEvent::ANIRegister(env)) { - std::cerr << "Error from ohos::multimodalInput::keyEvent::ANIRegister" << std::endl; - status = ANI_ERROR; - } if (ANI_OK != ohos::inputMethod::ANIRegister(env)) { std::cerr << "Error from ohos::inputMethod::ANIRegister" << std::endl; status = ANI_ERROR; } - if (ANI_OK != ohos::multimodalInput::keyCode::ANIRegister(env)) { - std::cerr << "Error from ohos::multimodalInput::keyCode::ANIRegister" << std::endl; - status = ANI_ERROR; - } - if (ANI_OK != ohos::multimodalInput::inputEvent::ANIRegister(env)) { - std::cerr << "Error from ohos::multimodalInput::inputEvent::ANIRegister" << std::endl; - status = ANI_ERROR; - } if (ANI_OK != ohos::inputMethodEngine::ANIRegister(env)) { std::cerr << "Error from ohos::inputMethodEngine::ANIRegister" << std::endl; status = ANI_ERROR; diff --git a/frameworks/ets/taihe/inputMethod/src/input_method_ability_impl.cpp b/frameworks/ets/taihe/inputMethod/src/input_method_ability_impl.cpp index 8f4c7f632..a4d344c46 100644 --- a/frameworks/ets/taihe/inputMethod/src/input_method_ability_impl.cpp +++ b/frameworks/ets/taihe/inputMethod/src/input_method_ability_impl.cpp @@ -14,13 +14,14 @@ */ #include "input_method_ability_impl.h" #include "input_method_panel_impl.h" +#include "js_utils.h" +#include "event_checker.h" namespace OHOS { namespace MiscServices { using namespace taihe; std::mutex InputMethodAbilityImpl::engineMutex_; -std::shared_ptr InputMethodAbilityImpl::inputMethodEngine_{ nullptr }; - +std::shared_ptr InputMethodAbilityImpl::inputMethodEngine_ {nullptr}; std::shared_ptr InputMethodAbilityImpl::GetInstance() { if (inputMethodEngine_ == nullptr) { @@ -43,20 +44,20 @@ SecurityMode_t InputMethodAbilityImpl::GetSecurityMode() int32_t ret = InputMethodAbility::GetInstance().GetSecurityMode(security); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to get security mode"); - set_business_error(JsUtils::Convert(ret), "failed to get security mode"); - return ConvertSecurityMode(security); + taihe::set_business_error(JsUtils::Convert(ret), "failed to get security mode"); + return CommonConvert::ConvertSecurityMode(static_cast(security)); } IMSA_HILOGI("GetSecurityMode success!"); - return ConvertSecurityMode(security); + return CommonConvert::ConvertSecurityMode(static_cast(security)); } void InputMethodAbilityImpl::DestroyPanelAsync(Panel_t panel) { // ohos::inputMethodEngine::weak::Panel -> panel - IMFPanelImpl* panelImpl = reinterpret_castpanel->GetImplPtr(); + IMFPanelImpl* panelImpl = reinterpret_cast(panel->GetImplPtr()); if (panelImpl == nullptr) { IMSA_HILOGE("Failed to unwrap IMFPanelImpl"); - set_business_error(IMFErrorCode::EXCEPTION_PARAMCHECK, "Failed to unwrap IMFPanelImpl"); + taihe::set_business_error(IMFErrorCode::EXCEPTION_PARAMCHECK, "Failed to unwrap IMFPanelImpl"); return; } auto panelNative = panelImpl->GetNativePtr(); @@ -66,7 +67,7 @@ void InputMethodAbilityImpl::DestroyPanelAsync(Panel_t panel) auto errCode = InputMethodAbility::GetInstance().DestroyPanel(panelNative); if (errCode != ErrorCode::NO_ERROR) { IMSA_HILOGE("DestroyPanel failed, errCode: %{public}d!", errCode); - set_business_error(JsUtils::Convert(ret), "DestroyPanel failed"); + taihe::set_business_error(JsUtils::Convert(errCode), "DestroyPanel failed"); return; } IMSA_HILOGI("DestroyPanel success!"); @@ -79,12 +80,12 @@ void InputMethodAbilityImpl::RegisterListener(std::string const &type, callbackT return; } if (type == "privateCommand" && !InputMethodAbility::GetInstance().IsDefaultIme()) { - set_business_error(JsUtils::Convert(ErrorCode::ERROR_NOT_DEFAULT_IME), "default ime check failed"); + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_NOT_DEFAULT_IME), "default ime check failed"); return; } #ifndef SCENE_BOARD_ENABLE if (type == "callingDisplayDidChange") { - set_business_error(JsUtils::Convert(ErrorCode::ERROR_DEVICE_UNSUPPORTED), "capability not supported."); + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_DEVICE_UNSUPPORTED), "capability not supported."); return; } #endif @@ -118,7 +119,7 @@ void InputMethodAbilityImpl::UnRegisterListener(std::string const &type, taihe:: return; } if (type == "privateCommand" && !InputMethodAbility::GetInstance().IsDefaultIme()) { - set_business_error(JsUtils::Convert(ErrorCode::ERROR_NOT_DEFAULT_IME), "default ime check failed"); + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_NOT_DEFAULT_IME), "default ime check failed"); return; } std::lock_guard lock(mutex_); @@ -178,7 +179,7 @@ void InputMethodAbilityImpl::OnInputStart() for (auto &cb : cbVec) { auto &func = std::get>(cb->callback); // 获取kbController, inputClient - func(); + // func(); } } @@ -213,7 +214,7 @@ void InputMethodAbilityImpl::OnSecurityChange(int32_t security) auto &cbVec = jsCbMap_["securityModeChange"]; for (auto &cb : cbVec) { auto &func = std::get>(cb->callback); - SecurityMode_t modeType = ConvertSecurityMode(static_cast(security)); + SecurityMode_t modeType = CommonConvert::ConvertSecurityMode(static_cast(security)); func(modeType); } } diff --git a/frameworks/ets/taihe/inputMethod/src/input_method_keyboard_delegate_impl.cpp b/frameworks/ets/taihe/inputMethod/src/input_method_keyboard_delegate_impl.cpp index ed2d974df..5354f2871 100644 --- a/frameworks/ets/taihe/inputMethod/src/input_method_keyboard_delegate_impl.cpp +++ b/frameworks/ets/taihe/inputMethod/src/input_method_keyboard_delegate_impl.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ #include "input_method_keyboard_delegate_impl.h" +#include "input_method_ability.h" +#include "event_checker.h" namespace OHOS { namespace MiscServices { @@ -143,6 +145,18 @@ void KeyboardDelegateImpl::OnKeyCodeConsumeResult(bool isConsumed, sptr consumer) +{ + IMSA_HILOGI("result: %{public}d.", isConsumed); + keyEventConsume_ = true; + keyEventResult_ = isConsumed; + if (keyCodeConsume_) { + consumer->OnKeyEventResult(keyCodeResult_ || keyEventResult_); + keyEventConsume_ = false; + keyEventResult_ = false; + } +} + bool KeyboardDelegateImpl::OnKeyEvent(const std::shared_ptr &keyEvent, sptr &consumer) { std::string type = "keyEvent"; @@ -150,17 +164,8 @@ bool KeyboardDelegateImpl::OnKeyEvent(const std::shared_ptr &keyE auto &cbVec = jsCbMap_[type]; for (auto &cb : cbVec) { auto &func = std::get>(cb->callback); - KeyEvent_t event; - // 转换 依赖keyEvent - int32_t ret = ErrorCode::ERROR_BAD_PARAMETERS; - ret = TaiheKeyEvnet(*keyEvent, event); - if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("create key event failed"); - return false; - } - // 后续增加 - bool isConsumed = false; - isConsumed = func(event); + // KeyEvent_t event; + bool isConsumed = func(CommonConvert::ToTaiheKeyEvent(keyEvent)); if (consumer != nullptr) { IMSA_HILOGE("consumer result: %{public}d!", isConsumed); OnKeyEventConsumeResult(isConsumed, consumer); @@ -209,7 +214,7 @@ void KeyboardDelegateImpl::OnEditorAttributeChange(const InputAttribute &inputAt auto &cbVec = jsCbMap_[type]; for (auto &cb : cbVec) { auto &func = std::get>(cb->callback); - func(NativeAttributeToAni(inputAttribute)); + func(CommonConvert::NativeAttributeToAni(inputAttribute)); } } @@ -221,11 +226,11 @@ bool KeyboardDelegateImpl::OnDealKeyEvent(const std::shared_ptr & return false; } std::lock_guard lock(mutex_); - auto &cbVec = jsCbMap_["keyEvent"]; - for (auto &cb : cbVec) { + auto &cbEventVec = jsCbMap_["keyEvent"]; + for (auto &cb : cbEventVec) { auto &func = std::get>(cb->callback); // keyevent转换 - bool isKeyEventConsumed = func(); + bool isKeyEventConsumed = func(CommonConvert::ToTaiheKeyEvent(keyEvent)); if (consumer != nullptr) { if (!isKeyEventConsumed) { if (keyEvent != nullptr && keyEvent->GetKeyAction() == MMI::KeyEvent::KEY_ACTION_DOWN) { @@ -238,9 +243,8 @@ bool KeyboardDelegateImpl::OnDealKeyEvent(const std::shared_ptr & } } std::string type = (keyEvent->GetKeyAction() == ARGC_TWO ? "keyDown" : "keyUp"); - std::lock_guard lock(mutex_); - auto &cbVec = jsCbMap_[type]; - for (auto &cb : cbVec) { + auto &cbCodeVec = jsCbMap_[type]; + for (auto &cb : cbCodeVec) { auto &func = std::get>(cb->callback); KeyEventType_t event { .keyCode = keyEvent->GetKeyCode(), @@ -259,6 +263,7 @@ bool KeyboardDelegateImpl::OnDealKeyEvent(const std::shared_ptr & consumer->OnKeyEventResult(isKeyCodeConsumed); } } + return true; } } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/taihe/inputMethod/src/input_method_panel_impl.cpp b/frameworks/ets/taihe/inputMethod/src/input_method_panel_impl.cpp index c83bb01e6..ee73dcc75 100644 --- a/frameworks/ets/taihe/inputMethod/src/input_method_panel_impl.cpp +++ b/frameworks/ets/taihe/inputMethod/src/input_method_panel_impl.cpp @@ -13,8 +13,9 @@ * limitations under the License. */ #include "input_method_panel_impl.h" - +#include "js_utils.h" #include "input_method_panel_listener.h" +#include "event_checker.h" namespace OHOS { namespace MiscServices { @@ -32,10 +33,12 @@ std::shared_ptr PanelImpl::GetInstance() } if (panel_ == nullptr) { std::lock_guard lock(panelMutex_); - if (panel_ == nullptr) { - auto panel = std::make_shared(); - panel_ = panel; + auto panel = std::make_shared(); + if (panel == nullptr) { + IMSA_HILOGE("create panel failed!"); + return nullptr; } + panel_ = panel; } return panel_; } @@ -56,11 +59,13 @@ std::shared_ptr PanelImpl::GetNative() void PanelImpl::CreatePanel(uintptr_t ctx, PanelInfo_t const& info, std::shared_ptr &panel) { - // ctx转换 - auto ret = InputMethodAbility::GetInstance().CreatePanel(ctx, info, panel); + // ctx info 转换 + std::shared_ptr context; + PanelInfo panelInfo = CommonConvert::AniConvertPanelInfoToNative(info); + auto ret = InputMethodAbility::GetInstance().CreatePanel(context, panelInfo, panel); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("panel create failed!"); - set_business_error(IMFErrorCode::EXCEPTION_IME, "panel create failed!"); + taihe::set_business_error(IMFErrorCode::EXCEPTION_IME, "panel create failed!"); return; } if (panel != nullptr) { @@ -73,12 +78,12 @@ void PanelImpl::StartMoving() { if (inputMethodPanel_ == nullptr) { IMSA_HILOGE("panel is nullptr!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to start moving, panel is nullptr"); + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to start moving, panel is nullptr"); return; } auto ret = inputMethodPanel_->StartMoving(); if (ret != ErrorCode::NO_ERROR) { - set_business_error(JsUtils::Convert(ret), "failed to start moving"); + taihe::set_business_error(JsUtils::Convert(ret), "failed to start moving"); } } @@ -102,37 +107,37 @@ void PanelImpl::UpdateRegion(taihe::array_view inputRegion) { if (inputMethodPanel_ == nullptr) { IMSA_HILOGE("panel is nullptr!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "panel is nullptr!"); + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "panel is nullptr!"); return; } if (inputMethodPanel_->GetPanelType() != PanelType::SOFT_KEYBOARD) { - set_business_error(JsUtils::Convert(ErrorCode::ERROR_INVALID_PANEL_TYPE), + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_INVALID_PANEL_TYPE), "only used for SOFT_KEYBOARD panel"); return; } if (!IsPanelFlagValid(inputMethodPanel_->GetPanelFlag(), true)) { IMSA_HILOGE("invalid panelFlag!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_INVALID_PANEL_FLAG), + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_INVALID_PANEL_FLAG), "param flag should be FIXED or FLOATING"); return; } // inputRegion -> vector hotArea std::vector hotArea; int32_t code = inputMethodPanel_->UpdateRegion(hotArea); - if (ret == ErrorCode::NO_ERROR) { + if (code == ErrorCode::NO_ERROR) { IMSA_HILOGI("UpdateRegion success!"); return; } else if (code == ErrorCode::ERROR_INVALID_PANEL_TYPE) { IMSA_HILOGE("only used for SOFT_KEYBOARD panel!"); - set_business_error(JsUtils::Convert(code), "only used for SOFT_KEYBOARD panel!"); + taihe::set_business_error(JsUtils::Convert(code), "only used for SOFT_KEYBOARD panel!"); return; } else if (code == ErrorCode::ERROR_INVALID_PANEL_FLAG) { IMSA_HILOGE("only used for fixed or floating panel!"); - set_business_error(JsUtils::Convert(code), "only used for fixed or floating panel!"); + taihe::set_business_error(JsUtils::Convert(code), "only used for fixed or floating panel!"); return; } IMSA_HILOGE("UpdateRegion failed!"); - set_business_error(JsUtils::Convert(code), "UpdateRegion failed!"); + taihe::set_business_error(JsUtils::Convert(code), "UpdateRegion failed!"); return; } @@ -140,7 +145,7 @@ void PanelImpl::AdjustPanelRect(PanelFlag_t flag, PanelRect_t const& rect) { if (inputMethodPanel_ == nullptr) { IMSA_HILOGE("panel is nullptr!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "panel is nullptr!"); + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "panel is nullptr!"); return; } // PanelFlag_t -> PanelFlag PanelRect_t -> LayoutParams @@ -152,19 +157,19 @@ void PanelImpl::AdjustPanelRect(PanelFlag_t flag, PanelRect_t const& rect) return; } else if (ret == ErrorCode::ERROR_PARAMETER_CHECK_FAILED) { IMSA_HILOGE("invalid param"); - set_business_error(JsUtils::Convert(ret), + taihe::set_business_error(JsUtils::Convert(ret), "width limit:[0, displayWidth], height limit:[0, 70 percent of displayHeight]!"); return; } IMSA_HILOGE("AdjustPanelRect failed!"); - set_business_error(JsUtils::Convert(ret), "AdjustPanelRect failed!"); + taihe::set_business_error(JsUtils::Convert(ret), "AdjustPanelRect failed!"); } void PanelImpl::AdjustPanelRectEnhanced(PanelFlag_t flag, EnhancedPanelRect_t const& rect) { if (inputMethodPanel_ == nullptr) { IMSA_HILOGE("panel is nullptr!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "panel is nullptr!"); + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "panel is nullptr!"); return; } // PanelFlag_t -> PanelFlag EnhancedPanelRect_t -> EnhancedLayoutParams 、HotAreas @@ -178,12 +183,12 @@ void PanelImpl::AdjustPanelRectEnhanced(PanelFlag_t flag, EnhancedPanelRect_t co return; } else if (ret == ErrorCode::ERROR_PARAMETER_CHECK_FAILED) { IMSA_HILOGE("invalid param"); - set_business_error(JsUtils::Convert(ret), + taihe::set_business_error(JsUtils::Convert(ret), "width limit:[0, displayWidth], height limit:[0, 70 percent of displayHeight]!"); return; } else if (ret == ErrorCode::ERROR_INVALID_PANEL_TYPE) { IMSA_HILOGE("only used for SOFT_KEYBOARD panel"); - set_business_error(JsUtils::Convert(ret), "only used for SOFT_KEYBOARD panel"); + taihe::set_business_error(JsUtils::Convert(ret), "only used for SOFT_KEYBOARD panel"); return; } } @@ -193,18 +198,18 @@ uint32_t PanelImpl::GetDisplayIdSync() uint64_t displayId = 0; if (inputMethodPanel_ == nullptr) { IMSA_HILOGE("panel is nullptr!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "panel is nullptr!"); + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "panel is nullptr!"); return static_cast(displayId); } auto ret = inputMethodPanel_->GetDisplayId(displayId); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed get displayId!"); - set_business_error(JsUtils::Convert(ret), "failed get displayId!"); + taihe::set_business_error(JsUtils::Convert(ret), "failed get displayId!"); return static_cast(displayId); } if (displayId > UINT32_MAX) { IMSA_HILOGE("displayId is too large, displayId: %{public}" PRIu64 "", displayId); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_WINDOW_MANAGER), "displayId is too large"); + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_WINDOW_MANAGER), "displayId is too large"); return static_cast(displayId); } IMSA_HILOGI("get displayId success!"); @@ -215,12 +220,12 @@ ImmersiveMode_t PanelImpl::GetImmersiveMode() { if (inputMethodPanel_ == nullptr) { IMSA_HILOGE("panel is nullptr!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to get ImmersiveMode, panel is nullptr!"); - return ImmersiveMode::key_t::NONE_IMMERSIVE; + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to get ImmersiveMode, panel is nullptr!"); + return CommonConvert::ConvertMode(ImmersiveMode::NONE_IMMERSIVE); } auto immersiveMode = inputMethodPanel_->GetImmersiveMode(); IMSA_HILOGI("get Immersive mode success!"); - return ConvertMode(immersiveMode); + return CommonConvert::ConvertMode(immersiveMode); } bool PanelImpl::IsVaildImmersiveMode(ImmersiveMode mode) @@ -237,20 +242,20 @@ void PanelImpl::SetImmersiveMode(ImmersiveMode_t mode) { if (inputMethodPanel_ == nullptr) { IMSA_HILOGE("panel is nullptr!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to set ImmersiveMode, panel is nullptr!"); + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to set ImmersiveMode, panel is nullptr!"); return; } ImmersiveMode immersiveMode = static_cast(mode.get_value()); if (!IsVaildImmersiveMode(immersiveMode)) { IMSA_HILOGE("immersiveMode type must be ImmersiveMode and can not be IMMERSIVE"); - set_business_error(IMFErrorCode::EXCEPTION_PARAMCHECK, + taihe::set_business_error(IMFErrorCode::EXCEPTION_PARAMCHECK, "immersiveMode type must be ImmersiveMode and can not be IMMERSIVE"); return; } auto ret = inputMethodPanel_->SetImmersiveMode(immersiveMode); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("SetImmersiveMode failed!"); - set_business_error(JsUtils::Convert(ret), "SetImmersiveMode failed!"); + taihe::set_business_error(JsUtils::Convert(ret), "SetImmersiveMode failed!"); return; } IMSA_HILOGI("set Immersive mode success!"); @@ -260,13 +265,13 @@ void PanelImpl::SetPrivacyMode(bool isPrivacyMode) { if (inputMethodPanel_ == nullptr) { IMSA_HILOGE("panel is nullptr!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to set PrivacyMode, panel is nullptr!"); + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to set PrivacyMode, panel is nullptr!"); return; } auto ret = inputMethodPanel_->SetPrivacyMode(isPrivacyMode); if (ret == static_cast(WMError::WM_ERROR_INVALID_PERMISSION)) { IMSA_HILOGE("permission denied"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_STATUS_PERMISSION_DENIED), + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_STATUS_PERMISSION_DENIED), "ohos.permission.PRIVACY_WINDOW permission denied"); return; } else if (ret != ErrorCode::NO_ERROR) { @@ -280,17 +285,10 @@ void PanelImpl::ChangeFlag(PanelFlag_t flag) { if (inputMethodPanel_ == nullptr) { IMSA_HILOGE("panel is nullptr!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to ChangeFlag, panel is nullptr!"); - return; - } - PanelFlag panelFlag = static_cast(flag.get_value()); - if (panelFlag != PanelFlag::FLG_FIXED || - panelFlag != PanelFlag::FLG_FLOATING || - panelFlag != PanelFlag::FLG_CANDIDATE_COLUMN) { - IMSA_HILOGE("invaild panelFlag!"); - set_business_error(IMFErrorCode::EXCEPTION_PARAMCHECK, "flag type must be one of PanelFlag!"); + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to ChangeFlag, panel is nullptr!"); return; } + auto panelFlag = static_cast(flag.get_value()); auto ret = inputMethodPanel_->ChangePanelFlag(panelFlag); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to ChangePanelFlag!"); @@ -303,13 +301,13 @@ void PanelImpl::MoveToAsync(int32_t x, int32_t y) { if (inputMethodPanel_ == nullptr) { IMSA_HILOGE("panel is nullptr!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to MoveTo, panel is nullptr!"); + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to MoveTo, panel is nullptr!"); return; } auto code = inputMethodPanel_->MoveTo(x, y); if (code == ErrorCode::ERROR_PARAMETER_CHECK_FAILED) { IMSA_HILOGE("moveTo failed!"); - set_business_error(JsUtils::Convert(code), "failed to moveTo!"); + taihe::set_business_error(JsUtils::Convert(code), "failed to moveTo!"); return; } IMSA_HILOGI("moveTo success!"); @@ -319,13 +317,13 @@ void PanelImpl::ResizeAsync(uint32_t width, uint32_t height) { if (inputMethodPanel_ == nullptr) { IMSA_HILOGE("panel is nullptr!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to Resize, panel is nullptr!"); + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to Resize, panel is nullptr!"); return; } auto code = inputMethodPanel_->Resize(width, height); if (code != ErrorCode::NO_ERROR) { IMSA_HILOGE("Resize failed!"); - set_business_error(JsUtils::Convert(code), "failed to Resize!"); + taihe::set_business_error(JsUtils::Convert(code), "failed to Resize!"); return; } IMSA_HILOGE("Resize success!"); @@ -335,20 +333,21 @@ void PanelImpl::SetUiContentAsync(taihe::string_view path) { if (inputMethodPanel_ == nullptr) { IMSA_HILOGE("panel is nullptr!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to SetUiContent, panel is nullptr!"); + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to SetUiContent, panel is nullptr!"); return; } // env 类型有问题 lmq 方案 - ani_env *env = taihe::get_env(); - std::string contentInfo = std::string(path); - auto code = inputMethodPanel_->SetUiContent(contentInfo, env, nullptr); + // ani_env *env = taihe::get_env(); + // std::string contentInfo = std::string(path); + int32_t code = ErrorCode::NO_ERROR; + // auto code = inputMethodPanel_->SetUiContent(contentInfo, env, nullptr); if (code == ErrorCode::ERROR_PARAMETER_CHECK_FAILED) { IMSA_HILOGE("path should be a path to specific page."); - set_business_error(JsUtils::Convert(code), "path should be a path to specific page."); + taihe::set_business_error(JsUtils::Convert(code), "path should be a path to specific page."); return; } else if (code != ErrorCode::NO_ERROR) { IMSA_HILOGE("SetUiContent failed!"); - set_business_error(JsUtils::Convert(code), "SetUiContent failed!"); + taihe::set_business_error(JsUtils::Convert(code), "SetUiContent failed!"); return; } IMSA_HILOGI("SetUiContent success!"); @@ -356,16 +355,15 @@ void PanelImpl::SetUiContentAsync(taihe::string_view path) void PanelImpl::HideAsync() { - InputMethodSyncTrace tracer("Hide"); if (inputMethodPanel_ == nullptr) { IMSA_HILOGE("panel is nullptr!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to Hide, panel is nullptr!"); + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to Hide, panel is nullptr!"); return; } auto code = InputMethodAbility::GetInstance().HidePanel(inputMethodPanel_); if (code != ErrorCode::NO_ERROR) { IMSA_HILOGE("Hide failed!"); - set_business_error(JsUtils::Convert(code), "Hide failed!"); + taihe::set_business_error(JsUtils::Convert(code), "Hide failed!"); return; } IMSA_HILOGI("Hide success!"); @@ -373,16 +371,15 @@ void PanelImpl::HideAsync() void PanelImpl::ShowAsync() { - InputMethodSyncTrace tracer("Show"); if (inputMethodPanel_ == nullptr) { IMSA_HILOGE("panel is nullptr!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to Show, panel is nullptr!"); + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_IME), "failed to Show, panel is nullptr!"); return; } auto code = InputMethodAbility::GetInstance().ShowPanel(inputMethodPanel_); if (code != ErrorCode::NO_ERROR) { IMSA_HILOGE("Show failed!"); - set_business_error(JsUtils::Convert(code), "Show failed!"); + taihe::set_business_error(JsUtils::Convert(code), "Show failed!"); return; } IMSA_HILOGI("Show success!"); @@ -398,7 +395,7 @@ void PanelImpl::RegisterListener(std::string const &type, callbackTypes &&cb, ui IMSA_HILOGD("RegisterListener type: %{public}s.", type.c_str()); if (type == "sizeUpdate") { if (!InputMethodAbility::GetInstance().IsSystemApp()) { - set_business_error(IMFErrorCode::EXCEPTION_SYSTEM_PERMISSION, "not system application.") + taihe::set_business_error(IMFErrorCode::EXCEPTION_SYSTEM_PERMISSION, "not system application."); return; } } @@ -406,12 +403,12 @@ void PanelImpl::RegisterListener(std::string const &type, callbackTypes &&cb, ui IMSA_HILOGE("inputMethodPanel is nullptr!"); return; } - std::shared_ptr observer = PanelListener::GetInstance(); - observer->Subscribe(inputMethodPanel_->windowId_, type, cb, opq); + std::shared_ptr observer = InputMethodPanelListener::GetInstance(); + observer->Subscribe(inputMethodPanel_->windowId_, type, std::forward(cb), opq); bool ret = inputMethodPanel_->SetPanelStatusListener(observer, type); if (!ret) { IMSA_HILOGE("failed to subscribe %{public}s!", type.c_str()); - observer->RemoveInfo(type, inputMethodPanel_->windowId_); + observer->RemoveInfo(inputMethodPanel_->windowId_, type); return; } } @@ -425,7 +422,7 @@ void PanelImpl::UnRegisterListener(std::string const &type, taihe::optional_view IMSA_HILOGD("RegisterListener type: %{public}s.", type.c_str()); if (type == "sizeUpdate") { if (!InputMethodAbility::GetInstance().IsSystemApp()) { - set_business_error(IMFErrorCode::EXCEPTION_SYSTEM_PERMISSION, "not system application.") + taihe::set_business_error(IMFErrorCode::EXCEPTION_SYSTEM_PERMISSION, "not system application."); return; } } @@ -433,8 +430,8 @@ void PanelImpl::UnRegisterListener(std::string const &type, taihe::optional_view IMSA_HILOGE("inputMethodPanel is nullptr!"); return; } - std::shared_ptr observer = PanelListener::GetInstance(); - observer->RemoveInfo(inputMethodPanel_->windowId_, type, cb, opq); + std::shared_ptr observer = InputMethodPanelListener::GetInstance(); + observer->RemoveInfo(inputMethodPanel_->windowId_, type); inputMethodPanel_->ClearPanelListener(type); } } // namespace MiscServices diff --git a/frameworks/ets/taihe/inputMethod/src/input_method_panel_listener.cpp b/frameworks/ets/taihe/inputMethod/src/input_method_panel_listener.cpp index 4f026d187..0373b0a1e 100644 --- a/frameworks/ets/taihe/inputMethod/src/input_method_panel_listener.cpp +++ b/frameworks/ets/taihe/inputMethod/src/input_method_panel_listener.cpp @@ -19,14 +19,14 @@ namespace OHOS { namespace MiscServices { std::mutex InputMethodPanelListener::listenerMutex_; -std::shared_ptr InputMethodPanelListener::instance_{ nullptr }; +std::shared_ptr InputMethodPanelListener::instance_{ nullptr }; -std::shared_ptr InputMethodPanelListener::GetInstance() +std::shared_ptr InputMethodPanelListener::GetInstance() { if (instance_ == nullptr) { std::lock_guard lock(listenerMutex_); if (instance_ == nullptr) { - instance_ = std::make_shared(); + instance_ = std::make_shared(); } } return instance_; @@ -45,7 +45,7 @@ void InputMethodPanelListener::Subscribe(uint32_t windowId, const std::string &t return; } // 1 : n : n -> 1: n(1: 1)[] - auto subscriptionAction = [&type](uint32_t windowId, + auto subscriptionAction = [&type, &env, &callbackRef, &cb](uint32_t windowId, std::map> &cbs) -> bool { if (cbs.find(type) != cbs.end()) { env->GlobalReference_Delete(callbackRef); @@ -67,7 +67,7 @@ void InputMethodPanelListener::Subscribe(uint32_t windowId, const std::string &t jsCbMap_.Compute(windowId, subscriptionAction); } -void InputMethodPanelListener::RemoveInfo(const std::string &type, uint32_t windowId, taihe::optional_view opq) +void InputMethodPanelListener::RemoveInfo(uint32_t windowId, const std::string &type) { std::lock_guard lock(mutex_); jsCbMap_.ComputeIfPresent(windowId, @@ -77,29 +77,46 @@ void InputMethodPanelListener::RemoveInfo(const std::string &type, uint32_t wind }); } +std::unique_ptr InputMethodPanelListener::GetCallback(uint32_t windowId, const std::string &type) +{ + std::unique_ptr callBack = nullptr; + jsCbMap_.ComputeIfPresent(windowId, + [&type, &callBack](auto windowId, std::map> &cbs) { + auto it = cbs.find(type); + if (it == cbs.end()) { + return !cbs.empty(); + } + callBack = std::move(it->second); + return !cbs.empty(); + }); + return callBack; +} + void InputMethodPanelListener::OnPanelStatus(uint32_t windowId, bool isShow) { std::string type = isShow ? "show" : "hide"; std::lock_guard lock(mutex_); - auto &cbVec = jsCbMap_[windowId]; - for (auto &cb : cbVec) { - auto cbObj = cb[type]; - auto &func = std::get>(cbObj->callback); - func(); + auto cbVec = GetCallback(windowId, type); + if (cbVec == nullptr) { + IMSA_HILOGE("callBack is nullptr!"); + return; } + auto &func = std::get>(cbVec->callback); + func(); } void InputMethodPanelListener::OnSizeChange(uint32_t windowId, const WindowSize &size) { std::string type = "sizeChange"; std::lock_guard lock(mutex_); - auto &cbVec = jsCbMap_[windowId]; - for (auto &cb : cbVec) { - auto cbObj = cb[type]; - auto &func = std::get)>>(cbObj->callback); - // WindowSize -> uintptr_t(taihe window.size) 、keyboardArea(空) - func(); + auto cbVec = GetCallback(windowId, type); + if (cbVec == nullptr) { + IMSA_HILOGE("callBack is nullptr!"); + return; } + auto &func = std::get)>>(cbVec->callback); + // WindowSize -> uintptr_t 、PanelAdjustInfo -> KeyboardArea_t + //func(); } void InputMethodPanelListener::OnSizeChange(uint32_t windowId, const WindowSize &size, @@ -107,13 +124,20 @@ void InputMethodPanelListener::OnSizeChange(uint32_t windowId, const WindowSize { std::string type = "sizeUpdate"; std::lock_guard lock(mutex_); - auto &cbVec = jsCbMap_[windowId]; - for (auto &cb : cbVec) { - auto cbObj = cb[type]; - auto &func = std::get>(cbObj->callback); - // WindowSize -> uintptr_t 、PanelAdjustInfo -> KeyboardArea_t - func(); + auto cbVec = GetCallback(windowId, type); + if (cbVec == nullptr) { + IMSA_HILOGE("callBack is nullptr!"); + return; } + auto &func = std::get>(cbVec->callback); + // WindowSize -> uintptr_t 、PanelAdjustInfo -> KeyboardArea_t + // func(); +} + +void InputMethodPanelListener::SetEventHandler(std::shared_ptr handler) +{ + std::unique_lock lock(eventHandlerMutex_); + handler_ = handler; } } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/taihe/inputMethod/src/ohos.inputMethodEngine.impl.cpp b/frameworks/ets/taihe/inputMethod/src/ohos.inputMethodEngine.impl.cpp index ed35c099b..d9752b9e7 100644 --- a/frameworks/ets/taihe/inputMethod/src/ohos.inputMethodEngine.impl.cpp +++ b/frameworks/ets/taihe/inputMethod/src/ohos.inputMethodEngine.impl.cpp @@ -3,11 +3,15 @@ #include "taihe/runtime.hpp" #include "stdexcept" +#include "ani_common_engine.h" #include "panel_info.h" #include "input_attribute.h" #include "input_method_utils.h" +#include "input_method_ability.h" #include "js_utils.h" -#include "inputmethod_trace.h" +#include "input_method_panel_impl.h" +#include "input_method_ability_impl.h" +#include "input_method_keyboard_delegate_impl.h" using namespace OHOS::MiscServices; namespace { @@ -66,30 +70,39 @@ public: taihe::string GetBackwardAsync(int32_t length) { + taihe::string result = ""; + return result; } taihe::string GetForwardAsync(int32_t length) { + taihe::string result = ""; + return result; } bool InsertTextAsync(taihe::string_view text) { + return false; } bool DeleteBackwardAsync(int32_t length) { + return false; } bool DeleteForwardAsync(int32_t length) { + return false; } bool SendKeyFunctionAsync(int32_t action) { + return false; } int32_t GetTextIndexAtCursorAsync() { + return 0; } EditorAttribute_t GetEditorAttributeAsync() @@ -103,7 +116,7 @@ public: config.inputAttribute.isTextPreviewSupported); } else { IMSA_HILOGE("failed to get text config: %{public}d!", ret); - set_business_error(IMFErrorCode::EXCEPTION_IMCLIENT, "failed to get text config!"); + taihe::set_business_error(IMFErrorCode::EXCEPTION_IMCLIENT, "failed to get text config!"); return result; } result = CommonConvert::NativeAttributeToAni(config.inputAttribute); @@ -117,21 +130,21 @@ public: arrayBuffer.jsArgc = 1; if (msgParam.has_value()) { arrayBuffer.jsArgc = 2; + arrayBuffer.msgParam.resize(msgParam.value().size()); auto const &value = msgParam.value(); - arrayBuffer.msgParam(value.size()); for (size_t i = 0; i < value.size(); ++i) { arrayBuffer.msgParam[i] = value[i]; } } if (!ArrayBuffer::IsSizeValid(arrayBuffer)) { IMSA_HILOGE("msgId limit 256B and msgParam limit 128KB."); - set_business_error(IMFErrorCode::EXCEPTION_PARAMCHECK, "msgId limit 256B and msgParam limit 128KB."); + taihe::set_business_error(IMFErrorCode::EXCEPTION_PARAMCHECK, "msgId limit 256B and msgParam limit 128KB."); return; } int32_t ret = InputMethodAbility::GetInstance().SendMessage(arrayBuffer); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to get text config: %{public}d!", ret); - set_business_error(IMFErrorCode::EXCEPTION_IMCLIENT, "failed to get text config!"); + taihe::set_business_error(IMFErrorCode::EXCEPTION_IMCLIENT, "failed to get text config!"); } } @@ -139,13 +152,14 @@ public: { if (msgHandler.has_value()) { IMSA_HILOGI("RecvMessage on."); - ani_env *env = get_env(); - std::shared_ptr()>taiheCallbackOnTerminated = std::make_shared()>(msgHandler.OnTerminated); - std::shared_ptr onTerminatedCB = std::reinterpret_pointer_cast(taiheCallbackOnTerminated); - std::shared_ptr()>taiheCallbackOnMessage = std::make_shared()>(msgHandler.onMessage); - std::shared_ptr onMessageCB = std::reinterpret_pointer_cast(taiheCallbackOnMessage); - std::shared_ptr callback = std::make_shared(env, onTerminatedCB, onMessageCB); - InputMethodAbility::GetInstance().RegisterMsgHandler(callback); + // + // ani_env *env = taihe::get_env(); + // std::shared_ptr()>taiheCallbackOnTerminated = std::make_shared()>(msgHandler.OnTerminated); + // std::shared_ptr onTerminatedCB = std::reinterpret_pointer_cast(taiheCallbackOnTerminated); + // std::shared_ptr()>taiheCallbackOnMessage = std::make_shared()>(msgHandler.onMessage); + // std::shared_ptr onMessageCB = std::reinterpret_pointer_cast(taiheCallbackOnMessage); + // std::shared_ptr callback = std::make_shared(env, onTerminatedCB, onMessageCB); + //InputMethodAbility::GetInstance().RegisterMsgHandler(callback); } else { IMSA_HILOGI("RecvMessage off."); InputMethodAbility::GetInstance().RegisterMsgHandler(); @@ -158,11 +172,10 @@ public: void FinishTextPreviewSync() { - InputMethodSyncTrace tracer("Taihe_FinishTextPreviewSync", GenerateTraceId()); IMSA_HILOGD("Taihe TextInputClientEngine in"); int32_t ret = InputMethodAbility::GetInstance().FinishTextPreview(); if (ret != ErrorCode::NO_ERROR) { - set_business_error(JsUtils::Convert(ret), "failed to finish text preview!"); + taihe::set_business_error(JsUtils::Convert(ret), "failed to finish text preview!"); } } @@ -173,7 +186,7 @@ public: int32_t ret = InputMethodAbility::GetInstance().GetCallingWindowInfo(windowInfo); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGI("GetCallingWindowInfo failed."); - set_business_error(JsUtils::Convert(ret), "GetCallingWindowInfo failed."); + taihe::set_business_error(JsUtils::Convert(ret), "GetCallingWindowInfo failed."); return result; } // windowInfo -> ohos::inputMethodEngine::WindowInfo; @@ -182,16 +195,16 @@ public: void SendPrivateCommandAsync(taihe::map_view commandData) { - ValueMap privateCommand = AniConvertPCommandToNative(commandData); + ValueMap privateCommand = CommonConvert::AniConvertPCommandToNative(commandData); if (!TextConfig::IsPrivateCommandValid(privateCommand)) { IMSA_HILOGE("privateCommand invaild."); - set_business_error(IMFErrorCode::EXCEPTION_PARAMCHECK, "commandData size limit 32KB, count limit 5."); + taihe::set_business_error(IMFErrorCode::EXCEPTION_PARAMCHECK, "commandData size limit 32KB, count limit 5."); return; } int32_t ret = InputMethodAbility::GetInstance().SendPrivateCommand(privateCommand); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("SendPrivateCommand failed."); - set_business_error(JsUtils::Convert(ret), "SendPrivateCommand failed."); + taihe::set_business_error(JsUtils::Convert(ret), "SendPrivateCommand failed."); return; } IMSA_HILOGI("SendPrivateCommand success."); @@ -224,7 +237,7 @@ public: int32_t ret = InputMethodAbility::GetInstance().SelectByMovement(direction); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGI("failed to select by movement!"); - set_business_error(JsUtils::Convert(ret), "failed to select by movement!"); + taihe::set_business_error(JsUtils::Convert(ret), "failed to select by movement!"); } } @@ -237,7 +250,7 @@ public: int32_t ret = InputMethodAbility::GetInstance().SelectByRange(tmpRange.start, tmpRange.end); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGI("failed to select by range!"); - set_business_error(JsUtils::Convert(ret), "failed to select by range!"); + taihe::set_business_error(JsUtils::Convert(ret), "failed to select by range!"); } } @@ -245,7 +258,7 @@ public: { if (direction < 0) { IMSA_HILOGE("direction should be no less than 0!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_PARAMETER_CHECK_FAILED), + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_PARAMETER_CHECK_FAILED), "direction should be no less than 0!"); return; } @@ -253,63 +266,61 @@ public: int32_t ret = InputMethodAbility::GetInstance().MoveCursor(direction); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGI("failed to move cursor!"); - set_business_error(JsUtils::Convert(ret), "failed to move cursor!"); + taihe::set_business_error(JsUtils::Convert(ret), "failed to move cursor!"); } } taihe::string GetBackwardSync(int32_t length) { + taihe::string result = ""; if (length < 0) { IMSA_HILOGE("length should be no less than 0!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_PARAMETER_CHECK_FAILED), + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_PARAMETER_CHECK_FAILED), "length should be no less than 0!"); - return; + return result; } IMSA_HILOGD("get backward, length: %{public}d.", length); std::u16string text; - taihe::string result; int32_t ret = InputMethodAbility::GetInstance().GetTextAfterCursor(length, text); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to get backward!"); - set_business_error(JsUtils::Convert(ret), "failed to get backward!"); + taihe::set_business_error(JsUtils::Convert(ret), "failed to get backward!"); return result; } IMSA_HILOGI("get backward success!"); - result = std::string(Str16ToStr8(text)); + result = std::string(OHOS::Str16ToStr8(text)); return result; } taihe::string GetForwardSync(int32_t length) { - InputMethodSyncTrace tracer("GetForwardSync", GenerateTraceId()); + taihe::string result = ""; if (length < 0) { IMSA_HILOGE("length should be no less than 0!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_PARAMETER_CHECK_FAILED), + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_PARAMETER_CHECK_FAILED), "length should be no less than 0!"); - return; + return result; } IMSA_HILOGD("get forward, length: %{public}d.", length); std::u16string text; - taihe::string result; int32_t ret = InputMethodAbility::GetInstance().GetTextBeforeCursor(length, text); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to get forward!"); - set_business_error(JsUtils::Convert(ret), "failed to get forward!"); + taihe::set_business_error(JsUtils::Convert(ret), "failed to get forward!"); return result; } IMSA_HILOGI("get forward success!"); - result = std::string(Str16ToStr8(text)); + result = std::string(OHOS::Str16ToStr8(text)); return result; } void InsertTextSync(taihe::string_view text) { - InputMethodSyncTrace tracer("InsertTextSync", GenerateTraceId()); std::string tmpText = std::string(text); int32_t ret = InputMethodAbility::GetInstance().InsertText(tmpText); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to insert text!"); - set_business_error(JsUtils::Convert(ret), "failed to insert text!"); + taihe::set_business_error(JsUtils::Convert(ret), "failed to insert text!"); } IMSA_HILOGI("insert text success!"); } @@ -318,7 +329,7 @@ public: { if (length < 0) { IMSA_HILOGE("length should be no less than 0!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_PARAMETER_CHECK_FAILED), + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_PARAMETER_CHECK_FAILED), "length should be no less than 0!"); return; } @@ -326,17 +337,16 @@ public: int32_t ret = InputMethodAbility::GetInstance().DeleteBackward(length); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to delete backward"); - set_business_error(JsUtils::Convert(ret), "failed to delete backward"); + taihe::set_business_error(JsUtils::Convert(ret), "failed to delete backward"); } IMSA_HILOGI("delete backward success!"); } void DeleteForwardSync(int32_t length) { - InputMethodSyncTrace tracer("DeleteForwardSync", GenerateTraceId()); if (length < 0) { IMSA_HILOGE("length should be no less than 0!"); - set_business_error(JsUtils::Convert(ErrorCode::ERROR_PARAMETER_CHECK_FAILED), + taihe::set_business_error(JsUtils::Convert(ErrorCode::ERROR_PARAMETER_CHECK_FAILED), "length should be no less than 0!"); return; } @@ -344,7 +354,7 @@ public: int32_t ret = InputMethodAbility::GetInstance().DeleteForward(length); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to delete forward"); - set_business_error(JsUtils::Convert(ret), "failed to delete forward"); + taihe::set_business_error(JsUtils::Convert(ret), "failed to delete forward"); } IMSA_HILOGI("delete forward success!"); } @@ -356,14 +366,14 @@ public: int32_t ret = InputMethodAbility::GetInstance().GetTextConfig(config); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to get text config: %{public}d!", ret); - set_business_error(IMFErrorCode::EXCEPTION_IMCLIENT, "failed to get text config!"); + taihe::set_business_error(IMFErrorCode::EXCEPTION_IMCLIENT, "failed to get text config!"); return result; } IMSA_HILOGD("inputPattern: %{public}d, enterKeyType: %{public}d, isTextPreviewSupported: %{public}d.", config.inputAttribute.inputPattern, config.inputAttribute.enterKeyType, config.inputAttribute.isTextPreviewSupported); IMSA_HILOGI("get editor attribute success!"); - result = NativeAttributeToAni(config.inputAttribute); + result = CommonConvert::NativeAttributeToAni(config.inputAttribute); return result; } @@ -373,9 +383,8 @@ public: int32_t index = 0; int32_t ret = InputMethodAbility::GetInstance().GetTextIndexAtCursor(index); if (ret != ErrorCode::NO_ERROR) { - JsUtils::ThrowException(env, JsUtils::Convert(ret), "failed to get text index at cursor!", TYPE_NONE); IMSA_HILOGE("failed to get text index at cursor: %{public}d!", ret); - set_business_error(JsUtils::Convert(ret), "failed to get text index at cursor!"); + taihe::set_business_error(JsUtils::Convert(ret), "failed to get text index at cursor!"); return index; } IMSA_HILOGI("get text index at cursor success"); @@ -395,7 +404,7 @@ class KeyboardControllerImpl { int32_t ret = InputMethodAbility::GetInstance().HideKeyboardSelf(); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to hide keyboard self: %{public}d!", ret); - set_business_error(JsUtils::Convert(ret), "failed to hide keyboard self!"); + taihe::set_business_error(JsUtils::Convert(ret), "failed to hide keyboard self!"); return; } } @@ -405,7 +414,7 @@ class KeyboardControllerImpl { int32_t ret = InputMethodAbility::GetInstance().ExitCurrentInputType(); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to exit current input type: %{public}d!", ret); - set_business_error(JsUtils::Convert(ret), "failed to exit current input type!"); + taihe::set_business_error(JsUtils::Convert(ret), "failed to exit current input type!"); return; } } -- Gitee From 224a67732ed3fe939470548ada82c7f6a0c0b299 Mon Sep 17 00:00:00 2001 From: KangPeng Date: Tue, 9 Sep 2025 14:21:47 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E5=88=A0=E9=99=A4=E9=94=99=E8=AF=AFani?= =?UTF-8?q?=E5=A4=B4=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: KangPeng --- frameworks/ets/taihe/inputMethod/src/ani_constructor.cpp | 1 - .../ets/taihe/inputMethod/src/ohos.inputMethodEngine.impl.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/frameworks/ets/taihe/inputMethod/src/ani_constructor.cpp b/frameworks/ets/taihe/inputMethod/src/ani_constructor.cpp index 10962456d..11ae92c08 100644 --- a/frameworks/ets/taihe/inputMethod/src/ani_constructor.cpp +++ b/frameworks/ets/taihe/inputMethod/src/ani_constructor.cpp @@ -19,7 +19,6 @@ #include "ohos.inputMethod.ani.hpp" #include "ohos.multimodalInput.keyCode.ani.hpp" #include "ohos.multimodalInput.inputEvent.ani.hpp" -#include "taihe.platform.ani.ani.hpp" #include "ohos.inputMethodEngine.ani.hpp" #if __has_include() #include diff --git a/frameworks/ets/taihe/inputMethod/src/ohos.inputMethodEngine.impl.cpp b/frameworks/ets/taihe/inputMethod/src/ohos.inputMethodEngine.impl.cpp index d9752b9e7..a161a75a7 100644 --- a/frameworks/ets/taihe/inputMethod/src/ohos.inputMethodEngine.impl.cpp +++ b/frameworks/ets/taihe/inputMethod/src/ohos.inputMethodEngine.impl.cpp @@ -152,7 +152,7 @@ public: { if (msgHandler.has_value()) { IMSA_HILOGI("RecvMessage on."); - // + // 有问题 // ani_env *env = taihe::get_env(); // std::shared_ptr()>taiheCallbackOnTerminated = std::make_shared()>(msgHandler.OnTerminated); // std::shared_ptr onTerminatedCB = std::reinterpret_pointer_cast(taiheCallbackOnTerminated); -- Gitee