diff --git a/shell/platform/ohos/BUILD.gn b/shell/platform/ohos/BUILD.gn index 689f5015c2a163805cc04cd776451815973c7ac3..c8e36f5796a88e0230a7095e12d56d603d38c046 100644 --- a/shell/platform/ohos/BUILD.gn +++ b/shell/platform/ohos/BUILD.gn @@ -84,6 +84,7 @@ source_set("flutter_ohos_sources") { "ohos_surface_gl_skia.h", "types.h", "ohos_logging.h", + "./accessibility/ohos_accessibility_features.h", ] #configs += [ "//flutter/shell/platform/ohos/config:gtk" ] @@ -114,6 +115,7 @@ source_set("flutter_ohos_sources") { "ohos_image_generator.cpp", "ohos_external_texture_gl.cpp", "./surface/ohos_snapshot_surface_producer.cpp", + "./accessibility/ohos_accessibility_features.cpp", ] # Set flag to stop headers being directly included (library users should not do this) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_features.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_features.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6953998fe39973bcde04d3c9f1f9a9d1539d0f40 --- /dev/null +++ b/shell/platform/ohos/accessibility/ohos_accessibility_features.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development 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 "flutter/shell/platform/ohos/accessibility/ohos_accessibility_features.h" +#include "flutter/shell/platform/ohos/ohos_shell_holder.h" +#include "flutter/fml/logging.h" + +namespace flutter { + + OhosAccessibilityFeatures OhosAccessibilityFeatures::instance; + + OhosAccessibilityFeatures::OhosAccessibilityFeatures() {}; + OhosAccessibilityFeatures::~OhosAccessibilityFeatures() {}; + + OhosAccessibilityFeatures* OhosAccessibilityFeatures::GetInstance() { + return &OhosAccessibilityFeatures::instance; + } + + /** + * bold text for AccessibilityFeature + */ + void OhosAccessibilityFeatures::SetBoldText(double fontWeightScale, int64_t shell_holder_id) { + bool shouldBold = fontWeightScale > 1.0; + + if (shouldBold) { + accessibilityFeatureFlags |= static_cast(flutter::AccessibilityFeatureFlag::kBoldText); + FML_DLOG(INFO) << "SetBoldText -> accessibilityFeatureFlags: "<(flutter::AccessibilityFeatureFlag::kBoldText); + } + + SendAccessibilityFlags(shell_holder_id); + } + + /** + * send the accessibility flags to flutter dart sdk + */ + void OhosAccessibilityFeatures::SendAccessibilityFlags(int64_t shell_holder_id) { + auto ohos_shell_holder = reinterpret_cast(shell_holder_id); + ohos_shell_holder->GetPlatformView()->PlatformView::SetAccessibilityFeatures(accessibilityFeatureFlags); + FML_DLOG(INFO) << "SendAccessibilityFlags -> accessibilityFeatureFlags = " + << accessibilityFeatureFlags; + // set accessibility feature flag to 0 + accessibilityFeatureFlags = 0; + } + +} \ No newline at end of file diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_features.h b/shell/platform/ohos/accessibility/ohos_accessibility_features.h new file mode 100644 index 0000000000000000000000000000000000000000..b6abf906b0166c9115ea3932ea239afe8c1bee52 --- /dev/null +++ b/shell/platform/ohos/accessibility/ohos_accessibility_features.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development 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 OHOS_ACCESSIBILITY_FEATURES_H +#define OHOS_ACCESSIBILITY_FEATURES_H +#include +#include "flutter/lib/ui/window/platform_configuration.h" +#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" + +namespace flutter { + +class OhosAccessibilityFeatures { + public: + OhosAccessibilityFeatures(); + ~OhosAccessibilityFeatures(); + + static OhosAccessibilityFeatures* GetInstance(); + + void SetBoldText(double fontWeightScale, int64_t shell_holder_id); + void SendAccessibilityFlags(int64_t shell_holder_id); + + private: + static OhosAccessibilityFeatures instance; + + // Font weight adjustment (FontWeight.Bold - FontWeight.Normal = w700 - w400 = 300) + static const int32_t BOLD_TEXT_WEIGHT_ADJUSTMENT = 300; + int32_t accessibilityFeatureFlags = 0; +}; + +} +#endif \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets index 53a5eabeca7ef8c0b205a413100d8693733f1c4a..be366b7cb7029b1208a0a17abb6f04a023cb8126 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets @@ -17,6 +17,7 @@ import common from '@ohos.app.ability.common'; import resourceManager from '@ohos.resourceManager'; import image from '@ohos.multimedia.image'; import FlutterNapi from '../../../ets/embedding/engine/FlutterNapi'; +import { ByteBuffer } from '../../../ets/util/ByteBuffer'; import { FlutterCallbackInformation } from '../../../ets/view/FlutterCallbackInformation'; export const getContext: (a: number) => napiContext; @@ -110,6 +111,12 @@ export const nativeXComponentDispatchMouseWheel: (nativeShellHolderId: number, timestamp: number ) => void; + +// send updateSemantics and updateCustomAccessibilityActions from ets to c++ +export const nativeUpdateSemantics: (buffer: ByteBuffer, strings: string[], stringAttributeArgs: ByteBuffer[]) => void; +export const nativeUpdateCustomAccessibilityActions: (buffer: ByteBuffer, strings: string[]) => void; + + /** * Detaches flutterNapi和engine之间的关联 * 这个方法执行前提是flutterNapi已经和engine关联 @@ -134,4 +141,29 @@ export const nativeDecodeUtf8: (array: Uint8Array) => string; export const nativeSetTextureBufferSize: (nativeShellHolderId: number, textureId: number, width: number, height: number) => void; -export const nativeLookupCallbackInformation: (callback: FlutterCallbackInformation, handler: number) => number; \ No newline at end of file +/** + * accessibiltyChannel中的 + */ +export const nativeSetAccessibilityFeatures: (accessibilityFeatureFlags: number, responseId: number) => void; + +export const nativeAccessibilityStateChange: (state: Boolean) => void; + +export const nativeAnnounce: (message: string) => void; + +export const nativeSetSemanticsEnabled: (nativeShellHolderId: number, enabled: boolean) => void; + +export const nativeSetFontWeightScale: (nativeShellHolderId: number, fontWeightScale: number) => void; + +export const nativeGetShellHolderId: (nativeShellHolderId: number) => void; + +export const nativeLookupCallbackInformation: (callback: FlutterCallbackInformation, handler: number) => number; + +export const nativeUnicodeIsEmoji: (code: number) => number; + +export const nativeUnicodeIsEmojiModifier: (code: number) => number; + +export const nativeUnicodeIsEmojiModifierBase: (code: number) => number; + +export const nativeUnicodeIsVariationSelector: (code: number) => number; + +export const nativeUnicodeIsRegionalIndicatorSymbol: (code: number) => number; \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets index 78f1a520e7ec6efbc792f1164c8933dafc439d6d..9be47241dc8c077a9e8a39e9fc35869cf54486b2 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets @@ -22,7 +22,7 @@ import { FlutterCallbackInformation } from '../../view/FlutterCallbackInformatio import image from '@ohos.multimedia.image'; import { EngineLifecycleListener } from './FlutterEngine'; import { ByteBuffer } from '../../util/ByteBuffer'; -import { Action } from '../../view/AccessibilityBridge' +import { AccessibilityManager, Action } from '../../view/AccessibilityBridge' import LocalizationPlugin from '../../plugin/localization/LocalizationPlugin'; import i18n from '@ohos.i18n'; import Any from '../../plugin/common/Any'; @@ -54,6 +54,9 @@ export default class FlutterNapi { localizationPlugin: LocalizationPlugin | null = null; isDisplayingFlutterUi: boolean = false; + accessibilityManager: AccessibilityManager | null = null; + + /** * 更新刷新率 * @param rate @@ -502,6 +505,43 @@ export default class FlutterNapi { } } + getShellHolderId(): void { + this.ensureRunningOnMainThread(); + if (this.isAttached()) { + flutter.nativeGetShellHolderId(this.nativeShellHolderId!); + } + } + + setFontWeightScale(fontWeightScale: number): void { + this.ensureRunningOnMainThread(); + if (this.isAttached()) { + Log.i(TAG, "setFontWeightScale: " + fontWeightScale); + flutter.nativeSetFontWeightScale(this.nativeShellHolderId!, fontWeightScale); + } else { + Log.w(TAG, "setFontWeightScale is detached !"); + } + } + + static unicodeIsEmoji(code: number): boolean { + return Boolean(flutter.nativeUnicodeIsEmoji(code)); + } + + static unicodeIsEmojiModifier(code: number): boolean { + return Boolean(flutter.nativeUnicodeIsEmojiModifier(code)); + } + + static unicodeIsEmojiModifierBase(code: number): boolean { + return Boolean(flutter.nativeUnicodeIsEmojiModifierBase(code)); + } + + static unicodeIsVariationSelector(code: number): boolean { + return Boolean(flutter.nativeUnicodeIsVariationSelector(code)); + } + + static unicodeIsRegionalIndicatorSymbol(code: number): boolean { + return Boolean(flutter.nativeUnicodeIsRegionalIndicatorSymbol(code)); + } + } export interface AccessibilityDelegate { diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets index 8ba4463178e5737bd4e4e4d4f27aa6457c67ef83..4013fed1897c82c3aa82c1b8480ff80873f29af0 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets @@ -36,6 +36,7 @@ import appRecovery from '@ohos.app.ability.appRecovery'; import FlutterManager from './FlutterManager'; import { FlutterView } from '../../view/FlutterView'; import ApplicationInfoLoader from '../engine/loader/ApplicationInfoLoader'; +import { AccessibilityManager } from '../../view/AccessibilityBridge'; const TAG = "FlutterAbility"; const EVENT_BACK_PRESS = 'EVENT_BACK_PRESS'; @@ -51,6 +52,7 @@ export class FlutterAbility extends UIAbility implements Host { private flutterView: FlutterView | null = null; private mainWindow?: window.Window | null; private errorManagerId:number = 0; + private accessibilityManager?: AccessibilityManager | null; getFlutterView(): FlutterView | null { return this.flutterView; @@ -377,6 +379,10 @@ export class FlutterAbility extends UIAbility implements Host { .setTextScaleFactor(config.fontSizeScale == undefined? 1.0 : config.fontSizeScale) .send(); //热启动生命周期内,实时监听系统设置环境改变并实时发送相应信息 + //实时获取系统字体加粗系数 + this.delegate?.getFlutterNapi()?.setFontWeightScale(config.fontWeightScale == undefined? 0 : config.fontWeightScale); + Log.i(TAG, 'fontWeightScale: ' + JSON.stringify(config.fontWeightScale)); + if (config.language != '') { this.getFlutterEngine()?.getLocalizationPlugin()?.sendLocaleToFlutter(); } diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/ListenableEditingState.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/ListenableEditingState.ets index 837253925b36ccecde2d1c0b3c9beda366918781..351277019b2ba94b0b7cd759d33574c48b0b3198 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/ListenableEditingState.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/ListenableEditingState.ets @@ -19,6 +19,7 @@ import inputMethod from '@ohos.inputMethod'; import ArrayList from '@ohos.util.ArrayList'; import { TextEditingDelta } from './TextEditingDelta'; import TextInputChannel from '../../embedding/engine/systemchannels/TextInputChannel'; +import { FlutterTextUtils } from './TextUtils'; const TAG = "ListenableEditingState"; @@ -260,15 +261,13 @@ export class ListenableEditingState { if (start == 0 && end == 0) { return; } - let tbStart = start == end ? start - 1 : start; - let tbEnd = start == end ? -1 : 0; - let crCode: number = this.mStringCache.charCodeAt(tbStart) - if ( 0xdc00 <= crCode && crCode <= 0xdffff ) { - tbStart = tbStart - 1 + let unicodeStart = start; + if (start == end) { + unicodeStart = FlutterTextUtils.getOffsetBefore(this.mStringCache, start); } - this.replace(tbStart, end, "", 0, tbEnd); - this.mSelectionStartCache = tbStart; - let tempStr: string = this.mStringCache.slice(0, tbStart) + this.mStringCache.slice(end); + this.replace(unicodeStart, end, "", 0, 0); + this.mSelectionStartCache = unicodeStart; + let tempStr: string = this.mStringCache.slice(0, unicodeStart) + this.mStringCache.slice(end); this.mStringCache = tempStr; this.mSelectionEndCache = this.mSelectionStartCache; } else if (leftOrRight == true) { @@ -276,14 +275,13 @@ export class ListenableEditingState { if (start == this.mStringCache.length) { return; } - let tbStart = start == end ? 1 : 0; - let crCode: number = this.mStringCache.charCodeAt(tbStart) - if ( 0xdc00 <= crCode && crCode <= 0xdffff ) { - tbStart = tbStart - 1 + let unicodeEnd = end; + if (start == end) { + unicodeEnd = FlutterTextUtils.getOffsetAfter(this.mStringCache, start); } - this.replace(start, end, "", tbStart, 0); + this.replace(start, unicodeEnd, "", 0, 0); this.mSelectionEndCache = start; - let tempStr: string = this.mStringCache.slice(0, start) + (end + 1 >= this.mStringCache.length ? "" : this.mStringCache.slice(end + 1)); + let tempStr: string = this.mStringCache.slice(0, start) + (unicodeEnd >= this.mStringCache.length ? "" : this.mStringCache.slice(unicodeEnd)); this.mStringCache = tempStr; this.mSelectionStartCache = this.mSelectionEndCache; } diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets index c499dacb3980aad684fed843d274e5aa4a8d9d6f..2d5c4ac2a3126a34a95acdfd54605be16dc2b005 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets @@ -17,17 +17,11 @@ import TextInputChannel, { Configuration, TextEditState, TextInputMethodHandler, - TextInputType } from '../../embedding/engine/systemchannels/TextInputChannel'; import inputMethod from '@ohos.inputMethod'; import Log from '../../util/Log'; import { EditingStateWatcher, ListenableEditingState } from './ListenableEditingState'; import Any from '../common/Any'; -import { window } from '@kit.ArkUI'; -import FlutterManager from '../../embedding/ohos/FlutterManager'; -import { IntentionCode } from '@ohos.multimodalInput.intentionCode'; -import {KeyCode} from '@kit.InputKit'; -import { BusinessError } from '@kit.BasicServicesKit'; /// 临时规避缺少newline对应枚举问题 const NEWLINE_KEY_TYPE: number = 8; @@ -85,9 +79,9 @@ class TextInputMethodHandlerImpl implements TextInputMethodHandler { private mRestartInputPending: boolean = false; private plugin: EditingStateWatcher | Any; private imcFlag: boolean = false; - private inputTypeNone: string = 'NONE' + private inputTypeNone: string = 'NONE'; private keyboardStatus: inputMethod.KeyboardStatus = inputMethod.KeyboardStatus.HIDE; - private inputAttribute: inputMethod.InputAttribute = { textInputType: 0, enterKeyType: 1 } + private inputAttribute: inputMethod.InputAttribute = { textInputType: 0, enterKeyType: 1 }; constructor(plugin: TextInputPlugin | Any) { this.textConfig = { @@ -153,19 +147,12 @@ class TextInputMethodHandlerImpl implements TextInputMethodHandler { if (!this.imcFlag) { this.listenKeyBoardEvent(); } - this.inputMethodController.showTextInput().then(() => { - Log.d(TextInputMethodHandlerImpl.TAG, "Succeeded in showing softKeyboard"); - }).catch((err: Any) => { - Log.e(TextInputMethodHandlerImpl.TAG, "Failed to show softKeyboard:" + JSON.stringify(err)); - }); } private async hideTextInput(): Promise { - this.inputMethodController.hideTextInput().then(() => { - Log.d(TextInputMethodHandlerImpl.TAG, "Succeeded in hide softKeyboard"); - }).catch((err: Any) => { - Log.e(TextInputMethodHandlerImpl.TAG, "Failed to hide softKeyboard:" + JSON.stringify(err)); - }) + this.inputMethodController.detach(); + this.keyboardStatus = inputMethod.KeyboardStatus.NONE; + this.cancelListenKeyBoardEvent(); } async attach(showKeyboard: boolean): Promise { @@ -177,7 +164,7 @@ class TextInputMethodHandlerImpl implements TextInputMethodHandler { } async updateAttribute(): Promise { - if (this.keyboardStatus == inputMethod.KeyboardStatus.HIDE) { + if (this.keyboardStatus != inputMethod.KeyboardStatus.SHOW) { return; } try { @@ -273,37 +260,12 @@ class TextInputMethodHandlerImpl implements TextInputMethodHandler { this.imcFlag = true; } - sendKeyboardEvent(type: KeyType, keyCode: number): void { - let event: KeyEvent = { - type: type, - keyCode: keyCode, - keyText: '', - keySource: KeySource.Keyboard, - deviceId: 0, - metaKey: 0, - timestamp: 0, - stopPropagation: (): void => { - throw new Error('Function not implemented.'); - }, - intentionCode: IntentionCode.INTENTION_BACK - } - FlutterManager.getInstance().getFlutterViewList().forEach((value) => { - value.onKeyEvent(event) - }) - } - private insertTextCallback = (text: string) => { Log.d(TextInputMethodHandlerImpl.TAG, "insertText: " + text); this.mEditable.handleInsertTextEvent(text); } private deleteLeftCallback = (length: number) => { - /// 暂时规避方案 - /// OS机制与Android不一致,需要去监听软键盘事件才能发送KeyEvent事件 - if (this.mEditable.getStringCache() == "") { - this.sendKeyboardEvent(KeyType.Down, KeyCode.KEYCODE_DEL) - this.sendKeyboardEvent(KeyType.Up, KeyCode.KEYCODE_DEL) - } this.mEditable.handleDeleteEvent(false, length); } @@ -323,8 +285,6 @@ class TextInputMethodHandlerImpl implements TextInputMethodHandler { this.keyboardStatus = state; if (state == inputMethod.KeyboardStatus.HIDE) { this.plugin.textInputChannel.onConnectionClosed(this.inputTarget.id); - this.hideTextInput() - this.cancelListenKeyBoardEvent() } } diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextUtils.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextUtils.ets new file mode 100644 index 0000000000000000000000000000000000000000..61aa4b3dee7fe35658c24b51ebf1205708d7f923 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextUtils.ets @@ -0,0 +1,371 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import FlutterNapi from '../../embedding/engine/FlutterNapi'; +import Log from '../../util/Log'; + +const LINE_FEED: number = 0x0A; +const CARRIAGE_RETURN: number = 0x0D; +const COMBINING_ENCLOSING_KEYCAP: number = 0x20E3; +const CANCEL_TAG: number = 0xE007F; +const ZERO_WIDTH_JOINER: number = 0x200D; + +const TAG = "TextUtils"; + +export class FlutterTextUtils { + + static isEmoji(code: number): boolean { + return FlutterNapi.unicodeIsEmoji(code); + } + + static isEmojiModifier(code: number): boolean { + return FlutterNapi.unicodeIsEmojiModifier(code); + } + + static isEmojiModifierBase(code: number): boolean { + return FlutterNapi.unicodeIsEmojiModifierBase(code); + } + + static isVariationSelector(code: number): boolean { + return FlutterNapi.unicodeIsVariationSelector(code); + } + + static isRegionalIndicatorSymbol(code: number): boolean { + return FlutterNapi.unicodeIsRegionalIndicatorSymbol(code); + } + + static isTagSpecChar(code: number): boolean { + return 0xE0020 <= code && code <= 0xE007E; + } + + static isKeycapBase(code: number): boolean { + return ('0'.charCodeAt(0) <= code && code <= '9'.charCodeAt(0)) || code == '#'.charCodeAt(0) || code == '*'.charCodeAt(0); + } + + static codePointBefore(text: string, offset: number): number { + if (offset <= 0 || offset > text.length) { + throw new RangeError('Offset out of range'); + } + + // Get the character before the offset + const char = text[offset - 1]; + + // Check if it is a low surrogate (part of a surrogate pair) + if (offset > 1 && char >= '\uDC00' && char <= '\uDFFF') { + const prevChar = text[offset - 2]; + // Check if the previous character is a high surrogate + if (prevChar >= '\uD800' && prevChar <= '\uDBFF') { + // If it is, combine the surrogate pair into a full Unicode code point + return (prevChar.charCodeAt(0) - 0xD800) * 0x400 + (char.charCodeAt(0) - 0xDC00) + 0x10000; + } + } + + // Return the code point of the single character (if it's not a surrogate pair) + return char.charCodeAt(0); + } + + static codePointAt(text: string, offset: number): number { + if (offset >= text.length) { + throw new RangeError('Offset out of range'); + } + let char = text[offset]; + + // Check if it is a high surrogate (part of a surrogate pair) + if (char >= '\uD800' && char <= '\uDBFF' && offset + 1 < text.length) { + const nextChar = text[offset + 1]; + // Check if the previous character is a low surrogate + if (nextChar >= '\uDC00' && nextChar <= '\uDFFF') { + // If it is, combine the surrogate pair into a full Unicode code point + return (char.charCodeAt(0) - 0xD800) * 0x400 + (nextChar.charCodeAt(0) - 0xDC00) + 0x10000; + } + } + return char.charCodeAt(0); + } + + static charCount(codePoint: number): number { + // If the code point is in the BMP range (0x0000 - 0xFFFF), it needs 1 UTF-16 code unit + if (codePoint <= 0xFFFF) { + return 1; + } + // If the code point is in the supplementary range (0x10000 - 0x10FFFF), it needs 2 UTF-16 code units + return 2; + } + + static getOffsetBefore(text: string, offset: number): number { + if (offset <= 1) { + return 0; + } + + let codePoint: number = FlutterTextUtils.codePointBefore(text, offset); + let deleteCharCount: number = FlutterTextUtils.charCount(codePoint); + let lastOffset: number = offset - deleteCharCount; + + if (lastOffset == 0) { + return 0; + } + + // Line Feed + if (codePoint == LINE_FEED) { + codePoint = FlutterTextUtils.codePointBefore(text, lastOffset); + if (codePoint == CARRIAGE_RETURN) { + ++deleteCharCount; + } + return offset - deleteCharCount; + } + + // Flags + if (FlutterTextUtils.isRegionalIndicatorSymbol(codePoint)) { + codePoint = FlutterTextUtils.codePointBefore(text, lastOffset); + lastOffset -= FlutterTextUtils.charCount(codePoint); + let regionalIndicatorSymbolCount: number = 1; + while (lastOffset > 0 && FlutterTextUtils.isRegionalIndicatorSymbol(codePoint)) { + codePoint = FlutterTextUtils.codePointBefore(text, lastOffset); + lastOffset -= FlutterTextUtils.charCount(codePoint); + regionalIndicatorSymbolCount++; + } + if (FlutterTextUtils.isRegionalIndicatorSymbol(codePoint)) { + regionalIndicatorSymbolCount++; + } + if (regionalIndicatorSymbolCount % 2 == 0) { + deleteCharCount += 2; + } + return offset - deleteCharCount; + } + + // Keycaps + if (codePoint == COMBINING_ENCLOSING_KEYCAP) { + codePoint = FlutterTextUtils.codePointBefore(text, lastOffset); + lastOffset -= FlutterTextUtils.charCount(codePoint); + if (lastOffset > 0 && FlutterTextUtils.isVariationSelector(codePoint)) { + let tmpCodePoint: number = FlutterTextUtils.codePointBefore(text, lastOffset); + if (FlutterTextUtils.isKeycapBase(tmpCodePoint)) { + deleteCharCount += FlutterTextUtils.charCount(codePoint) + FlutterTextUtils.charCount(tmpCodePoint); + } + } else if (FlutterTextUtils.isKeycapBase(codePoint)) { + deleteCharCount += FlutterTextUtils.charCount(codePoint); + } + return offset - deleteCharCount; + } + + /** + * Following if statements for Emoji tag sequence and Variation selector are skipping these + * modifiers for going through the last statement that is for handling emojis. They return the + * offset if they don't find proper base characters + */ + // Emoji Tag Sequence + if (codePoint == CANCEL_TAG) { // tag_end + codePoint = FlutterTextUtils.codePointBefore(text, lastOffset); + lastOffset -= FlutterTextUtils.charCount(codePoint); + while (lastOffset > 0 && FlutterTextUtils.isTagSpecChar(codePoint)) { // tag_spec + deleteCharCount += FlutterTextUtils.charCount(codePoint); + codePoint = FlutterTextUtils.codePointBefore(text, lastOffset); + lastOffset -= FlutterTextUtils.charCount(codePoint); + } + if (!FlutterTextUtils.isEmoji(codePoint)) { // tag_base not found. Just delete the end. + return offset - 2; + } + deleteCharCount += FlutterTextUtils.charCount(codePoint); + } + + if (FlutterTextUtils.isVariationSelector(codePoint)) { + codePoint = FlutterTextUtils.codePointBefore(text, lastOffset); + if (!FlutterTextUtils.isEmoji(codePoint)) { + return offset - deleteCharCount; + } + deleteCharCount += FlutterTextUtils.charCount(codePoint); + + lastOffset -= FlutterTextUtils.charCount(codePoint); + } + + if (FlutterTextUtils.isEmoji(codePoint)) { + let isZwj: boolean = false; + let lastSeenVariantSelectorCharCount: number = 0; + do { + if (isZwj) { + deleteCharCount += FlutterTextUtils.charCount(codePoint) + lastSeenVariantSelectorCharCount + 1; + isZwj = false; + } + lastSeenVariantSelectorCharCount = 0; + if (FlutterTextUtils.isEmojiModifier(codePoint)) { + codePoint = FlutterTextUtils.codePointBefore(text, lastOffset); + lastOffset -= FlutterTextUtils.charCount(codePoint); + if (lastOffset > 0 && FlutterTextUtils.isVariationSelector(codePoint)) { + codePoint = FlutterTextUtils.codePointBefore(text, lastOffset); + if (!FlutterTextUtils.isEmoji(codePoint)) { + return offset - deleteCharCount; + } + lastSeenVariantSelectorCharCount = FlutterTextUtils.charCount(codePoint); + lastOffset -= FlutterTextUtils.charCount(codePoint); + } + if (FlutterTextUtils.isEmojiModifierBase(codePoint)) { + deleteCharCount += lastSeenVariantSelectorCharCount + FlutterTextUtils.charCount(codePoint); + } + break; + } + + if (lastOffset > 0) { + codePoint = FlutterTextUtils.codePointBefore(text, lastOffset); + lastOffset -= FlutterTextUtils.charCount(codePoint); + if (codePoint == ZERO_WIDTH_JOINER) { + isZwj = true; + codePoint = FlutterTextUtils.codePointBefore(text, lastOffset); + lastOffset -= FlutterTextUtils.charCount(codePoint); + if (lastOffset > 0 && FlutterTextUtils.isVariationSelector(codePoint)) { + codePoint = FlutterTextUtils.codePointBefore(text, lastOffset); + lastSeenVariantSelectorCharCount = FlutterTextUtils.charCount(codePoint); + lastOffset -= FlutterTextUtils.charCount(codePoint); + } + } + } + + if (lastOffset == 0) { + break; + } + } while (isZwj && FlutterTextUtils.isEmoji(codePoint)); + + if (isZwj && lastOffset == 0) { + deleteCharCount += FlutterTextUtils.charCount(codePoint) + lastSeenVariantSelectorCharCount + 1; + isZwj = false; + } + } + + return offset - deleteCharCount; + } + + static getOffsetAfter(text: string, offset: number): number { + const len = text.length; + if (offset >= len - 1) { + return len; + } + + let codePoint: number = FlutterTextUtils.codePointAt(text, offset); + let nextCharCount: number = FlutterTextUtils.charCount(codePoint); + let nextOffset: number = offset + nextCharCount; + + if (nextOffset == 0) { + return 0; + } + // Line Feed + if (codePoint == LINE_FEED) { + codePoint = FlutterTextUtils.codePointAt(text, nextOffset); + if (codePoint == CARRIAGE_RETURN) { + ++nextCharCount; + } + return offset + nextCharCount; + } + + // Flags + if (FlutterTextUtils.isRegionalIndicatorSymbol(codePoint)) { + if (nextOffset >= len - 1 + || !FlutterTextUtils.isRegionalIndicatorSymbol(FlutterTextUtils.codePointAt(text, nextOffset))) { + return offset + nextCharCount; + } + // In this case there are at least two regional indicator symbols ahead of + // offset. If those two regional indicator symbols are a pair that + // represent a region together, the next offset should be after both of + // them. + let regionalIndicatorSymbolCount: number = 0; + let regionOffset: number = offset; + while (regionOffset > 0 + && FlutterTextUtils.isRegionalIndicatorSymbol(FlutterTextUtils.codePointBefore(text, regionOffset))) { + regionOffset -= FlutterTextUtils.charCount(FlutterTextUtils.codePointBefore(text, regionOffset)); + regionalIndicatorSymbolCount++; + } + if (regionalIndicatorSymbolCount % 2 == 0) { + nextCharCount += 2; + } + return offset + nextCharCount; + } + + // Keycaps + if (FlutterTextUtils.isKeycapBase(codePoint)) { + nextCharCount += FlutterTextUtils.charCount(codePoint); + } + if (codePoint == COMBINING_ENCLOSING_KEYCAP) { + codePoint = FlutterTextUtils.codePointBefore(text, nextOffset); + nextOffset += FlutterTextUtils.charCount(codePoint); + if (nextOffset < len && FlutterTextUtils.isVariationSelector(codePoint)) { + let tmpCodePoint: number = FlutterTextUtils.codePointAt(text, nextOffset); + if (FlutterTextUtils.isKeycapBase(tmpCodePoint)) { + nextCharCount += FlutterTextUtils.charCount(codePoint) + FlutterTextUtils.charCount(tmpCodePoint); + } + } else if (FlutterTextUtils.isKeycapBase(codePoint)) { + nextCharCount += FlutterTextUtils.charCount(codePoint); + } + return offset + nextCharCount; + } + + if (FlutterTextUtils.isEmoji(codePoint)) { + let isZwj: boolean = false; + let lastSeenVariantSelectorCharCount: number = 0; + do { + if (isZwj) { + nextCharCount += FlutterTextUtils.charCount(codePoint) + lastSeenVariantSelectorCharCount + 1; + isZwj = false; + } + lastSeenVariantSelectorCharCount = 0; + if (FlutterTextUtils.isEmojiModifier(codePoint)) { + break; + } + + if (nextOffset < len) { + codePoint = FlutterTextUtils.codePointAt(text, nextOffset); + nextOffset += FlutterTextUtils.charCount(codePoint); + if (codePoint == COMBINING_ENCLOSING_KEYCAP) { + codePoint = FlutterTextUtils.codePointBefore(text, nextOffset); + nextOffset += FlutterTextUtils.charCount(codePoint); + if (nextOffset < len && FlutterTextUtils.isVariationSelector(codePoint)) { + let tmpCodePoint: number = FlutterTextUtils.codePointAt(text, nextOffset); + if (FlutterTextUtils.isKeycapBase(tmpCodePoint)) { + nextCharCount += FlutterTextUtils.charCount(codePoint) + FlutterTextUtils.charCount(tmpCodePoint); + } + } else if (FlutterTextUtils.isKeycapBase(codePoint)) { + nextCharCount += FlutterTextUtils.charCount(codePoint); + } + return offset + nextCharCount; + } + if (FlutterTextUtils.isEmojiModifier(codePoint)) { + nextCharCount += lastSeenVariantSelectorCharCount + FlutterTextUtils.charCount(codePoint); + break; + } + if (FlutterTextUtils.isVariationSelector(codePoint)) { + nextCharCount += lastSeenVariantSelectorCharCount + FlutterTextUtils.charCount(codePoint); + break; + } + if (codePoint == ZERO_WIDTH_JOINER) { + isZwj = true; + codePoint = FlutterTextUtils.codePointAt(text, nextOffset); + nextOffset += FlutterTextUtils.charCount(codePoint); + if (nextOffset < len && FlutterTextUtils.isVariationSelector(codePoint)) { + codePoint = FlutterTextUtils.codePointAt(text, nextOffset); + lastSeenVariantSelectorCharCount = FlutterTextUtils.charCount(codePoint); + nextOffset += FlutterTextUtils.charCount(codePoint); + } + } + } + + if (nextOffset >= len) { + break; + } + } while (isZwj && FlutterTextUtils.isEmoji(codePoint)); + + if (isZwj && nextOffset >= len) { + nextCharCount += FlutterTextUtils.charCount(codePoint) + lastSeenVariantSelectorCharCount + 1; + isZwj = false; + } + } + + return offset + nextCharCount; + } +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/platform/PlatformViewsController.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/platform/PlatformViewsController.ets index 8afcd8704308748e02eb41e0d5f2dea566814d63..e0552a797a4549025b5fe333704281f5de1492cf 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/platform/PlatformViewsController.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/platform/PlatformViewsController.ets @@ -88,8 +88,6 @@ export default class PlatformViewsController implements PlatformViewsAccessibili private currentFrameUsedPlatformViewIds: HashSet; private platformViewParent: Map; private nodeControllers: Stack; - private viewPhysicalInfo: Map = new Map(); - private dValue: number = 3; constructor() { this.registry = new PlatformViewRegistryImpl(); @@ -138,9 +136,6 @@ export default class PlatformViewsController implements PlatformViewsAccessibili return; } this.platformViews.delete(viewId); - if (this.viewPhysicalInfo.has(viewId)) { - this.viewPhysicalInfo.delete(viewId); - } let textureId = this.viewIdWithTextureId.get(viewId); if (textureId != undefined) { @@ -182,26 +177,6 @@ export default class PlatformViewsController implements PlatformViewsAccessibili let viewWrapper = this.viewWrappers.get(request.viewId) let params: DVModelParameters | undefined = viewWrapper?.getDvModel()!.params - - const platformView = this.platformViews.get(request.viewId); - if (platformView?.getType() === 'web') { - let oldPhysicalHeight: number = 0; - if (this.viewPhysicalInfo.has(viewId)) { - oldPhysicalHeight = this.viewPhysicalInfo.get(viewId) as number; - //高度变化小于3,不做刷新处理,减少闪烁 - if (physicalHeight - oldPhysicalHeight < this.dValue) { - - this.setParams(params!, "width", physicalWidth); - this.setParams(params!, "height", oldPhysicalHeight); - - onComplete.run(new PlatformViewBufferSize(physicalWidth, oldPhysicalHeight)); - return; - } - } - } - - //保存组件最高位置,解决webview上下滑动带来的组件高度变化而引起的页面闪烁 - this.viewPhysicalInfo.set(viewId, physicalHeight); this.setParams(params!, "width", physicalWidth); this.setParams(params!, "height", physicalHeight); diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets index 0e08f41fe9171658365b4e2c806b075807ddc423..cff9525630a7e0f25ba539247eee391362ddcb79 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets @@ -12,10 +12,30 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import AccessibilityChannel from '../embedding/engine/systemchannels/AccessibilityChannel'; +import { ByteBuffer } from '../util/ByteBuffer'; +import Log from '../util/Log'; + +const TAG = "AccessibilityBridge"; export default class AccessibilityBridge { - constructor(){ + private accessibilityChannel: AccessibilityChannel | null = null; + + constructor(){} +} + +export class AccessibilityManager { + private fontWeightScale: number | null = null; + + setFontWeightScale(fontWeightScale: number): void { + this.fontWeightScale = fontWeightScale; + Log.i(TAG, 'setFontWeightScale: ' + JSON.stringify(this.fontWeightScale)); + } + + getFontWeightScale(): number { + Log.i(TAG, 'getFontWeightScale: ' + JSON.stringify(this.fontWeightScale)); + return this.fontWeightScale!; } } diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets index 0f76a36f534ba5aec81a9550c560ea66e46c42f1..3924d55c20703ef1c60121bec2818978ccb80a94 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets @@ -134,6 +134,7 @@ export class FlutterView { private navigationAvoidArea: window.AvoidArea; private gestureAvoidArea: window.AvoidArea; private keyboardAvoidArea: window.AvoidArea; + private needSetViewport: boolean = false; constructor(viewId: string, context: Context) { @@ -176,16 +177,16 @@ export class FlutterView { private avoidAreaChangeCallback = (data: window.AvoidAreaOptions) => { Log.i(TAG, "avoidAreaChangeCallback, type=" + data.type); + if (data.type == window.AvoidAreaType.TYPE_SYSTEM) { //0 + this.systemAvoidArea = data.area; + } else if (data.type == window.AvoidAreaType.TYPE_SYSTEM_GESTURE) { //2 + this.gestureAvoidArea = data.area; + } else if (data.type == window.AvoidAreaType.TYPE_KEYBOARD) { //3 + this.keyboardAvoidArea = data.area; + } else if (data.type == window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR) { //4 + this.navigationAvoidArea = data.area; + } if (this.isAttachedToFlutterEngine()) { - if (data.type == window.AvoidAreaType.TYPE_SYSTEM) { //0 - this.systemAvoidArea = data.area; - } else if (data.type == window.AvoidAreaType.TYPE_SYSTEM_GESTURE) { //2 - this.gestureAvoidArea = data.area; - } else if (data.type == window.AvoidAreaType.TYPE_KEYBOARD) { //3 - this.keyboardAvoidArea = data.area; - } else if (data.type == window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR) { //4 - this.navigationAvoidArea = data.area; - } this.onAreaChange(null); } } @@ -357,7 +358,7 @@ export class FlutterView { } // 根据是否全屏显示,设置标题栏高度(若全屏,则及时规避) - if (this.checkFullScreen && (setFullScreen || FlutterManager.getInstance().getFullScreenListener().useFullScreen())) { // 全屏显示 + if (this.checkFullScreen && (setFullScreen || this.mainWindow?.getWindowProperties().isLayoutFullScreen)) { // 全屏显示 this.viewportMetrics.physicalViewPaddingTop = this.systemAvoidArea?.topRect.height ?? 0; this.viewportMetrics.physicalViewPaddingBottom = this.navigationAvoidArea?.bottomRect.height ?? 0; } else { // 非全屏显示(保持规避效果) @@ -371,18 +372,19 @@ export class FlutterView { this.onKeyboardAreaChange() this.onGestureAreaChange() - if (!this.viewportMetrics.isEqual(originalMetrics)) { - this.updateViewportMetrics() + if (!this.viewportMetrics.isEqual(originalMetrics) || this.needSetViewport) { + if (!this.updateViewportMetrics()) { + this.needSetViewport = true; + } } } private onKeyboardAreaChange() { if (this.checkKeyboard) { - let keyboardAvoidArea = this.mainWindow?.getWindowAvoidArea(window.AvoidAreaType.TYPE_KEYBOARD); - this.viewportMetrics.physicalViewInsetTop = keyboardAvoidArea?.topRect.height ?? 0 - this.viewportMetrics.physicalViewInsetLeft = keyboardAvoidArea?.leftRect.width ?? 0 - this.viewportMetrics.physicalViewInsetBottom = keyboardAvoidArea?.bottomRect.height ?? 0 - this.viewportMetrics.physicalViewInsetRight = keyboardAvoidArea?.rightRect.width ?? 0 + this.viewportMetrics.physicalViewInsetTop = this.keyboardAvoidArea?.topRect.height ?? 0 + this.viewportMetrics.physicalViewInsetLeft = this.keyboardAvoidArea?.leftRect.width ?? 0 + this.viewportMetrics.physicalViewInsetBottom = this.keyboardAvoidArea?.bottomRect.height ?? 0 + this.viewportMetrics.physicalViewInsetRight = this.keyboardAvoidArea?.rightRect.width ?? 0 } else { this.viewportMetrics.physicalViewInsetTop = 0 this.viewportMetrics.physicalViewInsetLeft = 0 @@ -393,11 +395,10 @@ export class FlutterView { private onGestureAreaChange() { if (this.checkGesture) { - let gestureAvoidArea = this.mainWindow?.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM_GESTURE); - this.viewportMetrics.systemGestureInsetTop = gestureAvoidArea?.topRect.height ?? 0 - this.viewportMetrics.systemGestureInsetLeft = gestureAvoidArea?.leftRect.width ?? 0 - this.viewportMetrics.systemGestureInsetBottom = gestureAvoidArea?.bottomRect.height ?? 0 - this.viewportMetrics.systemGestureInsetRight = gestureAvoidArea?.rightRect.width ?? 0 + this.viewportMetrics.systemGestureInsetTop = this.gestureAvoidArea?.topRect.height ?? 0 + this.viewportMetrics.systemGestureInsetLeft = this.gestureAvoidArea?.leftRect.width ?? 0 + this.viewportMetrics.systemGestureInsetBottom = this.gestureAvoidArea?.bottomRect.height ?? 0 + this.viewportMetrics.systemGestureInsetRight = this.gestureAvoidArea?.rightRect.width ?? 0 } else { this.viewportMetrics.systemGestureInsetTop = 0 this.viewportMetrics.systemGestureInsetLeft = 0 @@ -410,7 +411,7 @@ export class FlutterView { return this.flutterEngine != null } - private updateViewportMetrics() { + private updateViewportMetrics(): boolean { if (this.isAttachedToFlutterEngine()) { Log.i(TAG, 'updateViewportMetrics devicePixelRatio:' + this.viewportMetrics.devicePixelRatio) this?.flutterEngine?.getFlutterNapi()?.setViewportMetrics(this.viewportMetrics.devicePixelRatio, @@ -432,7 +433,9 @@ export class FlutterView { new Array(0), new Array(0), new Array(0)) + return true; } + return false; } onKeyEvent(event: KeyEvent) { diff --git a/shell/platform/ohos/library_loader.cpp b/shell/platform/ohos/library_loader.cpp index 473feb562ef2e514295f71ca29a328f405596f71..ab9f2df807134c44bface863e2065f255af61cd3 100644 --- a/shell/platform/ohos/library_loader.cpp +++ b/shell/platform/ohos/library_loader.cpp @@ -132,15 +132,43 @@ static napi_value Init(napi_env env, napi_value exports) { DECLARE_NAPI_FUNCTION( "nativeSetTextureBackGroundPixelMap", flutter::PlatformViewOHOSNapi::nativeSetTextureBackGroundPixelMap), + DECLARE_NAPI_FUNCTION("nativeEncodeUtf8", + flutter::PlatformViewOHOSNapi::nativeEncodeUtf8), + DECLARE_NAPI_FUNCTION("nativeDecodeUtf8", + flutter::PlatformViewOHOSNapi::nativeDecodeUtf8), DECLARE_NAPI_FUNCTION( - "nativeEncodeUtf8", - flutter::PlatformViewOHOSNapi::nativeEncodeUtf8), + "nativeUpdateSemantics", + flutter::PlatformViewOHOSNapi::nativeUpdateSemantics), + DECLARE_NAPI_FUNCTION( + "nativeUpdateCustomAccessibilityActions", + flutter::PlatformViewOHOSNapi::nativeUpdateCustomAccessibilityActions), + + DECLARE_NAPI_FUNCTION( + "nativeSetFontWeightScale", + flutter::PlatformViewOHOSNapi::nativeSetFontWeightScale), + DECLARE_NAPI_FUNCTION( "nativeDecodeUtf8", flutter::PlatformViewOHOSNapi::nativeDecodeUtf8), DECLARE_NAPI_FUNCTION( "nativeLookupCallbackInformation", flutter::PlatformViewOHOSNapi::nativeLookupCallbackInformation), + + DECLARE_NAPI_FUNCTION( + "nativeUnicodeIsEmoji", + flutter::PlatformViewOHOSNapi::nativeUnicodeIsEmoji), + DECLARE_NAPI_FUNCTION( + "nativeUnicodeIsEmojiModifier", + flutter::PlatformViewOHOSNapi::nativeUnicodeIsEmojiModifier), + DECLARE_NAPI_FUNCTION( + "nativeUnicodeIsEmojiModifierBase", + flutter::PlatformViewOHOSNapi::nativeUnicodeIsEmojiModifierBase), + DECLARE_NAPI_FUNCTION( + "nativeUnicodeIsVariationSelector", + flutter::PlatformViewOHOSNapi::nativeUnicodeIsVariationSelector), + DECLARE_NAPI_FUNCTION( + "nativeUnicodeIsRegionalIndicatorSymbol", + flutter::PlatformViewOHOSNapi::nativeUnicodeIsRegionalIndicatorSymbol), }; FML_DLOG(INFO) << "Init NAPI size=" << sizeof(desc) / sizeof(desc[0]); diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index d46617ef3a738051ec6cfe7fff79c14bea7b4778..f6f23e803a185c6d26cd0c1f00e05eef512baf4c 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -1798,6 +1798,55 @@ napi_value PlatformViewOHOSNapi::nativeDecodeUtf8(napi_env env, napi_callback_in return result; } +napi_value PlatformViewOHOSNapi::nativeUpdateSemantics( + napi_env env, + napi_callback_info info) { + + return nullptr; +} + +napi_value PlatformViewOHOSNapi::nativeUpdateCustomAccessibilityActions( + napi_env env, + napi_callback_info info) { + + return nullptr; +} + +/** + * 无障碍特征之字体加粗功能,获取ets侧系统字体粗细系数 + */ +napi_value PlatformViewOHOSNapi::nativeSetFontWeightScale(napi_env env, napi_callback_info info) { + napi_status ret; + size_t argc = 2; + napi_value args[2] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + // get param nativeShellHolderId + int64_t shell_holder; + ret = napi_get_value_int64(env, args[0], &shell_holder); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "PlatformViewOHOSNapi::nativeSetFontWeightScale " + "napi_get_value_int64 error:" + << ret; + return nullptr; + } + //get param fontWeightScale + double fontWeightScale = 1.0; + ret = napi_get_value_double(env, args[1], &fontWeightScale); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "PlatformViewOHOSNapi::nativeSetFontWeightScale " + "napi_get_value_double error:" + << ret; + return nullptr; + } + // accessibility features get the params + auto ohosAccessibilityFeatures = OhosAccessibilityFeatures::GetInstance(); + ohosAccessibilityFeatures->SetBoldText(fontWeightScale, shell_holder); + FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeSetFontWeightScale -> shell_holder: " + << shell_holder + << " fontWeightScale: "<< fontWeightScale; + return nullptr; +} + napi_value PlatformViewOHOSNapi::nativeLookupCallbackInformation(napi_env env, napi_callback_info info) { napi_value result; @@ -1850,4 +1899,114 @@ napi_value PlatformViewOHOSNapi::nativeLookupCallbackInformation(napi_env env, n napi_create_int32(env, 0, &result); return result; } + +napi_value PlatformViewOHOSNapi::nativeUnicodeIsEmoji(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + bool is_emoji = false; + int64_t codePoint = 0; + bool ret = napi_get_value_int64(env, args[0], &codePoint); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "nativeXComponentAttachFlutterEngine shell_holder " + "napi_get_value_int64 error"; + return nullptr; + } + + is_emoji = u_hasBinaryProperty(codePoint, UProperty::UCHAR_EMOJI); + + napi_value result; + napi_create_int32(env, (int)is_emoji, &result); + return result; +} + +napi_value PlatformViewOHOSNapi::nativeUnicodeIsEmojiModifier(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + bool is_emoji = false; + int64_t codePoint = 0; + bool ret = napi_get_value_int64(env, args[0], &codePoint); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "nativeXComponentAttachFlutterEngine shell_holder " + "napi_get_value_int64 error"; + return nullptr; + } + + is_emoji = u_hasBinaryProperty(codePoint, UProperty::UCHAR_EMOJI_MODIFIER); + + napi_value result; + napi_create_int32(env, (int)is_emoji, &result); + return result; +} + +napi_value PlatformViewOHOSNapi::nativeUnicodeIsEmojiModifierBase(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + bool is_emoji = false; + int64_t codePoint = 0; + bool ret = napi_get_value_int64(env, args[0], &codePoint); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "nativeXComponentAttachFlutterEngine shell_holder " + "napi_get_value_int64 error"; + return nullptr; + } + + is_emoji = u_hasBinaryProperty(codePoint, UProperty::UCHAR_EMOJI_MODIFIER_BASE); + + napi_value result; + napi_create_int32(env, (int)is_emoji, &result); + return result; +} + +napi_value PlatformViewOHOSNapi::nativeUnicodeIsVariationSelector(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + bool is_emoji = false; + int64_t codePoint = 0; + bool ret = napi_get_value_int64(env, args[0], &codePoint); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "nativeXComponentAttachFlutterEngine shell_holder " + "napi_get_value_int64 error"; + return nullptr; + } + + is_emoji = u_hasBinaryProperty(codePoint, UProperty::UCHAR_VARIATION_SELECTOR); + + napi_value result; + napi_create_int32(env, (int)is_emoji, &result); + return result; +} + +napi_value PlatformViewOHOSNapi::nativeUnicodeIsRegionalIndicatorSymbol(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + bool is_emoji = false; + int64_t codePoint = 0; + bool ret = napi_get_value_int64(env, args[0], &codePoint); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "nativeXComponentAttachFlutterEngine shell_holder " + "napi_get_value_int64 error"; + return nullptr; + } + + is_emoji = u_hasBinaryProperty(codePoint, UProperty::UCHAR_REGIONAL_INDICATOR); + + napi_value result; + napi_create_int32(env, (int)is_emoji, &result); + return result; +} } // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.h b/shell/platform/ohos/napi/platform_view_ohos_napi.h index 9ca6b6f90b41da0860243cbcbe67e953b59eddb0..65f11e8776365cece1613c8f855a6e283cd76bd6 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.h +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.h @@ -28,6 +28,9 @@ #include "flutter/shell/common/run_configuration.h" #include "flutter/shell/platform/ohos/napi_common.h" #include "napi/native_api.h" + +#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_features.h" + // class for all c++ to call js function namespace flutter { @@ -199,16 +202,45 @@ class PlatformViewOHOSNapi { static napi_value nativeXComponentDetachFlutterEngine( napi_env env, napi_callback_info info); - static napi_value nativeXComponentDispatchMouseWheel( + static napi_value nativeXComponentDispatchMouseWheel(napi_env env, + napi_callback_info info); + static napi_value nativeEncodeUtf8(napi_env env, napi_callback_info info); + static napi_value nativeDecodeUtf8(napi_env env, napi_callback_info info); + + /** + * ets call c++ + */ + static napi_value nativeUpdateSemantics(napi_env env, + napi_callback_info info); + static napi_value nativeUpdateCustomAccessibilityActions( + napi_env env, + napi_callback_info info); + + static napi_value nativeSetFontWeightScale( napi_env env, napi_callback_info info); - static napi_value nativeEncodeUtf8( + + static napi_value nativeLookupCallbackInformation( napi_env env, napi_callback_info info); - static napi_value nativeDecodeUtf8( + + static napi_value nativeUnicodeIsEmoji( napi_env env, napi_callback_info info); - static napi_value nativeLookupCallbackInformation( + + static napi_value nativeUnicodeIsEmojiModifier( + napi_env env, + napi_callback_info info); + + static napi_value nativeUnicodeIsEmojiModifierBase( + napi_env env, + napi_callback_info info); + + static napi_value nativeUnicodeIsVariationSelector( + napi_env env, + napi_callback_info info); + + static napi_value nativeUnicodeIsRegionalIndicatorSymbol( napi_env env, napi_callback_info info); diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index 46fa22e2a0e027fda5bd4ddbcc4b8c0fdef860dc..fda7cae8a09d23be4530818ccf48a889a7563cf3 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -38,6 +38,45 @@ constexpr const char *CHARACTER_STRING_WHITESPACE = " "; constexpr const char *EGL_EXT_PLATFORM_WAYLAND = "EGL_EXT_platform_wayland"; constexpr const char *EGL_KHR_PLATFORM_WAYLAND = "EGL_KHR_platform_wayland"; constexpr const char *EGL_GET_PLATFORM_DISPLAY_EXT = "eglGetPlatformDisplayEXT"; +constexpr uint32_t WHITE_COLOR = 0xFFFFFFFF; + +static int PixelMapToWindowFormat(PIXEL_FORMAT pixel_format) +{ + switch (pixel_format) { + case PIXEL_FORMAT_RGB_565: + return NATIVEBUFFER_PIXEL_FMT_RGB_565; + case PIXEL_FORMAT_RGBA_8888: + return NATIVEBUFFER_PIXEL_FMT_RGBA_8888; + case PIXEL_FORMAT_BGRA_8888: + return NATIVEBUFFER_PIXEL_FMT_BGRA_8888; + case PIXEL_FORMAT_RGB_888: + return NATIVEBUFFER_PIXEL_FMT_RGB_888; + case PIXEL_FORMAT_NV21: + return NATIVEBUFFER_PIXEL_FMT_YCRCB_420_SP; + case PIXEL_FORMAT_NV12: + return NATIVEBUFFER_PIXEL_FMT_YCBCR_420_SP; + case PIXEL_FORMAT_RGBA_1010102: + return NATIVEBUFFER_PIXEL_FMT_RGBA_1010102; + case PIXEL_FORMAT_YCBCR_P010: + return NATIVEBUFFER_PIXEL_FMT_YCBCR_P010; + case PIXEL_FORMAT_YCRCB_P010: + return NATIVEBUFFER_PIXEL_FMT_YCRCB_P010; + case PIXEL_FORMAT_ALPHA_8: + case PIXEL_FORMAT_RGBA_F16: + case PIXEL_FORMAT_UNKNOWN: + default: + // no support/unknow format: cannot copy + return 0; + } + return 0; +} + +static bool IsPixelMapYUVFormat(PIXEL_FORMAT format) +{ + return format == PIXEL_FORMAT_NV21 || format == PIXEL_FORMAT_NV12 || + format == PIXEL_FORMAT_YCBCR_P010 || format == PIXEL_FORMAT_YCRCB_P010; +} + OHOSExternalTextureGL::OHOSExternalTextureGL(int64_t id, const std::shared_ptr& ohos_surface) : Texture(id), ohos_surface_(std::move(ohos_surface)), transform(SkMatrix::I()) @@ -61,14 +100,7 @@ OHOSExternalTextureGL::~OHOSExternalTextureGL() { FML_DLOG(INFO) << "~OHOSExternalTextureGL, texture_name_=" << texture_name_ << ", Id()=" << Id(); if (state_ == AttachmentState::attached) { - if (texture_name_ != 0) { - glDeleteTextures(1, &texture_name_); - texture_name_ = 0; - } - if (backGroundTextureName_ != 0) { - glDeleteTextures(1, &backGroundTextureName_); - backGroundTextureName_ = 0; - } + Detach(); } state_ = AttachmentState::uninitialized; nativeImage_ = nullptr; @@ -86,7 +118,6 @@ OHOSExternalTextureGL::~OHOSExternalTextureGL() void OHOSExternalTextureGL::Attach() { - FML_DLOG(INFO) << "OHOSExternalTextureGL::Attach, Id()=" << Id(); if (state_ != AttachmentState::uninitialized) { FML_LOG(ERROR) << "OHOSExternalTextureGL::Attach, the current status is not uninitialized"; return; @@ -105,11 +136,12 @@ void OHOSExternalTextureGL::Attach() FML_LOG(ERROR) << "Error with OH_NativeImage_Create"; return; } - nativeWindow_ = OH_NativeImage_AcquireNativeWindow(nativeImage_); - if (nativeWindow_ == nullptr) { - FML_LOG(ERROR) << "Error with OH_NativeImage_AcquireNativeWindow"; - return; - } + } + + nativeWindow_ = OH_NativeImage_AcquireNativeWindow(nativeImage_); + if (nativeWindow_ == nullptr) { + FML_LOG(ERROR) << "Error with OH_NativeImage_AcquireNativeWindow"; + return; } int32_t ret = OH_NativeImage_AttachContext(nativeImage_, texture_name_); @@ -131,10 +163,14 @@ void OHOSExternalTextureGL::Paint(PaintContext& context, FML_LOG(ERROR) << "OHOSExternalTextureGL::Paint, the current status is detached"; return; } + if (!freeze && texture_update_ && pixelMap_ == nullptr) { + // 多引擎场景(multi_flutters_ohos)需要在这里执行Update + Update(); + } GrGLTextureInfo textureInfo; - if (!freeze && !first_update_ && !isEmulator_ && backGroundTextureName_ == 0 && pixelMap_ == nullptr) { + if (!freeze && !first_update_ && !isEmulator_ && !new_frame_ready_ && pixelMap_ == nullptr) { setBackground(bounds.width(), bounds.height()); textureInfo = {GL_TEXTURE_EXTERNAL_OES, backGroundTextureName_, GL_RGBA8_OES}; } else { @@ -178,20 +214,20 @@ void OHOSExternalTextureGL::Paint(PaintContext& context, void OHOSExternalTextureGL::OnGrContextCreated() { - FML_DLOG(INFO) << " OHOSExternalTextureGL::OnGrContextCreated"; + FML_DLOG(INFO) << " OHOSExternalTextureGL::OnGrContextCreated" + << ", texture_name_=" << texture_name_ + << ", Id()=" << Id(); state_ = AttachmentState::uninitialized; } void OHOSExternalTextureGL::OnGrContextDestroyed() { - FML_DLOG(INFO) << " OHOSExternalTextureGL::OnGrContextDestroyed"; + FML_DLOG(INFO) << " OHOSExternalTextureGL::OnGrContextDestroyed" + << ", texture_name_=" << texture_name_ + << ", Id()=" << Id(); if (state_ == AttachmentState::attached) { Detach(); - glDeleteTextures(1, &texture_name_); - } - state_ = AttachmentState::detached; - if (backGroundTextureName_ != 0) { - glDeleteTextures(1, &backGroundTextureName_); + state_ = AttachmentState::detached; } } @@ -199,6 +235,7 @@ void OHOSExternalTextureGL::MarkNewFrameAvailable() { FML_DLOG(INFO) << " OHOSExternalTextureGL::MarkNewFrameAvailable"; new_frame_ready_ = true; + texture_update_ = true; if (texture_name_ == 0) { Attach(); } @@ -215,14 +252,9 @@ void OHOSExternalTextureGL::OnTextureUnregistered() << ", nativeImage_=" << nativeImage_ << ", backGroundNativeImage_=" << backGroundNativeImage_; first_update_ = false; - if (nativeImage_ != nullptr) { - OH_NativeImage_UnsetOnFrameAvailableListener(nativeImage_); - OH_NativeImage_Destroy(&nativeImage_); - nativeImage_ = nullptr; - } - if (backGroundNativeImage_ != nullptr) { - OH_NativeImage_Destroy(&backGroundNativeImage_); - backGroundNativeImage_ = nullptr; + if (state_ == AttachmentState::attached) { + Detach(); + state_ = AttachmentState::detached; } } @@ -234,6 +266,7 @@ void OHOSExternalTextureGL::Update() return; } int32_t ret = OH_NativeImage_UpdateSurfaceImage(nativeImage_); + texture_update_ = false; if (ret != 0) { FML_LOG(ERROR) << "OHOSExternalTextureGL OH_NativeImage_UpdateSurfaceImage err code:" << ret; return; @@ -249,12 +282,36 @@ void OHOSExternalTextureGL::Detach() FML_LOG(ERROR) << "OHOSExternalTextureGL::Detach, the current status is not attached"; return; } - OH_NativeImage_DetachContext(nativeImage_); - OH_NativeImage_DetachContext(backGroundNativeImage_); - OH_NativeWindow_DestroyNativeWindow(nativeWindow_); - OH_NativeWindow_DestroyNativeWindow(backGroundNativeWindow_); - nativeWindow_ = nullptr; - backGroundNativeWindow_ = nullptr; + + if (nativeImage_ != nullptr) { + OH_NativeImage_DetachContext(nativeImage_); + OH_NativeImage_UnsetOnFrameAvailableListener(nativeImage_); + OH_NativeImage_Destroy(&nativeImage_); + nativeImage_ = nullptr; + } + if (nativeWindow_ != nullptr) { + OH_NativeWindow_DestroyNativeWindow(nativeWindow_); + nativeWindow_ = nullptr; + } + + if (backGroundNativeImage_ != nullptr) { + OH_NativeImage_DetachContext(backGroundNativeImage_); + OH_NativeImage_Destroy(&backGroundNativeImage_); + backGroundNativeImage_ = nullptr; + } + if (backGroundNativeWindow_ != nullptr) { + OH_NativeWindow_DestroyNativeWindow(backGroundNativeWindow_); + backGroundNativeWindow_ = nullptr; + } + + if (texture_name_ != 0) { + glDeleteTextures(1, &texture_name_); + texture_name_ = 0; + } + if (backGroundTextureName_ != 0) { + glDeleteTextures(1, &backGroundTextureName_); + backGroundTextureName_ = 0; + } } void OHOSExternalTextureGL::UpdateTransform(OH_NativeImage *image) @@ -326,6 +383,15 @@ void OHOSExternalTextureGL::setBackground(int32_t width, int32_t height) void OHOSExternalTextureGL::setTextureBufferSize(int32_t width, int32_t height) { FML_DLOG(INFO) << "OHOSExternalTextureGL::SetTextureBufferSize"; + if (nativeWindow_ == nullptr && nativeImage_) { + nativeWindow_ = OH_NativeImage_AcquireNativeWindow(nativeImage_); + } + + if (nativeWindow_ == nullptr) { + FML_LOG(ERROR) << "OHOSExternalTextureGL::SetTextureBufferSize nativeWindow_ is nullptr"; + return; + } + int code = SET_BUFFER_GEOMETRY; int32_t ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, code, width, height); if (ret != 0) { @@ -358,12 +424,9 @@ void OHOSExternalTextureGL::ProduceColorToBackGroundImage(int32_t width, int32_t } uint32_t* destAddr = static_cast(mappedAddr); - uint32_t value = 0xFFFFFFFF; - for (int32_t x = 0; x < handle->width; x++) { - for (int32_t y = 0; y < handle->height; y++) { - *destAddr++ = value; - } + for (int32_t x = 0; x < handle->size / PIXEL_SIZE; x++) { + *destAddr++ = WHITE_COLOR; } // munmap after use @@ -410,6 +473,10 @@ void OHOSExternalTextureGL::ProducePixelMapToBackGroundImage() << ret; return; } + + int windowFormat = PixelMapToWindowFormat((PIXEL_FORMAT)pixelMapInfo.pixelFormat); + ret = OH_NativeWindow_NativeWindowHandleOpt(backGroundNativeWindow_, SET_FORMAT, windowFormat); + uint64_t usage = 0; OH_NativeWindow_NativeWindowHandleOpt(backGroundNativeWindow_, GET_USAGE, &usage); usage |= NATIVEBUFFER_USAGE_CPU_READ; @@ -478,13 +545,19 @@ void OHOSExternalTextureGL::HandlePixelMapBuffer(NativePixelMap* pixelMap, OHNat FML_DLOG(INFO) << "OHOSExternalTextureGL pixelMapInfo rowSize:" << pixelMapInfo.rowSize << " format:" << pixelMapInfo.pixelFormat; + uint32_t real_height = pixelMapInfo.height; + if (IsPixelMapYUVFormat((PIXEL_FORMAT)pixelMapInfo.pixelFormat)) { + // y is height, uv is height/2 + real_height = pixelMapInfo.height + (pixelMapInfo.height + 1) / 2; + } + // 复制图片纹理数据到内存中,需要处理DMA内存补齐相关的逻辑 if (pixelMapInfo.width * PIXEL_SIZE != pixelMapInfo.rowSize) { // 直接复制整块内存 - memcpy(destAddr, pixel, pixelMapInfo.height * pixelMapInfo.rowSize); + memcpy(destAddr, pixel, real_height * pixelMapInfo.rowSize); } else { // 需要处理DMA内存补齐相关的逻辑 - for (uint32_t i = 0; i < pixelMapInfo.height; i++) { + for (uint32_t i = 0; i < real_height; i++) { memcpy(destAddr, pixel, pixelMapInfo.rowSize); destAddr += stride / PIXEL_SIZE; pixel += pixelMapInfo.width; @@ -524,6 +597,12 @@ void OHOSExternalTextureGL::ProducePixelMapToNativeImage() return; } + ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, SET_TIMEOUT, 0); + if (ret != 0) { + FML_LOG(ERROR) << "OHOSExternalTextureGL SET_TIMEOUT err:" << ret; + return; + } + uint64_t usage = 0; OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, GET_USAGE, &usage); usage |= NATIVEBUFFER_USAGE_CPU_READ; diff --git a/shell/platform/ohos/ohos_external_texture_gl.h b/shell/platform/ohos/ohos_external_texture_gl.h index 5ac18743a67d53aed5fac19176371923b9186f48..26847c228b420b1469c0c58987d487f95befcba2 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.h +++ b/shell/platform/ohos/ohos_external_texture_gl.h @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -96,6 +97,8 @@ class OHOSExternalTextureGL : public flutter::Texture { bool new_frame_ready_ = false; + bool texture_update_ = false; + GLuint texture_name_ = 0; GLuint backGroundTextureName_ = 0; diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.cpp b/shell/platform/ohos/ohos_xcomponent_adapter.cpp index 4d49b0c7536dbdc58ac623f75907d43830d02b04..ce9b10f61d4301818eca106aa4f50d0fa9905e5c 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.cpp +++ b/shell/platform/ohos/ohos_xcomponent_adapter.cpp @@ -199,6 +199,14 @@ static int32_t SetNativeWindowOpt(OHNativeWindow* nativeWindow, ",w:%{public}d x %{public}d:%{public}d", nativeWindow, width, height, ret); } + + ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_TIMEOUT, 0); + if (ret) { + LOGE( + "Set NativeWindow SET_TIMEOUT Failed :window:%{public}p " + ",w:%{public}d x %{public}d:%{public}d", + nativeWindow, width, height, ret); + } return ret; } @@ -330,9 +338,13 @@ void XComponentBase::OnSurfaceCreated(OH_NativeXComponent* component, (int)height_); ret = SetNativeWindowOpt((OHNativeWindow*)window, width_, height_); if (ret) { - LOGD("SetNativeWindowOpt failed:%{public}d", ret); + LOGE("SetNativeWindowOpt failed:%{public}d", ret); } if (isEngineAttached_) { + ret = OH_NativeWindow_NativeObjectReference(window); + if (ret) { + LOGE("NativeObjectReference failed:%{public}d", ret); + } PlatformViewOHOSNapi::SurfaceCreated(std::stoll(shellholderId_), window); } else { LOGE("OnSurfaceCreated XComponentBase is not attached"); @@ -362,8 +374,12 @@ void XComponentBase::OnSurfaceDestroyed(OH_NativeXComponent* component, LOGD("XComponentManger::OnSurfaceDestroyed"); if (isEngineAttached_) { PlatformViewOHOSNapi::SurfaceDestroyed(std::stoll(shellholderId_)); + int32_t ret = OH_NativeWindow_NativeObjectUnreference(window); + if (ret) { + LOGE("NativeObjectUnreference failed:%{public}d", ret); + } } else { - LOGE("OnSurfaceCreated OnSurfaceDestroyed is not attached"); + LOGE("XComponentManger::OnSurfaceDestroyed XComponentBase is not attached"); } }