diff --git a/BUILD.gn b/BUILD.gn index 7a102d594bf570c401e4a55e5682fd014a56ab81..66d7f4ee309563f57b44666715e24c00e26ce1ca 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -152,6 +152,7 @@ group("unittests") { "//flutter/runtime:no_dart_plugin_registrant_unittests", "//flutter/runtime:runtime_unittests", "//flutter/shell/common:shell_unittests", + "//flutter/shell/platform/ohos:flutter_ohos_unittests", "//flutter/shell/platform/embedder:embedder_a11y_unittests", "//flutter/shell/platform/embedder:embedder_proctable_unittests", "//flutter/shell/platform/embedder:embedder_unittests", diff --git a/shell/platform/ohos/BUILD.gn b/shell/platform/ohos/BUILD.gn index 689f5015c2a163805cc04cd776451815973c7ac3..3b1b9c21c22bf75c09ee0f33409db179cc4db42f 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) @@ -174,6 +176,7 @@ executable("flutter_ohos_unittests") { sources = [ #"testing/mock_texture_registrar.cc", + "testing/ohos_assert_provider_test.cc" ] public_configs = [ "//flutter:config" ] @@ -195,6 +198,15 @@ executable("flutter_ohos_unittests") { "//flutter/shell/platform/embedder:embedder_test_utils", "//flutter/testing", ] + + ldflags = ["-lace_ndk.z"] + ldflags += ["-lnative_window"] + ldflags += ["-lnative_vsync"] + ldflags += ["-limage_ndk.z"] + ldflags += ["-lrawfile.z"] + ldflags += ["-lnative_image"] + ldflags += ["-lpixelmap_ndk.z"] + ldflags += ["-lqos"] } shared_library("flutter_shell_native") { 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..0cf14a41b0c7d79abacb39c43617b4e57832685d 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,19 @@ 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; 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..787722ab0645ac2372e98b745168f68963cb9159 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,23 @@ 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 !"); + } + } + } 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/TextInputPlugin.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets index c499dacb3980aad684fed843d274e5aa4a8d9d6f..60888e9b95c7058aa9f3b6b1cbe2bea2aedd4510 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; @@ -84,7 +78,6 @@ class TextInputMethodHandlerImpl implements TextInputMethodHandler { mEditable: ListenableEditingState; private mRestartInputPending: boolean = false; private plugin: EditingStateWatcher | Any; - private imcFlag: boolean = false; private inputTypeNone: string = 'NONE' private keyboardStatus: inputMethod.KeyboardStatus = inputMethod.KeyboardStatus.HIDE; private inputAttribute: inputMethod.InputAttribute = { textInputType: 0, enterKeyType: 1 } @@ -150,22 +143,11 @@ class TextInputMethodHandlerImpl implements TextInputMethodHandler { return; } await this.attach(true); - 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)); - }); + this.listenKeyBoardEvent(); } 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(); } async attach(showKeyboard: boolean): Promise { @@ -270,26 +252,6 @@ class TextInputMethodHandlerImpl implements TextInputMethodHandler { return; } Log.d(TextInputMethodHandlerImpl.TAG, "listenKeyBoardEvent success"); - 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) => { @@ -298,12 +260,6 @@ class TextInputMethodHandlerImpl implements TextInputMethodHandler { } 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); } @@ -339,7 +295,6 @@ class TextInputMethodHandlerImpl implements TextInputMethodHandler { this.inputMethodController.off('sendFunctionKey', this.sendFunctionKeyCallback); this.inputMethodController.off('sendKeyboardStatus', this.sendKeyboardStatusCallback); this.inputMethodController.off('selectByRange', this.selectByRangeCallback); - this.imcFlag = false; } public clearTextInputClient(): void { 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..c3fd15e16e554032f4d1b4317ddcf91208eb2e98 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 @@ -89,7 +89,7 @@ export default class PlatformViewsController implements PlatformViewsAccessibili private platformViewParent: Map; private nodeControllers: Stack; private viewPhysicalInfo: Map = new Map(); - private dValue: number = 3; + private dValue: number = 1; constructor() { this.registry = new PlatformViewRegistryImpl(); @@ -188,7 +188,7 @@ export default class PlatformViewsController implements PlatformViewsAccessibili let oldPhysicalHeight: number = 0; if (this.viewPhysicalInfo.has(viewId)) { oldPhysicalHeight = this.viewPhysicalInfo.get(viewId) as number; - //高度变化小于3,不做刷新处理,减少闪烁 + //高度变化小于1,不做刷新处理,减少闪烁 if (physicalHeight - oldPhysicalHeight < this.dValue) { this.setParams(params!, "width", physicalWidth); 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..f5963414742306aefb26bfb7c0484f9518fdfcf6 100644 --- a/shell/platform/ohos/library_loader.cpp +++ b/shell/platform/ohos/library_loader.cpp @@ -132,9 +132,21 @@ 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), diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index d46617ef3a738051ec6cfe7fff79c14bea7b4778..2594687c158d8c59f05df1eeb72aeec826efbfea 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; diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.h b/shell/platform/ohos/napi/platform_view_ohos_napi.h index 9ca6b6f90b41da0860243cbcbe67e953b59eddb0..4cbe6cd5724ccc53f05fc34065ecef2c8613d3c4 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,15 +202,24 @@ class PlatformViewOHOSNapi { static napi_value nativeXComponentDetachFlutterEngine( napi_env env, napi_callback_info info); - static napi_value nativeXComponentDispatchMouseWheel( - napi_env env, - napi_callback_info info); - static napi_value nativeEncodeUtf8( + 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 nativeDecodeUtf8( + + static napi_value nativeSetFontWeightScale( napi_env env, napi_callback_info info); + static napi_value nativeLookupCallbackInformation( 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..05c8449bf5e64c9a800b3258f61c8d13700e1baf 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -39,6 +39,44 @@ 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"; +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()) { @@ -134,7 +172,7 @@ void OHOSExternalTextureGL::Paint(PaintContext& context, 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 { @@ -410,6 +448,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 +520,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; diff --git a/shell/platform/ohos/ohos_external_texture_gl.h b/shell/platform/ohos/ohos_external_texture_gl.h index 5ac18743a67d53aed5fac19176371923b9186f48..2458ac9c540e3b0cafa4debce439f94dcac9da8f 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 diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.cpp b/shell/platform/ohos/ohos_xcomponent_adapter.cpp index 4d49b0c7536dbdc58ac623f75907d43830d02b04..d6b8f9446d91fda32f09f6f8df86ba3867bef704 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.cpp +++ b/shell/platform/ohos/ohos_xcomponent_adapter.cpp @@ -330,9 +330,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 +366,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"); } } diff --git a/shell/platform/ohos/testing/ohos_assert_provider_test.cc b/shell/platform/ohos/testing/ohos_assert_provider_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..2a67bc5a1cc4f7626a824773a17cc1b5193f926b --- /dev/null +++ b/shell/platform/ohos/testing/ohos_assert_provider_test.cc @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 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 +#include +#include +#include +#include + +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +#include "../ohos_asset_provider.h" + +TEST(OHOSAssetProviderTest, Build001) { + std::shared_ptr provider = std::make_shared(nullptr); + EXPECT_EQ(provider, nullptr); +}