diff --git a/OAT.xml b/OAT.xml
new file mode 100644
index 0000000000000000000000000000000000000000..56397aff4d85febeda65a11f60aa2634fc352738
--- /dev/null
+++ b/OAT.xml
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/example/lib/utils/config.dart b/example/lib/utils/config.dart
index 632f01b98b3f152a8d25a6ce08d15b3831d2a196..d45c39d7936eb0a53256905f7003beb29c57e39a 100644
--- a/example/lib/utils/config.dart
+++ b/example/lib/utils/config.dart
@@ -2,7 +2,7 @@ import 'dart:collection';
import 'package:flutter/material.dart';
-final class _ListenerEntry extends LinkedListEntry<_ListenerEntry> {
+class _ListenerEntry extends LinkedListEntry<_ListenerEntry> {
_ListenerEntry(this.listener);
final VoidCallback listener;
}
diff --git a/example/ohos/.gitignore b/example/ohos/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..6ca13b3170eec5dd5ac5ad7f1c4dd0118845f473
--- /dev/null
+++ b/example/ohos/.gitignore
@@ -0,0 +1,19 @@
+/node_modules
+/oh_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
+.cxx
+/.clangd
+/.clang-format
+/.clang-tidy
+**/.test
+*.har
+**/BuildProfile.ets
+**/oh-package-lock.json5
+
+**/src/main/resources/rawfile/flutter_assets/
+**/libs/arm64-v8a/libapp.so
+**/libs/arm64-v8a/libflutter.so
+**/libs/arm64-v8a/libvmservice_snapshot.so
diff --git a/example/ohos/AppScope/app.json5 b/example/ohos/AppScope/app.json5
new file mode 100644
index 0000000000000000000000000000000000000000..54b452371434d157a929b2998ae0b4007bf6294c
--- /dev/null
+++ b/example/ohos/AppScope/app.json5
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+{
+ "app": {
+ "bundleName": "com.example.window_manager_plus_example",
+ "vendor": "example",
+ "versionCode": 1000000,
+ "versionName": "1.0.0",
+ "icon": "$media:app_icon",
+ "label": "$string:app_name"
+ }
+}
\ No newline at end of file
diff --git a/example/ohos/AppScope/resources/base/element/string.json b/example/ohos/AppScope/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..c7c7511f937ff71fc713637e40f9611a47861a72
--- /dev/null
+++ b/example/ohos/AppScope/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "window_manager_plus_example"
+ }
+ ]
+}
diff --git a/example/ohos/AppScope/resources/base/media/app_icon.png b/example/ohos/AppScope/resources/base/media/app_icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/example/ohos/AppScope/resources/base/media/app_icon.png differ
diff --git a/example/ohos/build-profile.json5 b/example/ohos/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..04ec2113ba2579cb805793634ee4a11a1464a1bf
--- /dev/null
+++ b/example/ohos/build-profile.json5
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+{
+ "app": {
+ "signingConfigs": [],
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "default",
+ "compatibleSdkVersion": "5.0.0(12)",
+ "runtimeOS": "HarmonyOS"
+ }
+ ]
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default"
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/example/ohos/entry/.gitignore b/example/ohos/entry/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..2795a1c5b1fe53659dd1b71d90ba0592eaf7e043
--- /dev/null
+++ b/example/ohos/entry/.gitignore
@@ -0,0 +1,7 @@
+
+/node_modules
+/oh_modules
+/.preview
+/build
+/.cxx
+/.test
\ No newline at end of file
diff --git a/example/ohos/entry/build-profile.json5 b/example/ohos/entry/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..633d360fbc91a3186a23b66ab71b27e5618944cb
--- /dev/null
+++ b/example/ohos/entry/build-profile.json5
@@ -0,0 +1,29 @@
+/*
+* 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.
+*/
+
+{
+ "apiType": 'stageMode',
+ "buildOption": {
+ },
+ "targets": [
+ {
+ "name": "default",
+ "runtimeOS": "HarmonyOS"
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/example/ohos/entry/hvigorfile.ts b/example/ohos/entry/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..894fc15c6b793f085e6c8506e43d719af658e8ff
--- /dev/null
+++ b/example/ohos/entry/hvigorfile.ts
@@ -0,0 +1,17 @@
+/*
+* 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.
+*/
+
+// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
+export { hapTasks } from '@ohos/hvigor-ohos-plugin';
diff --git a/example/ohos/entry/oh-package.json5 b/example/ohos/entry/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..b0ac9797a95abbb76a81e6f70eeaae49397b6dda
--- /dev/null
+++ b/example/ohos/entry/oh-package.json5
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+{
+ "name": "entry",
+ "version": "1.0.0",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "author": "",
+ "license": "",
+ "dependencies": {
+ "window_manager_plus": "file:../har/window_manager_plus.har",
+ "integration_test": "file:../har/integration_test.har",
+ "screen_retriever": "file:../har/screen_retriever.har"
+ }
+}
\ No newline at end of file
diff --git a/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets b/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..f18870b8f69743cf8a6658ea4d7614904ed0a7f7
--- /dev/null
+++ b/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets
@@ -0,0 +1,90 @@
+/*
+* 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 { FlutterAbility, FlutterEngine } from '@ohos/flutter_ohos';
+import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant';
+import window from '@ohos.window';
+import { AbilityConstant, Want } from '@kit.AbilityKit';
+import WindowManagerPlusPlugin, { WindowStageManager } from 'window_manager_plus';
+
+const WINDOW_NAME_KEY = 'WINDOW_NAME';
+const INIT_ROUTE_KEY = 'INIT_ROUTE';
+
+/**
+ * flutter多窗口entry模板代码
+ */
+export default class EntryAbility extends FlutterAbility {
+ windowName: string = '0';
+ //默认窗口id=0
+ initRoute: string = '/';
+
+ configureFlutterEngine(flutterEngine: FlutterEngine) {
+ super.configureFlutterEngine(flutterEngine)
+ GeneratedPluginRegistrant.registerWith(flutterEngine)
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage): void {
+ super.onWindowStageCreate(windowStage);
+ if (this.windowName) {
+ WindowStageManager.addStage(this.windowName, windowStage);
+ }
+ }
+
+ async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
+ super.onCreate(want, launchParam);
+ const record: Record | undefined = want.parameters;
+ if (record && record[WINDOW_NAME_KEY]) {
+ if (record[WINDOW_NAME_KEY]) {
+ this.windowName = record[WINDOW_NAME_KEY].toString();
+ }
+ if (record[INIT_ROUTE_KEY]) {
+ this.initRoute = record[INIT_ROUTE_KEY].toString();
+ }
+ }
+ }
+
+ getInitialRoute(): string {
+ return this.initRoute;
+ }
+
+ onWindowStageWillDestroy(windowStage: window.WindowStage): void {
+ try {
+ super.onWindowStageWillDestroy(windowStage);
+ } catch (e) {
+ console.error('error on onWindowStageWillDestroy' + e);
+ }
+ if (this.windowName) {
+ WindowManagerPlusPlugin.releaseWindowManager(parseInt(this.windowName));
+ }
+ if (this.windowName) {
+ WindowStageManager.removeStage(this.windowName);
+ }
+ }
+
+ getDartEntrypointArgs(): string[] {
+ let arr: string[] = super.getDartEntrypointArgs();
+ if (!arr) {
+ arr = [];
+ }
+ if (this.windowName) {
+ arr.push(this.windowName);
+ }
+ return arr;
+ }
+
+ isDefaultFullScreen(): boolean {
+ return false;
+ }
+}
diff --git a/example/ohos/entry/src/main/ets/pages/Index.ets b/example/ohos/entry/src/main/ets/pages/Index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..1125f9fdd95f4310a182c1c9e3680f37f73686c9
--- /dev/null
+++ b/example/ohos/entry/src/main/ets/pages/Index.ets
@@ -0,0 +1,38 @@
+/*
+* 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 common from '@ohos.app.ability.common';
+import { FlutterPage } from '@ohos/flutter_ohos'
+
+let storage = LocalStorage.getShared()
+const EVENT_BACK_PRESS = 'EVENT_BACK_PRESS'
+
+@Entry(storage)
+@Component
+struct Index {
+ private context = getContext(this) as common.UIAbilityContext
+ @LocalStorageLink('viewId') viewId: string = "";
+
+ build() {
+ Column() {
+ FlutterPage({ viewId: this.viewId })
+ }
+ }
+
+ onBackPress(): boolean {
+ this.context.eventHub.emit(EVENT_BACK_PRESS)
+ return true
+ }
+}
\ No newline at end of file
diff --git a/example/ohos/entry/src/main/module.json5 b/example/ohos/entry/src/main/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..4408d22b92029ca34cf2c0ed7396db985cfe617b
--- /dev/null
+++ b/example/ohos/entry/src/main/module.json5
@@ -0,0 +1,56 @@
+/*
+* 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.
+*/
+{
+ "module": {
+ "name": "entry",
+ "type": "entry",
+ "description": "$string:module_desc",
+ "mainElement": "EntryAbility",
+ "deviceTypes": [
+ "phone",
+ "tablet",
+ "2in1"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:main_pages",
+ "abilities": [
+ {
+ "name": "EntryAbility",
+ "srcEntry": "./ets/entryability/EntryAbility.ets",
+ "description": "$string:EntryAbility_desc",
+ "icon": "$media:icon",
+ "label": "$string:EntryAbility_label",
+ "startWindowIcon": "$media:icon",
+ "startWindowBackground": "$color:start_window_background",
+ "exported": true,
+ "launchType": "multiton",
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ]
+ }
+ ],
+ "requestPermissions": [
+ {"name" : "ohos.permission.INTERNET"},
+ ]
+ }
+}
\ No newline at end of file
diff --git a/example/ohos/entry/src/main/resources/base/element/color.json b/example/ohos/entry/src/main/resources/base/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02
--- /dev/null
+++ b/example/ohos/entry/src/main/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/example/ohos/entry/src/main/resources/base/element/string.json b/example/ohos/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..3131bad26604ac44d35a7cc7e4cb59b06e2cbdec
--- /dev/null
+++ b/example/ohos/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "window_manager_plus_example"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/example/ohos/entry/src/main/resources/base/media/icon.png b/example/ohos/entry/src/main/resources/base/media/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/example/ohos/entry/src/main/resources/base/media/icon.png differ
diff --git a/example/ohos/entry/src/main/resources/base/profile/main_pages.json b/example/ohos/entry/src/main/resources/base/profile/main_pages.json
new file mode 100644
index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce
--- /dev/null
+++ b/example/ohos/entry/src/main/resources/base/profile/main_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "pages/Index"
+ ]
+}
diff --git a/example/ohos/entry/src/main/resources/en_US/element/string.json b/example/ohos/entry/src/main/resources/en_US/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..3131bad26604ac44d35a7cc7e4cb59b06e2cbdec
--- /dev/null
+++ b/example/ohos/entry/src/main/resources/en_US/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "window_manager_plus_example"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/example/ohos/entry/src/main/resources/zh_CN/element/string.json b/example/ohos/entry/src/main/resources/zh_CN/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..77704b65572b3f50e4ef7cd7189867b76b63862e
--- /dev/null
+++ b/example/ohos/entry/src/main/resources/zh_CN/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "模块描述"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "window_manager_plus_example"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets b/example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..25d4c71ff3cd584f5d64f6f8c0ac864928c234c4
--- /dev/null
+++ b/example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets
@@ -0,0 +1,50 @@
+/*
+* 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 hilog from '@ohos.hilog';
+import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'
+
+export default function abilityTest() {
+ describe('ActsAbilityTest', function () {
+ // Defines a test suite. Two parameters are supported: test suite name and test suite function.
+ beforeAll(function () {
+ // Presets an action, which is performed only once before all test cases of the test suite start.
+ // This API supports only one parameter: preset action function.
+ })
+ beforeEach(function () {
+ // Presets an action, which is performed before each unit test case starts.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: preset action function.
+ })
+ afterEach(function () {
+ // Presets a clear action, which is performed after each unit test case ends.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: clear action function.
+ })
+ afterAll(function () {
+ // Presets a clear action, which is performed after all test cases of the test suite end.
+ // This API supports only one parameter: clear action function.
+ })
+ it('assertContain',0, function () {
+ // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
+ hilog.info(0x0000, 'testTag', '%{public}s', 'it begin');
+ let a = 'abc'
+ let b = 'b'
+ // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
+ expect(a).assertContain(b)
+ expect(a).assertEqual(a)
+ })
+ })
+}
\ No newline at end of file
diff --git a/example/ohos/entry/src/ohosTest/ets/test/List.test.ets b/example/ohos/entry/src/ohosTest/ets/test/List.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..f4140030e65d20df6af30a6bf51e464dea8f8aa6
--- /dev/null
+++ b/example/ohos/entry/src/ohosTest/ets/test/List.test.ets
@@ -0,0 +1,20 @@
+/*
+* 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 abilityTest from './Ability.test'
+
+export default function testsuite() {
+ abilityTest()
+}
\ No newline at end of file
diff --git a/example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets b/example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..4ca645e6013cfce8e7dbb728313cb8840c4da660
--- /dev/null
+++ b/example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets
@@ -0,0 +1,63 @@
+/*
+* 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 UIAbility from '@ohos.app.ability.UIAbility';
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+import hilog from '@ohos.hilog';
+import { Hypium } from '@ohos/hypium';
+import testsuite from '../test/List.test';
+import window from '@ohos.window';
+
+export default class TestAbility extends UIAbility {
+ onCreate(want, launchParam) {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate');
+ hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? '');
+ hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:'+ JSON.stringify(launchParam) ?? '');
+ var abilityDelegator: any
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
+ var abilityDelegatorArguments: any
+ abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
+ hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!');
+ Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite)
+ }
+
+ onDestroy() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage) {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate');
+ windowStage.loadContent('testability/pages/Index', (err, data) => {
+ if (err.code) {
+ hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
+ return;
+ }
+ hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s',
+ JSON.stringify(data) ?? '');
+ });
+ }
+
+ onWindowStageDestroy() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy');
+ }
+
+ onForeground() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground');
+ }
+
+ onBackground() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground');
+ }
+}
\ No newline at end of file
diff --git a/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets b/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..cef0447cd2f137ef82d223ead2e156808878ab90
--- /dev/null
+++ b/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets
@@ -0,0 +1,49 @@
+/*
+* 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 hilog from '@ohos.hilog';
+
+@Entry
+@Component
+struct Index {
+ aboutToAppear() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility index aboutToAppear');
+ }
+ @State message: string = 'Hello World'
+ build() {
+ Row() {
+ Column() {
+ Text(this.message)
+ .fontSize(50)
+ .fontWeight(FontWeight.Bold)
+ Button() {
+ Text('next page')
+ .fontSize(20)
+ .fontWeight(FontWeight.Bold)
+ }.type(ButtonType.Capsule)
+ .margin({
+ top: 20
+ })
+ .backgroundColor('#0D9FFB')
+ .width('35%')
+ .height('5%')
+ .onClick(()=>{
+ })
+ }
+ .width('100%')
+ }
+ .height('100%')
+ }
+ }
\ No newline at end of file
diff --git a/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts b/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1def08f2e9dcbfa3454a07b7a3b82b173bb90d02
--- /dev/null
+++ b/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts
@@ -0,0 +1,64 @@
+/*
+* 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 hilog from '@ohos.hilog';
+import TestRunner from '@ohos.application.testRunner';
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+
+var abilityDelegator = undefined
+var abilityDelegatorArguments = undefined
+
+async function onAbilityCreateCallback() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback');
+}
+
+async function addAbilityMonitorCallback(err: any) {
+ hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
+}
+
+export default class OpenHarmonyTestRunner implements TestRunner {
+ constructor() {
+ }
+
+ onPrepare() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare ');
+ }
+
+ async onRun() {
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run');
+ abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
+ var testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility'
+ let lMonitor = {
+ abilityName: testAbilityName,
+ onAbilityCreate: onAbilityCreateCallback,
+ };
+ abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
+ var cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName
+ var debug = abilityDelegatorArguments.parameters['-D']
+ if (debug == 'true')
+ {
+ cmd += ' -D'
+ }
+ hilog.info(0x0000, 'testTag', 'cmd : %{public}s', cmd);
+ abilityDelegator.executeShellCommand(cmd,
+ (err: any, d: any) => {
+ hilog.info(0x0000, 'testTag', 'executeShellCommand : err : %{public}s', JSON.stringify(err) ?? '');
+ hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.stdResult ?? '');
+ hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.exitCode ?? '');
+ })
+ hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end');
+ }
+}
\ No newline at end of file
diff --git a/example/ohos/entry/src/ohosTest/module.json5 b/example/ohos/entry/src/ohosTest/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..fab77ce2e0c61e3ad010bab5b27ccbd15f9a8c96
--- /dev/null
+++ b/example/ohos/entry/src/ohosTest/module.json5
@@ -0,0 +1,51 @@
+/*
+* 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.
+*/
+
+{
+ "module": {
+ "name": "entry_test",
+ "type": "feature",
+ "description": "$string:module_test_desc",
+ "mainElement": "TestAbility",
+ "deviceTypes": [
+ "phone"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:test_pages",
+ "abilities": [
+ {
+ "name": "TestAbility",
+ "srcEntry": "./ets/testability/TestAbility.ets",
+ "description": "$string:TestAbility_desc",
+ "icon": "$media:icon",
+ "label": "$string:TestAbility_label",
+ "exported": true,
+ "startWindowIcon": "$media:icon",
+ "startWindowBackground": "$color:start_window_background",
+ "skills": [
+ {
+ "actions": [
+ "action.system.home"
+ ],
+ "entities": [
+ "entity.system.home"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/example/ohos/entry/src/ohosTest/resources/base/element/color.json b/example/ohos/entry/src/ohosTest/resources/base/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02
--- /dev/null
+++ b/example/ohos/entry/src/ohosTest/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/example/ohos/entry/src/ohosTest/resources/base/element/string.json b/example/ohos/entry/src/ohosTest/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..65d8fa5a7cf54aa3943dcd0214f58d1771bc1f6c
--- /dev/null
+++ b/example/ohos/entry/src/ohosTest/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_test_desc",
+ "value": "test ability description"
+ },
+ {
+ "name": "TestAbility_desc",
+ "value": "the test ability"
+ },
+ {
+ "name": "TestAbility_label",
+ "value": "test label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/example/ohos/entry/src/ohosTest/resources/base/media/icon.png b/example/ohos/entry/src/ohosTest/resources/base/media/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/example/ohos/entry/src/ohosTest/resources/base/media/icon.png differ
diff --git a/example/ohos/entry/src/ohosTest/resources/base/profile/test_pages.json b/example/ohos/entry/src/ohosTest/resources/base/profile/test_pages.json
new file mode 100644
index 0000000000000000000000000000000000000000..b7e7343cacb32ce982a45e76daad86e435e054fe
--- /dev/null
+++ b/example/ohos/entry/src/ohosTest/resources/base/profile/test_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "testability/pages/Index"
+ ]
+}
diff --git a/example/ohos/hvigor/hvigor-config.json5 b/example/ohos/hvigor/hvigor-config.json5
new file mode 100644
index 0000000000000000000000000000000000000000..541ba35711b75986f9295410ee38fdb8f2572878
--- /dev/null
+++ b/example/ohos/hvigor/hvigor-config.json5
@@ -0,0 +1,20 @@
+/*
+* 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.
+*/
+
+{
+ "modelVersion": "5.0.0",
+ "dependencies": {
+ }
+}
\ No newline at end of file
diff --git a/example/ohos/hvigorfile.ts b/example/ohos/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8f2d2aafe6d6a3a71a9944ebd0c91fbc308ac9d1
--- /dev/null
+++ b/example/ohos/hvigorfile.ts
@@ -0,0 +1,21 @@
+/*
+* 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 { appTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
\ No newline at end of file
diff --git a/example/ohos/oh-package.json5 b/example/ohos/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..f2d99857dfc4840f17e10db44906047032ac716c
--- /dev/null
+++ b/example/ohos/oh-package.json5
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+{
+ "modelVersion": "5.0.0",
+ "name": "window_manager_plus_example",
+ "version": "1.0.0",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "author": "",
+ "license": "",
+ "dependencies": {
+ "@ohos/flutter_ohos": "file:./har/flutter.har"
+ },
+ "devDependencies": {
+ "@ohos/hypium": "1.0.6"
+ },
+ "overrides": {
+ "@ohos/flutter_ohos": "file:./har/flutter.har",
+ "window_manager_plus": "file:./har/window_manager_plus.har",
+ "integration_test": "file:./har/integration_test.har",
+ "@ohos/flutter_module": "file:./entry",
+ "screen_retriever": "file:./har/screen_retriever.har"
+ }
+}
\ No newline at end of file
diff --git a/example/pubspec.lock b/example/pubspec.lock
index 5c163646e19dcad22b5fbd5d2d286555484ebeef..369b5aef2fff058aeb836b6537be46d09c315e47 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -1,20 +1,28 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
+ archive:
+ dependency: transitive
+ description:
+ name: archive
+ sha256: "80e5141fafcb3361653ce308776cfd7d45e6e9fbb429e14eec571382c0c5fecb"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "3.3.2"
async:
dependency: transitive
description:
name: async
- sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
- url: "https://pub.dev"
+ sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.11.0"
+ version: "2.10.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.1"
bot_toast:
@@ -22,57 +30,65 @@ packages:
description:
name: bot_toast
sha256: "6b93030a99a98335b8827ecd83021e92e885ffc61d261d3825ffdecdd17f3bdf"
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "4.1.3"
characters:
dependency: transitive
description:
name: characters
- sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
- url: "https://pub.dev"
+ sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.3.0"
+ version: "1.2.1"
clock:
dependency: transitive
description:
name: clock
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.1"
collection:
dependency: transitive
description:
name: collection
- sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
- url: "https://pub.dev"
+ sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.17.0"
+ crypto:
+ dependency: transitive
+ description:
+ name: crypto
+ sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.18.0"
+ version: "3.0.2"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
- sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
- url: "https://pub.dev"
+ sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.0.8"
+ version: "1.0.6"
fake_async:
dependency: transitive
description:
name: fake_async
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.1"
file:
dependency: transitive
description:
name: file
- sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
- url: "https://pub.dev"
+ sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "7.0.0"
+ version: "6.1.4"
flutter:
dependency: "direct main"
description: flutter
@@ -98,172 +114,93 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
- json_annotation:
- dependency: transitive
- description:
- name: json_annotation
- sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
- url: "https://pub.dev"
- source: hosted
- version: "4.9.0"
- leak_tracker:
- dependency: transitive
- description:
- name: leak_tracker
- sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
- url: "https://pub.dev"
- source: hosted
- version: "10.0.5"
- leak_tracker_flutter_testing:
+ js:
dependency: transitive
description:
- name: leak_tracker_flutter_testing
- sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
- url: "https://pub.dev"
+ name: js
+ sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "3.0.5"
- leak_tracker_testing:
- dependency: transitive
- description:
- name: leak_tracker_testing
- sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
- url: "https://pub.dev"
- source: hosted
- version: "3.0.1"
- lints:
- dependency: transitive
- description:
- name: lints
- sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
- url: "https://pub.dev"
- source: hosted
- version: "4.0.0"
+ version: "0.6.5"
matcher:
dependency: transitive
description:
name: matcher
- sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
- url: "https://pub.dev"
+ sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "0.12.16+1"
+ version: "0.12.13"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
- sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
- url: "https://pub.dev"
+ sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "0.11.1"
+ version: "0.2.0"
menu_base:
dependency: transitive
description:
name: menu_base
sha256: "820368014a171bd1241030278e6c2617354f492f5c703d7b7d4570a6b8b84405"
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "0.1.1"
meta:
dependency: transitive
description:
name: meta
- sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
- url: "https://pub.dev"
- source: hosted
- version: "1.15.0"
- mostly_reasonable_lints:
- dependency: "direct dev"
- description:
- name: mostly_reasonable_lints
- sha256: e19fec63536866ba307b3dfbc258b4bce9b3745129f038006b56b4067c6293d8
- url: "https://pub.dev"
+ sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "0.1.2"
+ version: "1.8.0"
path:
dependency: transitive
description:
name: path
- sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
- url: "https://pub.dev"
+ sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.9.0"
+ version: "1.8.2"
platform:
dependency: transitive
description:
name: platform
- sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65"
- url: "https://pub.dev"
- source: hosted
- version: "3.1.5"
- plugin_platform_interface:
- dependency: transitive
- description:
- name: plugin_platform_interface
- sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
- url: "https://pub.dev"
+ sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.1.8"
+ version: "3.1.0"
preference_list:
dependency: "direct main"
description:
name: preference_list
- sha256: "1429f8fe03605d5eaf6dc333208d7bbf028bae707c3c1c32386939e4d7f58154"
- url: "https://pub.dev"
+ sha256: d3419b2ec57a6ad2156bd682a46cf3194bf162b36bb013790c7b29e6438f107a
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "0.0.2"
+ version: "0.0.1"
process:
dependency: transitive
description:
name: process
- sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32"
- url: "https://pub.dev"
+ sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "5.0.2"
+ version: "4.2.4"
screen_retriever:
dependency: transitive
description:
- name: screen_retriever
- sha256: "570dbc8e4f70bac451e0efc9c9bb19fa2d6799a11e6ef04f946d7886d2e23d0c"
- url: "https://pub.dev"
- source: hosted
- version: "0.2.0"
- screen_retriever_linux:
- dependency: transitive
- description:
- name: screen_retriever_linux
- sha256: f7f8120c92ef0784e58491ab664d01efda79a922b025ff286e29aa123ea3dd18
- url: "https://pub.dev"
- source: hosted
- version: "0.2.0"
- screen_retriever_macos:
- dependency: transitive
- description:
- name: screen_retriever_macos
- sha256: "71f956e65c97315dd661d71f828708bd97b6d358e776f1a30d5aa7d22d78a149"
- url: "https://pub.dev"
- source: hosted
- version: "0.2.0"
- screen_retriever_platform_interface:
- dependency: transitive
- description:
- name: screen_retriever_platform_interface
- sha256: ee197f4581ff0d5608587819af40490748e1e39e648d7680ecf95c05197240c0
- url: "https://pub.dev"
- source: hosted
- version: "0.2.0"
- screen_retriever_windows:
- dependency: transitive
- description:
- name: screen_retriever_windows
- sha256: "449ee257f03ca98a57288ee526a301a430a344a161f9202b4fcc38576716fe13"
- url: "https://pub.dev"
- source: hosted
- version: "0.2.0"
+ path: "."
+ ref: "dev_v0.1.9"
+ resolved-ref: e90de0e1d743ffcd305789ecb5ac1bfa4cf6f7c9
+ url: "https://gitee.com/openharmony-sig/fluttertpc_screen_retriever.git"
+ source: git
+ version: "0.1.9"
shortid:
dependency: transitive
description:
name: shortid
sha256: d0b40e3dbb50497dad107e19c54ca7de0d1a274eb9b4404991e443dadb9ebedb
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "0.1.2"
sky_engine:
@@ -275,32 +212,32 @@ packages:
dependency: transitive
description:
name: source_span
- sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
- url: "https://pub.dev"
+ sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.10.0"
+ version: "1.9.1"
stack_trace:
dependency: transitive
description:
name: stack_trace
- sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
- url: "https://pub.dev"
+ sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.11.1"
+ version: "1.11.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
- sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
- url: "https://pub.dev"
+ sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.1.2"
+ version: "2.1.1"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0"
sync_http:
@@ -308,7 +245,7 @@ packages:
description:
name: sync_http
sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961"
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "0.3.1"
term_glyph:
@@ -316,56 +253,64 @@ packages:
description:
name: term_glyph
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
- sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
- url: "https://pub.dev"
+ sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "0.7.2"
+ version: "0.4.16"
tray_manager:
dependency: "direct main"
description:
name: tray_manager
- sha256: bdc3ac6c36f3d12d871459e4a9822705ce5a1165a17fa837103bc842719bf3f7
- url: "https://pub.dev"
+ sha256: "4ab709d70a4374af172f8c39e018db33a4271265549c6fc9d269a65e5f4b0225"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "0.2.1"
+ typed_data:
+ dependency: transitive
+ description:
+ name: typed_data
+ sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "0.2.4"
+ version: "1.3.1"
vector_math:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.4"
vm_service:
dependency: transitive
description:
name: vm_service
- sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
- url: "https://pub.dev"
+ sha256: e7fb6c2282f7631712b69c19d1bff82f3767eea33a2321c14fa59ad67ea391c7
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "14.2.5"
+ version: "9.4.0"
webdriver:
dependency: transitive
description:
name: webdriver
- sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e"
- url: "https://pub.dev"
+ sha256: ef67178f0cc7e32c1494645b11639dd1335f1d18814aa8435113a92e9ef9d841
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "3.0.3"
+ version: "3.0.1"
window_manager_plus:
dependency: "direct main"
description:
path: ".."
relative: true
source: path
- version: "1.0.0"
+ version: "1.0.5"
sdks:
- dart: ">=3.3.0 <4.0.0"
- flutter: ">=3.18.0-18.0.pre.54"
+ dart: ">=2.19.6 <3.0.0"
+ flutter: ">=3.3.0"
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
index bc7784d3ed76a40b32a65447d230d2539ca5e131..59d49ba17dc997b43dd0db36b068de780f11d618 100644
--- a/example/pubspec.yaml
+++ b/example/pubspec.yaml
@@ -3,15 +3,15 @@ description: Demonstrates how to use the window_manager_plus plugin.
publish_to: "none"
environment:
- sdk: ">=3.0.0 <4.0.0"
+ sdk: ">=2.19.6 <4.0.0"
dependencies:
bot_toast: ^4.1.3
cupertino_icons: ^1.0.2
flutter:
sdk: flutter
- preference_list: ^0.0.2
- tray_manager: ^0.2.4
+ preference_list: ^0.0.1
+ tray_manager: ^0.2.1
window_manager_plus:
path: ../
@@ -20,7 +20,6 @@ dev_dependencies:
sdk: flutter
integration_test:
sdk: flutter
- mostly_reasonable_lints: ^0.1.2
flutter:
uses-material-design: true
diff --git a/lib/src/window_listener.dart b/lib/src/window_listener.dart
index 2e6f0a60acc059a4e41245813b208229d2b0bed9..837016e8cddba9d9637b6901fc0ca0019c719e05 100644
--- a/lib/src/window_listener.dart
+++ b/lib/src/window_listener.dart
@@ -4,7 +4,7 @@ import 'package:window_manager_plus/src/window_manager.dart';
/// If this is used as a Global Listener using the [WindowManagerPlus.addGlobalListener] static method,
/// the `windowId` parameter will be the ID of the window that emitted the event,
/// otherwise, it will be always `null`.
-abstract mixin class WindowListener {
+mixin WindowListener {
/// Emitted when the window is going to be closed.
void onWindowClose([int? windowId]) {}
diff --git a/ohos/.gitignore b/ohos/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..c0f9ca4c47ca2d6aea523c5e0cf3331566bbf88a
--- /dev/null
+++ b/ohos/.gitignore
@@ -0,0 +1,9 @@
+/node_modules
+/oh_modules
+/.preview
+/.idea
+/build
+/.cxx
+/.test
+/BuildProfile.ets
+/oh-package-lock.json5
diff --git a/ohos/build-profile.json5 b/ohos/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..b1fd98dbe794839b511425d5d0e052658e756b32
--- /dev/null
+++ b/ohos/build-profile.json5
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+{
+ "apiType": "stageMode",
+ "buildOption": {
+ },
+ "targets": [
+ {
+ "name": "default"
+ }
+ ]
+}
diff --git a/ohos/hvigorfile.ts b/ohos/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..47e6e1f81d365872f101585f5dbf816bcad65864
--- /dev/null
+++ b/ohos/hvigorfile.ts
@@ -0,0 +1,2 @@
+// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
+export { harTasks } from '@ohos/hvigor-ohos-plugin';
\ No newline at end of file
diff --git a/ohos/index.ets b/ohos/index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..1136f96ea2c1690bb716ff2f20f1aed82c6fbe9b
--- /dev/null
+++ b/ohos/index.ets
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import WindowManagerPlusPlugin from './src/main/ets/components/plugin/WindowManagerPlusPlugin';
+export default WindowManagerPlusPlugin;
+export { default as WindowStageManager } from './src/main/ets/components/plugin/WindowStageManager';
diff --git a/ohos/local.properties b/ohos/local.properties
new file mode 100644
index 0000000000000000000000000000000000000000..4ca8eb882f1a1634ae0304f3f5fa1b0df68dd14b
--- /dev/null
+++ b/ohos/local.properties
@@ -0,0 +1 @@
+hwsdk.dir=C:\\Program Files\\Huawei\\DevEco Studio\\sdk
\ No newline at end of file
diff --git a/ohos/oh-package.json5 b/ohos/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..2eeb1574ab45438f4c6f2b895b2907de597e623d
--- /dev/null
+++ b/ohos/oh-package.json5
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+{
+ "name": "window_manager_plus",
+ "version": "1.0.0",
+ "description": "Please describe the basic information.",
+ "main": "index.ets",
+ "author": "",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@ohos/flutter_ohos": "file:./har/flutter.har"
+ }
+}
diff --git a/ohos/src/main/ets/components/plugin/MultiWindowAbility.ets b/ohos/src/main/ets/components/plugin/MultiWindowAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..8e6f29c2544ca256dfef4de4100a12f2b43a80b7
--- /dev/null
+++ b/ohos/src/main/ets/components/plugin/MultiWindowAbility.ets
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { AbilityConstant, UIAbility, Want } from "@kit.AbilityKit";
+import window from "@ohos.window";
+import WindowStageManager from "./WindowStageManager";
+
+export const WINDOW_NAME_KEY = 'WINDOW_NAME';
+export const INIT_ROUTE_KEY = 'INIT_ROUTE';
+
+export default class MultiWindowAbility extends UIAbility {
+ windowName?: string;
+
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
+ super.onCreate(want, launchParam);
+ const record: Record | undefined = want.parameters;
+ if (record && record[WINDOW_NAME_KEY]) {
+ this.windowName = record[WINDOW_NAME_KEY].toString();
+ }
+ }
+
+
+ onWindowStageCreate(windowStage: window.WindowStage): void {
+ super.onWindowStageCreate(windowStage);
+ if (this.windowName) {
+ WindowStageManager.addStage(this.windowName, windowStage);
+ }
+ }
+
+ onWindowStageWillDestroy(windowStage: window.WindowStage): void {
+ super.onWindowStageWillDestroy(windowStage);
+ if (this.windowName) {
+ WindowStageManager.removeStage(this.windowName);
+ }
+ }
+}
\ No newline at end of file
diff --git a/ohos/src/main/ets/components/plugin/WindowManagerPlus.ets b/ohos/src/main/ets/components/plugin/WindowManagerPlus.ets
new file mode 100644
index 0000000000000000000000000000000000000000..a8685ada107a64b5d1504519d82ad1083030bd88
--- /dev/null
+++ b/ohos/src/main/ets/components/plugin/WindowManagerPlus.ets
@@ -0,0 +1,571 @@
+/*
+ * Copyright (C) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { HashMap } from '@kit.ArkTS';
+import { MethodCall, MethodCallHandler, MethodChannel, MethodResult } from '@ohos/flutter_ohos';
+import { window } from '@kit.ArkUI';
+import WindowManagerPlusPlugin from './WindowManagerPlusPlugin';
+import app from '@system.app';
+import { BusinessError } from '@kit.BasicServicesKit';
+import { bundleManager, common } from '@kit.AbilityKit';
+import { getMethodArg } from './WindowManagerUtil';
+import display from '@ohos.display';
+import WindowStateManager from './WindowStageManager';
+
+
+export default class WindowManagerPlus implements MethodCallHandler {
+ windowId?: number;
+ channel: MethodChannel | null = null;
+ windowClass: window.Window | null = null;
+ eventType: window.WindowEventType = window.WindowEventType.WINDOW_SHOWN;
+ statusType: window.WindowStatusType = window.WindowStatusType.UNDEFINED;
+ isPreventClose: boolean = false;
+ isLayoutFullScreen: boolean = false;
+ private moveTimeoutId: number = 0;
+ //多窗口处理handler集合
+ static windowManagerPlusMap: HashMap = new HashMap();
+ static autoRiseId: number = 0;
+
+ /**
+ * 创建新窗口
+ * @param args
+ */
+ public static createWindow(args: string[]): number {
+ const windowId: number = WindowManagerPlus.getNewWindowId();
+ return windowId;
+ }
+
+ public static getNewWindowId(): number {
+ WindowManagerPlus.autoRiseId += 1;
+ return WindowManagerPlus.autoRiseId;
+ }
+
+ onWindowInit() {
+ if (this.windowId != undefined && this.windowId >= 0) {
+ WindowManagerPlus.autoRiseId = this.windowId;
+ }
+ this.windowClass?.on('windowEvent', (type: window.WindowEventType) => {
+ this.eventType = type;
+ console.info('windowEvent. Event:' + type);
+ switch (type) {
+ case window.WindowEventType.WINDOW_ACTIVE:
+ this.onWindowFocus();
+ break;
+ case window.WindowEventType.WINDOW_INACTIVE:
+ this.onWindowBlur();
+ break;
+ // case window.WindowEventType.WINDOW_DESTROYED:
+ // 这个时机赶不上napi detach,所以在willDestroy中触发
+ // if (this.windowId != undefined && this.windowId >= 0) {
+ // WindowManagerPlusPlugin.releaseWindowManager(this.windowId);
+ // }
+ // break;
+ default:
+ break;
+ }
+ })
+ this.windowClass?.on('windowStatusChange', (type: window.WindowStatusType) => {
+ //检查是否退出窗口状态
+ this.checkWindowStatus(type);
+ if (this.statusType !== type) {
+ this.statusType = type;
+ console.log('windowStatusChange: ' + this.statusType);
+ switch (type) {
+ case window.WindowStatusType.FULL_SCREEN:
+ if (this.windowClass?.getWindowProperties().isFullScreen &&
+ this.windowClass?.getWindowProperties().isLayoutFullScreen) {
+ this.isLayoutFullScreen = true;
+ this.onWindowEnterFullScreen();
+ } else {
+ this.isLayoutFullScreen = false;
+ this.onWindowMaximize();
+ }
+ break;
+ case window.WindowStatusType.MAXIMIZE:
+ this.onWindowMaximize();
+ break;
+ case window.WindowStatusType.MINIMIZE:
+ this.onWindowMinimize();
+ break;
+ default:
+ break;
+ }
+ }
+ })
+ this.windowClass?.on('windowRectChange', (data: window.RectChangeOptions) => {
+ if (data.reason === window.RectChangeReason.MOVE) {
+ //窗口拖拽移动
+ this.onWindowMove();
+ this.setMovedTimeout();
+ } else if (data.reason === window.RectChangeReason.DRAG_START || data.reason === window.RectChangeReason.DRAG) {
+ //窗口拖拽缩放
+ this.onWindowResize();
+ } else if (data.reason === window.RectChangeReason.DRAG_END) {
+ //窗口结束拖拽缩放
+ this.onWindowResized();
+ }
+ });
+ }
+
+ private setMovedTimeout() {
+ clearTimeout(this.moveTimeoutId);
+ this.moveTimeoutId = setTimeout(() => {
+ this.onWindowMoved();
+ }, 200);
+ }
+
+ public release() {
+ this.onWindowClose();
+ this.channel?.setMethodCallHandler(null);
+ try {
+ this.windowClass?.off('windowEvent');
+ this.windowClass?.off('windowStatusChange');
+ this.windowClass?.off('windowRectChange');
+ } catch (exception) {
+ console.error(`Failed to unregister callback. Cause code: ${exception.code}, message: ${exception.message}`);
+ }
+ }
+
+ /**
+ * 获取一个可用的window
+ * @returns
+ */
+ public static getAvailableWindow(): window.Window | null {
+ const windowStage: window.WindowStage | undefined = WindowStateManager.getAvailableStage();
+ try {
+ if (windowStage) {
+ return windowStage.getMainWindowSync();
+ }
+ } catch (exception) {
+ console.error('Failed to obtain the main window. Cause: ' + JSON.stringify(exception));
+ }
+ return null;
+ }
+
+ /**
+ * 返回已创建窗口的id
+ * @returns
+ */
+ public static getWindowsIds(): Array {
+ return Array.from(WindowManagerPlus.windowManagerPlusMap.keys());
+ }
+
+
+ public setAsFrameless(): void {
+
+ }
+
+ onMethodCall(call: MethodCall, result: MethodResult): void {
+ const argsObj: ESObject = call.args;
+ let windowId: number = -1;
+ if (argsObj instanceof Map) {
+ if (argsObj['windowId']) {
+ windowId = argsObj['windowId'] as number;
+ }
+ }
+ switch (call.method) {
+ case "invokeMethodToWindow":
+ const arg0: ESObject = getMethodArg(call, "targetWindowId");
+ const targetWindowId: number = arg0 != null ? arg0 : -1;
+ if (WindowManagerPlus.windowManagerPlusMap.hasKey(targetWindowId)) {
+ WindowManagerPlus.windowManagerPlusMap.get(targetWindowId).channel?.invokeMethod('onEvent',
+ call.argument('args'), {
+ success: (response: ESObject) => {
+ result.success(response);
+ },
+ error: (errorCode: string, errorMessage: string, errorDetails: ESObject) => {
+ result.error(errorCode, errorMessage, errorDetails);
+ },
+ notImplemented: () => {
+ result.error("1", "target channel not implemented onEvent method", null);
+ }
+ });
+ } else {
+ result.error("0", "Cannot invokeMethodToWindow! targetWindowId not found", null);
+ }
+ break;
+ case "waitUntilReadyToShow":
+ //doNothing
+ result.success(true);
+ break;
+ case "setAsFrameless":
+ //隐藏标题栏和边框
+ this.windowClass?.setWindowSystemBarEnable([]);
+ // this.windowClass?.setSpecificSystemBarEnabled('navigationIndicator',false);
+ break;
+ case "destroy":
+ this.destroy();
+ result.success(true);
+ break;
+ case "close":
+ console.log('close: ' + this.isPreventClose);
+ if (!this.isPreventClose) {
+ this.destroy();
+ result.success(true);
+ }
+ result.success(false);
+ break;
+ case "isPreventClose":
+ result.success(this.isPreventClose);
+ break;
+ case "setPreventClose":
+ this.isPreventClose = getMethodArg(call, 'isPreventClose');
+ console.log('setPreventClose: ' + this.isPreventClose);
+ result.success(true);
+ break;
+ case "focus":
+ // window.shiftAppWindowFocus(0,0);
+ break;
+ case "blur":
+ // window.shiftAppWindowFocus(0,0);
+ break;
+ case "isFocused":
+ result.success(this.eventType === window.WindowEventType.WINDOW_ACTIVE);
+ break;
+ case "show":
+ this.windowClass?.showWindow();
+ result.success(true);
+ break;
+ case "hide":
+ this.windowClass?.minimize();
+ result.success(true);
+ break;
+ case "isVisible":
+ result.success(this.windowClass?.isWindowShowing());
+ break;
+ case "isMaximized":
+ result.success(this.statusType == window.WindowStatusType.MAXIMIZE ||
+ this.windowClass?.getWindowProperties().isFullScreen);
+ break;
+ case "maximize":
+ this.windowClass?.maximize(window.MaximizePresentation.FOLLOW_APP_IMMERSIVE_SETTING);
+ result.success(true);
+ break;
+ case "unmaximize":
+ this.windowClass?.recover();
+ result.success(true);
+ break;
+ case "isMinimized":
+ result.success(this.statusType == window.WindowStatusType.MINIMIZE);
+ break;
+ case "isMaximizable":
+ result.success(true);
+ break;
+ case "setMaximizable":
+ result.success(true);
+ break;
+ case "minimize":
+ this.windowClass?.minimize();
+ result.success(true);
+ break;
+ case "restore":
+ console.log('not implemented');
+ break;
+ case "isDockable":
+ console.log('not implemented');
+ break;
+ case "isDocked":
+ console.log('not implemented');
+ break;
+ case "dock":
+ console.log('not implemented');
+ break;
+ case "undock":
+ console.log('not implemented');
+ break;
+ case "isFullScreen":
+ result.success(this.windowClass?.getWindowProperties().isFullScreen &&
+ this.windowClass?.getWindowProperties().isLayoutFullScreen);
+ break;
+ case "setFullScreen":
+ const isFullScreen: boolean = getMethodArg(call, 'isFullScreen');
+ this.windowClass?.setWindowLayoutFullScreen(isFullScreen);
+ result.success(true);
+ break;
+ case "setAspectRatio":
+ const aspectRatio: number = getMethodArg(call, 'aspectRatio');
+ if (aspectRatio > 0) {
+ this.windowClass?.setAspectRatio(aspectRatio);
+ } else {
+ this.windowClass?.resetAspectRatio();
+ }
+ result.success(true);
+ break;
+ case "setBackgroundColor":
+ const backgroundColorA: number = getMethodArg(call, 'backgroundColorA');
+ const backgroundColorR: number = getMethodArg(call, 'backgroundColorR');
+ const backgroundColorG: number = getMethodArg(call, 'backgroundColorG');
+ const backgroundColorB: number = getMethodArg(call, 'backgroundColorB');
+ console.log(`setBackgroundColor: ${backgroundColorA}, ${backgroundColorR}, ${backgroundColorG}, ${backgroundColorB}`);
+ const argb = this.toArgbString(backgroundColorA, backgroundColorR, backgroundColorG, backgroundColorB);
+ this.windowClass?.setWindowBackgroundColor(argb);
+ break;
+ case "getBounds":
+ let windowRect = this.windowClass?.getWindowProperties().windowRect;
+ console.log('getBounds windowRect: ' + windowRect);
+ let rectMap: Map = new Map();
+ rectMap.set('x', windowRect?.left);
+ rectMap.set('y', windowRect?.top);
+ rectMap.set('width', windowRect?.width);
+ rectMap.set('height', windowRect?.height);
+ result.success(rectMap);
+ break;
+ case "setBounds":
+ const x: number = getMethodArg(call, 'x');
+ const y: number = getMethodArg(call, 'y');
+ const width: number = getMethodArg(call, 'width');
+ const height: number = getMethodArg(call, 'height');
+ console.log(`setBounds x: ${x}, y: ${y}, width: ${width}, height: ${height},`);
+ let displayClass = display.getDefaultDisplaySync();
+ this.windowClass?.moveWindowTo(x, y).then(() => {
+ this.windowClass?.resize(width, height);
+ })
+ break;
+ case "setMinimumSize":
+ let minWindowLimits = this.windowClass?.getWindowLimits();
+ console.log('setMinimumSize minWindowLimits: ' + JSON.stringify(minWindowLimits));
+ const minWidth: number = getMethodArg(call, 'width');
+ const minHeight: number = getMethodArg(call, 'height');
+ console.log(`setMinimumSize: ${minWidth}, ${minHeight}`);
+ let minLimits: window.WindowLimits = {
+ minWidth: minWidth,
+ minHeight: minHeight,
+ maxWidth: minWindowLimits?.maxWidth,
+ maxHeight: minWindowLimits?.maxHeight
+ }
+ this.windowClass?.setWindowLimits(minLimits)
+ break;
+ case "setMaximumSize":
+ let maxWindowLimits = this.windowClass?.getWindowLimits();
+ console.log('setMaximumSize maxWindowLimits: ' + JSON.stringify(maxWindowLimits));
+ const maxWidth: number = getMethodArg(call, 'width');
+ const maxHeight: number = getMethodArg(call, 'height');
+ console.log(`setMaximumSize: ${maxWidth}, ${maxHeight}`);
+ let maxLimits: window.WindowLimits = {
+ minWidth: maxWindowLimits?.minWidth,
+ minHeight: maxWindowLimits?.minHeight,
+ maxWidth: maxWidth,
+ maxHeight: maxHeight
+ }
+ this.windowClass?.setWindowLimits(maxLimits)
+ break;
+ case "isResizable":
+ console.log('not implemented');
+ break;
+ case "setResizable":
+ console.log('not implemented');
+ break;
+ case "isMovable":
+ console.log('not implemented');
+ break;
+ case "setMovable":
+ console.log('not implemented');
+ break;
+ case "isMinimizable":
+ console.log('not implemented');
+ break;
+ case "setMinimizable":
+ console.log('not implemented');
+ break;
+ case "isClosable":
+ console.log('not implemented');
+ break;
+ case "setClosable":
+ console.log('not implemented');
+ break;
+ case "isAlwaysOnTop":
+ console.log('not implemented');
+ break;
+ case "setAlwaysOnTop":
+ console.log('not implemented');
+ break;
+ case "getTitle":
+ console.log('not implemented');
+ break;
+ case "setTitle":
+ console.log('not implemented');
+ break;
+ case "setTitleBarStyle":
+ console.log('setTitleBarStyle');
+ //const windowButtonVisibility: boolean = getMethodArg(call, 'windowButtonVisibility');
+ //this.windowClass?.setWindowDecorVisible(windowButtonVisibility);
+ break;
+ case "getTitleBarHeight":
+ console.log('getTitleBarHeight');
+ result.success(this.windowClass?.getWindowDecorHeight());
+ break;
+ case "isSkipTaskbar":
+ console.log('not implemented');
+ break;
+ case "setSkipTaskbar":
+ console.log('not implemented');
+ break;
+ case "setBadgeLabel":
+ console.log('not implemented');
+ break;
+ case "setProgressBar":
+ console.log('not implemented');
+ break;
+ case "isVisibleOnAllWorkspaces":
+ console.log('not implemented');
+ break;
+ case "setVisibleOnAllWorkspaces":
+ console.log('not implemented');
+ break;
+ case "hasShadow":
+ console.log('not implemented');
+ break;
+ case "setHasShadow":
+ console.log('not implemented');
+ break;
+ case "getOpacity":
+ console.log('not implemented');
+ break;
+ case "setOpacity":
+ console.log('not implemented');
+ break;
+ case "setBrightness":
+ const brightness: string = getMethodArg(call, 'brightness');
+ console.log('setBrightness brightness: ' + brightness);
+ if (brightness == 'light') {
+ this.windowClass?.setWindowBrightness(1);
+ } else if (brightness == 'dark') {
+ this.windowClass?.setWindowBrightness(0);
+ }
+ break;
+ case "setIgnoreMouseEvents":
+ console.log('not implemented');
+ break;
+ case "startDragging":
+ console.log('not implemented');
+ break;
+
+ default:
+ result.notImplemented();
+ }
+ // if (call.method == "createWindow") {
+ // result.success("OpenHarmony ^ ^ ")
+ // } else if (call.method == "getAllWindowManagerIds") {
+ // result.success("OpenHarmony ^ ^ ")
+ // } else {
+ // result.notImplemented()
+ // }
+ }
+
+ private toArgbString(a: number, r: number, g: number, b: number): string {
+ if (a < 0 || a > 255 || r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) {
+ throw new Error('All values must be between 0 and 255');
+ }
+ const toHex = (num: number): string => num.toString(16).padStart(2, '0');
+ return `#${toHex(a)}${toHex(r)}${toHex(g)}${toHex(b)}`;
+ }
+
+ private destroy() {
+ let context = this.windowClass?.getUIContext().getHostContext() as common.UIAbilityContext;
+ context?.terminateSelf(() => {
+ // 这个时机赶不上napi detach,所以在willDestroy中触发
+ // if (this.windowId != undefined && this.windowId >= 0) {
+ // WindowManagerPlusPlugin.releaseWindowManager(this.windowId);
+ // }
+ })
+ }
+
+ private onWindowBlur() {
+ console.log('onWindowBlur');
+ this.emitEvent("blur");
+ }
+
+ private onWindowClose() {
+ console.log('onWindowClose');
+ this.emitEvent("close");
+ }
+
+ private onWindowEnterFullScreen() {
+ console.log('onWindowEnterFullScreen');
+ this.emitEvent("enter-full-screen");
+ }
+
+ private onWindowFocus() {
+ console.log('onWindowFocus');
+ this.emitEvent("focus");
+ }
+
+ private onWindowLeaveFullScreen() {
+ console.log('onWindowLeaveFullScreen');
+ this.emitEvent("leave-full-screen");
+ }
+
+ private onWindowMaximize() {
+ console.log('onWindowMaximize');
+ this.emitEvent("maximize");
+ }
+
+ private onWindowMinimize() {
+ console.log('onWindowMinimize');
+ this.emitEvent("minimize");
+ }
+
+ private onWindowMove() {
+ console.log('onWindowMove');
+ this.emitEvent("move");
+ }
+
+ private onWindowMoved() {
+ console.log('onWindowMoved');
+ this.emitEvent("moved");
+ }
+
+ private onWindowResize() {
+ console.log('onWindowResize');
+ this.emitEvent("resize");
+ }
+
+ private onWindowResized() {
+ console.log('onWindowResized');
+ this.emitEvent("resized");
+ }
+
+ private onWindowRestore() {
+ console.log('onWindowRestore');
+ this.emitEvent("restore");
+ }
+
+ private onWindowUnmaximize() {
+ console.log('onWindowUnmaximize');
+ this.emitEvent("unmaximize");
+ }
+
+ private emitEvent(eventName: string) {
+ console.log('emitEvent, eventName:' + eventName);
+ let args: Map = new Map();
+ args.set('eventName', eventName);
+ this.channel?.invokeMethod('onEvent', args);
+ }
+
+ private checkWindowStatus(type: window.WindowStatusType) {
+ if (this.statusType != type) {
+ if (this.statusType === window.WindowStatusType.FULL_SCREEN) {
+ if (this.isLayoutFullScreen) {
+ this.onWindowLeaveFullScreen();
+ } else {
+ this.onWindowUnmaximize();
+ }
+ } else if (this.statusType === window.WindowStatusType.MAXIMIZE) {
+ this.onWindowUnmaximize();
+ } else if (this.statusType === window.WindowStatusType.MINIMIZE) {
+ this.onWindowRestore();
+ }
+ }
+ }
+}
diff --git a/ohos/src/main/ets/components/plugin/WindowManagerPlusPlugin.ets b/ohos/src/main/ets/components/plugin/WindowManagerPlusPlugin.ets
new file mode 100644
index 0000000000000000000000000000000000000000..59fa158a5e00da3eea6567e11522e9487121e6c8
--- /dev/null
+++ b/ohos/src/main/ets/components/plugin/WindowManagerPlusPlugin.ets
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {
+ FlutterPlugin,
+ FlutterPluginBinding,
+ MethodCall,
+ MethodCallHandler,
+ MethodChannel,
+ MethodResult,
+} from '@ohos/flutter_ohos';
+import WindowManagerPlus from './WindowManagerPlus';
+import { window } from '@kit.ArkUI';
+import { bundleManager, common, Want } from '@kit.AbilityKit';
+import { WINDOW_NAME_KEY, INIT_ROUTE_KEY } from './MultiWindowAbility';
+import WindowStageManager from './WindowStageManager';
+import { getMethodArg } from './WindowManagerUtil';
+
+/** WindowManagerPlusPlugin **/
+export default class WindowManagerPlusPlugin implements FlutterPlugin, MethodCallHandler {
+ private channelStatic: MethodChannel | null = null;
+ private channel: MethodChannel | null = null;
+ private static binding: FlutterPluginBinding;
+
+ constructor() {
+ }
+
+ getUniqueClassName(): string {
+ return "WindowManagerPlusPlugin"
+ }
+
+ onAttachedToEngine(binding: FlutterPluginBinding): void {
+ WindowManagerPlusPlugin.binding = binding;
+ this.channelStatic = new MethodChannel(binding.getBinaryMessenger(), "window_manager_plus_static");
+ this.channelStatic.setMethodCallHandler(this);
+
+ this.channel = new MethodChannel(binding.getBinaryMessenger(), "window_manager_plus");
+ this.channel.setMethodCallHandler(this);
+ }
+
+ onDetachedFromEngine(binding: FlutterPluginBinding): void {
+ if (this.channelStatic != null) {
+ this.channelStatic.setMethodCallHandler(null)
+ }
+ }
+
+ /**
+ * 每个FlutterEngine初始化时会调用该方法
+ * @param windowId
+ */
+ public static ensureInitialized(windowId: number, window?: window.Window) {
+ console.log(`ensureInitialized :${windowId}`);
+ if (WindowManagerPlus.windowManagerPlusMap.hasKey(windowId)) {
+ console.log(`this window has init,winId=${windowId}`);
+ return;
+ }
+ if (!window) {
+ const stage: window.WindowStage | undefined = WindowStageManager.getState(windowId.toString());
+ if (stage) {
+ window = stage.getMainWindowSync();
+ }
+ }
+ const windowManager: WindowManagerPlus = WindowManagerPlusPlugin.createNewManager(windowId, window);
+ WindowManagerPlus.windowManagerPlusMap.set(windowId, windowManager);
+ }
+
+ /**
+ * 回收窗口
+ * @param windowId
+ */
+ public static releaseWindowManager(windowId: number) {
+ console.log('releaseWindowManager:'+windowId);
+ if (WindowManagerPlus.windowManagerPlusMap.hasKey(windowId)) {
+ WindowStageManager.removeStage(windowId.toString());
+ const windowManager: WindowManagerPlus = WindowManagerPlus.windowManagerPlusMap.get(windowId);
+ WindowManagerPlus.windowManagerPlusMap.remove(windowId);
+ windowManager.release();
+ }
+ }
+
+ public static createNewManager(windowId: number, window?: window.Window): WindowManagerPlus {
+ const windowManager: WindowManagerPlus = new WindowManagerPlus();
+ windowManager.windowId = windowId;
+ windowManager.channel =
+ new MethodChannel(WindowManagerPlusPlugin.binding.getBinaryMessenger(), `window_manager_plus_${windowId}`);
+ windowManager.channel.setMethodCallHandler(windowManager);
+ if (windowId == 0) {
+ windowManager.windowClass = WindowManagerPlus.getAvailableWindow();
+ } else if (window) {
+ windowManager.windowClass = window;
+ }
+ windowManager.onWindowInit();
+ return windowManager;
+ }
+
+ onMethodCall(call: MethodCall, result: MethodResult): void {
+ switch (call.method) {
+ case "createWindow":
+ const newWindowId: number = WindowManagerPlus.createWindow([]);
+ let windowClass = WindowManagerPlus.getAvailableWindow();
+ let context = windowClass?.getUIContext().getHostContext() as common.UIAbilityContext;
+ const want: Want = bundleManager.getLaunchWant();
+ let record: Record | undefined = want.parameters;
+ if (!record) {
+ record = {};
+ }
+ record[WINDOW_NAME_KEY] = newWindowId.toString();
+ let defaultRoute:string = '/';
+ //从入参的args字符数组中,找到"initRoute /xxx/aaa"字符串,作为新开窗口的初始路由
+ const arg0: ESObject = getMethodArg(call, "args");
+ if(arg0){
+ const arr:Array = arg0 as Array;
+ for(let i=0;i = new Map();
+
+ static addStage(key: string, stage: window.WindowStage) {
+ WindowStateManager.stageMap.set(key, stage);
+ }
+
+ static removeStage(key: string) {
+ WindowStateManager.stageMap.delete(key);
+ }
+
+ static getAvailableStage(): window.WindowStage | undefined {
+ if (WindowStateManager.stageMap.size > 0) {
+ const keysArray = Array.from(WindowStateManager.stageMap.keys());
+ const key: string = keysArray[0];
+ return WindowStateManager.stageMap.get(key);
+ }
+ return undefined;
+ }
+
+ static getState(key: string): window.WindowStage | undefined {
+ if (WindowStateManager.stageMap.has(key)) {
+ return WindowStateManager.stageMap.get(key);
+ }
+ return undefined;
+ }
+}
\ No newline at end of file
diff --git a/ohos/src/main/module.json5 b/ohos/src/main/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..3a7442e0848814375df04f6a0f343638d4d351a0
--- /dev/null
+++ b/ohos/src/main/module.json5
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+{
+ "module": {
+ "name": "window_manager_plus",
+ "type": "har",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ]
+ }
+}
diff --git a/pubspec.lock b/pubspec.lock
index e0c97aed1907e2eca831dafd663a1ed28f42028a..55e2bfee0b51d8df286857c7eb4ba1e5d5cd8d72 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -5,45 +5,40 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
- sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834
- url: "https://pub.dev"
+ sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "72.0.0"
- _macros:
- dependency: transitive
- description: dart
- source: sdk
- version: "0.3.2"
+ version: "61.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
- sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139
- url: "https://pub.dev"
+ sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "6.7.0"
+ version: "5.13.0"
args:
dependency: transitive
description:
name: args
- sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
- url: "https://pub.dev"
+ sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.5.0"
+ version: "2.4.2"
async:
dependency: transitive
description:
name: async
- sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
- url: "https://pub.dev"
+ sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.11.0"
+ version: "2.10.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.1"
build_config:
@@ -51,23 +46,23 @@ packages:
description:
name: build_config
sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.1"
characters:
dependency: transitive
description:
name: characters
- sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
- url: "https://pub.dev"
+ sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.3.0"
+ version: "1.2.1"
checked_yaml:
dependency: transitive
description:
name: checked_yaml
sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.3"
clock:
@@ -75,57 +70,57 @@ packages:
description:
name: clock
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.1"
collection:
dependency: transitive
description:
name: collection
- sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
- url: "https://pub.dev"
+ sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.18.0"
+ version: "1.17.0"
convert:
dependency: transitive
description:
name: convert
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.1"
crypto:
dependency: transitive
description:
name: crypto
- sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27
- url: "https://pub.dev"
+ sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "3.0.5"
+ version: "3.0.3"
dependency_validator:
dependency: "direct dev"
description:
name: dependency_validator
- sha256: "81b5dc4cc34a1c05d2fa24aa8d658cb8f048ca23e63d5aaec420200190f1c4b0"
- url: "https://pub.dev"
+ sha256: d27143159d8c2e83bf33e794e3e642c14fd888e2da8f512e6ad38bc854bbf3ec
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "4.1.1"
+ version: "4.1.2"
fake_async:
dependency: transitive
description:
name: fake_async
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.1"
file:
dependency: transitive
description:
name: file
- sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
- url: "https://pub.dev"
+ sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "7.0.1"
+ version: "6.1.4"
flutter:
dependency: "direct main"
description: flutter
@@ -141,7 +136,7 @@ packages:
description:
name: glob
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.2"
io:
@@ -149,177 +144,98 @@ packages:
description:
name: io
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.4"
- json_annotation:
+ js:
dependency: transitive
description:
- name: json_annotation
- sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
- url: "https://pub.dev"
+ name: js
+ sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "4.9.0"
- leak_tracker:
- dependency: transitive
- description:
- name: leak_tracker
- sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
- url: "https://pub.dev"
- source: hosted
- version: "10.0.5"
- leak_tracker_flutter_testing:
- dependency: transitive
- description:
- name: leak_tracker_flutter_testing
- sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
- url: "https://pub.dev"
- source: hosted
- version: "3.0.5"
- leak_tracker_testing:
- dependency: transitive
- description:
- name: leak_tracker_testing
- sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
- url: "https://pub.dev"
- source: hosted
- version: "3.0.1"
- lints:
+ version: "0.6.5"
+ json_annotation:
dependency: transitive
description:
- name: lints
- sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
- url: "https://pub.dev"
+ name: json_annotation
+ sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "4.0.0"
+ version: "4.8.1"
logging:
dependency: transitive
description:
name: logging
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0"
- macros:
- dependency: transitive
- description:
- name: macros
- sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
- url: "https://pub.dev"
- source: hosted
- version: "0.1.2-main.4"
matcher:
dependency: transitive
description:
name: matcher
- sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
- url: "https://pub.dev"
+ sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "0.12.16+1"
+ version: "0.12.13"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
- sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
- url: "https://pub.dev"
+ sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "0.11.1"
+ version: "0.2.0"
meta:
dependency: transitive
description:
name: meta
- sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
- url: "https://pub.dev"
- source: hosted
- version: "1.15.0"
- mostly_reasonable_lints:
- dependency: "direct dev"
- description:
- name: mostly_reasonable_lints
- sha256: e19fec63536866ba307b3dfbc258b4bce9b3745129f038006b56b4067c6293d8
- url: "https://pub.dev"
+ sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "0.1.2"
+ version: "1.8.0"
package_config:
dependency: transitive
description:
name: package_config
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0"
path:
dependency: "direct main"
description:
name: path
- sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
- url: "https://pub.dev"
+ sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.9.0"
- plugin_platform_interface:
- dependency: transitive
- description:
- name: plugin_platform_interface
- sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
- url: "https://pub.dev"
- source: hosted
- version: "2.1.8"
+ version: "1.8.2"
pub_semver:
dependency: transitive
description:
name: pub_semver
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.4"
pubspec_parse:
dependency: transitive
description:
name: pubspec_parse
- sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8
- url: "https://pub.dev"
+ sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.3.0"
+ version: "1.2.3"
screen_retriever:
dependency: "direct main"
description:
- name: screen_retriever
- sha256: "570dbc8e4f70bac451e0efc9c9bb19fa2d6799a11e6ef04f946d7886d2e23d0c"
- url: "https://pub.dev"
- source: hosted
- version: "0.2.0"
- screen_retriever_linux:
- dependency: transitive
- description:
- name: screen_retriever_linux
- sha256: f7f8120c92ef0784e58491ab664d01efda79a922b025ff286e29aa123ea3dd18
- url: "https://pub.dev"
- source: hosted
- version: "0.2.0"
- screen_retriever_macos:
- dependency: transitive
- description:
- name: screen_retriever_macos
- sha256: "71f956e65c97315dd661d71f828708bd97b6d358e776f1a30d5aa7d22d78a149"
- url: "https://pub.dev"
- source: hosted
- version: "0.2.0"
- screen_retriever_platform_interface:
- dependency: transitive
- description:
- name: screen_retriever_platform_interface
- sha256: ee197f4581ff0d5608587819af40490748e1e39e648d7680ecf95c05197240c0
- url: "https://pub.dev"
- source: hosted
- version: "0.2.0"
- screen_retriever_windows:
- dependency: transitive
- description:
- name: screen_retriever_windows
- sha256: "449ee257f03ca98a57288ee526a301a430a344a161f9202b4fcc38576716fe13"
- url: "https://pub.dev"
- source: hosted
- version: "0.2.0"
+ path: "."
+ ref: "dev_v0.1.9"
+ resolved-ref: e90de0e1d743ffcd305789ecb5ac1bfa4cf6f7c9
+ url: "https://gitee.com/openharmony-sig/fluttertpc_screen_retriever.git"
+ source: git
+ version: "0.1.9"
sky_engine:
dependency: transitive
description: flutter
@@ -329,32 +245,32 @@ packages:
dependency: transitive
description:
name: source_span
- sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
- url: "https://pub.dev"
+ sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.10.0"
+ version: "1.9.1"
stack_trace:
dependency: transitive
description:
name: stack_trace
- sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
- url: "https://pub.dev"
+ sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.11.1"
+ version: "1.11.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
- sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
- url: "https://pub.dev"
+ sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.1.2"
+ version: "2.1.1"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0"
term_glyph:
@@ -362,23 +278,23 @@ packages:
description:
name: term_glyph
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
- sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
- url: "https://pub.dev"
+ sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "0.7.2"
+ version: "0.4.16"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.2"
vector_math:
@@ -386,33 +302,25 @@ packages:
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.4"
- vm_service:
- dependency: transitive
- description:
- name: vm_service
- sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
- url: "https://pub.dev"
- source: hosted
- version: "14.2.5"
watcher:
dependency: transitive
description:
name: watcher
- sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
- url: "https://pub.dev"
+ sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.1.0"
+ version: "1.0.2"
yaml:
dependency: transitive
description:
name: yaml
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
- url: "https://pub.dev"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.2"
sdks:
- dart: ">=3.4.0 <4.0.0"
- flutter: ">=3.18.0-18.0.pre.54"
+ dart: ">=2.19.6 <3.0.0"
+ flutter: ">=3.3.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 46f11b97d5bc892a14fcd5420acb1b565bcc3526..7bdfca366fdca5a78262fd24c24b51e7b7aa94b1 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -10,6 +10,7 @@ platforms:
#linux:
macos:
windows:
+ ohos:
topics:
- window
- window-resize
@@ -18,20 +19,22 @@ topics:
- desktop
environment:
- sdk: ">=3.0.0 <4.0.0"
+ sdk: ">=2.19.6 <4.0.0"
flutter: ">=3.3.0"
dependencies:
flutter:
sdk: flutter
path: ^1.8.0
- screen_retriever: ^0.2.0
+ screen_retriever:
+ git:
+ url: https://gitee.com/openharmony-sig/fluttertpc_screen_retriever.git
+ ref: dev_v0.1.9
dev_dependencies:
dependency_validator: ^4.1.1
flutter_test:
sdk: flutter
- mostly_reasonable_lints: ^0.1.2
flutter:
plugin:
@@ -42,3 +45,5 @@ flutter:
pluginClass: WindowManagerPlusPlugin
windows:
pluginClass: WindowManagerPlusPlugin
+ ohos:
+ pluginClass: WindowManagerPlusPlugin